diff options
author | Sven Göthel <[email protected]> | 2024-02-14 20:23:24 +0100 |
---|---|---|
committer | Sven Göthel <[email protected]> | 2024-02-14 20:23:24 +0100 |
commit | e4b49663f6c6f138a8718847b68d1d78fba8fe73 (patch) | |
tree | 3628be91f48347a6b26ebf9d7e0809ddae1d4321 /src/jogl | |
parent | 52277dc625b515ecc3ff0d26ca05428f3d973427 (diff) |
Bug 1501: Refine convex == !complex: Use 'complex' term, have env-property toggle OutlineShape's isComplex() for visibility
We may use complex for other criteria than !convex, i.e. self-intersecting etc.
Diffstat (limited to 'src/jogl')
5 files changed, 91 insertions, 69 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java index 25791e17d..0c42e791c 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java +++ b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java @@ -46,6 +46,8 @@ import com.jogamp.math.geom.plane.AffineTransform; import com.jogamp.math.geom.plane.Path2F; import com.jogamp.math.geom.plane.Winding; +import jogamp.opengl.Debug; + /** * A Generic shape objects which is defined by a list of Outlines. * This Shape can be transformed to triangulations. @@ -119,6 +121,9 @@ import com.jogamp.math.geom.plane.Winding; * @see Region */ public final class OutlineShape implements Comparable<OutlineShape> { + private static final boolean FORCE_COMPLEXSHAPE = Debug.debug("graph.curve.triangulation.force.complexshape"); + private static final boolean FORCE_SIMPLESHAPE = Debug.debug("graph.curve.triangulation.force.simpleshape"); + /** * Outline's vertices have undefined state until transformed. */ @@ -159,7 +164,7 @@ public final class OutlineShape implements Comparable<OutlineShape> { private final ArrayList<Triangle> triangles; private final ArrayList<Vertex> vertices; private int addedVerticeCount; - private boolean convexFlag; + private boolean complexShape; private VerticesState outlineState; @@ -187,7 +192,11 @@ public final class OutlineShape implements Comparable<OutlineShape> { this.triangles = new ArrayList<Triangle>(); this.vertices = new ArrayList<Vertex>(); this.addedVerticeCount = 0; - this.convexFlag = true; + if( FORCE_COMPLEXSHAPE ) { + complexShape = true; + } else { + complexShape = false; + } this.dirtyBits = 0; this.sharpness = DEFAULT_SHARPNESS; } @@ -221,7 +230,11 @@ public final class OutlineShape implements Comparable<OutlineShape> { vertices.clear(); triangles.clear(); addedVerticeCount = 0; - convexFlag = true; + if( FORCE_COMPLEXSHAPE ) { + complexShape = true; + } else { + complexShape = false; + } dirtyBits = 0; } @@ -262,10 +275,9 @@ public final class OutlineShape implements Comparable<OutlineShape> { } /** - * Returns cached or computed result whether all {@code polyline}s of {@link #getOutline(int)} are of convex shape, see {@link Outline#isConvex()}. + * Returns cached or computed result if at least one {@code polyline} of {@link #getOutline(int)} is a complex shape, see {@link Outline#isComplex()}. * <p> - * A polyline with less than 3 elements is marked convex for simplicity, - * since a non-convex complex shape may need to pass intersection testing within triangulation. + * A polyline with less than 3 elements is marked a simple shape for simplicity. * </p> * <p> * The result is cached. @@ -273,32 +285,35 @@ public final class OutlineShape implements Comparable<OutlineShape> { * @see #setOverrideConvex(boolean) * @see #clearOverrideConvex() */ - public boolean isConvex() { - if( 0 == ( OVERRIDE_CONVEX & dirtyBits ) ) { - if( 0 != ( DIRTY_CONVEX & dirtyBits ) ) { - convexFlag = true; - final int sz = this.getOutlineCount(); - for(int i=0; i<sz && convexFlag; ++i) { - convexFlag = getOutline(i).isConvex(); - } - dirtyBits &= ~DIRTY_CONVEX; + public boolean isComplex() { + if( !FORCE_COMPLEXSHAPE && !FORCE_SIMPLESHAPE && + 0 == ( OVERRIDE_CONVEX & dirtyBits ) && + 0 != ( DIRTY_CONVEX & dirtyBits ) ) + { + complexShape = false; + final int sz = this.getOutlineCount(); + for(int i=0; i<sz && !complexShape; ++i) { + complexShape = getOutline(i).isComplex(); } + dirtyBits &= ~DIRTY_CONVEX; } - return convexFlag; + return complexShape; } /** - * Overrides {@link #isConvex()} using the given value instead of computing via {@link Outline#isConvex()}. + * Overrides {@link #isComplex()} using the given value instead of computing via {@link Outline#isComplex()}. * @see #clearOverrideConvex() - * @see #isConvex() + * @see #isComplex() */ public void setOverrideConvex(final boolean convex) { - dirtyBits |= OVERRIDE_CONVEX; - convexFlag = convex; + if( !FORCE_COMPLEXSHAPE && !FORCE_SIMPLESHAPE ) { + dirtyBits |= OVERRIDE_CONVEX; + complexShape = convex; + } } /** - * Clears the {@link #isConvex()} override done by {@link #setOverrideConvex(boolean)} + * Clears the {@link #isComplex()} override done by {@link #setOverrideConvex(boolean)} * @see #setOverrideConvex(boolean) - * @see #isConvex() + * @see #isComplex() */ public void clearOverrideConvex() { dirtyBits &= ~OVERRIDE_CONVEX; @@ -1018,7 +1033,7 @@ public final class OutlineShape implements Comparable<OutlineShape> { triangles.clear(); final Triangulator triangulator2d = Triangulation.create(); - triangulator2d.setConvexShape( isConvex() ); + triangulator2d.setComplexShape( isComplex() ); for(int index = 0; index<outlines.size(); index++) { triangulator2d.addCurve(triangles, outlines.get(index), sharpness); } diff --git a/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java b/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java index eaebde076..a9f9b06c2 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java +++ b/src/jogl/classes/com/jogamp/graph/curve/tess/Triangulator.java @@ -49,8 +49,16 @@ import com.jogamp.graph.geom.Triangle; */ public interface Triangulator { - /** Mark the to be triangulated shape convex or non-convex, causing further processing costs if non-convex like intersection tests. Default is assuming a convex shape. */ - public void setConvexShape(boolean convex); + /** + * Mark the to be triangulated shape complex or non-complex. + * <p> + * Complex shapes may cause further processing costs, e.g. intersection tests to overcome self-intersecting shapes. + * </p> + * <p> + * Default is assuming a simple non-complex shape. + * </p> + */ + public void setComplexShape(boolean complex); /** * Add a curve to the list of Outlines diff --git a/src/jogl/classes/com/jogamp/graph/geom/Outline.java b/src/jogl/classes/com/jogamp/graph/geom/Outline.java index 8c39004a0..1525483c5 100644 --- a/src/jogl/classes/com/jogamp/graph/geom/Outline.java +++ b/src/jogl/classes/com/jogamp/graph/geom/Outline.java @@ -57,11 +57,11 @@ public class Outline implements Comparable<Outline> { private final AABBox bbox; private boolean dirtyBBox; private Winding winding; - private boolean convexFlag; + private boolean complexShape; private int dirtyBits; private static final int DIRTY_WINDING = 1 << 0; - private static final int DIRTY_CONVEX = 1 << 0; + private static final int DIRTY_COMPLEXSHAPE = 1 << 0; /**Create an outline defined by control vertices. * An outline can contain off Curve vertices which define curved @@ -73,7 +73,7 @@ public class Outline implements Comparable<Outline> { bbox = new AABBox(); dirtyBBox = false; winding = Winding.CCW; - convexFlag = false; + complexShape = false; dirtyBits = 0; } @@ -84,8 +84,16 @@ public class Outline implements Comparable<Outline> { final int count = src.vertices.size(); vertices = new ArrayList<Vertex>(count); winding = Winding.CCW; - convexFlag = false; - dirtyBits = DIRTY_WINDING | DIRTY_CONVEX; + complexShape = false; + dirtyBits = DIRTY_WINDING | DIRTY_COMPLEXSHAPE; + if( 0 == ( src.dirtyBits & DIRTY_WINDING ) ) { + winding = src.winding; + dirtyBits &= ~DIRTY_WINDING; + } + if( 0 == ( src.dirtyBits & DIRTY_COMPLEXSHAPE ) ) { + complexShape = src.complexShape; + dirtyBits &= ~DIRTY_COMPLEXSHAPE; + } for(int i=0; i<count; i++) { vertices.add( src.vertices.get(i).copy() ); } @@ -105,15 +113,10 @@ public class Outline implements Comparable<Outline> { public Outline(final Outline src, final Winding enforce) { final int count = src.vertices.size(); vertices = new ArrayList<Vertex>(count); + complexShape = false; + dirtyBits = DIRTY_COMPLEXSHAPE; final Winding had_winding = src.getWinding(); winding = had_winding; - if( 0 == ( src.dirtyBits & DIRTY_CONVEX ) ) { - convexFlag = src.convexFlag; - dirtyBits = 0; - } else { - convexFlag = false; - dirtyBits = DIRTY_CONVEX; - } if( enforce != had_winding ) { for(int i=count-1; i>=0; --i) { vertices.add( src.vertices.get(i).copy() ); @@ -124,6 +127,10 @@ public class Outline implements Comparable<Outline> { vertices.add( src.vertices.get(i).copy() ); } } + if( 0 == ( src.dirtyBits & DIRTY_COMPLEXSHAPE ) ) { + complexShape = src.complexShape; + dirtyBits &= ~DIRTY_COMPLEXSHAPE; + } closed = src.closed; bbox = new AABBox(src.bbox); dirtyBBox = src.dirtyBBox; @@ -171,22 +178,22 @@ public class Outline implements Comparable<Outline> { } /** - * Returns the cached or computed result whether this {@link Outline}s {@code polyline} has a convex shape using {@link VectorUtil#isConvex(ArrayList, boolean)}. + * Returns cached or computed result if whether this {@link Outline}s {@code polyline} is a complex shape. * <p> - * A polyline with less than 3 elements is marked convex for simplicity, - * since a non-convex complex shape may need to pass intersection testing within triangulation. + * A polyline with less than 3 elements is marked a simple shape for simplicity. * </p> * <p> * The result is cached. * </p> */ - public boolean isConvex() { - if( 0 == ( dirtyBits & DIRTY_CONVEX ) ) { - return convexFlag; + public boolean isComplex() { + if( 0 == ( dirtyBits & DIRTY_COMPLEXSHAPE ) ) { + return complexShape; } - convexFlag = VectorUtil.isConvex1( getVertices(), true ); - dirtyBits &= ~DIRTY_CONVEX; - return convexFlag; + complexShape = !VectorUtil.isConvex1( getVertices(), true ); + // complexShape = VectorUtil.isSelfIntersecting1( getVertices() ); + dirtyBits &= ~DIRTY_COMPLEXSHAPE; + return complexShape; } public final int getVertexCount() { @@ -217,7 +224,7 @@ public class Outline implements Comparable<Outline> { if(!dirtyBBox) { bbox.resize(vertex.getCoord()); } - dirtyBits |= DIRTY_WINDING | DIRTY_CONVEX; + dirtyBits |= DIRTY_WINDING | DIRTY_COMPLEXSHAPE; } /** Replaces the {@link Vertex} element at the given {@code position}. @@ -234,7 +241,7 @@ public class Outline implements Comparable<Outline> { } vertices.set(position, vertex); dirtyBBox = true; - dirtyBits |= DIRTY_WINDING | DIRTY_CONVEX; + dirtyBits |= DIRTY_WINDING | DIRTY_COMPLEXSHAPE; } public final Vertex getVertex(final int index){ @@ -253,7 +260,7 @@ public class Outline implements Comparable<Outline> { */ public final Vertex removeVertex(final int position) throws IndexOutOfBoundsException { dirtyBBox = true; - dirtyBits |= DIRTY_WINDING | DIRTY_CONVEX; + dirtyBits |= DIRTY_WINDING | DIRTY_COMPLEXSHAPE; return vertices.remove(position); } diff --git a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java index 08b75478d..d69b33f1f 100644 --- a/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java +++ b/src/jogl/classes/jogamp/graph/curve/tess/CDTriangulator2D.java @@ -50,15 +50,13 @@ public class CDTriangulator2D implements Triangulator { protected static final boolean DEBUG = Debug.debug("graph.curve.Triangulation"); - private static final boolean FORCE_NONCONVEX = Debug.debug("graph.curve.triangulation.force.non-convex"); - private static final boolean FORCE_CONVEX = Debug.debug("graph.curve.triangulation.force.convex"); private static final boolean TEST_LINE_AA = Debug.debug("graph.curve.triangulation.LINE_AA"); private static final boolean TEST_MARK_LINE = Debug.debug("graph.curve.triangulation.MARK_AA"); private static final boolean TEST_ENABLED = TEST_LINE_AA || TEST_MARK_LINE; private final ArrayList<Loop> loops = new ArrayList<Loop>(); - private boolean convexFlag; + private boolean complexShape; private int addedVerticeCount; private int maxTriID; @@ -66,19 +64,13 @@ public class CDTriangulator2D implements Triangulator { /** Constructor for a new Delaunay triangulator */ public CDTriangulator2D() { - if( FORCE_NONCONVEX ) { - convexFlag = false; - } else { - convexFlag = true; - } + complexShape = false; reset(); } @Override - public void setConvexShape(final boolean convex) { - if( !FORCE_NONCONVEX && !FORCE_CONVEX ) { - convexFlag = convex; - } + public void setComplexShape(final boolean complex) { + complexShape = complex; } @Override @@ -114,7 +106,7 @@ public class CDTriangulator2D implements Triangulator { final GraphOutline innerPoly = extractBoundaryTriangles(sink, outline, false /* hole */, sharpness); // vertices.addAll(polyline.getVertices()); if( innerPoly.getGraphPoint().size() >= 3 ) { - loop = Loop.createBoundary(innerPoly, convexFlag); + loop = Loop.createBoundary(innerPoly, complexShape); if( null != loop ) { loops.add(loop); } diff --git a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java index a69fbd6b5..838cf8b5f 100644 --- a/src/jogl/classes/jogamp/graph/curve/tess/Loop.java +++ b/src/jogl/classes/jogamp/graph/curve/tess/Loop.java @@ -41,13 +41,13 @@ import com.jogamp.graph.geom.Triangle; public class Loop { private final AABBox box = new AABBox(); private final GraphOutline initialOutline; - private final boolean isConvex; + private final boolean complexShape; private HEdge root; private final List<GraphOutline> outlines = new ArrayList<GraphOutline>(); - private Loop(final GraphOutline polyline, final int edgeType, final boolean isConvex){ + private Loop(final GraphOutline polyline, final int edgeType, final boolean complexShape){ this.initialOutline = polyline; - this.isConvex = isConvex; + this.complexShape = complexShape; this.root = initFromPolyline(initialOutline, edgeType); } @@ -249,7 +249,7 @@ public class Loop { final Vertex rootPoint = root.getGraphPoint().getPoint(); final Vertex nextPoint = next1.getGraphPoint().getPoint(); final Vertex candPoint = next1.getNext().getGraphPoint().getPoint(); - if( !isConvex && intersectsOutline(rootPoint, nextPoint, candPoint) ) { + if( complexShape && intersectsOutline(rootPoint, nextPoint, candPoint) ) { return null; } return new Triangle(rootPoint, nextPoint, candPoint, checkVerticesBoundary(root)); @@ -290,7 +290,7 @@ public class Loop { final Vertex rootPoint = root.getGraphPoint().getPoint(); final Vertex nextPoint = next1.getGraphPoint().getPoint(); final Vertex candPoint = next1.getNext().getGraphPoint().getPoint(); - if( !isConvex && intersectsOutlineDbg(rootPoint, nextPoint, candPoint) ) { + if( complexShape && intersectsOutlineDbg(rootPoint, nextPoint, candPoint) ) { System.err.printf("Loop.cut.X0: last-simplex intersects%n"); return null; } @@ -409,7 +409,7 @@ public class Loop { if( !VectorUtil.isCCW( rootPoint, nextPoint, candPoint) ) { return null; } - if( !isConvex && intersectsOutline(rootPoint, nextPoint, candPoint) ) { + if( complexShape && intersectsOutline(rootPoint, nextPoint, candPoint) ) { return null; } if( !delaunay ) { @@ -440,7 +440,7 @@ public class Loop { candPoint, rootPoint, nextPoint, candPoint); return null; } - if( !isConvex && intersectsOutlineDbg(rootPoint, nextPoint, candPoint) ) { + if( complexShape && intersectsOutlineDbg(rootPoint, nextPoint, candPoint) ) { return null; } if( !delaunay ) { |