|
17 | 17 |
|
18 | 18 | import javax.vecmath.Point3d;
|
19 | 19 |
|
| 20 | +import org.jgrapht.alg.interfaces.ShortestPathAlgorithm; |
| 21 | +import org.jgrapht.alg.shortestpath.BFSShortestPath; |
20 | 22 | import org.jgrapht.graph.DefaultEdge;
|
21 | 23 | import org.jgrapht.graph.SimpleGraph;
|
22 | 24 | import org.joml.Vector2d;
|
@@ -636,6 +638,55 @@ public static PShape distanceField(PShape shape, double spacing) {
|
636 | 638 | return i;
|
637 | 639 | }
|
638 | 640 |
|
| 641 | + /** |
| 642 | + * Generates a tree structure representing the shortest paths from a given start |
| 643 | + * point to all other vertices in the provided mesh. The paths are computed |
| 644 | + * using the existing connectivity of the mesh edges, ensuring that the |
| 645 | + * shortest-path tree respects the original mesh structure. The tree is |
| 646 | + * constructed using a Breadth-First Search (BFS) algorithm. |
| 647 | + * <p> |
| 648 | + * The shortest-path tree represents the minimal set of mesh edges required to |
| 649 | + * connect the start point to all other vertices in the mesh, following the |
| 650 | + * mesh's inherent connectivity. This ensures that the paths are constrained by |
| 651 | + * the mesh's topology rather than creating arbitrary connections between |
| 652 | + * vertices. |
| 653 | + * <p> |
| 654 | + * If the provided start point does not exactly match a vertex in the mesh, the |
| 655 | + * closest vertex in the mesh to the start point is used as the actual starting |
| 656 | + * point for the shortest-path computation. |
| 657 | + * |
| 658 | + * @param mesh A GROUP shape representing a mesh from which the graph is |
| 659 | + * constructed. The mesh defines the connectivity between |
| 660 | + * vertices via its edges. |
| 661 | + * @param startPoint The starting point from which the shortest paths are |
| 662 | + * calculated. If this point does not exactly match a vertex |
| 663 | + * in the mesh, the closest vertex in the mesh will be used as |
| 664 | + * the starting point. |
| 665 | + * @return A PShape object representing the tree of shortest paths from the |
| 666 | + * start point to all other vertices in the mesh. The paths are |
| 667 | + * visualized with a semi-transparent pink stroke and are constrained by |
| 668 | + * the mesh's edge connectivity. |
| 669 | + * @since 2.1 |
| 670 | + */ |
| 671 | + public static PShape distanceTree(PShape mesh, PVector source) { |
| 672 | + var g = PGS_Conversion.toGraph(mesh); |
| 673 | + ShortestPathAlgorithm<PVector, PEdge> spa = new BFSShortestPath<>(g); |
| 674 | + |
| 675 | + final PVector sourceActual = PGS_Optimisation.closestPoint(g.vertexSet(), source); |
| 676 | + var paths = spa.getPaths(sourceActual); |
| 677 | + |
| 678 | +// var edges = g.vertexSet().stream().filter(v -> !v.equals(sourceActual)) // Exclude the source vertex |
| 679 | +// .flatMap(v -> paths.getPath(v).getEdgeList().stream()) // Flatten the edge lists into a single stream |
| 680 | +// .collect(Collectors.toSet()); // Collect the edges into a Set to remove duplicates |
| 681 | + |
| 682 | + var pathLines = g.vertexSet().stream() // |
| 683 | + .filter(v -> v != sourceActual) // Exclude the source vertex |
| 684 | + .map(v -> PGS_Conversion.fromPVector(paths.getPath(v).getVertexList())).toList(); |
| 685 | + var group = PGS_Conversion.flatten(pathLines); |
| 686 | + PGS_Conversion.setAllStrokeColor(group, ColorUtils.setAlpha(Colors.PINK, 50), 2); |
| 687 | + return group; |
| 688 | + } |
| 689 | + |
639 | 690 | /**
|
640 | 691 | * Calculates the longest center line passing through a given shape (using
|
641 | 692 | * default straightness weighting and smoothing parameters).
|
|
0 commit comments