diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8e8a0277..48d3b1a8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## **2.0** *(2024-08-xx)*
+**Version 2 is built with Java 17**
+
### Added
* `findShortestTour()` to `PGS_PointSet`. Computes an approximate Traveling Salesman path for a set of points.
* `pruneSparsePoints()` to `PGS_PointSet`. Prunes a list of points by removing points that are considered not sufficiently dense (far away from their nearest neighbours); a counterpart to `prunePointsWithinDistance()`.
@@ -16,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* `fix()` to `PGS_Processing`. Attempts to fix shapes with invalid geometry.
* Additional method signature for `frontChainPack()` that accepts a random seed.
* `isClockwise()` to `PGS_ShapePredicates`. Determines if the vertices of the specified shape form a clockwise loop.
+* `extractInnerVertices()` to `PGS_Meshing`. Extracts all inner vertices from a mesh.
### Changes
* Packed circles from `PGS_CirclePacking.stochasticPack()` will now always lie within shape bounds.
diff --git a/README.md b/README.md
index c85c6ee1..125d5406 100644
--- a/README.md
+++ b/README.md
@@ -546,6 +546,13 @@ Much of the functionality (but by no means all) is demonstrated below:
|
|
+
+
+ Extract Inner Vertices |
+
+
+ |
+
## *Geometric Optimisation*
diff --git a/resources/meshing/extractInnerVertices.gif b/resources/meshing/extractInnerVertices.gif
new file mode 100644
index 00000000..76f94835
Binary files /dev/null and b/resources/meshing/extractInnerVertices.gif differ
diff --git a/src/main/java/micycle/pgs/PGS_Meshing.java b/src/main/java/micycle/pgs/PGS_Meshing.java
index 070f7913..79026ec3 100644
--- a/src/main/java/micycle/pgs/PGS_Meshing.java
+++ b/src/main/java/micycle/pgs/PGS_Meshing.java
@@ -812,6 +812,25 @@ public static PShape extractInnerEdges(PShape mesh) {
return PGS_SegmentSet.dissolve(innerEdges);
}
+ /**
+ * Extracts the inner vertices from a mesh. Inner vertices are defined as
+ * vertices that are not part of the perimeter (nor holes) of the mesh.
+ *
+ * @param mesh The mesh shape to extract inner vertices from.
+ * @return A PShape object containing only the inner vertices of the original
+ * mesh.
+ * @since 2.0
+ */
+ public static List extractInnerVertices(PShape mesh) {
+ var allVertices = PGS_Conversion.toPVector(mesh);
+ var perimeterVertices = PGS_Conversion.toPVector(PGS_ShapeBoolean.unionMesh(mesh));
+ var allVerticesSet = new HashSet<>(allVertices);
+ var perimeterVerticesSet = new HashSet<>(perimeterVertices);
+
+ allVerticesSet.removeAll(perimeterVerticesSet);
+ return new ArrayList<>(allVerticesSet);
+ }
+
/**
* Merges the small faces within a mesh into their adjacent faces recursively,
* ensuring that no faces smaller than a specified area remain. This process is
@@ -867,8 +886,11 @@ public static PShape splitEdges(PShape split, int parts) {
return PGS.polygonizeEdges(splitEdges);
}
+ /**
+ * Applies the styling properties of oldMesh to newMesh.
+ */
private static PShape applyOriginalStyling(final PShape newMesh, final PShape oldMesh) {
- final PShapeData data = new PShapeData(oldMesh.getChild(0)); // use first child; assume global.
+ final PShapeData data = new PShapeData(oldMesh.getChildCount() > 0 ? oldMesh.getChild(0) : oldMesh); // note use first child
for (int i = 0; i < newMesh.getChildCount(); i++) {
data.applyTo(newMesh.getChild(i));
}