mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-06 04:00:08 +00:00
Refactored the Line class to be templated (to update old code, just replace "Line" with "Line<float>"). Corrected a mac ppc build problem.
This commit is contained in:
parent
0d611ec065
commit
082dff25dd
11 changed files with 601 additions and 984 deletions
|
|
@ -85,8 +85,6 @@
|
|||
|
||||
#if defined (__ppc__) || defined (__ppc64__)
|
||||
#define JUCE_PPC 1
|
||||
#undef MAC_OS_X_VERSION_MAX_ALLOWED
|
||||
#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_4
|
||||
#else
|
||||
#define JUCE_INTEL 1
|
||||
#endif
|
||||
|
|
@ -80044,12 +80042,12 @@ void Graphics::drawLine (const float startX, const float startY,
|
|||
fillPath (p);
|
||||
}
|
||||
|
||||
void Graphics::drawLine (const Line& line) const
|
||||
void Graphics::drawLine (const Line<float>& line) const
|
||||
{
|
||||
drawLine (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY());
|
||||
}
|
||||
|
||||
void Graphics::drawLine (const Line& line, const float lineThickness) const
|
||||
void Graphics::drawLine (const Line<float>& line, const float lineThickness) const
|
||||
{
|
||||
drawLine (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY(), lineThickness);
|
||||
}
|
||||
|
|
@ -80893,48 +80891,40 @@ public:
|
|||
: lookupTable (lookupTable_), numEntries (numEntries_)
|
||||
{
|
||||
jassert (numEntries_ >= 0);
|
||||
float x1 = gradient.x1;
|
||||
float y1 = gradient.y1;
|
||||
float x2 = gradient.x2;
|
||||
float y2 = gradient.y2;
|
||||
Point<float> p1 (gradient.x1, gradient.y1);
|
||||
Point<float> p2 (gradient.x2, gradient.y2);
|
||||
|
||||
if (! transform.isIdentity())
|
||||
{
|
||||
const Line l (x2, y2, x1, y1);
|
||||
const Point<float> p3 = l.getPointAlongLine (0.0f, 100.0f);
|
||||
float x3 = p3.getX();
|
||||
float y3 = p3.getY();
|
||||
const Line<float> l (p2, p1);
|
||||
Point<float> p3 = l.getPointAlongLine (0.0f, 100.0f);
|
||||
|
||||
transform.transformPoint (x1, y1);
|
||||
transform.transformPoint (x2, y2);
|
||||
transform.transformPoint (x3, y3);
|
||||
p1.applyTransform (transform);
|
||||
p2.applyTransform (transform);
|
||||
p3.applyTransform (transform);
|
||||
|
||||
const Line l2 (x2, y2, x3, y3);
|
||||
const float prop = l2.findNearestPointTo (x1, y1);
|
||||
const Point<float> newP2 (l2.getPointAlongLineProportionally (prop));
|
||||
|
||||
x2 = newP2.getX();
|
||||
y2 = newP2.getY();
|
||||
const Line<float> l2 (p2, p3);
|
||||
p2 = l2.getPointAlongLineProportionally (l2.findNearestPointTo (p1));
|
||||
}
|
||||
|
||||
vertical = fabs (x1 - x2) < 0.001f;
|
||||
horizontal = fabs (y1 - y2) < 0.001f;
|
||||
vertical = fabs (p1.getX() - p2.getX()) < 0.001f;
|
||||
horizontal = fabs (p1.getY() - p2.getY()) < 0.001f;
|
||||
|
||||
if (vertical)
|
||||
{
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (y2 - y1));
|
||||
start = roundToInt (y1 * scale);
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (p2.getY() - p1.getY()));
|
||||
start = roundToInt (p1.getY() * scale);
|
||||
}
|
||||
else if (horizontal)
|
||||
{
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (x2 - x1));
|
||||
start = roundToInt (x1 * scale);
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (p2.getX() - p1.getX()));
|
||||
start = roundToInt (p1.getX() * scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
grad = (y2 - y1) / (double) (x1 - x2);
|
||||
yTerm = y1 - x1 / grad;
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (yTerm * grad - (y2 * grad - x2)));
|
||||
grad = (p2.getY() - p1.getY()) / (double) (p1.getX() - p2.getX());
|
||||
yTerm = p1.getY() - p1.getX() / grad;
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (yTerm * grad - (p2.getY() * grad - p2.getX())));
|
||||
grad *= scale;
|
||||
}
|
||||
}
|
||||
|
|
@ -86885,364 +86875,6 @@ END_JUCE_NAMESPACE
|
|||
/*** Start of inlined file: juce_Line.cpp ***/
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
static bool juce_lineIntersection (const float x1, const float y1,
|
||||
const float x2, const float y2,
|
||||
const float x3, const float y3,
|
||||
const float x4, const float y4,
|
||||
float& intersectionX,
|
||||
float& intersectionY) throw()
|
||||
{
|
||||
if (x2 != x3 || y2 != y3)
|
||||
{
|
||||
const float dx1 = x2 - x1;
|
||||
const float dy1 = y2 - y1;
|
||||
const float dx2 = x4 - x3;
|
||||
const float dy2 = y4 - y3;
|
||||
const float divisor = dx1 * dy2 - dx2 * dy1;
|
||||
|
||||
if (divisor == 0)
|
||||
{
|
||||
if (! ((dx1 == 0 && dy1 == 0) || (dx2 == 0 && dy2 == 0)))
|
||||
{
|
||||
if (dy1 == 0 && dy2 != 0)
|
||||
{
|
||||
const float along = (y1 - y3) / dy2;
|
||||
intersectionX = x3 + along * dx2;
|
||||
intersectionY = y1;
|
||||
|
||||
return along >= 0 && along <= 1.0f;
|
||||
}
|
||||
else if (dy2 == 0 && dy1 != 0)
|
||||
{
|
||||
const float along = (y3 - y1) / dy1;
|
||||
intersectionX = x1 + along * dx1;
|
||||
intersectionY = y3;
|
||||
|
||||
return along >= 0 && along <= 1.0f;
|
||||
}
|
||||
else if (dx1 == 0 && dx2 != 0)
|
||||
{
|
||||
const float along = (x1 - x3) / dx2;
|
||||
intersectionX = x1;
|
||||
intersectionY = y3 + along * dy2;
|
||||
|
||||
return along >= 0 && along <= 1.0f;
|
||||
}
|
||||
else if (dx2 == 0 && dx1 != 0)
|
||||
{
|
||||
const float along = (x3 - x1) / dx1;
|
||||
intersectionX = x3;
|
||||
intersectionY = y1 + along * dy1;
|
||||
|
||||
return along >= 0 && along <= 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
intersectionX = 0.5f * (x2 + x3);
|
||||
intersectionY = 0.5f * (y2 + y3);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const float along1 = ((y1 - y3) * dx2 - (x1 - x3) * dy2) / divisor;
|
||||
|
||||
intersectionX = x1 + along1 * dx1;
|
||||
intersectionY = y1 + along1 * dy1;
|
||||
|
||||
if (along1 < 0 || along1 > 1.0f)
|
||||
return false;
|
||||
|
||||
const float along2 = ((y1 - y3) * dx1 - (x1 - x3) * dy1) / divisor;
|
||||
|
||||
return along2 >= 0 && along2 <= 1.0f;
|
||||
}
|
||||
|
||||
intersectionX = x2;
|
||||
intersectionY = y2;
|
||||
return true;
|
||||
}
|
||||
|
||||
Line::Line() throw()
|
||||
: startX (0.0f),
|
||||
startY (0.0f),
|
||||
endX (0.0f),
|
||||
endY (0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
Line::Line (const Line& other) throw()
|
||||
: startX (other.startX),
|
||||
startY (other.startY),
|
||||
endX (other.endX),
|
||||
endY (other.endY)
|
||||
{
|
||||
}
|
||||
|
||||
Line::Line (const float startX_, const float startY_,
|
||||
const float endX_, const float endY_) throw()
|
||||
: startX (startX_),
|
||||
startY (startY_),
|
||||
endX (endX_),
|
||||
endY (endY_)
|
||||
{
|
||||
}
|
||||
|
||||
Line::Line (const Point<float>& start,
|
||||
const Point<float>& end) throw()
|
||||
: startX (start.getX()),
|
||||
startY (start.getY()),
|
||||
endX (end.getX()),
|
||||
endY (end.getY())
|
||||
{
|
||||
}
|
||||
|
||||
Line& Line::operator= (const Line& other) throw()
|
||||
{
|
||||
startX = other.startX;
|
||||
startY = other.startY;
|
||||
endX = other.endX;
|
||||
endY = other.endY;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Line::~Line() throw()
|
||||
{
|
||||
}
|
||||
|
||||
const Point<float> Line::getStart() const throw()
|
||||
{
|
||||
return Point<float> (startX, startY);
|
||||
}
|
||||
|
||||
const Point<float> Line::getEnd() const throw()
|
||||
{
|
||||
return Point<float> (endX, endY);
|
||||
}
|
||||
|
||||
void Line::setStart (const float newStartX,
|
||||
const float newStartY) throw()
|
||||
{
|
||||
startX = newStartX;
|
||||
startY = newStartY;
|
||||
}
|
||||
|
||||
void Line::setStart (const Point<float>& newStart) throw()
|
||||
{
|
||||
startX = newStart.getX();
|
||||
startY = newStart.getY();
|
||||
}
|
||||
|
||||
void Line::setEnd (const float newEndX,
|
||||
const float newEndY) throw()
|
||||
{
|
||||
endX = newEndX;
|
||||
endY = newEndY;
|
||||
}
|
||||
|
||||
void Line::setEnd (const Point<float>& newEnd) throw()
|
||||
{
|
||||
endX = newEnd.getX();
|
||||
endY = newEnd.getY();
|
||||
}
|
||||
|
||||
bool Line::operator== (const Line& other) const throw()
|
||||
{
|
||||
return startX == other.startX
|
||||
&& startY == other.startY
|
||||
&& endX == other.endX
|
||||
&& endY == other.endY;
|
||||
}
|
||||
|
||||
bool Line::operator!= (const Line& other) const throw()
|
||||
{
|
||||
return startX != other.startX
|
||||
|| startY != other.startY
|
||||
|| endX != other.endX
|
||||
|| endY != other.endY;
|
||||
}
|
||||
|
||||
void Line::applyTransform (const AffineTransform& transform) throw()
|
||||
{
|
||||
transform.transformPoint (startX, startY);
|
||||
transform.transformPoint (endX, endY);
|
||||
}
|
||||
|
||||
float Line::getLength() const throw()
|
||||
{
|
||||
return (float) juce_hypot (startX - endX,
|
||||
startY - endY);
|
||||
}
|
||||
|
||||
float Line::getAngle() const throw()
|
||||
{
|
||||
return atan2f (endX - startX,
|
||||
endY - startY);
|
||||
}
|
||||
|
||||
const Point<float> Line::getPointAlongLine (const float distanceFromStart) const throw()
|
||||
{
|
||||
const float alpha = distanceFromStart / getLength();
|
||||
|
||||
return Point<float> (startX + (endX - startX) * alpha,
|
||||
startY + (endY - startY) * alpha);
|
||||
}
|
||||
|
||||
const Point<float> Line::getPointAlongLine (const float offsetX,
|
||||
const float offsetY) const throw()
|
||||
{
|
||||
const float dx = endX - startX;
|
||||
const float dy = endY - startY;
|
||||
const double length = juce_hypot (dx, dy);
|
||||
|
||||
if (length == 0)
|
||||
return Point<float> (startX, startY);
|
||||
else
|
||||
return Point<float> (startX + (float) (((dx * offsetX) - (dy * offsetY)) / length),
|
||||
startY + (float) (((dy * offsetX) + (dx * offsetY)) / length));
|
||||
}
|
||||
|
||||
const Point<float> Line::getPointAlongLineProportionally (const float alpha) const throw()
|
||||
{
|
||||
return Point<float> (startX + (endX - startX) * alpha,
|
||||
startY + (endY - startY) * alpha);
|
||||
}
|
||||
|
||||
float Line::getDistanceFromLine (const float x,
|
||||
const float y) const throw()
|
||||
{
|
||||
const double dx = endX - startX;
|
||||
const double dy = endY - startY;
|
||||
const double length = dx * dx + dy * dy;
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
const double prop = ((x - startX) * dx + (y - startY) * dy) / length;
|
||||
|
||||
if (prop >= 0.0f && prop < 1.0f)
|
||||
{
|
||||
return (float) juce_hypot (x - (startX + prop * dx),
|
||||
y - (startY + prop * dy));
|
||||
}
|
||||
}
|
||||
|
||||
return (float) jmin (juce_hypot (x - startX, y - startY),
|
||||
juce_hypot (x - endX, y - endY));
|
||||
}
|
||||
|
||||
float Line::findNearestPointTo (const float x,
|
||||
const float y) const throw()
|
||||
{
|
||||
const double dx = endX - startX;
|
||||
const double dy = endY - startY;
|
||||
const double length = dx * dx + dy * dy;
|
||||
|
||||
if (length <= 0.0)
|
||||
return 0.0f;
|
||||
|
||||
return jlimit (0.0f, 1.0f,
|
||||
(float) (((x - startX) * dx + (y - startY) * dy) / length));
|
||||
}
|
||||
|
||||
const Line Line::withShortenedStart (const float distanceToShortenBy) const throw()
|
||||
{
|
||||
const float length = getLength();
|
||||
|
||||
return Line (getPointAlongLine (jmin (distanceToShortenBy, length)),
|
||||
getEnd());
|
||||
}
|
||||
|
||||
const Line Line::withShortenedEnd (const float distanceToShortenBy) const throw()
|
||||
{
|
||||
const float length = getLength();
|
||||
|
||||
return Line (getStart(),
|
||||
getPointAlongLine (length - jmin (distanceToShortenBy, length)));
|
||||
}
|
||||
|
||||
bool Line::clipToPath (const Path& path,
|
||||
const bool keepSectionOutsidePath) throw()
|
||||
{
|
||||
const bool startInside = path.contains (startX, startY);
|
||||
const bool endInside = path.contains (endX, endY);
|
||||
|
||||
if (startInside == endInside)
|
||||
{
|
||||
if (keepSectionOutsidePath != startInside)
|
||||
{
|
||||
// entirely outside the path
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// entirely inside the path
|
||||
startX = 0.0f;
|
||||
startY = 0.0f;
|
||||
endX = 0.0f;
|
||||
endY = 0.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool changed = false;
|
||||
PathFlatteningIterator iter (path, AffineTransform::identity);
|
||||
|
||||
while (iter.next())
|
||||
{
|
||||
float ix, iy;
|
||||
|
||||
if (intersects (Line (iter.x1, iter.y1,
|
||||
iter.x2, iter.y2),
|
||||
ix, iy))
|
||||
{
|
||||
if ((startInside && keepSectionOutsidePath)
|
||||
|| (endInside && ! keepSectionOutsidePath))
|
||||
{
|
||||
setStart (ix, iy);
|
||||
}
|
||||
else
|
||||
{
|
||||
setEnd (ix, iy);
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
bool Line::intersects (const Line& line,
|
||||
float& intersectionX,
|
||||
float& intersectionY) const throw()
|
||||
{
|
||||
return juce_lineIntersection (startX, startY,
|
||||
endX, endY,
|
||||
line.startX, line.startY,
|
||||
line.endX, line.endY,
|
||||
intersectionX,
|
||||
intersectionY);
|
||||
}
|
||||
|
||||
bool Line::isVertical() const throw()
|
||||
{
|
||||
return startX == endX;
|
||||
}
|
||||
|
||||
bool Line::isHorizontal() const throw()
|
||||
{
|
||||
return startY == endY;
|
||||
}
|
||||
|
||||
bool Line::isPointAbove (const float x, const float y) const throw()
|
||||
{
|
||||
return startX != endX
|
||||
&& y < ((endY - startY) * (x - startX)) / (endX - startX) + startY;
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
/*** End of inlined file: juce_Line.cpp ***/
|
||||
|
||||
|
|
@ -88243,8 +87875,7 @@ bool Path::contains (const float x, const float y, const float tolerence) const
|
|||
|
||||
while (i.next())
|
||||
{
|
||||
if ((i.y1 <= y && i.y2 > y)
|
||||
|| (i.y2 <= y && i.y1 > y))
|
||||
if ((i.y1 <= y && i.y2 > y) || (i.y2 <= y && i.y1 > y))
|
||||
{
|
||||
const float intersectX = i.x1 + (i.x2 - i.x1) * (y - i.y1) / (i.y2 - i.y1);
|
||||
|
||||
|
|
@ -88258,30 +87889,58 @@ bool Path::contains (const float x, const float y, const float tolerence) const
|
|||
}
|
||||
}
|
||||
|
||||
return (useNonZeroWinding) ? (negativeCrossings != positiveCrossings)
|
||||
: ((negativeCrossings + positiveCrossings) & 1) != 0;
|
||||
return useNonZeroWinding ? (negativeCrossings != positiveCrossings)
|
||||
: ((negativeCrossings + positiveCrossings) & 1) != 0;
|
||||
}
|
||||
|
||||
bool Path::intersectsLine (const float x1, const float y1,
|
||||
const float x2, const float y2,
|
||||
const float tolerence)
|
||||
bool Path::contains (const Point<float>& point, const float tolerence) const
|
||||
{
|
||||
return contains (point.getX(), point.getY(), tolerence);
|
||||
}
|
||||
|
||||
bool Path::intersectsLine (const Line<float>& line, const float tolerence)
|
||||
{
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity, tolerence);
|
||||
|
||||
const Line line1 (x1, y1, x2, y2);
|
||||
Point<float> intersection;
|
||||
|
||||
while (i.next())
|
||||
{
|
||||
const Line line2 (i.x1, i.y1, i.x2, i.y2);
|
||||
|
||||
float ix, iy;
|
||||
if (line1.intersects (line2, ix, iy))
|
||||
if (line.intersects (Line<float> (i.x1, i.y1, i.x2, i.y2), intersection))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const Line<float> Path::getClippedLine (const Line<float>& line, const bool keepSectionOutsidePath) const
|
||||
{
|
||||
Line<float> result (line);
|
||||
const bool startInside = contains (line.getStart());
|
||||
const bool endInside = contains (line.getEnd());
|
||||
|
||||
if (startInside == endInside)
|
||||
{
|
||||
if (keepSectionOutsidePath == startInside)
|
||||
result = Line<float>();
|
||||
}
|
||||
else
|
||||
{
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity);
|
||||
Point<float> intersection;
|
||||
|
||||
while (i.next())
|
||||
{
|
||||
if (line.intersects (Line<float> (i.x1, i.y1, i.x2, i.y2), intersection))
|
||||
{
|
||||
if ((startInside && keepSectionOutsidePath) || (endInside && ! keepSectionOutsidePath))
|
||||
result.setStart (intersection);
|
||||
else
|
||||
result.setEnd (intersection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
||||
{
|
||||
if (cornerRadius <= 0.01f)
|
||||
|
|
|
|||
|
|
@ -105,8 +105,6 @@
|
|||
|
||||
#if defined (__ppc__) || defined (__ppc64__)
|
||||
#define JUCE_PPC 1
|
||||
#undef MAC_OS_X_VERSION_MAX_ALLOWED
|
||||
#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_4
|
||||
#else
|
||||
#define JUCE_INTEL 1
|
||||
#endif
|
||||
|
|
@ -9641,6 +9639,10 @@ public:
|
|||
|
||||
bool isOrigin() const throw() { return x == ValueType() && y == ValueType(); }
|
||||
|
||||
const Point withX (const ValueType newX) const throw() { return Point (newX, y); }
|
||||
|
||||
const Point withY (const ValueType newY) const throw() { return Point (x, newY); }
|
||||
|
||||
void setXY (const ValueType newX, const ValueType newY) throw() { x = newX; y = newY; }
|
||||
|
||||
void addXY (const ValueType xToAdd, const ValueType yToAdd) throw() { x += xToAdd; y += yToAdd; }
|
||||
|
|
@ -9653,10 +9655,22 @@ public:
|
|||
|
||||
Point& operator-= (const Point& other) throw() { x -= other.x; y -= other.y; return *this; }
|
||||
|
||||
const Point operator* (const ValueType multiplier) const throw() { return Point (x * multiplier, y * multiplier); }
|
||||
|
||||
Point& operator*= (const ValueType multiplier) throw() { x *= multiplier; y *= multiplier; return *this; }
|
||||
|
||||
const Point operator/ (const ValueType divisor) const throw() { return Point (x / divisor, y / divisor); }
|
||||
|
||||
Point& operator/= (const ValueType divisor) throw() { x /= divisor; y /= divisor; return *this; }
|
||||
|
||||
const Point operator-() const throw() { return Point (-x, -y); }
|
||||
|
||||
ValueType getDistanceFromOrigin() const throw() { return (ValueType) juce_hypot (x, y); }
|
||||
|
||||
ValueType getDistanceFrom (const Point& other) const throw() { return (ValueType) juce_hypot (x - other.x, y - other.y); }
|
||||
|
||||
ValueType getAngleToPoint (const Point& other) const throw() { return (ValueType) atan2 (other.x - x, other.y - y); }
|
||||
|
||||
void applyTransform (const AffineTransform& transform) throw() { transform.transformPoint (x, y); }
|
||||
|
||||
const String toString() const { return String (x) + ", " + String (y); }
|
||||
|
|
@ -9981,6 +9995,225 @@ public:
|
|||
#define __JUCE_PATH_JUCEHEADER__
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_Line.h ***/
|
||||
#ifndef __JUCE_LINE_JUCEHEADER__
|
||||
#define __JUCE_LINE_JUCEHEADER__
|
||||
|
||||
template <typename ValueType>
|
||||
class Line
|
||||
{
|
||||
public:
|
||||
|
||||
Line() throw() {}
|
||||
|
||||
Line (const Line& other) throw()
|
||||
: start (other.start),
|
||||
end (other.end)
|
||||
{
|
||||
}
|
||||
|
||||
Line (ValueType startX, ValueType startY, ValueType endX, ValueType endY) throw()
|
||||
: start (startX, startY),
|
||||
end (endX, endY)
|
||||
{
|
||||
}
|
||||
|
||||
Line (const Point<ValueType>& startPoint,
|
||||
const Point<ValueType>& endPoint) throw()
|
||||
: start (startPoint),
|
||||
end (endPoint)
|
||||
{
|
||||
}
|
||||
|
||||
Line& operator= (const Line& other) throw()
|
||||
{
|
||||
start = other.start;
|
||||
end = other.end;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Line() throw() {}
|
||||
|
||||
inline ValueType getStartX() const throw() { return start.getX(); }
|
||||
|
||||
inline ValueType getStartY() const throw() { return start.getY(); }
|
||||
|
||||
inline ValueType getEndX() const throw() { return end.getX(); }
|
||||
|
||||
inline ValueType getEndY() const throw() { return end.getY(); }
|
||||
|
||||
inline const Point<ValueType>& getStart() const throw() { return start; }
|
||||
|
||||
inline const Point<ValueType>& getEnd() const throw() { return end; }
|
||||
|
||||
void setStart (ValueType newStartX, ValueType newStartY) throw() { start.setXY (newStartX, newStartY); }
|
||||
|
||||
void setEnd (ValueType newEndX, ValueType newEndY) throw() { end.setXY (newEndX, newEndY); }
|
||||
|
||||
void setStart (const Point<ValueType>& newStart) throw() { start = newStart; }
|
||||
|
||||
void setEnd (const Point<ValueType>& newEnd) throw() { end = newEnd; }
|
||||
|
||||
void applyTransform (const AffineTransform& transform) throw()
|
||||
{
|
||||
start.applyTransform (transform);
|
||||
end.applyTransform (transform);
|
||||
}
|
||||
|
||||
ValueType getLength() const throw() { return start.getDistanceFrom (end); }
|
||||
|
||||
bool isVertical() const throw() { return start.getX() == end.getX(); }
|
||||
|
||||
bool isHorizontal() const throw() { return start.getY() == end.getY(); }
|
||||
|
||||
ValueType getAngle() const throw() { return start.getAngleToPoint (end); }
|
||||
|
||||
bool operator== (const Line& other) const throw() { return start == other.start && end == other.end; }
|
||||
|
||||
bool operator!= (const Line& other) const throw() { return start != other.start || end != other.end; }
|
||||
|
||||
bool intersects (const Line& line, Point<ValueType>& intersection) const throw()
|
||||
{
|
||||
return findIntersection (start, end, line.start, line.end, intersection);
|
||||
}
|
||||
|
||||
const Point<ValueType> getPointAlongLine (ValueType distanceFromStart) const throw()
|
||||
{
|
||||
return start + (end - start) * (distanceFromStart / getLength());
|
||||
}
|
||||
|
||||
const Point<ValueType> getPointAlongLine (ValueType distanceFromStart,
|
||||
ValueType perpendicularDistance) const throw()
|
||||
{
|
||||
const Point<ValueType> delta (end - start);
|
||||
const double length = juce_hypot (delta.getX(), delta.getY());
|
||||
if (length == 0)
|
||||
return start;
|
||||
|
||||
return Point<ValueType> (start.getX() + (ValueType) ((delta.getX() * distanceFromStart - delta.getY() * perpendicularDistance) / length),
|
||||
start.getY() + (ValueType) ((delta.getY() * distanceFromStart + delta.getX() * perpendicularDistance) / length));
|
||||
}
|
||||
|
||||
const Point<ValueType> getPointAlongLineProportionally (ValueType proportionOfLength) const throw()
|
||||
{
|
||||
return start + (end - start) * proportionOfLength;
|
||||
}
|
||||
|
||||
ValueType getDistanceFromLine (const Point<ValueType>& point) const throw()
|
||||
{
|
||||
const Point<ValueType> delta (end - start);
|
||||
const double length = delta.getX() * delta.getX() + delta.getY() * delta.getY();
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
const double prop = ((point.getX() - start.getX()) * delta.getX()
|
||||
+ (point.getY() - start.getY()) * delta.getY()) / length;
|
||||
|
||||
if (prop >= 0 && prop <= 1.0)
|
||||
return point.getDistanceFrom (start + delta * (ValueType) prop);
|
||||
}
|
||||
|
||||
return jmin (point.getDistanceFrom (start),
|
||||
point.getDistanceFrom (end));
|
||||
}
|
||||
|
||||
ValueType findNearestPointTo (const Point<ValueType>& point) const throw()
|
||||
{
|
||||
const Point<ValueType> delta (end - start);
|
||||
const double length = delta.getX() * delta.getX() + delta.getY() * delta.getY();
|
||||
|
||||
return length <= 0 ? 0
|
||||
: jlimit ((ValueType) 0, (ValueType) 1,
|
||||
(ValueType) (((point.getX() - start.getX()) * delta.getX()
|
||||
+ (point.getY() - start.getY()) * delta.getY()) / length));
|
||||
}
|
||||
|
||||
bool isPointAbove (const Point<ValueType>& point) const throw()
|
||||
{
|
||||
return start.getX() != end.getX()
|
||||
&& point.getY() < ((end.getY() - start.getY())
|
||||
* (point.getX() - start.getX())) / (end.getX() - start.getX()) + start.getY();
|
||||
}
|
||||
|
||||
const Line withShortenedStart (ValueType distanceToShortenBy) const throw()
|
||||
{
|
||||
return Line (getPointAlongLine (jmin (distanceToShortenBy, getLength())), end);
|
||||
}
|
||||
|
||||
const Line withShortenedEnd (ValueType distanceToShortenBy) const throw()
|
||||
{
|
||||
const ValueType length = getLength();
|
||||
return Line (start, getPointAlongLine (length - jmin (distanceToShortenBy, length)));
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
Point<ValueType> start, end;
|
||||
|
||||
static bool findIntersection (const Point<ValueType>& p1, const Point<ValueType>& p2,
|
||||
const Point<ValueType>& p3, const Point<ValueType>& p4,
|
||||
Point<ValueType>& intersection) throw()
|
||||
{
|
||||
if (p2 == p3)
|
||||
{
|
||||
intersection = p2;
|
||||
return true;
|
||||
}
|
||||
|
||||
const Point<ValueType> d1 (p2 - p1);
|
||||
const Point<ValueType> d2 (p4 - p2);
|
||||
const ValueType divisor = d1.getX() * d2.getY() - d2.getX() * d1.getY();
|
||||
|
||||
if (divisor == 0)
|
||||
{
|
||||
if (! (d1.isOrigin() || d2.isOrigin()))
|
||||
{
|
||||
if (d1.getY() == 0 && d2.getY() != 0)
|
||||
{
|
||||
const ValueType along = (p1.getY() - p3.getY()) / d2.getY();
|
||||
intersection = p1.withX (p3.getX() + along * d2.getX());
|
||||
return along >= 0 && along <= (ValueType) 1;
|
||||
}
|
||||
else if (d2.getY() == 0 && d1.getY() != 0)
|
||||
{
|
||||
const ValueType along = (p3.getY() - p1.getY()) / d1.getY();
|
||||
intersection = p3.withX (p1.getX() + along * d1.getX());
|
||||
return along >= 0 && along <= (ValueType) 1;
|
||||
}
|
||||
else if (d1.getX() == 0 && d2.getX() != 0)
|
||||
{
|
||||
const ValueType along = (p1.getX() - p3.getX()) / d2.getX();
|
||||
intersection = p1.withY (p3.getY() + along * d2.getY());
|
||||
return along >= 0 && along <= (ValueType) 1;
|
||||
}
|
||||
else if (d2.getX() == 0 && d1.getX() != 0)
|
||||
{
|
||||
const ValueType along = (p3.getX() - p1.getX()) / d1.getX();
|
||||
intersection = p3.withY (p1.getY() + along * d1.getY());
|
||||
return along >= 0 && along <= (ValueType) 1;
|
||||
}
|
||||
}
|
||||
|
||||
intersection = (p2 + p3) / (ValueType) 2;
|
||||
return false;
|
||||
}
|
||||
|
||||
const ValueType along1 = ((p1.getY() - p3.getY()) * d2.getX() - (p1.getX() - p3.getX()) * d2.getY()) / divisor;
|
||||
intersection = p1 + d1 * along1;
|
||||
|
||||
if (along1 < 0 || along1 > (ValueType) 1)
|
||||
return false;
|
||||
|
||||
const ValueType along2 = ((p1.getY() - p3.getY()) * d1.getX() - (p1.getX() - p3.getX()) * d1.getY()) / divisor;
|
||||
return along2 >= 0 && along2 <= (ValueType) 1;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // __JUCE_LINE_JUCEHEADER__
|
||||
/*** End of inlined file: juce_Line.h ***/
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_Rectangle.h ***/
|
||||
#ifndef __JUCE_RECTANGLE_JUCEHEADER__
|
||||
#define __JUCE_RECTANGLE_JUCEHEADER__
|
||||
|
|
@ -10602,10 +10835,14 @@ public:
|
|||
bool contains (float x, float y,
|
||||
float tolerence = 10.0f) const;
|
||||
|
||||
bool intersectsLine (float x1, float y1,
|
||||
float x2, float y2,
|
||||
bool contains (const Point<float>& point,
|
||||
float tolerence = 10.0f) const;
|
||||
|
||||
bool intersectsLine (const Line<float>& line,
|
||||
float tolerence = 10.0f);
|
||||
|
||||
const Line<float> getClippedLine (const Line<float>& line, bool keepSectionOutsidePath) const;
|
||||
|
||||
void clear() throw();
|
||||
|
||||
void startNewSubPath (float startX, float startY);
|
||||
|
|
@ -11070,99 +11307,6 @@ private:
|
|||
/*** End of inlined file: juce_PathStrokeType.h ***/
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_Line.h ***/
|
||||
#ifndef __JUCE_LINE_JUCEHEADER__
|
||||
#define __JUCE_LINE_JUCEHEADER__
|
||||
|
||||
class JUCE_API Line
|
||||
{
|
||||
public:
|
||||
|
||||
Line() throw();
|
||||
|
||||
Line (const Line& other) throw();
|
||||
|
||||
Line (float startX,
|
||||
float startY,
|
||||
float endX,
|
||||
float endY) throw();
|
||||
|
||||
Line (const Point<float>& start,
|
||||
const Point<float>& end) throw();
|
||||
|
||||
Line& operator= (const Line& other) throw();
|
||||
|
||||
~Line() throw();
|
||||
|
||||
inline float getStartX() const throw() { return startX; }
|
||||
|
||||
inline float getStartY() const throw() { return startY; }
|
||||
|
||||
inline float getEndX() const throw() { return endX; }
|
||||
|
||||
inline float getEndY() const throw() { return endY; }
|
||||
|
||||
const Point<float> getStart() const throw();
|
||||
|
||||
const Point<float> getEnd() const throw();
|
||||
|
||||
void setStart (float newStartX,
|
||||
float newStartY) throw();
|
||||
|
||||
void setEnd (float newEndX,
|
||||
float newEndY) throw();
|
||||
|
||||
void setStart (const Point<float>& newStart) throw();
|
||||
|
||||
void setEnd (const Point<float>& newEnd) throw();
|
||||
|
||||
void applyTransform (const AffineTransform& transform) throw();
|
||||
|
||||
float getLength() const throw();
|
||||
|
||||
bool isVertical() const throw();
|
||||
|
||||
bool isHorizontal() const throw();
|
||||
|
||||
float getAngle() const throw();
|
||||
|
||||
bool operator== (const Line& other) const throw();
|
||||
|
||||
bool operator!= (const Line& other) const throw();
|
||||
|
||||
bool intersects (const Line& line,
|
||||
float& intersectionX,
|
||||
float& intersectionY) const throw();
|
||||
|
||||
const Point<float> getPointAlongLine (float distanceFromStart) const throw();
|
||||
|
||||
const Point<float> getPointAlongLine (float distanceFromStart,
|
||||
float perpendicularDistance) const throw();
|
||||
|
||||
const Point<float> getPointAlongLineProportionally (float proportionOfLength) const throw();
|
||||
|
||||
float getDistanceFromLine (float x, float y) const throw();
|
||||
|
||||
float findNearestPointTo (float x, float y) const throw();
|
||||
|
||||
bool isPointAbove (float x, float y) const throw();
|
||||
|
||||
const Line withShortenedStart (float distanceToShortenBy) const throw();
|
||||
|
||||
const Line withShortenedEnd (float distanceToShortenBy) const throw();
|
||||
|
||||
bool clipToPath (const Path& path, bool keepSectionOutsidePath) throw();
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
float startX, startY, endX, endY;
|
||||
};
|
||||
|
||||
#endif // __JUCE_LINE_JUCEHEADER__
|
||||
/*** End of inlined file: juce_Line.h ***/
|
||||
|
||||
|
||||
/*** Start of inlined file: juce_Colours.h ***/
|
||||
#ifndef __JUCE_COLOURS_JUCEHEADER__
|
||||
#define __JUCE_COLOURS_JUCEHEADER__
|
||||
|
|
@ -12097,9 +12241,9 @@ public:
|
|||
void drawLine (float startX, float startY, float endX, float endY,
|
||||
float lineThickness) const;
|
||||
|
||||
void drawLine (const Line& line) const;
|
||||
void drawLine (const Line<float>& line) const;
|
||||
|
||||
void drawLine (const Line& line, float lineThickness) const;
|
||||
void drawLine (const Line<float>& line, float lineThickness) const;
|
||||
|
||||
void drawDashedLine (float startX, float startY,
|
||||
float endX, float endY,
|
||||
|
|
|
|||
|
|
@ -96,8 +96,6 @@
|
|||
|
||||
#if defined (__ppc__) || defined (__ppc64__)
|
||||
#define JUCE_PPC 1
|
||||
#undef MAC_OS_X_VERSION_MAX_ALLOWED
|
||||
#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_4
|
||||
#else
|
||||
#define JUCE_INTEL 1
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -544,12 +544,12 @@ void Graphics::drawLine (const float startX, const float startY,
|
|||
fillPath (p);
|
||||
}
|
||||
|
||||
void Graphics::drawLine (const Line& line) const
|
||||
void Graphics::drawLine (const Line<float>& line) const
|
||||
{
|
||||
drawLine (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY());
|
||||
}
|
||||
|
||||
void Graphics::drawLine (const Line& line, const float lineThickness) const
|
||||
void Graphics::drawLine (const Line<float>& line, const float lineThickness) const
|
||||
{
|
||||
drawLine (line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY(), lineThickness);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -359,13 +359,13 @@ public:
|
|||
|
||||
The line is 1 pixel wide and drawn with the current colour or brush.
|
||||
*/
|
||||
void drawLine (const Line& line) const;
|
||||
void drawLine (const Line<float>& line) const;
|
||||
|
||||
/** Draws a line between two points with a given thickness.
|
||||
|
||||
@see Path::addLineSegment
|
||||
*/
|
||||
void drawLine (const Line& line, float lineThickness) const;
|
||||
void drawLine (const Line<float>& line, float lineThickness) const;
|
||||
|
||||
/** Draws a dashed line using a custom set of dash-lengths.
|
||||
|
||||
|
|
|
|||
|
|
@ -177,48 +177,40 @@ public:
|
|||
: lookupTable (lookupTable_), numEntries (numEntries_)
|
||||
{
|
||||
jassert (numEntries_ >= 0);
|
||||
float x1 = gradient.x1;
|
||||
float y1 = gradient.y1;
|
||||
float x2 = gradient.x2;
|
||||
float y2 = gradient.y2;
|
||||
Point<float> p1 (gradient.x1, gradient.y1);
|
||||
Point<float> p2 (gradient.x2, gradient.y2);
|
||||
|
||||
if (! transform.isIdentity())
|
||||
{
|
||||
const Line l (x2, y2, x1, y1);
|
||||
const Point<float> p3 = l.getPointAlongLine (0.0f, 100.0f);
|
||||
float x3 = p3.getX();
|
||||
float y3 = p3.getY();
|
||||
const Line<float> l (p2, p1);
|
||||
Point<float> p3 = l.getPointAlongLine (0.0f, 100.0f);
|
||||
|
||||
transform.transformPoint (x1, y1);
|
||||
transform.transformPoint (x2, y2);
|
||||
transform.transformPoint (x3, y3);
|
||||
p1.applyTransform (transform);
|
||||
p2.applyTransform (transform);
|
||||
p3.applyTransform (transform);
|
||||
|
||||
const Line l2 (x2, y2, x3, y3);
|
||||
const float prop = l2.findNearestPointTo (x1, y1);
|
||||
const Point<float> newP2 (l2.getPointAlongLineProportionally (prop));
|
||||
|
||||
x2 = newP2.getX();
|
||||
y2 = newP2.getY();
|
||||
const Line<float> l2 (p2, p3);
|
||||
p2 = l2.getPointAlongLineProportionally (l2.findNearestPointTo (p1));
|
||||
}
|
||||
|
||||
vertical = fabs (x1 - x2) < 0.001f;
|
||||
horizontal = fabs (y1 - y2) < 0.001f;
|
||||
vertical = fabs (p1.getX() - p2.getX()) < 0.001f;
|
||||
horizontal = fabs (p1.getY() - p2.getY()) < 0.001f;
|
||||
|
||||
if (vertical)
|
||||
{
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (y2 - y1));
|
||||
start = roundToInt (y1 * scale);
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (p2.getY() - p1.getY()));
|
||||
start = roundToInt (p1.getY() * scale);
|
||||
}
|
||||
else if (horizontal)
|
||||
{
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (x2 - x1));
|
||||
start = roundToInt (x1 * scale);
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (p2.getX() - p1.getX()));
|
||||
start = roundToInt (p1.getX() * scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
grad = (y2 - y1) / (double) (x1 - x2);
|
||||
yTerm = y1 - x1 / grad;
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (yTerm * grad - (y2 * grad - x2)));
|
||||
grad = (p2.getY() - p1.getY()) / (double) (p1.getX() - p2.getX());
|
||||
yTerm = p1.getY() - p1.getX() / grad;
|
||||
scale = roundToInt ((numEntries << (int) numScaleBits) / (yTerm * grad - (p2.getY() * grad - p2.getX())));
|
||||
grad *= scale;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,375 +27,7 @@
|
|||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
|
||||
#include "juce_Line.h"
|
||||
#include "juce_PathIterator.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
static bool juce_lineIntersection (const float x1, const float y1,
|
||||
const float x2, const float y2,
|
||||
const float x3, const float y3,
|
||||
const float x4, const float y4,
|
||||
float& intersectionX,
|
||||
float& intersectionY) throw()
|
||||
{
|
||||
if (x2 != x3 || y2 != y3)
|
||||
{
|
||||
const float dx1 = x2 - x1;
|
||||
const float dy1 = y2 - y1;
|
||||
const float dx2 = x4 - x3;
|
||||
const float dy2 = y4 - y3;
|
||||
const float divisor = dx1 * dy2 - dx2 * dy1;
|
||||
|
||||
if (divisor == 0)
|
||||
{
|
||||
if (! ((dx1 == 0 && dy1 == 0) || (dx2 == 0 && dy2 == 0)))
|
||||
{
|
||||
if (dy1 == 0 && dy2 != 0)
|
||||
{
|
||||
const float along = (y1 - y3) / dy2;
|
||||
intersectionX = x3 + along * dx2;
|
||||
intersectionY = y1;
|
||||
|
||||
return along >= 0 && along <= 1.0f;
|
||||
}
|
||||
else if (dy2 == 0 && dy1 != 0)
|
||||
{
|
||||
const float along = (y3 - y1) / dy1;
|
||||
intersectionX = x1 + along * dx1;
|
||||
intersectionY = y3;
|
||||
|
||||
return along >= 0 && along <= 1.0f;
|
||||
}
|
||||
else if (dx1 == 0 && dx2 != 0)
|
||||
{
|
||||
const float along = (x1 - x3) / dx2;
|
||||
intersectionX = x1;
|
||||
intersectionY = y3 + along * dy2;
|
||||
|
||||
return along >= 0 && along <= 1.0f;
|
||||
}
|
||||
else if (dx2 == 0 && dx1 != 0)
|
||||
{
|
||||
const float along = (x3 - x1) / dx1;
|
||||
intersectionX = x3;
|
||||
intersectionY = y1 + along * dy1;
|
||||
|
||||
return along >= 0 && along <= 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
intersectionX = 0.5f * (x2 + x3);
|
||||
intersectionY = 0.5f * (y2 + y3);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const float along1 = ((y1 - y3) * dx2 - (x1 - x3) * dy2) / divisor;
|
||||
|
||||
intersectionX = x1 + along1 * dx1;
|
||||
intersectionY = y1 + along1 * dy1;
|
||||
|
||||
if (along1 < 0 || along1 > 1.0f)
|
||||
return false;
|
||||
|
||||
const float along2 = ((y1 - y3) * dx1 - (x1 - x3) * dy1) / divisor;
|
||||
|
||||
return along2 >= 0 && along2 <= 1.0f;
|
||||
}
|
||||
|
||||
intersectionX = x2;
|
||||
intersectionY = y2;
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
Line::Line() throw()
|
||||
: startX (0.0f),
|
||||
startY (0.0f),
|
||||
endX (0.0f),
|
||||
endY (0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
Line::Line (const Line& other) throw()
|
||||
: startX (other.startX),
|
||||
startY (other.startY),
|
||||
endX (other.endX),
|
||||
endY (other.endY)
|
||||
{
|
||||
}
|
||||
|
||||
Line::Line (const float startX_, const float startY_,
|
||||
const float endX_, const float endY_) throw()
|
||||
: startX (startX_),
|
||||
startY (startY_),
|
||||
endX (endX_),
|
||||
endY (endY_)
|
||||
{
|
||||
}
|
||||
|
||||
Line::Line (const Point<float>& start,
|
||||
const Point<float>& end) throw()
|
||||
: startX (start.getX()),
|
||||
startY (start.getY()),
|
||||
endX (end.getX()),
|
||||
endY (end.getY())
|
||||
{
|
||||
}
|
||||
|
||||
Line& Line::operator= (const Line& other) throw()
|
||||
{
|
||||
startX = other.startX;
|
||||
startY = other.startY;
|
||||
endX = other.endX;
|
||||
endY = other.endY;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Line::~Line() throw()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const Point<float> Line::getStart() const throw()
|
||||
{
|
||||
return Point<float> (startX, startY);
|
||||
}
|
||||
|
||||
const Point<float> Line::getEnd() const throw()
|
||||
{
|
||||
return Point<float> (endX, endY);
|
||||
}
|
||||
|
||||
void Line::setStart (const float newStartX,
|
||||
const float newStartY) throw()
|
||||
{
|
||||
startX = newStartX;
|
||||
startY = newStartY;
|
||||
}
|
||||
|
||||
void Line::setStart (const Point<float>& newStart) throw()
|
||||
{
|
||||
startX = newStart.getX();
|
||||
startY = newStart.getY();
|
||||
}
|
||||
|
||||
void Line::setEnd (const float newEndX,
|
||||
const float newEndY) throw()
|
||||
{
|
||||
endX = newEndX;
|
||||
endY = newEndY;
|
||||
}
|
||||
|
||||
void Line::setEnd (const Point<float>& newEnd) throw()
|
||||
{
|
||||
endX = newEnd.getX();
|
||||
endY = newEnd.getY();
|
||||
}
|
||||
|
||||
bool Line::operator== (const Line& other) const throw()
|
||||
{
|
||||
return startX == other.startX
|
||||
&& startY == other.startY
|
||||
&& endX == other.endX
|
||||
&& endY == other.endY;
|
||||
}
|
||||
|
||||
bool Line::operator!= (const Line& other) const throw()
|
||||
{
|
||||
return startX != other.startX
|
||||
|| startY != other.startY
|
||||
|| endX != other.endX
|
||||
|| endY != other.endY;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void Line::applyTransform (const AffineTransform& transform) throw()
|
||||
{
|
||||
transform.transformPoint (startX, startY);
|
||||
transform.transformPoint (endX, endY);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
float Line::getLength() const throw()
|
||||
{
|
||||
return (float) juce_hypot (startX - endX,
|
||||
startY - endY);
|
||||
}
|
||||
|
||||
float Line::getAngle() const throw()
|
||||
{
|
||||
return atan2f (endX - startX,
|
||||
endY - startY);
|
||||
}
|
||||
|
||||
const Point<float> Line::getPointAlongLine (const float distanceFromStart) const throw()
|
||||
{
|
||||
const float alpha = distanceFromStart / getLength();
|
||||
|
||||
return Point<float> (startX + (endX - startX) * alpha,
|
||||
startY + (endY - startY) * alpha);
|
||||
}
|
||||
|
||||
const Point<float> Line::getPointAlongLine (const float offsetX,
|
||||
const float offsetY) const throw()
|
||||
{
|
||||
const float dx = endX - startX;
|
||||
const float dy = endY - startY;
|
||||
const double length = juce_hypot (dx, dy);
|
||||
|
||||
if (length == 0)
|
||||
return Point<float> (startX, startY);
|
||||
else
|
||||
return Point<float> (startX + (float) (((dx * offsetX) - (dy * offsetY)) / length),
|
||||
startY + (float) (((dy * offsetX) + (dx * offsetY)) / length));
|
||||
}
|
||||
|
||||
const Point<float> Line::getPointAlongLineProportionally (const float alpha) const throw()
|
||||
{
|
||||
return Point<float> (startX + (endX - startX) * alpha,
|
||||
startY + (endY - startY) * alpha);
|
||||
}
|
||||
|
||||
float Line::getDistanceFromLine (const float x,
|
||||
const float y) const throw()
|
||||
{
|
||||
const double dx = endX - startX;
|
||||
const double dy = endY - startY;
|
||||
const double length = dx * dx + dy * dy;
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
const double prop = ((x - startX) * dx + (y - startY) * dy) / length;
|
||||
|
||||
if (prop >= 0.0f && prop < 1.0f)
|
||||
{
|
||||
return (float) juce_hypot (x - (startX + prop * dx),
|
||||
y - (startY + prop * dy));
|
||||
}
|
||||
}
|
||||
|
||||
return (float) jmin (juce_hypot (x - startX, y - startY),
|
||||
juce_hypot (x - endX, y - endY));
|
||||
}
|
||||
|
||||
float Line::findNearestPointTo (const float x,
|
||||
const float y) const throw()
|
||||
{
|
||||
const double dx = endX - startX;
|
||||
const double dy = endY - startY;
|
||||
const double length = dx * dx + dy * dy;
|
||||
|
||||
if (length <= 0.0)
|
||||
return 0.0f;
|
||||
|
||||
return jlimit (0.0f, 1.0f,
|
||||
(float) (((x - startX) * dx + (y - startY) * dy) / length));
|
||||
}
|
||||
|
||||
const Line Line::withShortenedStart (const float distanceToShortenBy) const throw()
|
||||
{
|
||||
const float length = getLength();
|
||||
|
||||
return Line (getPointAlongLine (jmin (distanceToShortenBy, length)),
|
||||
getEnd());
|
||||
}
|
||||
|
||||
const Line Line::withShortenedEnd (const float distanceToShortenBy) const throw()
|
||||
{
|
||||
const float length = getLength();
|
||||
|
||||
return Line (getStart(),
|
||||
getPointAlongLine (length - jmin (distanceToShortenBy, length)));
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool Line::clipToPath (const Path& path,
|
||||
const bool keepSectionOutsidePath) throw()
|
||||
{
|
||||
const bool startInside = path.contains (startX, startY);
|
||||
const bool endInside = path.contains (endX, endY);
|
||||
|
||||
if (startInside == endInside)
|
||||
{
|
||||
if (keepSectionOutsidePath != startInside)
|
||||
{
|
||||
// entirely outside the path
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// entirely inside the path
|
||||
startX = 0.0f;
|
||||
startY = 0.0f;
|
||||
endX = 0.0f;
|
||||
endY = 0.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool changed = false;
|
||||
PathFlatteningIterator iter (path, AffineTransform::identity);
|
||||
|
||||
while (iter.next())
|
||||
{
|
||||
float ix, iy;
|
||||
|
||||
if (intersects (Line (iter.x1, iter.y1,
|
||||
iter.x2, iter.y2),
|
||||
ix, iy))
|
||||
{
|
||||
if ((startInside && keepSectionOutsidePath)
|
||||
|| (endInside && ! keepSectionOutsidePath))
|
||||
{
|
||||
setStart (ix, iy);
|
||||
}
|
||||
else
|
||||
{
|
||||
setEnd (ix, iy);
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool Line::intersects (const Line& line,
|
||||
float& intersectionX,
|
||||
float& intersectionY) const throw()
|
||||
{
|
||||
return juce_lineIntersection (startX, startY,
|
||||
endX, endY,
|
||||
line.startX, line.startY,
|
||||
line.endX, line.endY,
|
||||
intersectionX,
|
||||
intersectionY);
|
||||
}
|
||||
|
||||
bool Line::isVertical() const throw()
|
||||
{
|
||||
return startX == endX;
|
||||
}
|
||||
|
||||
bool Line::isHorizontal() const throw()
|
||||
{
|
||||
return startY == endY;
|
||||
}
|
||||
|
||||
bool Line::isPointAbove (const float x, const float y) const throw()
|
||||
{
|
||||
return startX != endX
|
||||
&& y < ((endY - startY) * (x - startX)) / (endX - startX) + startY;
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -26,122 +26,138 @@
|
|||
#ifndef __JUCE_LINE_JUCEHEADER__
|
||||
#define __JUCE_LINE_JUCEHEADER__
|
||||
|
||||
#include "juce_Path.h"
|
||||
#include "juce_Point.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Represents a line, using 32-bit float co-ordinates.
|
||||
Represents a line.
|
||||
|
||||
This class contains a bunch of useful methods for various geometric
|
||||
tasks.
|
||||
|
||||
@see Point, Rectangle, Path, Graphics::drawLine
|
||||
*/
|
||||
class JUCE_API Line
|
||||
template <typename ValueType>
|
||||
class Line
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a line, using (0, 0) as its start and end points. */
|
||||
Line() throw();
|
||||
Line() throw() {}
|
||||
|
||||
/** Creates a copy of another line. */
|
||||
Line (const Line& other) throw();
|
||||
Line (const Line& other) throw()
|
||||
: start (other.start),
|
||||
end (other.end)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a line based on the co-ordinates of its start and end points. */
|
||||
Line (float startX,
|
||||
float startY,
|
||||
float endX,
|
||||
float endY) throw();
|
||||
Line (ValueType startX, ValueType startY, ValueType endX, ValueType endY) throw()
|
||||
: start (startX, startY),
|
||||
end (endX, endY)
|
||||
{
|
||||
}
|
||||
|
||||
/** Creates a line from its start and end points. */
|
||||
Line (const Point<float>& start,
|
||||
const Point<float>& end) throw();
|
||||
Line (const Point<ValueType>& startPoint,
|
||||
const Point<ValueType>& endPoint) throw()
|
||||
: start (startPoint),
|
||||
end (endPoint)
|
||||
{
|
||||
}
|
||||
|
||||
/** Copies a line from another one. */
|
||||
Line& operator= (const Line& other) throw();
|
||||
Line& operator= (const Line& other) throw()
|
||||
{
|
||||
start = other.start;
|
||||
end = other.end;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Destructor. */
|
||||
~Line() throw();
|
||||
~Line() throw() {}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the x co-ordinate of the line's start point. */
|
||||
inline float getStartX() const throw() { return startX; }
|
||||
inline ValueType getStartX() const throw() { return start.getX(); }
|
||||
|
||||
/** Returns the y co-ordinate of the line's start point. */
|
||||
inline float getStartY() const throw() { return startY; }
|
||||
inline ValueType getStartY() const throw() { return start.getY(); }
|
||||
|
||||
/** Returns the x co-ordinate of the line's end point. */
|
||||
inline float getEndX() const throw() { return endX; }
|
||||
inline ValueType getEndX() const throw() { return end.getX(); }
|
||||
|
||||
/** Returns the y co-ordinate of the line's end point. */
|
||||
inline float getEndY() const throw() { return endY; }
|
||||
inline ValueType getEndY() const throw() { return end.getY(); }
|
||||
|
||||
/** Returns the line's start point. */
|
||||
const Point<float> getStart() const throw();
|
||||
inline const Point<ValueType>& getStart() const throw() { return start; }
|
||||
|
||||
/** Returns the line's end point. */
|
||||
const Point<float> getEnd() const throw();
|
||||
inline const Point<ValueType>& getEnd() const throw() { return end; }
|
||||
|
||||
/** Changes this line's start point */
|
||||
void setStart (float newStartX,
|
||||
float newStartY) throw();
|
||||
void setStart (ValueType newStartX, ValueType newStartY) throw() { start.setXY (newStartX, newStartY); }
|
||||
|
||||
/** Changes this line's end point */
|
||||
void setEnd (float newEndX,
|
||||
float newEndY) throw();
|
||||
void setEnd (ValueType newEndX, ValueType newEndY) throw() { end.setXY (newEndX, newEndY); }
|
||||
|
||||
/** Changes this line's start point */
|
||||
void setStart (const Point<float>& newStart) throw();
|
||||
void setStart (const Point<ValueType>& newStart) throw() { start = newStart; }
|
||||
|
||||
/** Changes this line's end point */
|
||||
void setEnd (const Point<float>& newEnd) throw();
|
||||
void setEnd (const Point<ValueType>& newEnd) throw() { end = newEnd; }
|
||||
|
||||
/** Applies an affine transform to the line's start and end points. */
|
||||
void applyTransform (const AffineTransform& transform) throw();
|
||||
void applyTransform (const AffineTransform& transform) throw()
|
||||
{
|
||||
start.applyTransform (transform);
|
||||
end.applyTransform (transform);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the length of the line. */
|
||||
float getLength() const throw();
|
||||
ValueType getLength() const throw() { return start.getDistanceFrom (end); }
|
||||
|
||||
/** Returns true if the line's start and end x co-ordinates are the same. */
|
||||
bool isVertical() const throw();
|
||||
bool isVertical() const throw() { return start.getX() == end.getX(); }
|
||||
|
||||
/** Returns true if the line's start and end y co-ordinates are the same. */
|
||||
bool isHorizontal() const throw();
|
||||
bool isHorizontal() const throw() { return start.getY() == end.getY(); }
|
||||
|
||||
/** Returns the line's angle.
|
||||
|
||||
This value is the number of radians clockwise from the 3 o'clock direction,
|
||||
where the line's start point is considered to be at the centre.
|
||||
*/
|
||||
float getAngle() const throw();
|
||||
ValueType getAngle() const throw() { return start.getAngleToPoint (end); }
|
||||
|
||||
//==============================================================================
|
||||
/** Compares two lines. */
|
||||
bool operator== (const Line& other) const throw();
|
||||
bool operator== (const Line& other) const throw() { return start == other.start && end == other.end; }
|
||||
|
||||
/** Compares two lines. */
|
||||
bool operator!= (const Line& other) const throw();
|
||||
bool operator!= (const Line& other) const throw() { return start != other.start || end != other.end; }
|
||||
|
||||
//==============================================================================
|
||||
/** Finds the intersection between two lines.
|
||||
|
||||
@param line the other line
|
||||
@param intersectionX the x co-ordinate of the point where the lines meet (or
|
||||
@param intersection the position of the point where the lines meet (or
|
||||
where they would meet if they were infinitely long)
|
||||
the intersection (if the lines intersect). If the lines
|
||||
are parallel, this will just be set to the position
|
||||
of one of the line's endpoints.
|
||||
@param intersectionY the y co-ordinate of the point where the lines meet
|
||||
@returns true if the line segments intersect; false if they dont. Even if they
|
||||
don't intersect, the intersection co-ordinates returned will still
|
||||
be valid
|
||||
*/
|
||||
bool intersects (const Line& line,
|
||||
float& intersectionX,
|
||||
float& intersectionY) const throw();
|
||||
bool intersects (const Line& line, Point<ValueType>& intersection) const throw()
|
||||
{
|
||||
return findIntersection (start, end, line.start, line.end, intersection);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the location of the point which is a given distance along this line.
|
||||
|
|
@ -151,7 +167,10 @@ public:
|
|||
than the line itself
|
||||
@see getPointAlongLineProportionally
|
||||
*/
|
||||
const Point<float> getPointAlongLine (float distanceFromStart) const throw();
|
||||
const Point<ValueType> getPointAlongLine (ValueType distanceFromStart) const throw()
|
||||
{
|
||||
return start + (end - start) * (distanceFromStart / getLength());
|
||||
}
|
||||
|
||||
/** Returns a point which is a certain distance along and to the side of this line.
|
||||
|
||||
|
|
@ -166,8 +185,17 @@ public:
|
|||
end, then a positive value here will move to the
|
||||
right, negative value move to the left.
|
||||
*/
|
||||
const Point<float> getPointAlongLine (float distanceFromStart,
|
||||
float perpendicularDistance) const throw();
|
||||
const Point<ValueType> getPointAlongLine (ValueType distanceFromStart,
|
||||
ValueType perpendicularDistance) const throw()
|
||||
{
|
||||
const Point<ValueType> delta (end - start);
|
||||
const double length = juce_hypot (delta.getX(), delta.getY());
|
||||
if (length == 0)
|
||||
return start;
|
||||
|
||||
return Point<ValueType> (start.getX() + (ValueType) ((delta.getX() * distanceFromStart - delta.getY() * perpendicularDistance) / length),
|
||||
start.getY() + (ValueType) ((delta.getY() * distanceFromStart + delta.getX() * perpendicularDistance) / length));
|
||||
}
|
||||
|
||||
/** Returns the location of the point which is a given distance along this line
|
||||
proportional to the line's length.
|
||||
|
|
@ -179,7 +207,10 @@ public:
|
|||
can be negative or greater than 1.0).
|
||||
@see getPointAlongLine
|
||||
*/
|
||||
const Point<float> getPointAlongLineProportionally (float proportionOfLength) const throw();
|
||||
const Point<ValueType> getPointAlongLineProportionally (ValueType proportionOfLength) const throw()
|
||||
{
|
||||
return start + (end - start) * proportionOfLength;
|
||||
}
|
||||
|
||||
/** Returns the smallest distance between this line segment and a given point.
|
||||
|
||||
|
|
@ -187,12 +218,26 @@ public:
|
|||
distance from the line; if the point is a long way beyond one of the line's
|
||||
end-point's, it'll return the straight-line distance to the nearest end-point.
|
||||
|
||||
@param x x position of the point to test
|
||||
@param y y position of the point to test
|
||||
@returns the point's distance from the line
|
||||
@see getPositionAlongLineOfNearestPoint
|
||||
*/
|
||||
float getDistanceFromLine (float x, float y) const throw();
|
||||
ValueType getDistanceFromLine (const Point<ValueType>& point) const throw()
|
||||
{
|
||||
const Point<ValueType> delta (end - start);
|
||||
const double length = delta.getX() * delta.getX() + delta.getY() * delta.getY();
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
const double prop = ((point.getX() - start.getX()) * delta.getX()
|
||||
+ (point.getY() - start.getY()) * delta.getY()) / length;
|
||||
|
||||
if (prop >= 0 && prop <= 1.0)
|
||||
return point.getDistanceFrom (start + delta * (ValueType) prop);
|
||||
}
|
||||
|
||||
return jmin (point.getDistanceFrom (start),
|
||||
point.getDistanceFrom (end));
|
||||
}
|
||||
|
||||
/** Finds the point on this line which is nearest to a given point, and
|
||||
returns its position as a proportional position along the line.
|
||||
|
|
@ -204,7 +249,16 @@ public:
|
|||
turn this number into a position, use getPointAlongLineProportionally().
|
||||
@see getDistanceFromLine, getPointAlongLineProportionally
|
||||
*/
|
||||
float findNearestPointTo (float x, float y) const throw();
|
||||
ValueType findNearestPointTo (const Point<ValueType>& point) const throw()
|
||||
{
|
||||
const Point<ValueType> delta (end - start);
|
||||
const double length = delta.getX() * delta.getX() + delta.getY() * delta.getY();
|
||||
|
||||
return length <= 0 ? 0
|
||||
: jlimit ((ValueType) 0, (ValueType) 1,
|
||||
(ValueType) (((point.getX() - start.getX()) * delta.getX()
|
||||
+ (point.getY() - start.getY()) * delta.getY()) / length));
|
||||
}
|
||||
|
||||
/** Returns true if the given point lies above this line.
|
||||
|
||||
|
|
@ -212,7 +266,12 @@ public:
|
|||
coordinate of this line at the given x (assuming the line extends infinitely
|
||||
in both directions).
|
||||
*/
|
||||
bool isPointAbove (float x, float y) const throw();
|
||||
bool isPointAbove (const Point<ValueType>& point) const throw()
|
||||
{
|
||||
return start.getX() != end.getX()
|
||||
&& point.getY() < ((end.getY() - start.getY())
|
||||
* (point.getX() - start.getX())) / (end.getX() - start.getX()) + start.getY();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a shortened copy of this line.
|
||||
|
|
@ -220,36 +279,86 @@ public:
|
|||
This will chop off part of the start of this line by a certain amount, (leaving the
|
||||
end-point the same), and return the new line.
|
||||
*/
|
||||
const Line withShortenedStart (float distanceToShortenBy) const throw();
|
||||
const Line withShortenedStart (ValueType distanceToShortenBy) const throw()
|
||||
{
|
||||
return Line (getPointAlongLine (jmin (distanceToShortenBy, getLength())), end);
|
||||
}
|
||||
|
||||
/** Returns a shortened copy of this line.
|
||||
|
||||
This will chop off part of the end of this line by a certain amount, (leaving the
|
||||
start-point the same), and return the new line.
|
||||
*/
|
||||
const Line withShortenedEnd (float distanceToShortenBy) const throw();
|
||||
|
||||
/** Cuts off parts of this line to keep the parts that are either inside or
|
||||
outside a path.
|
||||
|
||||
Note that this isn't smart enough to cope with situations where the
|
||||
line would need to be cut into multiple pieces to correctly clip against
|
||||
a re-entrant shape.
|
||||
|
||||
@param path the path to clip against
|
||||
@param keepSectionOutsidePath if true, it's the section outside the path
|
||||
that will be kept; if false its the section inside
|
||||
the path
|
||||
@returns true if the line was changed.
|
||||
*/
|
||||
bool clipToPath (const Path& path, bool keepSectionOutsidePath) throw();
|
||||
const Line withShortenedEnd (ValueType distanceToShortenBy) const throw()
|
||||
{
|
||||
const ValueType length = getLength();
|
||||
return Line (start, getPointAlongLine (length - jmin (distanceToShortenBy, length)));
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
float startX, startY, endX, endY;
|
||||
Point<ValueType> start, end;
|
||||
|
||||
static bool findIntersection (const Point<ValueType>& p1, const Point<ValueType>& p2,
|
||||
const Point<ValueType>& p3, const Point<ValueType>& p4,
|
||||
Point<ValueType>& intersection) throw()
|
||||
{
|
||||
if (p2 == p3)
|
||||
{
|
||||
intersection = p2;
|
||||
return true;
|
||||
}
|
||||
|
||||
const Point<ValueType> d1 (p2 - p1);
|
||||
const Point<ValueType> d2 (p4 - p2);
|
||||
const ValueType divisor = d1.getX() * d2.getY() - d2.getX() * d1.getY();
|
||||
|
||||
if (divisor == 0)
|
||||
{
|
||||
if (! (d1.isOrigin() || d2.isOrigin()))
|
||||
{
|
||||
if (d1.getY() == 0 && d2.getY() != 0)
|
||||
{
|
||||
const ValueType along = (p1.getY() - p3.getY()) / d2.getY();
|
||||
intersection = p1.withX (p3.getX() + along * d2.getX());
|
||||
return along >= 0 && along <= (ValueType) 1;
|
||||
}
|
||||
else if (d2.getY() == 0 && d1.getY() != 0)
|
||||
{
|
||||
const ValueType along = (p3.getY() - p1.getY()) / d1.getY();
|
||||
intersection = p3.withX (p1.getX() + along * d1.getX());
|
||||
return along >= 0 && along <= (ValueType) 1;
|
||||
}
|
||||
else if (d1.getX() == 0 && d2.getX() != 0)
|
||||
{
|
||||
const ValueType along = (p1.getX() - p3.getX()) / d2.getX();
|
||||
intersection = p1.withY (p3.getY() + along * d2.getY());
|
||||
return along >= 0 && along <= (ValueType) 1;
|
||||
}
|
||||
else if (d2.getX() == 0 && d1.getX() != 0)
|
||||
{
|
||||
const ValueType along = (p3.getX() - p1.getX()) / d1.getX();
|
||||
intersection = p3.withY (p1.getY() + along * d1.getY());
|
||||
return along >= 0 && along <= (ValueType) 1;
|
||||
}
|
||||
}
|
||||
|
||||
intersection = (p2 + p3) / (ValueType) 2;
|
||||
return false;
|
||||
}
|
||||
|
||||
const ValueType along1 = ((p1.getY() - p3.getY()) * d2.getX() - (p1.getX() - p3.getX()) * d2.getY()) / divisor;
|
||||
intersection = p1 + d1 * along1;
|
||||
|
||||
if (along1 < 0 || along1 > (ValueType) 1)
|
||||
return false;
|
||||
|
||||
const ValueType along2 = ((p1.getY() - p3.getY()) * d1.getX() - (p1.getX() - p3.getX()) * d1.getY()) / divisor;
|
||||
return along2 >= 0 && along2 <= (ValueType) 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1040,8 +1040,7 @@ bool Path::contains (const float x, const float y, const float tolerence) const
|
|||
|
||||
while (i.next())
|
||||
{
|
||||
if ((i.y1 <= y && i.y2 > y)
|
||||
|| (i.y2 <= y && i.y1 > y))
|
||||
if ((i.y1 <= y && i.y2 > y) || (i.y2 <= y && i.y1 > y))
|
||||
{
|
||||
const float intersectX = i.x1 + (i.x2 - i.x1) * (y - i.y1) / (i.y2 - i.y1);
|
||||
|
||||
|
|
@ -1055,30 +1054,58 @@ bool Path::contains (const float x, const float y, const float tolerence) const
|
|||
}
|
||||
}
|
||||
|
||||
return (useNonZeroWinding) ? (negativeCrossings != positiveCrossings)
|
||||
: ((negativeCrossings + positiveCrossings) & 1) != 0;
|
||||
return useNonZeroWinding ? (negativeCrossings != positiveCrossings)
|
||||
: ((negativeCrossings + positiveCrossings) & 1) != 0;
|
||||
}
|
||||
|
||||
bool Path::intersectsLine (const float x1, const float y1,
|
||||
const float x2, const float y2,
|
||||
const float tolerence)
|
||||
bool Path::contains (const Point<float>& point, const float tolerence) const
|
||||
{
|
||||
return contains (point.getX(), point.getY(), tolerence);
|
||||
}
|
||||
|
||||
bool Path::intersectsLine (const Line<float>& line, const float tolerence)
|
||||
{
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity, tolerence);
|
||||
|
||||
const Line line1 (x1, y1, x2, y2);
|
||||
Point<float> intersection;
|
||||
|
||||
while (i.next())
|
||||
{
|
||||
const Line line2 (i.x1, i.y1, i.x2, i.y2);
|
||||
|
||||
float ix, iy;
|
||||
if (line1.intersects (line2, ix, iy))
|
||||
if (line.intersects (Line<float> (i.x1, i.y1, i.x2, i.y2), intersection))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const Line<float> Path::getClippedLine (const Line<float>& line, const bool keepSectionOutsidePath) const
|
||||
{
|
||||
Line<float> result (line);
|
||||
const bool startInside = contains (line.getStart());
|
||||
const bool endInside = contains (line.getEnd());
|
||||
|
||||
if (startInside == endInside)
|
||||
{
|
||||
if (keepSectionOutsidePath == startInside)
|
||||
result = Line<float>();
|
||||
}
|
||||
else
|
||||
{
|
||||
PathFlatteningIterator i (*this, AffineTransform::identity);
|
||||
Point<float> intersection;
|
||||
|
||||
while (i.next())
|
||||
{
|
||||
if (line.intersects (Line<float> (i.x1, i.y1, i.x2, i.y2), intersection))
|
||||
{
|
||||
if ((startInside && keepSectionOutsidePath) || (endInside && ! keepSectionOutsidePath))
|
||||
result.setStart (intersection);
|
||||
else
|
||||
result.setEnd (intersection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const Path Path::createPathWithRoundedCorners (const float cornerRadius) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#define __JUCE_PATH_JUCEHEADER__
|
||||
|
||||
#include "juce_AffineTransform.h"
|
||||
#include "juce_Point.h"
|
||||
#include "juce_Line.h"
|
||||
#include "juce_Rectangle.h"
|
||||
#include "../contexts/juce_Justification.h"
|
||||
#include "../contexts/juce_EdgeTable.h"
|
||||
|
|
@ -114,6 +114,22 @@ public:
|
|||
bool contains (float x, float y,
|
||||
float tolerence = 10.0f) const;
|
||||
|
||||
/** Checks whether a point lies within the path.
|
||||
|
||||
This is only relevent for closed paths (see closeSubPath()), and
|
||||
may produce false results if used on a path which has open sub-paths.
|
||||
|
||||
The path's winding rule is taken into account by this method.
|
||||
|
||||
The tolerence parameter is passed to the PathFlatteningIterator that
|
||||
is used to trace the path - for more info about it, see the notes for
|
||||
the PathFlatteningIterator constructor.
|
||||
|
||||
@see closeSubPath, setUsingNonZeroWinding
|
||||
*/
|
||||
bool contains (const Point<float>& point,
|
||||
float tolerence = 10.0f) const;
|
||||
|
||||
/** Checks whether a line crosses the path.
|
||||
|
||||
This will return positive if the line crosses any of the paths constituent
|
||||
|
|
@ -124,10 +140,22 @@ public:
|
|||
is used to trace the path - for more info about it, see the notes for
|
||||
the PathFlatteningIterator constructor.
|
||||
*/
|
||||
bool intersectsLine (float x1, float y1,
|
||||
float x2, float y2,
|
||||
bool intersectsLine (const Line<float>& line,
|
||||
float tolerence = 10.0f);
|
||||
|
||||
/** Cuts off parts of a line to keep the parts that are either inside or
|
||||
outside this path.
|
||||
|
||||
Note that this isn't smart enough to cope with situations where the
|
||||
line would need to be cut into multiple pieces to correctly clip against
|
||||
a re-entrant shape.
|
||||
|
||||
@param keepSectionOutsidePath if true, it's the section outside the path
|
||||
that will be kept; if false its the section inside
|
||||
the path
|
||||
*/
|
||||
const Line<float> getClippedLine (const Line<float>& line, bool keepSectionOutsidePath) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Removes all lines and curves, resetting the path completely. */
|
||||
void clear() throw();
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ public:
|
|||
/** Returns true if the point is (0, 0). */
|
||||
bool isOrigin() const throw() { return x == ValueType() && y == ValueType(); }
|
||||
|
||||
/** Returns a point which has the same Y position as this one, but a new X. */
|
||||
const Point withX (const ValueType newX) const throw() { return Point (newX, y); }
|
||||
|
||||
/** Returns a point which has the same X position as this one, but a new Y. */
|
||||
const Point withY (const ValueType newY) const throw() { return Point (x, newY); }
|
||||
|
||||
/** Changes the point's x and y co-ordinates. */
|
||||
void setXY (const ValueType newX, const ValueType newY) throw() { x = newX; y = newY; }
|
||||
|
||||
|
|
@ -89,12 +95,34 @@ public:
|
|||
/** Subtracts another point's co-ordinates to this one. */
|
||||
Point& operator-= (const Point& other) throw() { x -= other.x; y -= other.y; return *this; }
|
||||
|
||||
/** Returns a point whose coordinates are multiplied by a given value. */
|
||||
const Point operator* (const ValueType multiplier) const throw() { return Point (x * multiplier, y * multiplier); }
|
||||
|
||||
/** Multiplies the point's co-ordinates by a value. */
|
||||
Point& operator*= (const ValueType multiplier) throw() { x *= multiplier; y *= multiplier; return *this; }
|
||||
|
||||
/** Returns a point whose coordinates are divided by a given value. */
|
||||
const Point operator/ (const ValueType divisor) const throw() { return Point (x / divisor, y / divisor); }
|
||||
|
||||
/** Divides the point's co-ordinates by a value. */
|
||||
Point& operator/= (const ValueType divisor) throw() { x /= divisor; y /= divisor; return *this; }
|
||||
|
||||
/** Returns the inverse of this point. */
|
||||
const Point operator-() const throw() { return Point (-x, -y); }
|
||||
|
||||
/** Returns the straight-line distance between this point and another one. */
|
||||
ValueType getDistanceFromOrigin() const throw() { return (ValueType) juce_hypot (x, y); }
|
||||
|
||||
/** Returns the straight-line distance between this point and another one. */
|
||||
ValueType getDistanceFrom (const Point& other) const throw() { return (ValueType) juce_hypot (x - other.x, y - other.y); }
|
||||
|
||||
/** Returns the angle from this point to another one.
|
||||
|
||||
The return value is the number of radians clockwise from the 3 o'clock direction,
|
||||
where this point is the centre and the other point is on the radius.
|
||||
*/
|
||||
ValueType getAngleToPoint (const Point& other) const throw() { return (ValueType) atan2 (other.x - x, other.y - y); }
|
||||
|
||||
/** Uses a transform to change the point's co-ordinates.
|
||||
This will only compile if ValueType = float!
|
||||
@see AffineTransform::transformPoint
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue