/** * Finds the index of the closest edge to the query. * <p> * Edge cases: * <ul> * <li>If the polygon has one or no vertices, this method fails and returns {@code -1}. * </ul> * </p> * * @param point the coordinates of the query. Not modified. * @return the index of the closest edge to the query. * @throws OutdatedPolygonException if {@link ConvexPolygon2DBasics#update()} has not been called * since last time this polygon's vertices were edited. */ default int getClosestEdgeIndex(Point2DReadOnly point) { checkIfUpToDate(); return EuclidGeometryPolygonTools.closestEdgeIndexToPoint2D(point, getVertexBufferView(), getNumberOfVertices(), isClockwiseOrdered()); }
if (polygon1.isEmpty() || polygon2.isEmpty()) return false; if (polygon1.getNumberOfVertices() == 1 && polygon2.getNumberOfVertices() == 1) if (polygon1.getNumberOfVertices() == 1) int lineOfSightStartIndex = polygon2.lineOfSightStartIndex(polygon1.getVertex(0)); int lineOfSightEndIndex = polygon2.lineOfSightEndIndex(polygon1.getVertex(0)); success = lineOfSightStartIndex > -1 && lineOfSightEndIndex > -1; verticesIndices[1][0] = lineOfSightStartIndex; if (polygon2.getNumberOfVertices() == 1) int lineOfSightStartIndex = polygon1.lineOfSightStartIndex(polygon2.getVertex(0)); int lineOfSightEndIndex = polygon1.lineOfSightEndIndex(polygon2.getVertex(0)); success = lineOfSightStartIndex > -1 && lineOfSightEndIndex > -1; verticesIndices[0][0] = lineOfSightStartIndex; Point2DReadOnly vertex = polygon1.getVertex(0); if ((lineOfSight1StartIndex = polygon2.lineOfSightStartIndex(vertex)) == -1) return false; if ((lineOfSight1EndIndex = polygon2.lineOfSightEndIndex(vertex)) == -1) return false; if ((lineOfSight1StartIndex = polygon1.lineOfSightStartIndex(polygon2.getVertex(R2))) == -1) return false; if ((lineOfSight1EndIndex = polygon1.lineOfSightEndIndex(polygon2.getVertex(R2))) == -1)
/** * Packs the endpoints of an edge of this polygon into {@code edgeToPack}. * * @param edgeIndex index of the vertex that starts the edge. * @param edgeToPack line segment used to store the edge endpoints. Modified. * @throws OutdatedPolygonException if {@link ConvexPolygon2DBasics#update()} has not been called * since last time this polygon's vertices were edited. * @throws IndexOutOfBoundsException if the given {@code index} is negative or greater or equal * than this polygon's number of vertices. * @throws EmptyPolygonException if this polygon is empty when calling this method. */ default void getEdge(int edgeIndex, LineSegment2DBasics edgeToPack) { edgeToPack.set(getVertex(edgeIndex), getNextVertex(edgeIndex)); }
/** * Determines if the polygonToTest is inside the convex polygon. */ public static boolean isPolygonInside(ConvexPolygon2DReadOnly polygonToTest, double epsilon, ConvexPolygon2DReadOnly polygon) { for (int i = 0; i < polygonToTest.getNumberOfVertices(); i++) { if (!polygon.isPointInside(polygonToTest.getVertex(i), epsilon)) return false; } return true; }
/** * Gets the read-only reference to the {@code index}<sup>th</sup> vertex of this polygon. * <p> * This method calculates a new index to emulate a counter-clockwise ordering of this polygon's * vertices. The first vertex has the lowest x-coordinate. * </p> * * @param index the index of the vertex in the counter-clockwise ordered list. * @return the read-only reference to the vertex. * @throws OutdatedPolygonException if {@link ConvexPolygon2DBasics#update()} has not been called * since last time this polygon's vertices were edited. * @throws IndexOutOfBoundsException if the given {@code index} is negative or greater or equal * than this polygon's number of vertices. * @throws EmptyPolygonException if this polygon is empty when calling this method. */ default Point2DReadOnly getVertexCCW(int index) { return getVertex(getNumberOfVertices() - 1 - index); }
/** * Gets the read-only reference to the vertex located after the {@code index}<sup>th</sup> vertex * of this polygon. * <p> * Note that the first vertex has the lowest x-coordinate. * </p> * * @param index the index of the vertex. * @return the read-only reference to the next vertex. * @throws OutdatedPolygonException if {@link ConvexPolygon2DBasics#update()} has not been called * since last time this polygon's vertices were edited. * @throws IndexOutOfBoundsException if the given {@code index} is negative or greater or equal * than this polygon's number of vertices. * @throws EmptyPolygonException if this polygon is empty when calling this method. */ default Point2DReadOnly getNextVertex(int index) { return getVertex(getNextVertexIndex(index)); }
/** * 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); }
if (polygonP == null || polygonP.isEmpty()) return false; if (polygonQ == null || polygonQ.isEmpty()) return false; if (polygonP.getNumberOfVertices() == 2 && polygonQ.getNumberOfVertices() >= 2) else if (polygonQ.getNumberOfVertices() == 2) if (polygonP.getNumberOfVertices() == 1 && !polygonQ.isEmpty()) else if (polygonQ.getNumberOfVertices() == 1) Point2DReadOnly currentPolygonPPoint = polygonP.getVertex(currentPPolygonPointIndex); Point2DReadOnly currentPolygonQPoint = polygonQ.getVertex(currentQPolygonPointIndex); vectorToNextPointOnPolygonP.set(polygonP.getNextVertex(currentPPolygonPointIndex)); vectorToNextPointOnPolygonP.sub(polygonP.getVertex(currentPPolygonPointIndex)); vectorToNextPointOnPolygonP.normalize(); vectorToNextPointOnPolygonQ.set(polygonQ.getNextVertex(currentQPolygonPointIndex)); vectorToNextPointOnPolygonQ.sub(polygonQ.getVertex(currentQPolygonPointIndex)); vectorToNextPointOnPolygonQ.normalize(); currentPPolygonPointIndex = polygonP.getNextVertexIndex(currentPPolygonPointIndex); currentPolygonPPoint = polygonP.getVertex(currentPPolygonPointIndex); if (currentPPolygonPointIndex == (initialPolygonPIndex) % polygonP.getNumberOfVertices())
/** * Gets a read-only view of this polygon vertices. * <p> * WARNING: This method generates garbage. * </p> * <p> * The returned list is an unmodifiable list created with * {@link Collections#unmodifiableList(List)}. * </p> * * @return a read-only view of this polygon vertices. */ default List<? extends Point2DReadOnly> getPolygonVerticesView() { return getVertexBufferView().subList(0, getNumberOfVertices()); }
if (polygon.getNumberOfVertices() == 1) return 0; for (int i = 0; i < polygon.getNumberOfVertices(); i++) Point2DReadOnly startVertex = polygon.getVertex(i); Point2DReadOnly endVertex = polygon.getNextVertex(i); if (polygon.getNumberOfVertices() == 2) return 0; edgeToPack1.set(polygon.getPreviousVertex(i), startVertex); edgeToPack2.set(endVertex, polygon.getNextVertex(polygon.getNextVertexIndex(i))); return 2;
/** * Finds the index of the closest vertex to the query. * <p> * Edge cases: * <ul> * <li>If the polygon has no vertices, this method fails and returns {@code false}. * </ul> * </p> * * @param point the coordinates of the query. Not modified. * @param vertexToPack point used to store the result. Modified. * @return whether this method succeeded or not. * @throws OutdatedPolygonException if {@link ConvexPolygon2DBasics#update()} has not been called * since last time this polygon's vertices were edited. */ default boolean getClosestVertex(Point2DReadOnly point, Point2DBasics vertexToPack) { int vertexIndex = getClosestVertexIndex(point); if (vertexIndex == -1) return false; vertexToPack.set(getVertex(vertexIndex)); return true; }
/** * Computes the coordinates of the possible intersection(s) between this line and the given convex * polygon 2D. * <p> * WARNING: This method generates garbage. * </p> * <p> * Edge cases: * <ul> * <li>If the polygon has no vertices, this method behaves as if there is no intersections and * returns {@code null}. * <li>If no intersections exist, this method returns {@code null}. * </ul> * </p> * * @param convexPolygon the convex polygon this line may intersect. Not modified. * @return the intersections between between the line and the polygon or {@code null} if the method * failed or if there is no intersections. * @throws OutdatedPolygonException if the convex polygon is not up-to-date. */ default Point2DBasics[] intersectionWith(ConvexPolygon2DReadOnly convexPolygon) { return convexPolygon.intersectionWith(this); }
/** * Finds the index of the closest vertex to the query. * <p> * Edge cases: * <ul> * <li>If the polygon has no vertices, this method fails and returns {@code -1}. * </ul> * </p> * * @param point the coordinates of 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(Point2DReadOnly point) { checkIfUpToDate(); return EuclidGeometryPolygonTools.closestVertexIndexToPoint2D(point, getVertexBufferView(), getNumberOfVertices()); }
/** * Adds a subset of this polygon's vertices into the given list. * <p> * The subset consists of the vertices from the vertex at {@code startIndexInclusive} to the * vertex {@code endIndexInclusive} while going from start to end in a clockwise order. * </p> * * @param startIndexInclusive the index of the first vertex to add. * @param endIndexInclusive the index of the last vertex to add. * @param pointListToPack the list into which the vertices are to be added. * @throws OutdatedPolygonException if {@link ConvexPolygon2DBasics#update()} has not been called * since last time this polygon's vertices were edited. * @throws EmptyPolygonException if this polygon is empty when calling this method. */ default void getPointsInClockwiseOrder(int startIndexInclusive, int endIndexInclusive, List<Point2DReadOnly> pointListToPack) { checkIfUpToDate(); checkIndexInBoundaries(startIndexInclusive); checkIndexInBoundaries(endIndexInclusive); int index = startIndexInclusive; while (true) { pointListToPack.add(getVertex(index)); if (index == endIndexInclusive) break; index = getNextVertexIndex(index); } }
/** * Uses the fact that if a line passes through a vertex of a convex polygon, the angles to the * adjacent edges are going to be in opposite directions * * @return Whether or not the line including the point and vertex is tangent to the polygon */ private boolean pointMakesTangentToPolygon(ConvexPolygon2DReadOnly polygon, Point2DReadOnly point, int vertexIndex, double epsilon) { Point2DReadOnly vertex = polygon.getVertex(vertexIndex); Point2DReadOnly previous = polygon.getPreviousVertex(vertexIndex); Point2DReadOnly next = polygon.getNextVertex(vertexIndex); base.set(point.getX() - vertex.getX(), point.getY() - vertex.getY()); first.set(previous.getX() - vertex.getX(), previous.getY() - vertex.getY()); second.set(next.getX() - vertex.getX(), next.getY() - vertex.getY()); double firstAngle = base.angle(first); double secondAngle = base.angle(second); if (firstAngle * secondAngle >= 0) { // if both angles have the same sign, the line does not pass through the polygon return true; } if (MathTools.epsilonEquals(firstAngle, 0, epsilon) || MathTools.epsilonEquals(secondAngle, 0, epsilon)) { // if either angle is close to 0, assume floating point arithmetic error return true; } return false; }
checkIfUpToDate(); int lineOfSightEndIndex = lineOfSightEndIndex(observer); endVertexToPack.set(getVertex(lineOfSightEndIndex));
/** {@inheritDoc} */ @Override default FramePoint2DReadOnly getVertex(int index) { return (FramePoint2DReadOnly) ConvexPolygon2DReadOnly.super.getVertex(index); }
/** * Tests whether this polygon is empty, i.e. it has no vertices. * * @return {@code true} if this polygon is empty, {@code false} otherwise. */ default boolean isEmpty() { return getNumberOfVertices() == 0; }
int numberOfVertices = convexPolygon2d.getNumberOfVertices(); if (DEBUG) System.out.println(convexPolygon2d.getVertexCCW(i)); double V0x = convexPolygon2d.getVertexCCW(i).getX(); double V0y = convexPolygon2d.getVertexCCW(i).getY(); if (DEBUG) double V1x = convexPolygon2d.getNextVertexCCW(i).getX(); double V1y = convexPolygon2d.getNextVertexCCW(i).getY(); if (DEBUG)
/** * Gets the index of the vertex located after the vertex at the index {@code currentVertexIndex} * in the list of vertices. * <p> * Note that this polygon's vertices are clockwise ordered and that the first vertex has the * lowest x-coordinate. * </p> * * @param currentVertexIndex the current vertex index. * @return the next vertex index. * @throws OutdatedPolygonException if {@link ConvexPolygon2DBasics#update()} has not been called * since last time this polygon's vertices were edited. * @throws IndexOutOfBoundsException if the given {@code index} is negative or greater or equal * than this polygon's number of vertices. * @throws EmptyPolygonException if this polygon is empty when calling this method. */ default int getNextVertexIndex(int currentVertexIndex) { checkIfUpToDate(); checkIndexInBoundaries(currentVertexIndex); checkNonEmpty(); if (currentVertexIndex < getNumberOfVertices() - 1) return currentVertexIndex + 1; else return 0; }