Last active
January 2, 2023 18:14
-
-
Save radiovisual/c8b2f33a660828dec6c94e2260ec70f6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| PImage imageMask; | |
| ArrayList<ArrayList<PVector>> polygons; | |
| void setup() { | |
| size(512, 512); | |
| imageMask = loadImage("imageMask.png"); | |
| // Create an empty array to store the polygons | |
| polygons = new ArrayList<ArrayList<PVector>>(); | |
| // Iterate through each pixel in the image | |
| for (int y = 0; y < imageMask.height; y++) { | |
| for (int x = 0; x < imageMask.width; x++) { | |
| // If the pixel is black and hasn't been visited yet, start a new polygon and add it to the polygons array | |
| if (brightness(imageMask.get(x, y)) == 0) { | |
| ArrayList<PVector> polygon = new ArrayList<PVector>(); | |
| polygons.add(polygon); | |
| tracePolygon(polygon, x, y, 0); | |
| } | |
| } | |
| } | |
| // Smooth the polygon outlines | |
| smoothPolygons(); | |
| } | |
| void draw() { | |
| background(255); | |
| // Draw the polygons | |
| stroke(0); | |
| strokeWeight(1); | |
| noFill(); | |
| for (ArrayList<PVector> polygon : polygons) { | |
| beginShape(); | |
| for (PVector point : polygon) { | |
| vertex(point.x, point.y); | |
| } | |
| endShape(CLOSE); | |
| } | |
| } | |
| // Function to smooth the polygon outlines | |
| void smoothPolygons() { | |
| // Iterate through each polygon | |
| for (ArrayList<PVector> polygon : polygons) { | |
| // Create a new array to store the smoothed points | |
| ArrayList<PVector> smoothedPolygon = new ArrayList<PVector>(); | |
| // Iterate through each point in the polygon | |
| for (int i = 0; i < polygon.size(); i++) { | |
| PVector p1 = polygon.get(i); | |
| PVector p2 = polygon.get((i + 1) % polygon.size()); | |
| PVector p3 = polygon.get((i + 2) % polygon.size()); | |
| // Compute the angle between the three points | |
| float angle = abs(PVector.angleBetween(p2.sub(p1), p3.sub(p2))); | |
| // If the angle is acute, add the middle point to the smoothed polygon | |
| if (angle < PI / 2) { | |
| smoothedPolygon.add(p2); | |
| } else { | |
| // If the angle is obtuse, add a new point halfway between the middle point and the point with the smallest distance | |
| PVector p4 = p2.lerp(dist(p1.x, p1.y, p2.x, p2.y) < dist(p2.x, p2.y, p3.x, p3.y) ? p1 : p3, 0.5); | |
| smoothedPolygon.add(p4); | |
| } | |
| } | |
| // Replace the original polygon with the smoothed polygon | |
| polygon.clear(); | |
| polygon.addAll(smoothedPolygon); | |
| } | |
| } | |
| // Maximum recursion depth | |
| int maxRecursionDepth = 1000; | |
| // Function to trace the outline of a polygon | |
| void tracePolygon(ArrayList<PVector> polygon, int x, int y, int recursionDepth) { | |
| // Check the recursion depth | |
| if (recursionDepth > maxRecursionDepth) { | |
| return; | |
| } | |
| // Add the current point to the polygon if it hasn't already been visited | |
| if (brightness(imageMask.get(x, y)) == 0) { | |
| polygon.add(new PVector(x, y)); | |
| // Set the current pixel to white to mark it as visited | |
| imageMask.set(x, y, color(255)); | |
| } | |
| // Check the pixels around the current point | |
| for (int dx = -1; dx <= 1; dx++) { | |
| for (int dy = -1; dy <= 1; dy++) { | |
| // Skip the current point and pixels outside the image | |
| if (dx == 0 && dy == 0 || x + dx < 0 || x + dx >= imageMask.width || y + dy < 0 || y + dy >= imageMask.height) { | |
| continue; | |
| } | |
| // If the pixel is black and hasn't been visited yet, recursively trace the polygon from that point | |
| if (brightness(imageMask.get(x + dx, y + dy)) == 0) { | |
| tracePolygon(polygon, x + dx, y + dy, recursionDepth + 1); | |
| } | |
| } | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment