private static List<ConcaveHullVariables> computeConcaveHullBorderEdgesRecursive(ConcaveHullFactoryParameters parameters, List<ConcaveHullVariables> variables, MutableInt currentIteration) { List<ConcaveHullVariables> result = new ArrayList<>(); for (ConcaveHullVariables hullVariables : variables) { currentIteration.increment(); result.addAll(computeConcaveHullBorderEdgesRecursive(parameters, hullVariables, currentIteration)); } return result; }
/** * Computes the border edges {@link QuadEdge} that will define the concave hull. * This is an iterative process that starts a first guess of the concave hull, and then each iteration consists "breaking" edges that are too long according to the {@code edgeLengthThreshold}. * The algorithm is based on the <a href="https://en.wikipedia.org/wiki/Delaunay_triangulation"> Delaunay triangulation </a>. * @param edgeLengthThreshold maximum edge length the concave hull can have. * @param maxNumberOfIterations option to limit the maximum number of iterations of this algorithm. * @param removeAllTrianglesWithTwoBorderEdges when set to true, any triangle with two border edges with be removed regardless of the edges length. This tends to smoothen the resulting concave hull in general. * @param variables the set of variables pre-initialized used internally to find the border edges of the concave hull. * @return list of new intermediate variables containing the sets of edges defining the concave hull(s). */ private static List<ConcaveHullVariables> computeConcaveHullBorderEdgesRecursive(ConcaveHullFactoryParameters parameters, ConcaveHullVariables variables) { return computeConcaveHullBorderEdgesRecursive(parameters, variables, new MutableInt(0)); }
removeTriangleWithOneBorderEdge(variables, candidateEntry); currentIteration.increment(); return computeConcaveHullBorderEdgesRecursive(parameters, variables, currentIteration); case TWO_BORDER_EDGES_THREE_BORDER_VERTICES: removeTriangleWithTwoBorderEdges(variables, candidateEntry); currentIteration.increment(); return computeConcaveHullBorderEdgesRecursive(parameters, variables, currentIteration); case ONE_BORDER_EDGES_THREE_BORDER_VERTICES: return computeConcaveHullBorderEdgesRecursive(parameters, subVariablesList, currentIteration); return computeConcaveHullBorderEdgesRecursive(parameters, subVariablesList, currentIteration);
public static ConcaveHullFactoryResult createConcaveHull(List<Point2D> pointCloud2d, List<LineSegment2D> lineConstraints, ConcaveHullFactoryParameters parameters) { if (pointCloud2d.size() <= 3) return null; MultiPoint sites = filterAndCreateMultiPoint(pointCloud2d, lineConstraints, 0.01); MultiLineString constraintSegments = createMultiLineString(lineConstraints); ConcaveHullFactoryResult result = new ConcaveHullFactoryResult(); ConcaveHullVariables initialVariables = initializeTriangulation(sites, constraintSegments, result); List<ConcaveHullVariables> variablesList = computeConcaveHullBorderEdgesRecursive(parameters, initialVariables); result.intermediateVariables.addAll(variablesList); for (ConcaveHullVariables variables : result.intermediateVariables) { ConcaveHull concaveHull = computeConcaveHull(variables.getOrderedBorderEdges()); if (concaveHull != null) { concaveHull.ensureClockwiseOrdering(); result.concaveHullCollection.add(concaveHull); } } return result; }