Skip to content

Commit ebfc670

Browse files
authored
merge v2.0!
PGS 2.0 (Java 17)
2 parents 28fe7a9 + d1ff743 commit ebfc670

File tree

72 files changed

+3359
-1186
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+3359
-1186
lines changed

CHANGELOG.md

+43
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,49 @@ All notable changes to PGS will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Dates are *YYYY-MM-DD*.
77

8+
## **2.0** *(2024-08-xx)*
9+
10+
**NOTE: Beginning at v2.0, PGS is built with Java 17.**
11+
12+
### Added
13+
* `findShortestTour()` to `PGS_PointSet`. Computes an <i>approximate</i> Traveling Salesman path for a set of points.
14+
* `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()`.
15+
* Additional method signature for `PGS_Morphology.variableBuffer()` that accepts a callback function to define the buffer value at each vertex.
16+
* `boundsCenter()` to `PGS_Transformation`. Computes the center of the bounding box of a shape.
17+
* Additional method signature for `delaunayTriangulation(points)` that supports a boundary constraint.
18+
* `fix()` to `PGS_Processing`. Attempts to fix shapes with invalid geometry.
19+
* Additional method signature for `frontChainPack()` that accepts a random seed.
20+
* `isClockwise()` to `PGS_ShapePredicates`. Determines if the vertices of the specified shape form a clockwise loop.
21+
* `extractInnerVertices()` to `PGS_Meshing`. Extracts all inner vertices from a mesh.
22+
* `thomasClusters()` to `PGS_PointSet`. Generates random points having clustered properties using the Thomas Point Process.
23+
* `transform()` and `transformWithIndex()`* to `PGS_Processing`. Applies a specified transformation function to each child of the given PShape and returns a new PShape containing the transformed children (*additionally with child's index).
24+
* `apply()` and `applyWithIndex()`* to `PGS_Processing`. Applies a specified function to each child of the given PShape (*additionally with child's index).
25+
* `toContours()` to `PGS_Conversion`. Extracts the contours from a POLYGON or PATH PShape, represented as lists of PVector points.
26+
* `segmentsOnExterior()` to `PGS_Processing`. Extracts evenly spaced dashed line segments along the perimeter of a shape.
27+
* `multiplicativelyWeightedVoronoi()` to `PGS_Voronoi `. Generates a Multiplicatively Weighted Voronoi Diagrams diagram for a set of weighted sites.
28+
* `applyRandomWeights()` to `PGS_PointSet`. Applies random weights within a specified range to a list of points.
29+
* `findContainingFace()` to `PGS_Meshing`. Finds the single face from the mesh that contains the query point.
30+
* `findBreaks()` to `PGS_Meshing`. Returns the locations of invalid mesh face boundary segments if found.
31+
* `pinchWarp()` to `PGS_Morphology`. Applies a pinch warping effect to a shape, distorting vertices towards a specified point.
32+
33+
### Changes
34+
* Packed circles from `PGS_CirclePacking.stochasticPack()` will now always lie within shape bounds.
35+
* `PGS_Processing.pointsOnExterior()` methods now respect GROUP shapes and holes (inner rings) and will populate them with points.
36+
* `PGS_Morphology.simplifyDCE()` now supports GROUP shapes and polygon holes.
37+
* `PGS_Morphology.interpolate()` is much faster on shapes with many vertices.
38+
* Removed superfluous `height` argument from `PGS.createSupercircle()` method signature.
39+
* Renamed `fromPVector(shell, holes)` in `PGS_Conversion` to `fromContours(shell, holes)`.
40+
* Moved `PGS_Processing.cleanCoverage()` to `PGS_Meshing` and renamed to `fixBreaks()`.
41+
42+
### Fixed
43+
* `urquhartFaces()`, `relativeNeighborFaces()`, `gabrielFaces()` and `spannerFaces()` from `PGS_Meshing` now preserve holes from the input.
44+
* The output of `PGS_Morphology.smoothGaussian()` is no longer (slightly) affected by the vertex ordering of the input.
45+
* The `transform` and `reference` arguments for `PGS_Transformation.align()` were the wrong way round.
46+
47+
### Removed
48+
* `simplifyDCE(shape, targetNumVertices)` and `simplifyDCE(shape, vertexRemovalFraction)` in favour a single method that accepts a user-defined termination callback that is supplied with the current vertex candidate's coordinate, relevance score, and the number of vertices remaining.
49+
50+
851
## **1.4.0** *(2023-07-29)*
952

1053
### Added

README.md

+47-20
Original file line numberDiff line numberDiff line change
@@ -13,41 +13,41 @@ Docs are hosted via *GitHub Pages* [here](https://micycle1.github.io/PGS/).
1313
Library functionality is split over the following classes:
1414

1515
* `PGS_CirclePacking`
16-
* Circle packings of shapes, subject to varying constraints and patterns of tangencies
16+
* Circle packings of shapes, subject to varying constraints and patterns of tangencies.
1717
* `PGS_Coloring`
18-
* Minimal colorings of meshes (or mesh-like shapes)
18+
* Minimal colorings of meshes (or mesh-like shapes).
1919
* `PGS_Construction`
20-
* Construct uncommon/interesting 2D primitives
20+
* Construct uncommon/interesting 2D primitives.
2121
* `PGS_Contour`
2222
* Methods that produce various contours from shapes: medial axes, straight skeletons, offset curves, etc.
2323
* `PGS_Conversion`
2424
* Conversion between *Processing* PShapes and *JTS* Geometries (amongst other formats)
2525
* `PGS_Hull`
26-
* Convex and concave hulls of polygons and point sets
26+
* Convex and concave hulls of polygons and point sets.
2727
* `PGS_Meshing`
28-
* Mesh generation (excluding triangulation) and processing
28+
* Mesh generation (excluding triangulation) and processing.
2929
* `PGS_Morphology`
30-
* Methods that affect the geometry or topology of shapes (buffering, simplification, smoothing, etc.)
30+
* Methods that affect the geometry or topology of shapes (buffering, simplification, smoothing, etc.).
3131
* `PGS_Optimisation`
32-
* Solve geometric optimisation problems, such as finding the maximum inscribed circle, or the closest vertex to a coordinate
32+
* Solve geometric optimisation problems, such as finding the maximum inscribed circle, or the closest vertex to a coordinate.
3333
* `PGS_PointSet`
34-
* Generates sets of 2D points having a variety of different distributions and constraints
34+
* Generates sets of 2D points having a variety of different distributions and constraints.
3535
* `PGS_Processing`
36-
* Methods that process a shape in some way: compute hulls, partition, slice, etc.
36+
* Methods that process a shape in some way: partition, slice, clean, etc.
3737
* `PGS_SegmentSet`
38-
* Generates sets of random non-intersecting line segments
38+
* Generates sets of random non-intersecting line segments.
3939
* `PGS_ShapeBoolean`
40-
* Boolean set-operations for 2D shapes
40+
* Boolean set-operations for 2D shapes.
4141
* `PGS_ShapePredicates`
42-
* Various shape metrics (area, circularity, etc.) and predicates (*"do these shapes intersect?"*)
42+
* Various shape metrics (area, circularity, etc.) and predicates (*"do these shapes intersect?"*).
4343
* `PGS_Tiling`
4444
* Tiling, tessellation and subdivision of the plane using periodic or non-periodic geometric shapes.
4545
* `PGS_Transformation`
46-
* Various geometric and affine transformations that affect vertex coordinates
46+
* Various geometric and affine transformations that affect vertex coordinates.
4747
* `PGS_Triangulation`
48-
* Delaunay triangulation (constrained and refined) and earcut triangulation of shapes and point sets
48+
* Delaunay triangulation (constrained and refined) and earcut triangulation of shapes and point sets.
4949
* `PGS_Voronoi`
50-
* Voronoi Diagrams of shapes and point sets
50+
* Voronoi Diagrams of shapes and point sets.
5151

5252
## **Installation**
5353

@@ -314,6 +314,13 @@ Much of the functionality (but by no means all) is demonstrated below:
314314
<td valign="top" width="25%"><img src="resources/morphology/hobbySimplify.gif"></td>
315315
<td valign="top" width="25%"><img src="resources/morphology/ellipticFourierSmooth.gif"></td>
316316
</tr>
317+
318+
<tr>
319+
<td align="center" valign="center"><b>Pinch Warp</td>
320+
</tr>
321+
<tr>
322+
<td valign="top" width="25%"><img src="resources/morphology/pinchWarp.gif"></td>
323+
</tr>
317324
</table>
318325

319326
## *Hull*
@@ -357,8 +364,8 @@ Much of the functionality (but by no means all) is demonstrated below:
357364
<td align="center" valign="center"><b>Perimeter Extraction</td>
358365
</tr>
359366
<tr>
360-
<td valign="top" width="25%"><img src="resources/geometry_processing/pointsOnPerimeter.gif"></td>
361367
<td valign="top" width="25%"><img src="resources/geometry_processing/pointsOnPerimeter2.gif"></td>
368+
<td valign="top" width="25%"><img src="resources/geometry_processing/pointsOnPerimeter.gif"></td>
362369
<td valign="top" width="25%"><img src="resources/geometry_processing/pointOnPerimeter.gif"></td>
363370
<td valign="top" width="25%"><img src="resources/geometry_processing/perimeterExtract.gif"></td>
364371
</tr>
@@ -425,18 +432,19 @@ Much of the functionality (but by no means all) is demonstrated below:
425432
<td align="center" valign="center"><b>Densification</td>
426433
<td align="center" valign="center"><b>Tangent Angle</td>
427434
<td align="center" valign="center"><b>Eliminate Slivers</td>
428-
<td align="center" valign="center"><b>Clean Coverage</td>
435+
<td align="center" valign="center"><b>Segments on Exterior</td>
429436
</tr>
430437
<tr>
431438
<td valign="top" width="25%"><img src="resources/geometry_processing/densify.gif"></td>
432439
<td valign="top" width="25%"><img src="resources/geometry_processing/tangentAngle.png"></td>
433440
<td valign="top" width="25%"><img src="resources/morphology/slivers.gif"></td>
434-
<td valign="top" width="25%"><img src="resources/geometry_processing/cleanCoverage.gif"></td>
441+
<td valign="top" width="25%"><img src="resources/geometry_processing/linesOnExterior.gif"></td>
435442
</tr>
436443
</tr>
437444
<tr>
438445
<td align="center" valign="center"><b>Extract Holes</td>
439446
<td align="center" valign="center"><b>Nest</td>
447+
440448
</tr>
441449
<tr>
442450
<td valign="top" width="25%"><img src="resources/geometry_processing/extractHoles.gif"></td>
@@ -485,9 +493,11 @@ Much of the functionality (but by no means all) is demonstrated below:
485493
</tr>
486494
<tr>
487495
<td align="center" valign="center"><b>Centroidal Relaxation</td>
496+
<td align="center" valign="center"><b>Multiplicatively Weighted Voronoi</td>
488497
</tr>
489498
<tr>
490499
<td valign="top" width="25%"><img src="resources/voronoi/centroidal.gif"></td>
500+
<td valign="top" width="25%"><img src="resources/voronoi/mwvd.gif"></td>
491501
</tr>
492502
</table>
493503

@@ -546,6 +556,15 @@ Much of the functionality (but by no means all) is demonstrated below:
546556
<td valign="top" width="25%"><img src="resources/meshing/areaMerge.gif"></td>
547557
<td valign="top" width="25%"><img src="resources/meshing/innerEdges.gif"></td>
548558
</tr>
559+
560+
<tr>
561+
<td align="center" valign="center"><b>Extract Inner Vertices</td>
562+
<td align="center" valign="center"><b>Fix Breaks</td>
563+
</tr>
564+
<tr>
565+
<td valign="top" width="25%"><img src="resources/meshing/extractInnerVertices.gif"></td>
566+
<td valign="top" width="25%"><img src="resources/geometry_processing/cleanCoverage.gif"></td>
567+
</tr>
549568
</table>
550569

551570
## *Geometric Optimisation*
@@ -831,25 +850,33 @@ Much of the functionality (but by no means all) is demonstrated below:
831850
<tr>
832851
<td align="center" valign="center"><b>Sobol LDS</td>
833852
<td align="center" valign="center"><b>N-Rooks LDS</td>
834-
<td align="center" valign="center"><b>Distance Prune</td>
853+
<td align="center" valign="center"><b>Thomas Clusters</td>
835854
<td align="center" valign="center"><b>Hilbert Sort</td>
836855
</tr>
837856
<tr>
838857
<td valign="top" width="25%"><img src="resources/point_set/sobolLDS.gif"></td>
839858
<td valign="top" width="25%"><img src="resources/point_set/nRooksLDS.png"></td>
840-
<td valign="top" width="25%"><img src="resources/point_set/removeWithinDistance.gif"></td>
859+
<td valign="top" width="25%"><img src="resources/point_set/thomas.gif"></td>
841860
<td valign="top" width="25%"><img src="resources/point_set/hilbertSort.gif"></td>
842861
</tr>
843862
<tr>
844863
<td align="center" valign="center"><b>EMST</td>
864+
<td align="center" valign="center"><b>Shortest Tour (TSP)</td>
845865
<td align="center" valign="center"><b>Cluster</td>
846866
<td align="center" valign="center"><b>Weighted Median</td>
847867
</tr>
848868
<tr>
849869
<td valign="top" width="25%"><img src="resources/point_set/emst.png"></td>
870+
<td valign="top" width="25%"><img src="resources/point_set/tsp.png"></td>
850871
<td valign="top" width="25%"><img src="resources/point_set/cluster.png"></td>
851872
<td valign="top" width="25%"><img src="resources/point_set/weightedMedian.png"></td>
852873
</tr>
874+
<tr>
875+
<td align="center" valign="center"><b>Distance Prune</td>
876+
</tr>
877+
<tr>
878+
<td valign="top" width="25%"><img src="resources/point_set/removeWithinDistance.gif"></td>
879+
</tr>
853880
</table>
854881

855882
## *Segment Sets*

examples/contourMap/contourMap.pde

+5-4
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ List<PVector> heights;
99
float max = -1, min = 9999;
1010
UniformNoise noise;
1111

12-
final int RESOLUTION = 16; // lower is more resolution
12+
final int RESOLUTION = 15; // lower is more resolution
1313

1414
void setup() {
15-
size(800, 800, FX2D);
15+
size(1000, 1000, FX2D);
1616
smooth();
1717
noise = new UniformNoise();
1818
}
@@ -30,6 +30,7 @@ void draw() {
3030
map(isoline.getVertex(0).x, 0, width, 50, 255),
3131
map(isoline.getVertex(0).y, 0, height, 50, 255)
3232
));
33+
isoline.setStrokeWeight(3);
3334
shape(isoline);
3435
}
3536
}
@@ -39,8 +40,8 @@ void populateHeightMap() {
3940

4041
final float animSpeed = 0.005;
4142

42-
for (int x = 0; x <= width; x+=RESOLUTION) {
43-
for (int y = 0; y <= height; y+=RESOLUTION) {
43+
for (int x = 0; x <= width+RESOLUTION; x+=RESOLUTION) {
44+
for (int y = 0; y <= height+RESOLUTION; y+=RESOLUTION) {
4445
float z = noise.uniformNoise(x*0.0055 + frameCount*animSpeed, y*0.0055 + frameCount*animSpeed, 2, 0.5);
4546
PVector h = new PVector(x, y, 0);
4647

examples/drawOffsetCurves/drawOffsetCurves.pde

+12-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ PShape shape;
66
boolean inward = true;
77

88
void setup() {
9-
size(800, 800, FX2D);
9+
size(1000, 1000, FX2D);
1010
smooth();
1111
textAlign(CENTER, CENTER);
1212

@@ -29,7 +29,8 @@ void draw() {
2929

3030
colorMode(HSB, 1);
3131
for (int i = 0; i < offsetCurves.getChildCount(); i++) {
32-
offsetCurves.getChild(i).setStroke(color((float) mouseY/height, ((float) i / (offsetCurves.getChildCount()-1)) + 0.1, 1));
32+
color c = color((float) mouseY/height, ((float) i / (offsetCurves.getChildCount()-1)) + 0.1, 1);
33+
PGS_Conversion.setAllStrokeColor(offsetCurves.getChild(i), c, 2);
3334
}
3435
colorMode(RGB, 255);
3536

@@ -38,13 +39,19 @@ void draw() {
3839
textSize(36);
3940
text("Use mouse to draw!", width/2, height/2);
4041
textSize(14);
41-
text("Press any key to switch between inward/outward style.", width/2, height/2 + 30);
42+
text("LEFT mouse = add; RIGHT mouse = subtract.", width/2, height/2 + 30);
43+
text("Press any key to switch between inward/outward style.", width/2, height/2 + 60);
4244
}
4345
}
4446

4547
void mouseDragged() {
46-
shape = PGS_ShapeBoolean.union(shape, createShape(ELLIPSE, mouseX, mouseY, 100, 100));
47-
shape = PGS_Morphology.simplify(shape, 1);
48+
if (mouseButton == LEFT) {
49+
shape = PGS_ShapeBoolean.union(shape, createShape(ELLIPSE, mouseX, mouseY, 75, 75));
50+
} else if (mouseButton == RIGHT) {
51+
shape = PGS_ShapeBoolean.subtract(shape, createShape(ELLIPSE, mouseX, mouseY, 75, 75));
52+
}
53+
shape = PGS_Morphology.simplify(shape, 0.1);
54+
PGS_Conversion.setAllFillColor(shape, 255);
4855
PGS_Conversion.disableAllStroke(shape);
4956
}
5057

examples/ripplingTriangles/ripplingTriangles.pde

+32-8
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,32 @@ import java.util.List;
33
import micycle.pgs.*;
44
import micycle.uniformnoise.*;
55
import java.util.concurrent.atomic.AtomicInteger;
6+
import net.jafama.FastMath;
7+
68

79
PShape triangles; // triangle lattice arranged in a hexagon pattern
810
boolean warp = true;
911
UniformNoise noise;
1012

1113
void setup() {
12-
size(800, 800, FX2D);
14+
size(1000, 1000, FX2D);
1315
smooth();
1416
textAlign(LEFT, TOP);
1517

1618
noise = new UniformNoise(1337);
17-
triangles = PGS_Triangulation.delaunayTriangulation(PGS_PointSet.hexagon(width/2, height/2, 9, 45));
19+
triangles = PGS_Triangulation.delaunayTriangulation(PGS_PointSet.hexagon(width/2, height/2, 19, 30));
1820
triangles = PGS_Morphology.buffer(triangles, -2);
1921
frameRate(600);
2022
}
2123

2224
void draw() {
2325
colorMode(RGB, 255, 255, 255, 255);
24-
background(0, 0, 40);
26+
//background(0, 0, 40);
27+
fill(0,0,40,33);
28+
rect(0,0,width,height);
2529

2630
fill(0, 255, 255);
27-
text(frameRate, 2, 2); // fps
31+
//text(frameRate, 2, 2); // fps
2832

2933
colorMode(HSB, 1, 1, 1, 1);
3034

@@ -41,12 +45,13 @@ void draw() {
4145
triangle = PGS_Transformation.translate(triangle, (hue - 0.5f) * 100, (-hue + 0.5f) * 100);
4246

4347
if (warp) {
44-
triangle = PGS_Morphology.fieldWarp(triangle, 11, .11, millis() * 0.0005f, true, 1337);
45-
triangle = PGS_Morphology.simplify(triangle, 1);
48+
triangle = PGS_Morphology.fieldWarp(PGS_Processing.densify(triangle, 5), 11, .11, millis() * 0.0005f, !true, 1337);
49+
triangle = PGS_Morphology.simplify(triangle, 0.75);
4650
}
4751

48-
PGS_Conversion.setAllFillColor(triangle, color(hue, 1, 0.6f, 0.6f));
49-
PGS_Conversion.setAllStrokeColor(triangle, color(hue, 1, 1), 4);
52+
53+
PGS_Conversion.setAllFillColor(triangle, setAlpha(sinebow(hue), 85)); // color(hue, 1, 0.6f, 0.6f)
54+
PGS_Conversion.setAllStrokeColor(triangle, sinebow(hue), 3);
5055

5156
return triangle;
5257
}).sequential().forEach(t -> shape(t));
@@ -59,3 +64,22 @@ void mousePressed() {
5964
void keyPressed() {
6065
warp = !warp;
6166
}
67+
68+
public static int setAlpha(int c, int alpha) {
69+
return (c & 16777215) | alpha << 24;
70+
}
71+
72+
public static int sinebow(double t) {
73+
t = 0.5f - t;
74+
return rgbColor(255 * (sin2(t + 0 / 3f)),
75+
255 * (sin2(t + 1 / 3d)), 255 * (sin2(t + 2 / 3d)));
76+
}
77+
78+
private static double sin2(double t) {
79+
double z = FastMath.sin(PI * t);
80+
return z * z;
81+
}
82+
83+
public static int rgbColor(double red, double green, double blue) {
84+
return -16777216 | FastMath.roundToInt(red) << 16 | FastMath.roundToInt(green) << 8 | FastMath.roundToInt(blue);
85+
}

0 commit comments

Comments
 (0)