/** * 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; }
public ConcaveHullPocket() { clear(); }
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; }
int startBridgeIndex = pocket.getStartBridgeIndex(); int endBridgeIndex = pocket.getEndBridgeIndex(); if (pocket.getMaxDepth() < depthThreshold) removeAllExclusive(startBridgeIndex, endBridgeIndex, concaveHullVertices); else int deepestVertexIndex = pocket.getDeepestVertexIndex(); Vector2D cutDirection = new Vector2D(); Point2DReadOnly endBridgeVertex = pocket.getEndBridgeVertex(); Point2DReadOnly startBridgeVertex = pocket.getStartBridgeVertex(); cutDirection.sub(endBridgeVertex, startBridgeVertex); cutDirection.normalize(); Point2DReadOnly deepestVertex = pocket.getDeepestVertex(); int startBridgeIndex = pocket.getStartBridgeIndex(); int endBridgeIndex = pocket.getEndBridgeIndex();
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; }
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; }
ConcaveHullPocket pocket = new ConcaveHullPocket(); pocket.setBridgeIndices(startBridgeConcaveIndex, endBridgeConcaveIndex); pocket.setBridgeVertices(firstBridgeVertex, secondBridgeVertex); pocket.setMaxDepth(pocketMaxDepth); pocket.setDeepestVertex(concaveHullVertices.get(deepestPocketVertexIndex)); pocket.setDeepestVertexIndex(deepestPocketVertexIndex);
public void clear() { startBridgeIndex = -1; endBridgeIndex = -1; startBridgeVertex = null; endBridgeVertex = null; clearDepthParameters(); }
public static ConcaveHullPocket computeConcaveHullPocket(int concaveVertexIndex, List<? extends Point2DReadOnly> concaveHullVertices) { ConcaveHullPocket pocketToReturn = new ConcaveHullPocket(); boolean success = findBridgeVertices(concaveVertexIndex, pocketToReturn, concaveHullVertices); if (!success) return null; success = findDeepestVertexInPocket(pocketToReturn, concaveHullVertices); if (!success) return null; return pocketToReturn; }
public static boolean computeConcaveHullPocket(int concaveVertexIndex, ConcaveHullPocket pocketToPack, List<? extends Point2DReadOnly> concaveHullVertices) { pocketToPack.clear(); boolean success = findBridgeVertices(concaveVertexIndex, pocketToPack, concaveHullVertices); if (!success) { pocketToPack.clear(); return false; } success = findDeepestVertexInPocket(pocketToPack, concaveHullVertices); if (!success) { pocketToPack.clear(); return false; } return true; }