|
|
@@ -60,8 +60,7 @@ public: |
|
|
|
}
|
|
|
|
|
|
|
|
/** Creates a line from its start and end points. */
|
|
|
|
Line (Point<ValueType> startPoint,
|
|
|
|
Point<ValueType> endPoint) noexcept
|
|
|
|
Line (Point<ValueType> startPoint, Point<ValueType> endPoint) noexcept
|
|
|
|
: start (startPoint), end (endPoint)
|
|
|
|
{
|
|
|
|
}
|
|
|
@@ -109,7 +108,7 @@ public: |
|
|
|
void setEnd (const Point<ValueType> newEnd) noexcept { end = newEnd; }
|
|
|
|
|
|
|
|
/** Returns a line that is the same as this one, but with the start and end reversed, */
|
|
|
|
Line reversed() const noexcept { return Line (end, start); }
|
|
|
|
Line reversed() const noexcept { return { end, start }; }
|
|
|
|
|
|
|
|
/** Applies an affine transform to the line's start and end points. */
|
|
|
|
void applyTransform (const AffineTransform& transform) noexcept
|
|
|
@@ -145,15 +144,15 @@ public: |
|
|
|
*/
|
|
|
|
static Line fromStartAndAngle (Point<ValueType> startPoint, ValueType length, ValueType angle) noexcept
|
|
|
|
{
|
|
|
|
return Line (startPoint, startPoint.getPointOnCircumference (length, angle));
|
|
|
|
return { startPoint, startPoint.getPointOnCircumference (length, angle) };
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
/** Casts this line to float coordinates. */
|
|
|
|
Line<float> toFloat() const noexcept { return Line<float> (start.toFloat(), end.toFloat()); }
|
|
|
|
Line<float> toFloat() const noexcept { return { start.toFloat(), end.toFloat() }; }
|
|
|
|
|
|
|
|
/** Casts this line to double coordinates. */
|
|
|
|
Line<double> toDouble() const noexcept { return Line<double> (start.toDouble(), end.toDouble()); }
|
|
|
|
Line<double> toDouble() const noexcept { return { start.toDouble(), end.toDouble() }; }
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
/** Compares two lines. */
|
|
|
@@ -228,14 +227,14 @@ public: |
|
|
|
Point<ValueType> getPointAlongLine (ValueType distanceFromStart,
|
|
|
|
ValueType perpendicularDistance) const noexcept
|
|
|
|
{
|
|
|
|
const Point<ValueType> delta (end - start);
|
|
|
|
const double length = juce_hypot ((double) delta.x,
|
|
|
|
(double) delta.y);
|
|
|
|
auto delta = end - start;
|
|
|
|
auto length = juce_hypot ((double) delta.x,
|
|
|
|
(double) delta.y);
|
|
|
|
if (length <= 0)
|
|
|
|
return start;
|
|
|
|
|
|
|
|
return Point<ValueType> (start.x + static_cast<ValueType> ((delta.x * distanceFromStart - delta.y * perpendicularDistance) / length),
|
|
|
|
start.y + static_cast<ValueType> ((delta.y * distanceFromStart + delta.x * perpendicularDistance) / length));
|
|
|
|
return { start.x + static_cast<ValueType> ((delta.x * distanceFromStart - delta.y * perpendicularDistance) / length),
|
|
|
|
start.y + static_cast<ValueType> ((delta.y * distanceFromStart + delta.x * perpendicularDistance) / length) };
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns the location of the point which is a given distance along this line
|
|
|
@@ -267,13 +266,13 @@ public: |
|
|
|
ValueType getDistanceFromPoint (Point<ValueType> targetPoint,
|
|
|
|
Point<ValueType>& pointOnLine) const noexcept
|
|
|
|
{
|
|
|
|
const Point<ValueType> delta (end - start);
|
|
|
|
const double length = delta.x * delta.x + delta.y * delta.y;
|
|
|
|
auto delta = end - start;
|
|
|
|
auto length = delta.x * delta.x + delta.y * delta.y;
|
|
|
|
|
|
|
|
if (length > 0)
|
|
|
|
{
|
|
|
|
const double prop = ((targetPoint.x - start.x) * delta.x
|
|
|
|
+ (targetPoint.y - start.y) * delta.y) / length;
|
|
|
|
auto prop = ((targetPoint.x - start.x) * delta.x
|
|
|
|
+ (targetPoint.y - start.y) * delta.y) / length;
|
|
|
|
|
|
|
|
if (prop >= 0 && prop <= 1.0)
|
|
|
|
{
|
|
|
@@ -282,19 +281,17 @@ public: |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const float fromStart = targetPoint.getDistanceFrom (start);
|
|
|
|
const float fromEnd = targetPoint.getDistanceFrom (end);
|
|
|
|
auto fromStart = targetPoint.getDistanceFrom (start);
|
|
|
|
auto fromEnd = targetPoint.getDistanceFrom (end);
|
|
|
|
|
|
|
|
if (fromStart < fromEnd)
|
|
|
|
{
|
|
|
|
pointOnLine = start;
|
|
|
|
return fromStart;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pointOnLine = end;
|
|
|
|
return fromEnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
pointOnLine = end;
|
|
|
|
return fromEnd;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Finds the point on this line which is nearest to a given point, and
|
|
|
@@ -307,8 +304,8 @@ public: |
|
|
|
*/
|
|
|
|
ValueType findNearestProportionalPositionTo (Point<ValueType> point) const noexcept
|
|
|
|
{
|
|
|
|
const Point<ValueType> delta (end - start);
|
|
|
|
const double length = delta.x * delta.x + delta.y * delta.y;
|
|
|
|
auto delta = end - start;
|
|
|
|
auto length = delta.x * delta.x + delta.y * delta.y;
|
|
|
|
|
|
|
|
return length <= 0 ? 0
|
|
|
|
: jlimit (ValueType(), static_cast<ValueType> (1),
|
|
|
@@ -333,8 +330,7 @@ public: |
|
|
|
bool isPointAbove (Point<ValueType> point) const noexcept
|
|
|
|
{
|
|
|
|
return start.x != end.x
|
|
|
|
&& point.y < ((end.y - start.y)
|
|
|
|
* (point.x - start.x)) / (end.x - start.x) + start.y;
|
|
|
|
&& point.y < ((end.y - start.y) * (point.x - start.x)) / (end.x - start.x) + start.y;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
@@ -345,7 +341,7 @@ public: |
|
|
|
*/
|
|
|
|
Line withShortenedStart (ValueType distanceToShortenBy) const noexcept
|
|
|
|
{
|
|
|
|
return Line (getPointAlongLine (jmin (distanceToShortenBy, getLength())), end);
|
|
|
|
return { getPointAlongLine (jmin (distanceToShortenBy, getLength())), end };
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns a shortened copy of this line.
|
|
|
@@ -355,14 +351,16 @@ public: |
|
|
|
*/
|
|
|
|
Line withShortenedEnd (ValueType distanceToShortenBy) const noexcept
|
|
|
|
{
|
|
|
|
const ValueType length = getLength();
|
|
|
|
return Line (start, getPointAlongLine (length - jmin (distanceToShortenBy, length)));
|
|
|
|
auto length = getLength();
|
|
|
|
return { start, getPointAlongLine (length - jmin (distanceToShortenBy, length)) };
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
//==============================================================================
|
|
|
|
Point<ValueType> start, end;
|
|
|
|
|
|
|
|
static bool isZeroToOne (ValueType v) noexcept { return v >= 0 && v <= static_cast<ValueType> (1); }
|
|
|
|
|
|
|
|
static bool findIntersection (const Point<ValueType> p1, const Point<ValueType> p2,
|
|
|
|
const Point<ValueType> p3, const Point<ValueType> p4,
|
|
|
|
Point<ValueType>& intersection) noexcept
|
|
|
@@ -373,9 +371,9 @@ private: |
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Point<ValueType> d1 (p2 - p1);
|
|
|
|
const Point<ValueType> d2 (p4 - p3);
|
|
|
|
const ValueType divisor = d1.x * d2.y - d2.x * d1.y;
|
|
|
|
auto d1 = p2 - p1;
|
|
|
|
auto d2 = p4 - p3;
|
|
|
|
auto divisor = d1.x * d2.y - d2.x * d1.y;
|
|
|
|
|
|
|
|
if (divisor == 0)
|
|
|
|
{
|
|
|
@@ -383,30 +381,30 @@ private: |
|
|
|
{
|
|
|
|
if (d1.y == 0 && d2.y != 0)
|
|
|
|
{
|
|
|
|
const ValueType along = (p1.y - p3.y) / d2.y;
|
|
|
|
auto along = (p1.y - p3.y) / d2.y;
|
|
|
|
intersection = p1.withX (p3.x + along * d2.x);
|
|
|
|
return along >= 0 && along <= static_cast<ValueType> (1);
|
|
|
|
return isZeroToOne (along);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d2.y == 0 && d1.y != 0)
|
|
|
|
{
|
|
|
|
const ValueType along = (p3.y - p1.y) / d1.y;
|
|
|
|
auto along = (p3.y - p1.y) / d1.y;
|
|
|
|
intersection = p3.withX (p1.x + along * d1.x);
|
|
|
|
return along >= 0 && along <= static_cast<ValueType> (1);
|
|
|
|
return isZeroToOne (along);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d1.x == 0 && d2.x != 0)
|
|
|
|
{
|
|
|
|
const ValueType along = (p1.x - p3.x) / d2.x;
|
|
|
|
auto along = (p1.x - p3.x) / d2.x;
|
|
|
|
intersection = p1.withY (p3.y + along * d2.y);
|
|
|
|
return along >= 0 && along <= static_cast<ValueType> (1);
|
|
|
|
return isZeroToOne (along);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (d2.x == 0 && d1.x != 0)
|
|
|
|
{
|
|
|
|
const ValueType along = (p3.x - p1.x) / d1.x;
|
|
|
|
auto along = (p3.x - p1.x) / d1.x;
|
|
|
|
intersection = p3.withY (p1.y + along * d1.y);
|
|
|
|
return along >= 0 && along <= static_cast<ValueType> (1);
|
|
|
|
return isZeroToOne (along);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
@@ -414,13 +412,13 @@ private: |
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const ValueType along1 = ((p1.y - p3.y) * d2.x - (p1.x - p3.x) * d2.y) / divisor;
|
|
|
|
auto along1 = ((p1.y - p3.y) * d2.x - (p1.x - p3.x) * d2.y) / divisor;
|
|
|
|
intersection = p1 + d1 * along1;
|
|
|
|
|
|
|
|
if (along1 < 0 || along1 > static_cast<ValueType> (1))
|
|
|
|
if (! isZeroToOne (along1))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const ValueType along2 = ((p1.y - p3.y) * d1.x - (p1.x - p3.x) * d1.y) / divisor;
|
|
|
|
return along2 >= 0 && along2 <= static_cast<ValueType> (1);
|
|
|
|
auto along2 = ((p1.y - p3.y) * d1.x - (p1.x - p3.x) * d1.y) / divisor;
|
|
|
|
return isZeroToOne (along2);
|
|
|
|
}
|
|
|
|
};
|