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; }
int endBridgeIndex = pocket.getEndBridgeIndex(); int endBridgeIndex = pocket.getEndBridgeIndex();
private Node createConcavePocketsGraphics(PlanarRegionSegmentationRawData rawData, ConcaveHullFactoryResult concaveHullFactoryResult) { JavaFXMeshBuilder meshBuilder = new JavaFXMeshBuilder(); ConcaveHullCollection concaveHullCollection = concaveHullFactoryResult.getConcaveHullCollection(); RigidBodyTransform transform = rawData.getTransformFromLocalToWorld(); for (ConcaveHull concaveHull : concaveHullCollection) { Set<ConcaveHullPocket> pockets = concaveHull.findConcaveHullPockets(polygonizerParameters.getDepthThreshold()); for (ConcaveHullPocket pocket : pockets) { List<Point2D> pocketVertices = ListWrappingIndexTools.subListInclusive(pocket.getStartBridgeIndex(), pocket.getEndBridgeIndex(), concaveHull.getConcaveHullVertices()); Point2D average = new Point2D(); average.interpolate(pocket.getStartBridgeVertex(), pocket.getEndBridgeVertex(), 0.5); pocketVertices.add(0, average); ConcaveHullTools.ensureClockwiseOrdering(pocketVertices); meshBuilder.addPolygon(transform, pocketVertices); } } MeshView meshView = new MeshView(meshBuilder.generateMesh()); meshView.setMaterial(new PhongMaterial(OcTreeMeshBuilder.getRegionColor(rawData.getRegionId()))); return meshView; }
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; }