package spimedb.util.geom; import spimedb.util.geom.mesh2d.DelaunayTriangulation; import spimedb.util.geom.mesh2d.Voronoi; import java.util.ArrayList; import java.util.List; /** * This is an implementation of the {@link PolygonTesselator} interface and * abstract parent class for tesselating 2D polygons using a grid of additional * points created within the polygon. These inlier points are connected to the * original polygon vertices using a {@link DelaunayTriangulation}. The quality * and final amount of triangles used can be adjusted via the number of * additional grid points. This class currently has two concrete * implementations: {@link GlobalGridTesselator} and {@link LocalGridTesselator} * . */ public abstract class GridTesselator implements PolygonTesselator { protected float res; private final float rootSize; /** * Creates a new instance with the given grid resolution. * * @param res * snap distance for grid points */ public GridTesselator(float res) { this(res, Voronoi.DEFAULT_SIZE); } /** * Creates a new instance with the given grid resolution. * * @param res * snap distance for grid points */ public GridTesselator(float res, float rootSize) { this.res = res; this.rootSize = rootSize; } protected abstract List<Vec2D> createInsidePoints(Polygon2D poly, Rect bounds); public float getResolution() { return res; } public void setResolution(float res) { this.res = res; } /** * Tesselates/decomposes the given polygon into a list of 2D triangles using * the currently set grid resolution. * * @param poly * polygon to be tesselated * @return list of triangles */ public List<Triangle2D> tesselatePolygon(Polygon2D poly) { List<Triangle2D> triangles = new ArrayList<>(); Rect bounds = poly.getBounds(); // a Voronoi diagram relies on a Delaunay triangulation behind the // scenes Voronoi voronoi = new Voronoi(rootSize); // add perimeter points for (Vec2D v : poly.vertices) { voronoi.addPoint(v); } // add random inliers for (Vec2D v : createInsidePoints(poly, bounds)) { voronoi.addPoint(v); } // get filtered delaunay triangles: // ignore any triangles which share a vertex with the initial root // triangle or whose centroid is outside the polygon for (Triangle2D t : voronoi.getTriangles()) { if (Math.abs(t.a.x) != Voronoi.DEFAULT_SIZE && Math.abs(t.a.y) != Voronoi.DEFAULT_SIZE) { if (poly.containsPoint(t.computeCentroid())) { triangles.add(t); } } } return triangles; } }