From 667b466ca7c71a5bde5be59ec29ecce8cbddfafb Mon Sep 17 00:00:00 2001
From: Michael Carleton
Date: Fri, 14 Feb 2025 14:16:40 +0000
Subject: [PATCH] assorted
---
CHANGELOG.md | 1 +
src/main/java/micycle/pgs/PGS_Conversion.java | 2 +-
src/main/java/micycle/pgs/PGS_PointSet.java | 20 ++++++++++++++++++-
.../java/micycle/pgs/PGS_ShapePredicates.java | 14 ++++++++++++-
.../java/micycle/pgs/commons/ChaikinCut.java | 4 ++--
5 files changed, 36 insertions(+), 5 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8a5dde73..170cc09a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* `maximumInscribedTriangle()` to `PGS_Optimisation`. Finds an approximate largest area triangle (of arbitrary orientation) contained within a polygon.
* `closestPoint()` to `PGS_Optimisation`. Finds the closest point in a collection of points to a specified point.
* `distanceTree()` to `PGS_Contour`. Generates a tree structure representing the shortest paths from a start point to all other vertices in a mesh.
+* `vertexCount()` to `PGS_ShapePredicates`. Returns the total number of vertices that make up a shape.
### Changes
* Optimised `PGS_CirclePacking.tangencyPack()`. It's now around 1.5-2x faster and has higher precision.
diff --git a/src/main/java/micycle/pgs/PGS_Conversion.java b/src/main/java/micycle/pgs/PGS_Conversion.java
index 109e47e3..aead2bb2 100644
--- a/src/main/java/micycle/pgs/PGS_Conversion.java
+++ b/src/main/java/micycle/pgs/PGS_Conversion.java
@@ -1504,7 +1504,7 @@ public static PShape fromArray(double[][] shape, boolean close) {
/**
* Flattens a collection of PShapes into a single GROUP PShape which has the
* input shapes as its children. If the collection contains only one shape, it
- * is directly returned.
+ * is returned directly as a non-GROUP shape.
*
* @since 1.2.0
* @see #flatten(PShape...)
diff --git a/src/main/java/micycle/pgs/PGS_PointSet.java b/src/main/java/micycle/pgs/PGS_PointSet.java
index 76b48372..f7cae32a 100644
--- a/src/main/java/micycle/pgs/PGS_PointSet.java
+++ b/src/main/java/micycle/pgs/PGS_PointSet.java
@@ -43,9 +43,27 @@
* Generation of random sets of 2D points having a variety of different
* distributions and constraints (and associated functions).
*
+ *
+ * Note on Floating-Point Values and Collisions:
+ *
+ *
+ * When generating many random points, collisions in coordinate values are
+ * expected due to the limited precision of floating-point numbers. For example:
+ *
+ * - A {@code float} has ~24 bits of precision (23 explicit mantissa bits + 1
+ * implicit leading bit), which allows for ~16.8 million unique values in the
+ * range [0, 1).
+ * - When generating a large number of points (e.g., 100,000), the probability
+ * of collisions follows the birthday paradox formula:
n² / (2m)
,
+ * where n
is the number of samples and m
is the
+ * number of possible unique values.
+ * - For 100,000 points, this results in ~300 expected collisions in the
+ * x-coordinate, even when using a high-quality random number generator.
+ *
+ *
+ *
* @author Michael Carleton
* @since 1.2.0
- *
*/
public final class PGS_PointSet {
diff --git a/src/main/java/micycle/pgs/PGS_ShapePredicates.java b/src/main/java/micycle/pgs/PGS_ShapePredicates.java
index 39383651..9c3e69c9 100644
--- a/src/main/java/micycle/pgs/PGS_ShapePredicates.java
+++ b/src/main/java/micycle/pgs/PGS_ShapePredicates.java
@@ -453,6 +453,18 @@ public static double convexity(PShape shape) {
return g.getArea() / g.convexHull().getArea();
}
+ /**
+ * Returns the total number of vertices that make up a shape.
+ *
+ * Unlike PShape.getVertexCount()
this method properly returns the
+ * number of vertices in GROUP and primitive shapes.
+ *
+ * @since 2.1
+ */
+ public static int vertexCount(PShape shape) {
+ return fromPShape(shape).getNumPoints();
+ }
+
/**
* Counts the number of holes in a shape.
*
@@ -514,7 +526,7 @@ public static double maximumInteriorAngle(PShape shape) {
}
/**
- * Calculates the interior angles of a polygon represented by a {@link PShape}.
+ * Calculates all interior angles of a polygon represented by a {@link PShape}.
* The method calculates the interior angle at each vertex.
*
* The vertices of the input {@code shape} are assumed to represent a simple
diff --git a/src/main/java/micycle/pgs/commons/ChaikinCut.java b/src/main/java/micycle/pgs/commons/ChaikinCut.java
index 94fe5b09..514e0b2a 100644
--- a/src/main/java/micycle/pgs/commons/ChaikinCut.java
+++ b/src/main/java/micycle/pgs/commons/ChaikinCut.java
@@ -154,14 +154,14 @@ private static ArrayList chaikinCut(PVector a, PVector b, float ratio)
/**
* Determines whether to cut an edge. Returns false for edges with a euclidean
- * distance less than 1.0.
+ * distance less than 0.5.
*/
private static boolean cut(PVector a, PVector b) {
// TODO expand to exclude almost coincident edge pairs
final float dx = b.x - a.x;
final float dy = b.y - a.y;
final float d2 = dx * dx + dy * dy;
- return d2 > 1;
+ return d2 > 0.5;
}
}