Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PGS 2.0 (Java 17) #94

Draft
wants to merge 36 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f17c4e4
java 17
micycle1 Jul 29, 2023
2a6bebe
use tinspin v2.0
micycle1 Jul 30, 2023
43de62e
always use robust polygonization
micycle1 Jul 30, 2023
c68baa1
add findShortestTour() and pruneSparsePoints()
micycle1 Nov 13, 2023
00da9f7
Add variableBuffer with width callback
micycle1 Jan 26, 2024
0c3de21
remove original holes from new meshes in various methods in PGS_Meshing
micycle1 Jan 26, 2024
ea83fd2
refactoring: deprecate homotheticTransformation in favour of scale(..…
micycle1 Jan 27, 2024
dea9514
add points triangulation with constraint and boundsCenter()
micycle1 Jan 27, 2024
bdfc00b
add termination callback to DiscreteCurveEvolution
micycle1 Jan 27, 2024
71b4186
stochasticPack respect boundary
micycle1 Feb 4, 2024
1f0a76c
pointsOnExterior()` now respects holes etf
micycle1 Feb 5, 2024
4e52b74
add getShapeStylingData
micycle1 Feb 5, 2024
02b29de
various
micycle1 Feb 5, 2024
6bd8904
add fix()
micycle1 Feb 18, 2024
ef23b3b
small improvements / javadocs
micycle1 Feb 18, 2024
3148d38
add innerVoronoiRaw() etc
micycle1 Feb 18, 2024
939856f
update/improve examples
micycle1 Feb 18, 2024
3494e64
fix dce adding spurious closing vertex
micycle1 Feb 18, 2024
1e61ee6
front chain packer signature
micycle1 May 21, 2024
8d850d6
front-chain packer algo change
micycle1 May 21, 2024
dede427
Merge branch 'v2' into temp
micycle1 Aug 6, 2024
ebb985c
Merge pull request #117 from micycle1/temp
micycle1 Aug 6, 2024
9194158
optmise interpolate()
micycle1 Aug 8, 2024
26a90de
add isClockwise()
micycle1 Aug 8, 2024
1ef883c
supercircle arg + docs
micycle1 Aug 8, 2024
d1639bd
fix DCE bug when kinks have the same relevance
micycle1 Aug 8, 2024
d4cff64
make smoothGaussian() robust against vertex order
micycle1 Aug 8, 2024
1935eca
fixup align params
micycle1 Aug 10, 2024
157fee6
add extractInnerVertices()
micycle1 Aug 10, 2024
d749e48
add thomasClusters()
micycle1 Aug 10, 2024
537b22b
Handle sub-graphs in stochasticMerge()
micycle1 Oct 18, 2024
dbb6226
fieldwarp() - accept long type seeds
micycle1 Oct 18, 2024
4acce04
add transform() and apply()
micycle1 Oct 18, 2024
81ea122
adaptive quality buffering
micycle1 Oct 18, 2024
d051420
Refactor fromVertices() and split out toContours().
micycle1 Oct 19, 2024
ce1d7a4
assorted javadocs
micycle1 Oct 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,41 @@ All notable changes to PGS will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Dates are *YYYY-MM-DD*.

## **2.0** *(2024-08-xx)*

**NOTE: Beginning at v2.0, PGS is built with Java 17.**

### Added
* `findShortestTour()` to `PGS_PointSet`. Computes an <i>approximate</i> 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()`.
* Additional method signature for `PGS_Morphology.variableBuffer()` that accepts a callback function to define the buffer value at each vertex.
* `boundsCenter()` to `PGS_Transformation`. Computes the center of the bounding box of a shape.
* Additional method signature for `delaunayTriangulation(points)` that supports a boundary constraint.
* `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.
* `thomasClusters()` to `PGS_PointSet`. Generates random points having clustered properties using the Thomas Point Process.
* `transform()` to `PGS_Processing`. Applies a specified transformation function to each child of the given PShape and returns a new PShape containing the transformed children.
* `apply()` to `PGS_Processing`. Applies a specified function to each child of the given PShape.
* `toContours()` to `PGS_Conversion`. Extracts the contours from a POLYGON or PATH PShape, represented as lists of PVector points.

### Changes
* Packed circles from `PGS_CirclePacking.stochasticPack()` will now always lie within shape bounds.
* `PGS_Processing.pointsOnExterior()` methods now respect GROUP shapes and holes (inner rings) and will populate them with points.
* `PGS_Morphology.simplifyDCE()` now supports GROUP shapes and polygon holes.
* `PGS_Morphology.interpolate()` is much faster on shapes with many vertices.
* Removed superfluous `height` argument from `PGS.createSupercircle()` method signature.

### Fixed
* `urquhartFaces()`, `relativeNeighborFaces()`, `gabrielFaces()` and `spannerFaces()` from `PGS_Meshing` now preserve holes from the input.
* The output of `PGS_Morphology.smoothGaussian()` is no longer (slightly) affected by the vertex ordering of the input.
* The `transform` and `reference` arguments for `PGS_Transformation.align()` were the wrong way round.

### Removed
* `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.


## **1.4.0** *(2023-07-29)*

### Added
Expand Down
49 changes: 32 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,41 @@ Docs are hosted via *GitHub Pages* [here](https://micycle1.github.io/PGS/).
Library functionality is split over the following classes:

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

## **Installation**

Expand Down Expand Up @@ -546,6 +546,13 @@ Much of the functionality (but by no means all) is demonstrated below:
<td valign="top" width="25%"><img src="resources/meshing/areaMerge.gif"></td>
<td valign="top" width="25%"><img src="resources/meshing/innerEdges.gif"></td>
</tr>

<tr>
<td align="center" valign="center"><b>Extract Inner Vertices</td>
</tr>
<tr>
<td valign="top" width="25%"><img src="resources/meshing/extractInnerVertices.gif"></td>
</tr>
</table>

## *Geometric Optimisation*
Expand Down Expand Up @@ -831,25 +838,33 @@ Much of the functionality (but by no means all) is demonstrated below:
<tr>
<td align="center" valign="center"><b>Sobol LDS</td>
<td align="center" valign="center"><b>N-Rooks LDS</td>
<td align="center" valign="center"><b>Distance Prune</td>
<td align="center" valign="center"><b>Thomas Clusters</td>
<td align="center" valign="center"><b>Hilbert Sort</td>
</tr>
<tr>
<td valign="top" width="25%"><img src="resources/point_set/sobolLDS.gif"></td>
<td valign="top" width="25%"><img src="resources/point_set/nRooksLDS.png"></td>
<td valign="top" width="25%"><img src="resources/point_set/removeWithinDistance.gif"></td>
<td valign="top" width="25%"><img src="resources/point_set/thomas.gif"></td>
<td valign="top" width="25%"><img src="resources/point_set/hilbertSort.gif"></td>
</tr>
<tr>
<td align="center" valign="center"><b>EMST</td>
<td align="center" valign="center"><b>Shortest Tour (TSP)</td>
<td align="center" valign="center"><b>Cluster</td>
<td align="center" valign="center"><b>Weighted Median</td>
</tr>
<tr>
<td valign="top" width="25%"><img src="resources/point_set/emst.png"></td>
<td valign="top" width="25%"><img src="resources/point_set/tsp.png"></td>
<td valign="top" width="25%"><img src="resources/point_set/cluster.png"></td>
<td valign="top" width="25%"><img src="resources/point_set/weightedMedian.png"></td>
</tr>
<tr>
<td align="center" valign="center"><b>Distance Prune</td>
</tr>
<tr>
<td valign="top" width="25%"><img src="resources/point_set/removeWithinDistance.gif"></td>
</tr>
</table>

## *Segment Sets*
Expand Down
9 changes: 5 additions & 4 deletions examples/contourMap/contourMap.pde
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ List<PVector> heights;
float max = -1, min = 9999;
UniformNoise noise;

final int RESOLUTION = 16; // lower is more resolution
final int RESOLUTION = 15; // lower is more resolution

void setup() {
size(800, 800, FX2D);
size(1000, 1000, FX2D);
smooth();
noise = new UniformNoise();
}
Expand All @@ -30,6 +30,7 @@ void draw() {
map(isoline.getVertex(0).x, 0, width, 50, 255),
map(isoline.getVertex(0).y, 0, height, 50, 255)
));
isoline.setStrokeWeight(3);
shape(isoline);
}
}
Expand All @@ -39,8 +40,8 @@ void populateHeightMap() {

final float animSpeed = 0.005;

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

Expand Down
17 changes: 12 additions & 5 deletions examples/drawOffsetCurves/drawOffsetCurves.pde
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ PShape shape;
boolean inward = true;

void setup() {
size(800, 800, FX2D);
size(1000, 1000, FX2D);
smooth();
textAlign(CENTER, CENTER);

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

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

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

void mouseDragged() {
shape = PGS_ShapeBoolean.union(shape, createShape(ELLIPSE, mouseX, mouseY, 100, 100));
shape = PGS_Morphology.simplify(shape, 1);
if (mouseButton == LEFT) {
shape = PGS_ShapeBoolean.union(shape, createShape(ELLIPSE, mouseX, mouseY, 75, 75));
} else if (mouseButton == RIGHT) {
shape = PGS_ShapeBoolean.subtract(shape, createShape(ELLIPSE, mouseX, mouseY, 75, 75));
}
shape = PGS_Morphology.simplify(shape, 0.1);
PGS_Conversion.setAllFillColor(shape, 255);
PGS_Conversion.disableAllStroke(shape);
}

Expand Down
40 changes: 32 additions & 8 deletions examples/ripplingTriangles/ripplingTriangles.pde
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,32 @@ import java.util.List;
import micycle.pgs.*;
import micycle.uniformnoise.*;
import java.util.concurrent.atomic.AtomicInteger;
import net.jafama.FastMath;


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

void setup() {
size(800, 800, FX2D);
size(1000, 1000, FX2D);
smooth();
textAlign(LEFT, TOP);

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

void draw() {
colorMode(RGB, 255, 255, 255, 255);
background(0, 0, 40);
//background(0, 0, 40);
fill(0,0,40,33);
rect(0,0,width,height);

fill(0, 255, 255);
text(frameRate, 2, 2); // fps
//text(frameRate, 2, 2); // fps

colorMode(HSB, 1, 1, 1, 1);

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

if (warp) {
triangle = PGS_Morphology.fieldWarp(triangle, 11, .11, millis() * 0.0005f, true, 1337);
triangle = PGS_Morphology.simplify(triangle, 1);
triangle = PGS_Morphology.fieldWarp(PGS_Processing.densify(triangle, 5), 11, .11, millis() * 0.0005f, !true, 1337);
triangle = PGS_Morphology.simplify(triangle, 0.75);
}

PGS_Conversion.setAllFillColor(triangle, color(hue, 1, 0.6f, 0.6f));
PGS_Conversion.setAllStrokeColor(triangle, color(hue, 1, 1), 4);

PGS_Conversion.setAllFillColor(triangle, setAlpha(sinebow(hue), 85)); // color(hue, 1, 0.6f, 0.6f)
PGS_Conversion.setAllStrokeColor(triangle, sinebow(hue), 3);

return triangle;
}).sequential().forEach(t -> shape(t));
Expand All @@ -59,3 +64,22 @@ void mousePressed() {
void keyPressed() {
warp = !warp;
}

public static int setAlpha(int c, int alpha) {
return (c & 16777215) | alpha << 24;
}

public static int sinebow(double t) {
t = 0.5f - t;
return rgbColor(255 * (sin2(t + 0 / 3f)),
255 * (sin2(t + 1 / 3d)), 255 * (sin2(t + 2 / 3d)));
}

private static double sin2(double t) {
double z = FastMath.sin(PI * t);
return z * z;
}

public static int rgbColor(double red, double green, double blue) {
return -16777216 | FastMath.roundToInt(red) << 16 | FastMath.roundToInt(green) << 8 | FastMath.roundToInt(blue);
}
13 changes: 8 additions & 5 deletions examples/slice/slice.pde
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ void draw() {
background(0, 0, 40);

if ((frameCount-1) % 180 == 0) {
polygon = PGS_Construction.createRandomPolygon((int) random(3, 7), width, height);
polygon = PGS_Construction.createSuperRandomPolygon(width, choice(5,50) , random(0.05, 0.2), choice(0, 3), choice(1, 3), false, true, millis());
polygon = PGS_Transformation.resizeByMajorAxis(polygon, 666);
polygon = PGS_Transformation.translateEnvelopeTo(polygon, width/2, height/2);
}

slice(polygon);
Expand All @@ -26,16 +28,17 @@ void slice(PShape shape) {
PShape slices = PGS_Processing.slice(shape, pv1, pv2);
PShape s = slices.getChild(0);
PShape s2 = slices.getChild(1);

PGS_Conversion.setAllFillColor(s, color(237, 50, 162));
PGS_Conversion.setAllStrokeColor(s, color(237, 50, 162), 4);
PGS_Conversion.setAllStrokeColor(s, color(237, 50, 162), 3);
PGS_Conversion.setAllFillColor(s2, color(255));
//PGS_Conversion.setAllStrokeColor(s2, color(237, 50, 162), 3);

shape(s);
shape(s2);

strokeWeight(5);
stroke(0, 0, 40);
stroke(255, 255, 0, 100);
line(pv1.x, pv1.y, pv2.x, pv2.y);
stroke(color(237, 50, 162));
strokeWeight(15);
Expand Down
6 changes: 3 additions & 3 deletions examples/spiralOutline/spiralOutline.pde
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ PShape triangles;
UniformNoise noise;

void setup() {
size(800, 800, FX2D);
size(1000, 1000, FX2D);
smooth();
colorMode(HSB, 1, 1, 1);
rectMode(CORNER);
Expand All @@ -17,15 +17,15 @@ void setup() {
}

void draw() {
fill(0, 0, 0.1, 64);
fill(0, 0, 0.05, 64);
rect(0, 0, width, height);

PShape spiral = PGS_Construction.createLinearSpiral(width/2, height/2, 0.5+mouseX/200f, 250+mouseY/5f);
spiral = PGS_Transformation.rotate(spiral, new PVector(width/2, height/2), frameCount/100f);
spiral.setFill(false);
shape(spiral);

spiral = PGS_Morphology.simplify(spiral, 1);
spiral = PGS_Morphology.simplify(spiral, .1);
spiral = PGS_Morphology.buffer(spiral, 20);

int perimeters = 30; // perimeter sections
Expand Down
2 changes: 1 addition & 1 deletion jitpack.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
jdk:
- openjdk8
- openjdk17
Loading
Loading