28package com.jogamp.graph.geom;
30import java.io.PrintStream;
31import java.util.ArrayList;
33import com.jogamp.math.FloatUtil;
34import com.jogamp.math.VectorUtil;
35import com.jogamp.math.geom.AABBox;
36import com.jogamp.math.geom.plane.AffineTransform;
37import com.jogamp.math.geom.plane.Winding;
38import com.jogamp.graph.curve.OutlineShape;
39import com.jogamp.graph.curve.Region;
53public class Outline implements Comparable<Outline> {
55 private ArrayList<Vertex> vertices;
56 private boolean closed;
58 private boolean dirtyBBox;
60 private boolean complexShape;
61 private int dirtyBits;
63 private static final int DIRTY_WINDING = 1 << 0;
64 private static final int DIRTY_COMPLEXSHAPE = 1 << 0;
71 vertices =
new ArrayList<Vertex>(3);
84 final int count = src.vertices.size();
85 vertices =
new ArrayList<Vertex>(count);
88 dirtyBits = DIRTY_WINDING | DIRTY_COMPLEXSHAPE;
89 if( 0 == ( src.dirtyBits & DIRTY_WINDING ) ) {
90 winding = src.winding;
91 dirtyBits &= ~DIRTY_WINDING;
93 if( 0 == ( src.dirtyBits & DIRTY_COMPLEXSHAPE ) ) {
94 complexShape = src.complexShape;
95 dirtyBits &= ~DIRTY_COMPLEXSHAPE;
97 for(
int i=0; i<count; i++) {
98 vertices.add( src.vertices.get(i).copy() );
101 bbox =
new AABBox(src.bbox);
102 dirtyBBox = src.dirtyBBox;
114 final int count = src.vertices.size();
115 vertices =
new ArrayList<Vertex>(count);
116 complexShape =
false;
117 dirtyBits = DIRTY_COMPLEXSHAPE;
119 winding = had_winding;
120 if( enforce != had_winding ) {
121 for(
int i=count-1; i>=0; --i) {
122 vertices.add( src.vertices.get(i).copy() );
126 for(
int i=0; i<count; ++i) {
127 vertices.add( src.vertices.get(i).copy() );
130 if( 0 == ( src.dirtyBits & DIRTY_COMPLEXSHAPE ) ) {
131 complexShape = src.complexShape;
132 dirtyBits &= ~DIRTY_COMPLEXSHAPE;
135 bbox =
new AABBox(src.bbox);
136 dirtyBBox = src.dirtyBBox;
148 if( enforce != had_winding ) {
149 final int count = vertices.size();
150 final ArrayList<Vertex> ccw =
new ArrayList<Vertex>(count);
151 for(
int i=count-1; i>=0; --i) {
152 ccw.add(vertices.get(i));
156 dirtyBits &= ~DIRTY_WINDING;
168 if( 0 == ( dirtyBits & DIRTY_WINDING ) ) {
177 dirtyBits &= ~DIRTY_WINDING;
191 if( 0 == ( dirtyBits & DIRTY_COMPLEXSHAPE ) ) {
196 dirtyBits &= ~DIRTY_COMPLEXSHAPE;
201 return vertices.size();
220 public final void addVertex(
final int position,
final Vertex vertex)
throws NullPointerException, IndexOutOfBoundsException {
221 if (
null == vertex) {
222 throw new NullPointerException(
"vertex is null");
224 vertices.add(position, vertex);
226 bbox.
resize(vertex.getCoord());
228 dirtyBits |= DIRTY_WINDING | DIRTY_COMPLEXSHAPE;
239 public final void setVertex(
final int position,
final Vertex vertex)
throws NullPointerException, IndexOutOfBoundsException {
240 if (
null == vertex) {
241 throw new NullPointerException(
"vertex is null");
243 vertices.set(position, vertex);
245 dirtyBits |= DIRTY_WINDING | DIRTY_COMPLEXSHAPE;
249 return vertices.get(index);
253 return vertices.indexOf(vertex);
264 dirtyBits |= DIRTY_WINDING | DIRTY_COMPLEXSHAPE;
265 return vertices.remove(position);
269 return (vertices.size() == 0);
276 return vertices.get(vertices.size()-1);
290 this.vertices = vertices;
291 validateBoundingBox();
309 public final boolean setClosed(
final boolean closeTail) {
312 final Vertex first = vertices.get(0);
316 vertices.add(first.
copy());
318 vertices.add(0, last.
copy());
331 final int vsize = vertices.size();
332 for(
int i=0; i<vsize; i++) {
333 final Vertex v = vertices.get(i);
336 newOutline.closed = this.closed;
340 private final void validateBoundingBox() {
343 for (
int i=0; i<vertices.size(); i++) {
344 bbox.
resize(vertices.get(i).getCoord());
350 validateBoundingBox();
366 }
else if(thisSize < otherSize){
378 public boolean equals(
final Object obj) {
382 if(
null == obj || !(obj instanceof
Outline) ) {
401 throw new InternalError(
"hashCode not designed");
406 return getClass().getName() +
"@" + Integer.toHexString(super.hashCode());
409 public void print(
final PrintStream out) {
411 out.printf(
"Outline: %d, %s%n", vc,
getWinding());
412 for(
int vi=0; vi < vc; vi++) {
414 out.printf(
"- OL[%d]: %s%n", vi, v);
Define a single continuous stroke by control vertices.
final void addVertex(final int position, final Vertex vertex)
Insert the Vertex element at the given position to the outline loop/strip.
Outline(final Outline src)
Copy ctor.
final Winding getWinding()
Returns the cached or computed winding of this Outlines polyline using VectorUtil#area(ArrayList).
final void setVertex(final int position, final Vertex vertex)
Replaces the Vertex element at the given position.
final void setVertices(final ArrayList< Vertex > vertices)
Use the given outline loop/strip.
final boolean setClosed(final boolean closeTail)
Ensure this outline is closed.
final Vertex getLastVertex()
boolean equals(final Object obj)
final int compareTo(final Outline other)
Compare two outline's Bounding Box size.
final int getVertexCount()
final Outline transform(final AffineTransform t)
Return a transformed instance with all vertices are copied and transformed.
void print(final PrintStream out)
final void addVertex(final Vertex vertex)
Appends a vertex to the outline loop/strip.
final ArrayList< Vertex > getVertices()
final Vertex getVertex(final int index)
Outline(final Outline src, final Winding enforce)
Copy ctor w/ enforced Winding.
final void setWinding(final Winding enforce)
Sets Winding to this outline.
boolean isComplex()
Returns cached or computed result if whether this Outlines polyline is a complex shape.
final Vertex removeVertex(final int position)
Removes the Vertex element at the given position.
int getVertexIndex(final Vertex vertex)
Outline()
Create an outline defined by control vertices.
A Vertex exposing Vec3f vertex- and texture-coordinates.
boolean equals(final Object obj)
Basic Float math utility functions.
static boolean isEqual2(final float a, final float b)
Returns true if both values are equal, i.e.
boolean isEqual(final Vec3f o, final float epsilon)
Equals check using a given FloatUtil#EPSILON value and FloatUtil#isEqual(float, float,...
static Winding getWinding(final Vert2fImmutable a, final Vert2fImmutable b, final Vert2fImmutable c)
Compute the winding of the 3 given points.
static boolean isConvex1(final List< Vertex > polyline, final boolean shortIsConvex)
Returns whether the given on-curve polyline points denotes a convex shape with O(n) complexity.
Axis Aligned Bounding Box.
final boolean equals(final Object obj)
final AABBox reset()
Resets this box to the inverse low/high, allowing the next resize(float, float, float) command to hit...
final float getSize()
Get the size of this AABBox where the size is represented by the length of the vector between low and...
final AABBox resize(final AABBox newBox)
Resize the AABBox to encapsulate another AABox.
Winding direction, either clockwise (CW) or counter-clockwise (CCW).
CCW
Counter-Clockwise (CCW) positive winding direction.