/** * Tests if this line and the other line are perpendicular. * * @param other the query. Not modified. * @return {@code true} if the two lines are perpendicular, {@code false} otherwise. */ default boolean areLinesPerpendicular(Line2DReadOnly other) { // Dot product of two vectors is zero if the vectors are perpendicular return getDirection().dot(other.getDirection()) < 1e-7; }
/** * Checks if a line intersects the edge with the given index. */ public static boolean doesLineIntersectEdge(Line2DReadOnly line, int edgeIndex, ConvexPolygon2DReadOnly polygon) { if (polygon.getNumberOfVertices() < 2) return false; Point2DReadOnly edgeStart = polygon.getVertex(edgeIndex); Point2DReadOnly edgeEnd = polygon.getNextVertex(edgeIndex); double lineDirectionX = line.getDirectionX(); double lineDirectionY = line.getDirectionY(); double edgeDirectionX = edgeEnd.getX() - edgeStart.getX(); double edgeDirectionY = edgeEnd.getY() - edgeStart.getY(); if (EuclidGeometryTools.areVector2DsParallel(lineDirectionX, lineDirectionY, edgeDirectionX, edgeDirectionY, EuclidGeometryTools.ONE_TEN_MILLIONTH)) return false; else return EuclidGeometryTools.doLine2DAndLineSegment2DIntersect(line.getPoint(), line.getDirection(), edgeStart, edgeEnd); }
/** * Gets the x-component of this line's direction. * * @return the x-component of this line's direction. */ default double getDirectionX() { return getDirection().getX(); }
/** * Returns the vector that is perpendicular to this line and pointing to the left. * <p> * WARNING: This method generates garbage. * </p> * * @return the perpendicular vector to this line. */ default Vector2DBasics perpendicularVector() { return EuclidGeometryTools.perpendicularVector2D(getDirection()); }
/** * Gets the y-component of this line's direction. * * @return the y-component of this line's direction. */ default double getDirectionY() { return getDirection().getY(); }
/** * Packs into {@code vectorToPack} the vector that is perpendicular to this line and pointing to the * left. * * @param vectorToPack the perpendicular vector to this line. Modified. */ default void perpendicularVector(Vector2DBasics vectorToPack) { EuclidGeometryTools.perpendicularVector2D(getDirection(), vectorToPack); }
/** * Compares {@code this} with {@code other} to determine if the two lines are collinear. * * @param other the line to compare to. Not modified. * @param angleEpsilon the tolerance of the comparison for angle. * @param distanceEpsilon the tolerance of the comparison for distance. * @return {@code true} if the lines are collinear, {@code false} otherwise. */ default boolean isCollinear(Line2DReadOnly other, double angleEpsilon, double distanceEpsilon) { return EuclidGeometryTools.areLine2DsCollinear(getPoint(), getDirection(), other.getPoint(), other.getDirection(), angleEpsilon, distanceEpsilon); }
/** * Tests on a per component basis, if this line 2D is exactly equal to {@code other}. * * @param other the other line 2D to compare against this. Not modified. * @return {@code true} if the two lines are exactly equal component-wise, {@code false} otherwise. */ default boolean equals(Line2DReadOnly other) { if (other == null) return false; else return getPoint().equals(other.getPoint()) && getDirection().equals(other.getDirection()); } }
/** * Tests if the given is located on this line. * <p> * More precisely, the point is assumed to be on this line if it is located at a distance less than * {@code epsilon} from it. * </p> * * @param point the coordinates of the query. Not modified. * @param epsilon the tolerance used for this test. * @return {@code true} if the point is located on this line, {@code false} otherwise. */ default boolean isPointOnLine(Point2DReadOnly point, double epsilon) { return EuclidGeometryTools.distanceFromPoint2DToLine2D(point, getPoint(), getDirection()) < epsilon; }
/** * Computes the minimum distance the given 3D point and this line. * <p> * Edge cases: * <ul> * <li>if {@code direction.length() < }{@link EuclidGeometryTools#ONE_TRILLIONTH}, this method * returns the distance between {@code point} and the given {@code point}. * </ul> * </p> * * @param point 2D point to compute the distance from the line. Not modified. * @return the minimum distance between the 2D point and this 2D line. */ default double distance(Point2DReadOnly point) { return EuclidGeometryTools.distanceFromPoint2DToLine2D(point, getPoint(), getDirection()); }
/** * Calculates the coordinates of the point 'p' given the parameter 't' as follows:<br> * p = t * n + p<sub>0</sub><br> * where n is the unit-vector defining the direction of this line and p<sub>0</sub> is the point * defining this line which also corresponds to the point for which t=0. * <p> * Note that the absolute value of 't' is equal to the distance between the point 'p' and the point * p<sub>0</sub> defining this line. * </p> * * @param t the parameter used to calculate the point coordinates. * @param pointToPack the point in which the coordinates of 'p' are stored. Modified. */ default void pointOnLineGivenParameter(double t, Point2DBasics pointToPack) { pointToPack.scaleAdd(t, getDirection(), getPoint()); }
/** * Modifies {@code perpendicularLineToPack} such that it is perpendicular to this line, with its * direction pointing to the left of this line, while going through the given point. * * @param point the point the line has to go through. Not modified. * @param perpendicularLineToPack the line perpendicular to {@code this} and going through * {@code point}. Modified. */ default void perpendicularLineThroughPoint(Point2DReadOnly point, Line2DBasics perpendicularLineToPack) { perpendicularLineToPack.set(point.getX(), point.getY(), -getDirection().getY(), getDirection().getX()); }
/** * Tests on a per-component basis on the point and vector if this line is equal to {@code other} * with the tolerance {@code epsilon}. This method will return {@code false} if the two lines are * physically the same but either the point or vector of each line is different. For instance, if * {@code this.point == other.point} and {@code this.direction == - other.direction}, the two lines * are physically the same but this method returns {@code false}. * * @param other the query. Not modified. * @param epsilon the tolerance to use. * @return {@code true} if the two lines are equal, {@code false} otherwise. */ default boolean epsilonEquals(Line2DReadOnly other, double epsilon) { if (!getPoint().epsilonEquals(other.getPoint(), epsilon)) return false; if (!getDirection().epsilonEquals(other.getDirection(), epsilon)) return false; return true; }
/** * Computes the orthogonal projection of the given 2D point on this 2D line. * <p> * Edge cases: * <ul> * <li>if the given line direction is too small, i.e. * {@code lineDirection.lengthSquared() < }{@value EuclidGeometryTools#ONE_TRILLIONTH}, this method * fails and returns {@code false}. * </ul> * </p> * <p> * WARNING: This method generates garbage. * </p> * * @param pointToProject the point to compute the projection of. Not modified. * @return the projection of the point onto the line or {@code null} if the method failed. */ default Point2DBasics orthogonalProjectionCopy(Point2DReadOnly pointToProject) { return EuclidGeometryTools.orthogonalProjectionOnLine2D(pointToProject, getPoint(), getDirection()); }
/** * Gets a representative {@code String} of {@code line2D} given a specific format to use. * <p> * Using the default format {@link #DEFAULT_FORMAT}, this provides a {@code String} as follows: * * <pre> * Line 2D: point = ( 0.174, 0.732 ), direction = (-0.380, 0.130 ) * </pre> * </p> * * @param format the format to use for each number. * @param line2D the object to get the {@code String} of. Not modified. * @return the representative {@code String}. */ public static String getLine2DString(String format, Line2DReadOnly line2D) { if (line2D == null) return "null"; else return getLine2DString(format, line2D.getPoint(), line2D.getDirection()); }
/** * Gets the point and direction defining this line by storing their components in the given * arguments {@code pointToPack} and {@code directionToPack}. * * @param pointToPack point in which the coordinates of this line's point are stored. Modified. * @param directionToPack vector in which the components of this line's direction are stored. * Modified. */ default void get(Point2DBasics pointToPack, Vector2DBasics directionToPack) { pointToPack.set(getPoint()); directionToPack.set(getDirection()); }
/** * Gets the coordinates of two distinct points this line goes through. * * @param firstPointOnLineToPack the coordinates of a first point located on this line. Modified. * @param secondPointOnLineToPack the coordinates of a second point located on this line. Modified. */ default void getTwoPointsOnLine(Point2DBasics firstPointOnLineToPack, Point2DBasics secondPointOnLineToPack) { firstPointOnLineToPack.set(getPoint()); secondPointOnLineToPack.add(getPoint(), getDirection()); }
/** * Sets this line to be the same as the given line. * * @param other the other line to copy. Not modified. */ default void set(Line2DReadOnly other) { getPoint().set(other.getPoint()); getDirection().set(other.getDirection()); }
/** * Sets this line to represent the same geometry as the given {@code line2DReadOnly}. * <p> * After calling this method this line is in the XY-plane. * </p> * * @param line2DReadOnly the other line to copy. Not modified. */ default void set(Line2DReadOnly line2DReadOnly) { getPoint().set(line2DReadOnly.getPoint(), 0.0); getDirection().set(line2DReadOnly.getDirection(), 0.0); }
/** * Finds the index of the closest vertex to the given line. * <p> * Edge cases: * <ul> * <li>If the polygon has no vertices, this method fails and returns {@code -1}. * </ul> * </p> * * @param line the query. Not modified. * @return the index of the closest vertex to the query. * @throws OutdatedPolygonException if {@link ConvexPolygon2DBasics#update()} has not been called * since last time this polygon's vertices were edited. */ default int getClosestVertexIndex(Line2DReadOnly line) { checkIfUpToDate(); return EuclidGeometryPolygonTools.closestVertexIndexToLine2D(line.getPoint(), line.getDirection(), getVertexBufferView(), getNumberOfVertices()); }