| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE 6 technical preview.
 -    Copyright (c) 2020 - Raw Material Software Limited
 - 
 -    You may use this code under the terms of the GPL v3
 -    (see www.gnu.org/licenses).
 - 
 -    For this technical preview, this file is not subject to commercial licensing.
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce
 - {
 - 
 - //==============================================================================
 - /**
 -     Represents a line.
 - 
 -     This class contains a bunch of useful methods for various geometric
 -     tasks.
 - 
 -     The ValueType template parameter should be a primitive type - float or double
 -     are what it's designed for. Integer types will work in a basic way, but some methods
 -     that perform mathematical operations may not compile, or they may not produce
 -     sensible results.
 - 
 -     @see Point, Rectangle, Path, Graphics::drawLine
 - 
 -     @tags{Graphics}
 - */
 - template <typename ValueType>
 - class Line
 - {
 - public:
 -     //==============================================================================
 -     /** Creates a line, using (0, 0) as its start and end points. */
 -     Line() = default;
 - 
 -     /** Creates a copy of another line. */
 -     Line (const Line&) = default;
 - 
 -     /** Creates a line based on the coordinates of its start and end points. */
 -     Line (ValueType startX, ValueType startY, ValueType endX, ValueType endY) noexcept
 -         : start (startX, startY), end (endX, endY)
 -     {
 -     }
 - 
 -     /** Creates a line from its start and end points. */
 -     Line (Point<ValueType> startPoint, Point<ValueType> endPoint) noexcept
 -         : start (startPoint), end (endPoint)
 -     {
 -     }
 - 
 -     /** Copies a line from another one. */
 -     Line& operator= (const Line&) = default;
 - 
 -     /** Destructor. */
 -     ~Line() = default;
 - 
 -     //==============================================================================
 -     /** Returns the x coordinate of the line's start point. */
 -     inline ValueType getStartX() const noexcept                             { return start.x; }
 - 
 -     /** Returns the y coordinate of the line's start point. */
 -     inline ValueType getStartY() const noexcept                             { return start.y; }
 - 
 -     /** Returns the x coordinate of the line's end point. */
 -     inline ValueType getEndX() const noexcept                               { return end.x; }
 - 
 -     /** Returns the y coordinate of the line's end point. */
 -     inline ValueType getEndY() const noexcept                               { return end.y; }
 - 
 -     /** Returns the line's start point. */
 -     inline Point<ValueType> getStart() const noexcept                       { return start; }
 - 
 -     /** Returns the line's end point. */
 -     inline Point<ValueType> getEnd() const noexcept                         { return end; }
 - 
 -     /** Changes this line's start point */
 -     void setStart (ValueType newStartX, ValueType newStartY) noexcept       { start.setXY (newStartX, newStartY); }
 - 
 -     /** Changes this line's end point */
 -     void setEnd (ValueType newEndX, ValueType newEndY) noexcept             { end.setXY (newEndX, newEndY); }
 - 
 -     /** Changes this line's start point */
 -     void setStart (const Point<ValueType> newStart) noexcept                { start = newStart; }
 - 
 -     /** Changes this line's end point */
 -     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 { end, start }; }
 - 
 -     /** Applies an affine transform to the line's start and end points. */
 -     void applyTransform (const AffineTransform& transform) noexcept
 -     {
 -         start.applyTransform (transform);
 -         end.applyTransform (transform);
 -     }
 - 
 -     //==============================================================================
 -     /** Returns the length of the line. */
 -     ValueType getLength() const noexcept                                    { return start.getDistanceFrom (end); }
 - 
 -     /** Returns the length of the line. */
 -     ValueType getLengthSquared() const noexcept                             { return start.getDistanceSquaredFrom (end); }
 - 
 -     /** Returns true if the line's start and end x coordinates are the same. */
 -     bool isVertical() const noexcept                                        { return start.x == end.x; }
 - 
 -     /** Returns true if the line's start and end y coordinates are the same. */
 -     bool isHorizontal() const noexcept                                      { return start.y == end.y; }
 - 
 -     /** Returns the line's angle.
 - 
 -         This value is the number of radians clockwise from the 12 o'clock direction,
 -         where the line's start point is considered to be at the centre.
 -     */
 -     typename Point<ValueType>::FloatType getAngle() const noexcept          { return start.getAngleToPoint (end); }
 - 
 -     /** Creates a line from a start point, length and angle.
 - 
 -         This angle is the number of radians clockwise from the 12 o'clock direction,
 -         where the line's start point is considered to be at the centre.
 -     */
 -     static Line fromStartAndAngle (Point<ValueType> startPoint, ValueType length, ValueType angle) noexcept
 -     {
 -         return { startPoint, startPoint.getPointOnCircumference (length, angle) };
 -     }
 - 
 -     //==============================================================================
 -     /** Casts this line to float coordinates. */
 -     Line<float> toFloat() const noexcept                                    { return { start.toFloat(), end.toFloat() }; }
 - 
 -     /** Casts this line to double coordinates. */
 -     Line<double> toDouble() const noexcept                                  { return { start.toDouble(), end.toDouble() }; }
 - 
 -     //==============================================================================
 -     /** Compares two lines. */
 -     bool operator== (Line other) const noexcept                             { return start == other.start && end == other.end; }
 - 
 -     /** Compares two lines. */
 -     bool operator!= (Line other) const noexcept                             { return start != other.start || end != other.end; }
 - 
 -     //==============================================================================
 -     /** Finds the intersection between two lines.
 - 
 -         @param line     the line to intersect with
 -         @returns        the point at which the lines intersect, even if this lies beyond the end of the lines
 -     */
 -     Point<ValueType> getIntersection (Line line) const noexcept
 -     {
 -         Point<ValueType> p;
 -         findIntersection (start, end, line.start, line.end, p);
 -         return p;
 -     }
 - 
 -     /** Finds the intersection between two lines.
 - 
 -         @param line             the other line
 -         @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.
 -         @returns    true if the line segments intersect; false if they don't. Even if they
 -                     don't intersect, the intersection coordinates returned will still
 -                     be valid
 -     */
 -     bool intersects (Line line, Point<ValueType>& intersection) const noexcept
 -     {
 -         return findIntersection (start, end, line.start, line.end, intersection);
 -     }
 - 
 -     /** Returns true if this line intersects another. */
 -     bool intersects (Line other) const noexcept
 -     {
 -         Point<ValueType> ignored;
 -         return findIntersection (start, end, other.start, other.end, ignored);
 -     }
 - 
 -     //==============================================================================
 -     /** Returns the location of the point which is a given distance along this line.
 - 
 -         @param distanceFromStart    the distance to move along the line from its
 -                                     start point. This value can be negative or longer
 -                                     than the line itself
 -         @see getPointAlongLineProportionally
 -     */
 -     Point<ValueType> getPointAlongLine (ValueType distanceFromStart) const noexcept
 -     {
 -         return start + (end - start) * (distanceFromStart / getLength());
 -     }
 - 
 -     /** Returns a point which is a certain distance along and to the side of this line.
 - 
 -         This effectively moves a given distance along the line, then another distance
 -         perpendicularly to this, and returns the resulting position.
 - 
 -         @param distanceFromStart    the distance to move along the line from its
 -                                     start point. This value can be negative or longer
 -                                     than the line itself
 -         @param perpendicularDistance    how far to move sideways from the line. If you're
 -                                     looking along the line from its start towards its
 -                                     end, then a positive value here will move to the
 -                                     right, negative value move to the left.
 -     */
 -     Point<ValueType> getPointAlongLine (ValueType distanceFromStart,
 -                                         ValueType perpendicularDistance) const noexcept
 -     {
 -         auto delta = end - start;
 -         auto length = juce_hypot ((double) delta.x,
 -                                   (double) delta.y);
 -         if (length <= 0)
 -             return start;
 - 
 -         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
 -         proportional to the line's length.
 - 
 -         @param proportionOfLength   the distance to move along the line from its
 -                                     start point, in multiples of the line's length.
 -                                     So a value of 0.0 will return the line's start point
 -                                     and a value of 1.0 will return its end point. (This value
 -                                     can be negative or greater than 1.0).
 -         @see getPointAlongLine
 -     */
 -     Point<ValueType> getPointAlongLineProportionally (typename Point<ValueType>::FloatType proportionOfLength) const noexcept
 -     {
 -         return start + (end - start) * proportionOfLength;
 -     }
 - 
 -     /** Returns the smallest distance between this line segment and a given point.
 - 
 -         So if the point is close to the line, this will return the perpendicular
 -         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.
 - 
 -         pointOnLine receives the position of the point that is found.
 - 
 -         @returns the point's distance from the line
 -         @see getPositionAlongLineOfNearestPoint
 -     */
 -     ValueType getDistanceFromPoint (Point<ValueType> targetPoint,
 -                                     Point<ValueType>& pointOnLine) const noexcept
 -     {
 -         auto delta = end - start;
 -         auto length = delta.x * delta.x + delta.y * delta.y;
 - 
 -         if (length > 0)
 -         {
 -             auto prop = ((targetPoint.x - start.x) * delta.x
 -                        + (targetPoint.y - start.y) * delta.y) / (double) length;
 - 
 -             if (prop >= 0 && prop <= 1.0)
 -             {
 -                 pointOnLine = start + delta * prop;
 -                 return targetPoint.getDistanceFrom (pointOnLine);
 -             }
 -         }
 - 
 -         auto fromStart = targetPoint.getDistanceFrom (start);
 -         auto fromEnd   = targetPoint.getDistanceFrom (end);
 - 
 -         if (fromStart < fromEnd)
 -         {
 -             pointOnLine = start;
 -             return fromStart;
 -         }
 - 
 -         pointOnLine = end;
 -         return fromEnd;
 -     }
 - 
 -     /** Finds the point on this line which is nearest to a given point, and
 -         returns its position as a proportional position along the line.
 - 
 -         @returns    a value 0 to 1.0 which is the distance along this line from the
 -                     line's start to the point which is nearest to the point passed-in. To
 -                     turn this number into a position, use getPointAlongLineProportionally().
 -         @see getDistanceFromPoint, getPointAlongLineProportionally
 -     */
 -     ValueType findNearestProportionalPositionTo (Point<ValueType> point) const noexcept
 -     {
 -         auto delta = end - start;
 -         auto length = delta.x * delta.x + delta.y * delta.y;
 - 
 -         return length <= 0 ? 0
 -                            : jlimit (ValueType(), static_cast<ValueType> (1),
 -                                      static_cast<ValueType> ((((point.x - start.x) * delta.x
 -                                                              + (point.y - start.y) * delta.y) / length)));
 -     }
 - 
 -     /** Finds the point on this line which is nearest to a given point.
 -         @see getDistanceFromPoint, findNearestProportionalPositionTo
 -     */
 -     Point<ValueType> findNearestPointTo (Point<ValueType> point) const noexcept
 -     {
 -         return getPointAlongLineProportionally (findNearestProportionalPositionTo (point));
 -     }
 - 
 -     /** Returns true if the given point lies above this line.
 - 
 -         The return value is true if the point's y coordinate is less than the y
 -         coordinate of this line at the given x (assuming the line extends infinitely
 -         in both directions).
 -     */
 -     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;
 -     }
 - 
 -     //==============================================================================
 -     /** Returns a shortened copy of this line.
 - 
 -         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.
 -     */
 -     Line withShortenedStart (ValueType distanceToShortenBy) const noexcept
 -     {
 -         return { 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.
 -     */
 -     Line withShortenedEnd (ValueType distanceToShortenBy) const noexcept
 -     {
 -         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
 -     {
 -         if (p2 == p3)
 -         {
 -             intersection = p2;
 -             return true;
 -         }
 - 
 -         auto d1 = p2 - p1;
 -         auto d2 = p4 - p3;
 -         auto divisor = d1.x * d2.y - d2.x * d1.y;
 - 
 -         if (divisor == 0)
 -         {
 -             if (! (d1.isOrigin() || d2.isOrigin()))
 -             {
 -                 if (d1.y == 0 && d2.y != 0)
 -                 {
 -                     auto along = (p1.y - p3.y) / d2.y;
 -                     intersection = p1.withX (p3.x + along * d2.x);
 -                     return isZeroToOne (along);
 -                 }
 - 
 -                 if (d2.y == 0 && d1.y != 0)
 -                 {
 -                     auto along = (p3.y - p1.y) / d1.y;
 -                     intersection = p3.withX (p1.x + along * d1.x);
 -                     return isZeroToOne (along);
 -                 }
 - 
 -                 if (d1.x == 0 && d2.x != 0)
 -                 {
 -                     auto along = (p1.x - p3.x) / d2.x;
 -                     intersection = p1.withY (p3.y + along * d2.y);
 -                     return isZeroToOne (along);
 -                 }
 - 
 -                 if (d2.x == 0 && d1.x != 0)
 -                 {
 -                     auto along = (p3.x - p1.x) / d1.x;
 -                     intersection = p3.withY (p1.y + along * d1.y);
 -                     return isZeroToOne (along);
 -                 }
 -             }
 - 
 -             intersection = (p2 + p3) / static_cast<ValueType> (2);
 -             return false;
 -         }
 - 
 -         auto along1 = ((p1.y - p3.y) * d2.x - (p1.x - p3.x) * d2.y) / divisor;
 -         intersection = p1 + d1 * along1;
 - 
 -         if (! isZeroToOne (along1))
 -             return false;
 - 
 -         auto along2 = ((p1.y - p3.y) * d1.x - (p1.x - p3.x) * d1.y) / divisor;
 -         return isZeroToOne (along2);
 -     }
 - };
 - 
 - } // namespace juce
 
 
  |