public static Set<ConcaveHullPocket> findConcaveHullPockets(List<? extends Point2DReadOnly> concaveHullVertices, double depthThreshold) { Set<ConcaveHullPocket> pockets = new HashSet<>(); int startIndex = 0; while (startIndex < concaveHullVertices.size()) { ConcaveHullPocket newPocket = findFirstConcaveHullPocket(concaveHullVertices, startIndex); if (newPocket == null) break; if (newPocket.getMaxDepth() >= depthThreshold) { if (!pockets.add(newPocket)) break; } startIndex = newPocket.getEndBridgeIndex() + 1; } return pockets; }
/** * Find the deepest vertex in the given pocket. It updates {@link ConcaveHullPocket} fields * accordingly. The bridge indices are required to call this method. * * @param pocketToModify * @param concaveHullVertices * @return */ public static boolean findDeepestVertexInPocket(ConcaveHullPocket pocketToModify, List<? extends Point2DReadOnly> concaveHullVertices) { pocketToModify.clearDepthParameters(); int startBridgeIndex = pocketToModify.getStartBridgeIndex(); int endBridgeIndex = pocketToModify.getEndBridgeIndex(); Point2DReadOnly startBridgeVertex = concaveHullVertices.get(startBridgeIndex); Point2DReadOnly endBridgeVertex = concaveHullVertices.get(endBridgeIndex); for (int index = next(startBridgeIndex, concaveHullVertices); index != endBridgeIndex; index = next(index, concaveHullVertices)) { Point2DReadOnly vertex = concaveHullVertices.get(index); double depth = EuclidGeometryTools.distanceFromPoint2DToLine2D(vertex, startBridgeVertex, endBridgeVertex); if (depth > pocketToModify.getMaxDepth()) { pocketToModify.setDeepestVertexIndex(index); pocketToModify.setDeepestVertex(vertex); pocketToModify.setMaxDepth(depth); } } return pocketToModify.getDeepestVertexIndex() >= 0; }
if (pocket.getMaxDepth() < depthThreshold) removeAllExclusive(startBridgeIndex, endBridgeIndex, concaveHullVertices); else
public static int flattenShallowPockets(double depthThreshold, List<Point2D> concaveHullVerticesToFilter) { int numberOfVerticesRemoved = 0; ConcaveHullPocket pocket = new ConcaveHullPocket(); Vector2D shift = new Vector2D(); for (int currentIndex = 0; currentIndex < concaveHullVerticesToFilter.size(); currentIndex++) { if (isConvexAtVertex(currentIndex, concaveHullVerticesToFilter)) continue; boolean success = computeConcaveHullPocket(currentIndex, pocket, concaveHullVerticesToFilter); if (!success) continue; double maxDepth = pocket.getMaxDepth(); if (maxDepth > depthThreshold) continue; Point2D startBridgeVertex = new Point2D(pocket.getStartBridgeVertex()); Point2D endBridgeVertex = new Point2D(pocket.getEndBridgeVertex()); shift.sub(endBridgeVertex, startBridgeVertex); shift.normalize(); // Rotate to the right shift.set(shift.getY(), -shift.getX()); shift.scale(maxDepth); startBridgeVertex.add(shift); endBridgeVertex.add(shift); int startBridgeVertexIndex = pocket.getStartBridgeIndex(); int endBridgeVertexIndex = pocket.getEndBridgeIndex(); numberOfVerticesRemoved += removeAllExclusive(startBridgeVertexIndex, endBridgeVertexIndex, concaveHullVerticesToFilter); } return numberOfVerticesRemoved; }