aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/com/jogamp/graph
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-05-06 14:39:17 +0200
committerSven Gothel <[email protected]>2011-05-06 14:39:17 +0200
commitd75835796900cac602f7e5789601ffba0a27efe2 (patch)
tree4331f4fa053f2f2ea02eee4c1974d7ea71689be0 /src/jogl/classes/com/jogamp/graph
parent59aa8737528743b83cf56b804c9d713bc325c97c (diff)
Graph: More std. functionality (equals, clone) / Better in-place transformation (cubic -> quadratic)
Impl. more of John Pritchard <[email protected]> proposal https://github.com/syntelos/jogl/commit/05a7ec92d30e1e688b1eb7cc317cad83a0e8fd60 +++ More std. functionality (equals, deep clone) of AABBox, Vertex, Outline and OutlineShape. Simplify Vertex: - Remove 2 component constructor - Add on-curve in Vertex.Factory / Constructor - Adding equals(Object) - Remove Comparable/compareTo, since we only can make an equals statement Outline/OutlineShape: Handle dirty flag for boundary (new set/remove operation) OutlineShape: Better in-place transformation (cubic -> quadratic)
Diffstat (limited to 'src/jogl/classes/com/jogamp/graph')
-rwxr-xr-xsrc/jogl/classes/com/jogamp/graph/curve/OutlineShape.java283
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/AABBox.java66
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/Outline.java189
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/Vertex.java29
-rw-r--r--src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java116
-rwxr-xr-xsrc/jogl/classes/com/jogamp/graph/math/VectorUtil.java19
6 files changed, 480 insertions, 222 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
index d0413b1e4..fa8494d4e 100755
--- a/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
+++ b/src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java
@@ -30,6 +30,7 @@ package com.jogamp.graph.curve;
import java.util.ArrayList;
import java.util.Collections;
+import com.jogamp.graph.geom.AABBox;
import com.jogamp.graph.geom.Outline;
import com.jogamp.graph.geom.Triangle;
import com.jogamp.graph.geom.Vertex;
@@ -91,12 +92,12 @@ import com.jogamp.graph.curve.tess.CDTriangulator2D;
* @see Outline
* @see Region
*/
-public class OutlineShape {
+public class OutlineShape implements Comparable<OutlineShape> {
/**
- * Outline has original user state (vertices) until transformed.
+ * Outline's vertices have undefined state until transformed.
*/
public enum VerticesState {
- ORIGINAL(0), QUADRATIC_NURBS(1);
+ UNDEFINED(0), QUADRATIC_NURBS(1);
public final int state;
@@ -111,14 +112,19 @@ public class OutlineShape {
/** The list of {@link Outline}s that are part of this
* outline shape.
*/
- private ArrayList<Outline> outlines = new ArrayList<Outline>(3);
+ private ArrayList<Outline> outlines;
+ private AABBox bbox;
+ private boolean dirtyBBox;
/** Create a new Outline based Shape
*/
public OutlineShape(Vertex.Factory<? extends Vertex> factory) {
- vertexFactory = factory;
- outlines.add(new Outline());
- outlineState = VerticesState.ORIGINAL;
+ this.vertexFactory = factory;
+ this.outlines = new ArrayList<Outline>(3);
+ this.outlines.add(new Outline());
+ this.outlineState = VerticesState.UNDEFINED;
+ this.bbox = new AABBox();
+ this.dirtyBBox = false;
}
/** Returns the associated vertex factory of this outline shape
@@ -126,6 +132,10 @@ public class OutlineShape {
*/
public final Vertex.Factory<? extends Vertex> vertexFactory() { return vertexFactory; }
+ public int getOutlineNumber() {
+ return outlines.size();
+ }
+
/** Add a new empty {@link Outline}
* to the shape, this new outline will
* be placed at the end of the outline list.
@@ -137,28 +147,98 @@ public class OutlineShape {
outlines.add(new Outline());
}
- /** Adds an {@link Outline} to the OutlineShape object
- * if last outline of the shape is empty, it will replace
- * that last Outline with the new one. If outline is empty,
- * it will do nothing.
- * @param outline an Outline object
+ /** Appends the {@link Outline} element to the end,
+ * ensuring a clean tail.
+ * <p>A clean tail is ensured, ie no double empty Outlines. </p>
+ * @param outline Outline object to be added
+ * @throws NullPointerException if the {@link Outline} element is null
*/
- public void addOutline(Outline outline){
- if(outline.isEmpty()){
- return;
+ public void addOutline(Outline outline) throws NullPointerException {
+ addOutline(outlines.size(), outline);
+ }
+
+ /** Insert the {@link Outline} element at the given {@code position}.
+ * <p>If the {@code position} indicates the end of this list,
+ * a clean tail is ensured, ie no double empty Outlines. </p>
+ * @param position of the added Outline
+ * @param outline Outline object to be added
+ * @throws NullPointerException if the {@link Outline} element is null
+ * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position > getOutlineNumber())
+ */
+ public void addOutline(int position, Outline outline) throws NullPointerException, IndexOutOfBoundsException {
+ if (null == outline) {
+ throw new NullPointerException("outline is null");
}
- if(getLastOutline().isEmpty()){
- outlines.remove(getLastOutline());
+ if(outlines.size() == position) {
+ if(outline.isEmpty()) {
+ return;
+ }
+ if(getLastOutline().isEmpty()) {
+ outlines.set(position-1, outline);
+ if(!dirtyBBox) {
+ bbox.resize(outline.getBounds());
+ }
+ }
+ } else {
+ outlines.add(position, outline);
+ if(!dirtyBBox) {
+ bbox.resize(outline.getBounds());
+ }
}
- outlines.add(outline);
}
-
+
+ /** Replaces the {@link Outline} element at the given {@code position}.
+ * <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p>
+ *
+ * @param position of the replaced Outline
+ * @param outline replacement Outline object
+ * @throws NullPointerException if the {@link Outline} element is null
+ * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber())
+ */
+ public void setOutline(int position, Outline outline) throws NullPointerException, IndexOutOfBoundsException {
+ if (null == outline) {
+ throw new NullPointerException("outline is null");
+ }
+ outlines.set(position, outline);
+ dirtyBBox = true;
+ }
+
+ /** Removes the {@link Outline} element at the given {@code position}.
+ * <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p>
+ *
+ * @param position of the to be removed Outline
+ * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber())
+ */
+ public final Outline removeOutline(int position) throws IndexOutOfBoundsException {
+ dirtyBBox = true;
+ return outlines.remove(position);
+ }
+
+ /** Get the last added outline to the list
+ * of outlines that define the shape
+ * @return the last outline
+ */
+ public final Outline getLastOutline(){
+ return outlines.get(outlines.size()-1);
+ }
+
+ /** @return the {@code Outline} at {@code position}
+ * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getOutlineNumber())
+ */
+ public Outline getOutline(int position) throws IndexOutOfBoundsException {
+ return outlines.get(position);
+ }
+
/** Adds a vertex to the last open outline in the
* shape.
* @param v the vertex to be added to the OutlineShape
*/
public final void addVertex(Vertex v){
- getLastOutline().addVertex(v);
+ final Outline lo = getLastOutline();
+ lo.addVertex(v);
+ if(!dirtyBBox) {
+ bbox.resize(lo.getBounds());
+ }
}
/** Add a 2D {@link Vertex} to the last outline by defining the coordniate attribute
@@ -170,7 +250,7 @@ public class OutlineShape {
* of the shape around this vertex.
*/
public final void addVertex(float x, float y, boolean onCurve) {
- getLastOutline().addVertex(vertexFactory, x, y, onCurve);
+ addVertex(vertexFactory.create(x, y, 0f, onCurve));
}
/** Add a 3D {@link Vertex} to the last outline by defining the coordniate attribute
@@ -182,7 +262,7 @@ public class OutlineShape {
* of the shape around this vertex.
*/
public final void addVertex(float x, float y, float z, boolean onCurve) {
- getLastOutline().addVertex(vertexFactory, x, y, z, onCurve);
+ addVertex(vertexFactory.create(x, y, z, onCurve));
}
/** Add a vertex to the last outline by passing a float array and specifying the
@@ -197,7 +277,7 @@ public class OutlineShape {
* of the shape around this vertex.
*/
public final void addVertex(float[] coordsBuffer, int offset, int length, boolean onCurve) {
- getLastOutline().addVertex(vertexFactory, coordsBuffer, offset, length, onCurve);
+ addVertex(vertexFactory.create(coordsBuffer, offset, length, onCurve));
}
/** Closes the last outline in the shape
@@ -209,62 +289,59 @@ public class OutlineShape {
getLastOutline().setClosed(true);
}
- /** Get the last added outline to the list
- * of outlines that define the shape
- * @return the last outline
+ /**
+ * @return the outline's vertices state, {@link OutlineShape.VerticesState}
*/
- public final Outline getLastOutline(){
- return outlines.get(outlines.size()-1);
+ public final VerticesState getOutlineState() {
+ return outlineState;
}
- /** Make sure that the outlines represent
- * the specified destinationType, if not
- * transform outlines to destination type.
- * @param destinationType TODO
+
+ /** Ensure the outlines represent
+ * the specified destinationType.
+ *
+ * @param destinationType the target outline's vertices state. Currently only {@link OutlineShape.VerticesState#QUADRATIC_NURBS} are supported.
*/
public void transformOutlines(VerticesState destinationType){
if(outlineState != destinationType){
if(destinationType == VerticesState.QUADRATIC_NURBS){
- transformOutlinesQuadratic();
+ transformOutlines2Quadratic();
} else {
throw new IllegalStateException("destinationType "+destinationType.name()+" not supported (currently "+outlineState.name()+")");
}
}
}
- private void transformOutlinesQuadratic(){
- ArrayList<Outline> newOutlines = new ArrayList<Outline>(3);
-
- /**loop over the outlines and make sure no
- * adj off-curve vertices
- */
- for(Outline outline:outlines){
- Outline newOutline = new Outline();
-
- ArrayList<Vertex> vertices = outline.getVertices();
- int size =vertices.size()-1;
- for(int i=0;i<size;i++){
- Vertex currentVertex = vertices.get(i);
- Vertex nextVertex = vertices.get((i+1)%size);
- if(!(currentVertex.isOnCurve()) && !(nextVertex.isOnCurve())) {
- newOutline.addVertex(currentVertex);
-
- float[] newCoords = VectorUtil.mid(currentVertex.getCoord(), nextVertex.getCoord());
- newOutline.addVertex(vertexFactory, newCoords, 0, 3, true);
- }
- else {
- newOutline.addVertex(currentVertex);
- }
+ private void transformOutlines2Quadratic(){
+ final int count = getOutlineNumber();
+ for (int cc = 0; cc < count; cc++){
+ final Outline outline = getOutline(cc);
+ int vertexNumberLessOne = outline.getVertexNumber() - 1;
+ for(int i=0; i < vertexNumberLessOne; i++) {
+ final Vertex currentVertex = outline.getVertex(i);
+ final Vertex nextVertex = outline.getVertex(i+1);
+ if ( !currentVertex.isOnCurve() && !nextVertex.isOnCurve() ) {
+ final float[] newCoords = VectorUtil.mid(currentVertex.getCoord(), nextVertex.getCoord());
+ final Vertex v = vertexFactory.create(newCoords, 0, 3, true);
+ v.setOnCurve(true);
+ i++;
+ vertexNumberLessOne++;
+ outline.addVertex(i, v);
+ }
}
- newOutlines.add(newOutline);
+ // Cut off last vertex (which is on-curve)
+ // FIXME: original code skipped the last element (it _is_ unrelated to the xform above)
+ // FIXME: understand why the last element produces artifacts in rendering
+ if( vertexNumberLessOne >= 0 ) {
+ outline.removeVertex(vertexNumberLessOne);
+ }
}
- outlines = newOutlines;
outlineState = VerticesState.QUADRATIC_NURBS;
}
private void generateVertexIds(){
int maxVertexId = 0;
- for(Outline outline:outlines){
- ArrayList<Vertex> vertices = outline.getVertices();
+ for(int i=0; i<outlines.size(); i++) {
+ final ArrayList<Vertex> vertices = outlines.get(i).getVertices();
for(Vertex vert:vertices){
vert.setId(maxVertexId);
maxVertexId++;
@@ -272,18 +349,17 @@ public class OutlineShape {
}
}
- /** @return the list of vertices associated with the
- * {@code Outline} list of this object
+ /** @return the list of concatenated vertices associated with all
+ * {@code Outline}s of this object
*/
public ArrayList<Vertex> getVertices(){
ArrayList<Vertex> vertices = new ArrayList<Vertex>();
- for(Outline polyline:outlines){
- vertices.addAll(polyline.getVertices());
+ for(int i=0; i<outlines.size(); i++) {
+ vertices.addAll(outlines.get(i).getVertices());
}
return vertices;
}
-
/**Triangulate the {@link OutlineShape} generating a list of triangles
* @return an arraylist of triangles representing the filled region
* which is produced by the combination of the outlines
@@ -314,4 +390,81 @@ public class OutlineShape {
Collections.sort(outlines);
Collections.reverse(outlines);
}
+
+ /** Compare two outline shapes with Bounding Box area
+ * as criteria.
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public final int compareTo(OutlineShape outline) {
+ float size = getBounds().getSize();
+ float newSize = outline.getBounds().getSize();
+ if(size < newSize){
+ return -1;
+ }
+ else if(size > newSize){
+ return 1;
+ }
+ return 0;
+ }
+
+ private final void validateBoundingBox() {
+ dirtyBBox = false;
+ bbox.reset();
+ for (int i=0; i<outlines.size(); i++) {
+ bbox.resize(outlines.get(i).getBounds());
+ }
+ }
+
+ public final AABBox getBounds() {
+ if (dirtyBBox) {
+ validateBoundingBox();
+ }
+ return bbox;
+ }
+
+ /**
+ * @param obj the Object to compare this OutlineShape with
+ * @return true if {@code obj} is an OutlineShape, not null,
+ * same outlineState, equal bounds and equal outlines in the same order
+ */
+ public boolean equals(Object obj) {
+ if( obj == this) {
+ return true;
+ }
+ if( null == obj || !(obj instanceof OutlineShape) ) {
+ return false;
+ }
+ final OutlineShape o = (OutlineShape) obj;
+ if(getOutlineState() != o.getOutlineState()) {
+ return false;
+ }
+ if(getOutlineNumber() != o.getOutlineNumber()) {
+ return false;
+ }
+ if( !getBounds().equals( o.getBounds() ) ) {
+ return false;
+ }
+ for (int i=getOutlineNumber()-1; i>=0; i--) {
+ if( ! getOutline(i).equals( o.getOutline(i) ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return deep clone of this OutlineShape
+ */
+ public OutlineShape clone() {
+ OutlineShape o;
+ try {
+ o = (OutlineShape) super.clone();
+ } catch (CloneNotSupportedException e) { return null; /* never, ever */ }
+ o.bbox = bbox.clone();
+ o.outlines = new ArrayList<Outline>(outlines.size());
+ for(int i=0; i<outlines.size(); i++) {
+ o.outlines.add(outlines.get(i).clone());
+ }
+ return o;
+ }
}
diff --git a/src/jogl/classes/com/jogamp/graph/geom/AABBox.java b/src/jogl/classes/com/jogamp/graph/geom/AABBox.java
index 7051e9110..87f084919 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/AABBox.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/AABBox.java
@@ -35,7 +35,7 @@ import com.jogamp.graph.math.VectorUtil;
* right corner of the box.
*
*/
-public class AABBox {
+public class AABBox implements Cloneable {
private float[] low = new float[3];
private float[] high = new float[3];
private float[] center = new float[3];
@@ -79,7 +79,7 @@ public class AABBox {
}
/** resets this box to the inverse low/high, allowing the next {@link #resize(float, float, float)} command to hit. */
- public void reset() {
+ public final void reset() {
setLow(Float.MAX_VALUE,Float.MAX_VALUE,Float.MAX_VALUE);
setHigh(-1*Float.MAX_VALUE,-1*Float.MAX_VALUE,-1*Float.MAX_VALUE);
center[0] = 0f;
@@ -90,11 +90,11 @@ public class AABBox {
/** Get the max xyz-coordinates
* @return a float array containing the max xyz coordinates
*/
- public float[] getHigh() {
+ public final float[] getHigh() {
return high;
}
- private void setHigh(float hx, float hy, float hz) {
+ private final void setHigh(float hx, float hy, float hz) {
this.high[0] = hx;
this.high[1] = hy;
this.high[2] = hz;
@@ -103,11 +103,11 @@ public class AABBox {
/** Get the min xyz-coordinates
* @return a float array containing the min xyz coordinates
*/
- public float[] getLow() {
+ public final float[] getLow() {
return low;
}
- private void setLow(float lx, float ly, float lz) {
+ private final void setLow(float lx, float ly, float lz) {
this.low[0] = lx;
this.low[1] = ly;
this.low[2] = lz;
@@ -116,7 +116,7 @@ public class AABBox {
/** Resize the AABBox to encapsulate another AABox
* @param newBox AABBox to be encapsulated in
*/
- public void resize(AABBox newBox) {
+ public final void resize(AABBox newBox) {
float[] newLow = newBox.getLow();
float[] newHigh = newBox.getHigh();
@@ -139,7 +139,7 @@ public class AABBox {
computeCenter();
}
- private void computeCenter() {
+ private final void computeCenter() {
center[0] = (high[0] + low[0])/2;
center[1] = (high[1] + low[1])/2;
center[2] = (high[2] + low[2])/2;
@@ -151,7 +151,7 @@ public class AABBox {
* @param y y-axis coordinate value
* @param z z-axis coordinate value
*/
- public void resize(float x, float y, float z) {
+ public final void resize(float x, float y, float z) {
/** test low */
if (x < low[0])
low[0] = x;
@@ -171,6 +171,15 @@ public class AABBox {
computeCenter();
}
+ /** Resize the AABBox to encapsulate the passed
+ * xyz-coordinates.
+ * @param xyz xyz-axis coordinate values
+ * @param offset of the array
+ */
+ public final void resize(float[] xyz, int offset) {
+ resize(xyz[0+offset], xyz[1+offset], xyz[2+offset]);
+ }
+
/** Check if the x & y coordinates are bounded/contained
* by this AABBox
* @param x x-axis coordinate value
@@ -178,7 +187,7 @@ public class AABBox {
* @return true if x belong to (low.x, high.x) and
* y belong to (low.y, high.y)
*/
- public boolean contains(float x, float y) {
+ public final boolean contains(float x, float y) {
if(x<low[0] || x>high[0]){
return false;
}
@@ -196,7 +205,7 @@ public class AABBox {
* @return true if x belong to (low.x, high.x) and
* y belong to (low.y, high.y) and z belong to (low.z, high.z)
*/
- public boolean contains(float x, float y, float z) {
+ public final boolean contains(float x, float y, float z) {
if(x<low[0] || x>high[0]){
return false;
}
@@ -217,7 +226,7 @@ public class AABBox {
* @param h hight
* @return true if this AABBox might have a common region with this 2D region
*/
- public boolean intersects(float x, float y, float w, float h) {
+ public final boolean intersects(float x, float y, float w, float h) {
if (w <= 0 || h <= 0) {
return false;
}
@@ -241,21 +250,21 @@ public class AABBox {
* length of the vector between low and high.
* @return a float representing the size of the AABBox
*/
- public float getSize() {
+ public final float getSize() {
return VectorUtil.computeLength(low, high);
}
/**Get the Center of the AABBox
* @return the xyz-coordinates of the center of the AABBox
*/
- public float[] getCenter() {
+ public final float[] getCenter() {
return center;
}
/** Scale the AABBox by a constant
* @param size a constant float value
*/
- public void scale(float size) {
+ public final void scale(float size) {
float[] diffH = new float[3];
diffH[0] = high[0] - center[0];
diffH[1] = high[1] - center[1];
@@ -274,30 +283,43 @@ public class AABBox {
low = VectorUtil.vectorAdd(center, diffL);
}
- public float getMinX() {
+ public final float getMinX() {
return low[0];
}
- public float getMinY() {
+ public final float getMinY() {
return low[1];
}
- public float getWidth(){
+ public final float getWidth(){
return high[0] - low[0];
}
- public float getHeight() {
+ public final float getHeight() {
return high[1] - low[1];
}
- public float getDepth() {
+ public final float getDepth() {
return high[2] - low[2];
}
- public AABBox clone() {
+
+ public final AABBox clone() {
return new AABBox(this.low, this.high);
}
- public String toString() {
+ public final boolean equals(Object obj) {
+ if( obj == this ) {
+ return true;
+ }
+ if( null == obj || !(obj instanceof AABBox) ) {
+ return false;
+ }
+ final AABBox other = (AABBox) obj;
+ return VectorUtil.checkEquality(low, other.low) &&
+ VectorUtil.checkEquality(high, other.high) ;
+ }
+
+ public final String toString() {
return "[ "+low[0]+"/"+low[1]+"/"+low[1]+" .. "+high[0]+"/"+high[0]+"/"+high[0]+", ctr "+
center[0]+"/"+center[1]+"/"+center[1]+" ]";
}
diff --git a/src/jogl/classes/com/jogamp/graph/geom/Outline.java b/src/jogl/classes/com/jogamp/graph/geom/Outline.java
index 315be002f..e0c29cb84 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/Outline.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/Outline.java
@@ -43,110 +43,116 @@ import com.jogamp.graph.math.VectorUtil;
*
* @see OutlineShape, Region
*/
-public class Outline implements Comparable<Outline> {
+public class Outline implements Cloneable, Comparable<Outline> {
private ArrayList<Vertex> vertices = new ArrayList<Vertex>(3);
private boolean closed = false;
- private AABBox box = new AABBox();
+ private AABBox bbox = new AABBox();
+ private boolean dirtyBBox = false;
/**Create an outline defined by control vertices.
* An outline can contain off Curve vertices which define curved
* regions in the outline.
*/
- public Outline(){
+ public Outline() {
+ }
+ public final int getVertexNumber() {
+ return vertices.size();
}
- /** Add a vertex to the outline. The {@link Vertex} is added at the
- * end of the outline loop/strip.
+ /** Appends a vertex to the outline loop/strip.
* @param vertex Vertex to be added
+ * @throws NullPointerException if the {@link Vertex} element is null
*/
- public final void addVertex(Vertex vertex) {
- vertices.add(vertex);
- box.resize(vertex.getX(), vertex.getY(), vertex.getZ());
+ public final void addVertex(Vertex vertex) throws NullPointerException {
+ addVertex(vertices.size(), vertex);
}
- /** Add a {@link Vertex} by specifying its 2D attributes to the outline.
- * The {@link Vertex} is added at the
- * end of the outline loop/strip.
- * @param factory a {@link Factory} to get the required Vertex impl
- * @param x the x coordinate
- * @param y the y coordinate
- * @param onCurve flag if this vertex is on the final curve or defines a curved region
- * of the shape around this vertex.
+ /** Insert the {@link Vertex} element at the given {@code position} to the outline loop/strip.
+ * @param position of the added Vertex
+ * @param vertex Vertex object to be added
+ * @throws NullPointerException if the {@link Vertex} element is null
+ * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position > getVertexNumber())
*/
- public final void addVertex(Vertex.Factory<? extends Vertex> factory, float x, float y, boolean onCurve) {
- addVertex(factory, x, y, 0f, onCurve);
+ public final void addVertex(int position, Vertex vertex) throws NullPointerException, IndexOutOfBoundsException {
+ if (null == vertex) {
+ throw new NullPointerException("vertex is null");
+ }
+ vertices.add(position, vertex);
+ if(!dirtyBBox) {
+ bbox.resize(vertex.getX(), vertex.getY(), vertex.getZ());
+ }
}
-
- /** Add a {@link Vertex} by specifying its 3D attributes to the outline.
- * The {@link Vertex} is added at the
- * end of the outline loop/strip.
- * @param factory a {@link Factory} to get the required Vertex impl
- * @param x the x coordinate
- * @param y the y coordinate
- * @param z the z coordinate
- * @param onCurve flag if this vertex is on the final curve or defines a curved region
- * of the shape around this vertex.
+
+ /** Replaces the {@link Vertex} element at the given {@code position}.
+ * <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p>
+ *
+ * @param position of the replaced Vertex
+ * @param vertex replacement Vertex object
+ * @throws NullPointerException if the {@link Outline} element is null
+ * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getVertexNumber())
*/
- public final void addVertex(Vertex.Factory<? extends Vertex> factory, float x, float y, float z, boolean onCurve) {
- Vertex v = factory.create(x, y, z);
- v.setOnCurve(onCurve);
- addVertex(v);
+ public final void setVertex(int position, Vertex vertex) throws NullPointerException, IndexOutOfBoundsException {
+ if (null == vertex) {
+ throw new NullPointerException("vertex is null");
+ }
+ vertices.set(position, vertex);
+ dirtyBBox = true;
}
- /** Add a vertex to the outline by passing a float array and specifying the
- * offset and length in which. The attributes of the vertex are located.
- * The attributes should be continuous (stride = 0).
- * Attributes which value are not set (when length less than 3)
- * are set implicitly to zero.
- * @param factory a {@link Factory} to get the required Vertex impl
- * @param coordsBuffer the coordinate array where the vertex attributes are to be picked from
- * @param offset the offset in the buffer to the x coordinate
- * @param length the number of attributes to pick from the buffer (maximum 3)
- * @param onCurve flag if this vertex is on the final curve or defines a curved region
- * of the shape around this vertex.
- */
- public final void addVertex(Vertex.Factory<? extends Vertex> factory, float[] coordsBuffer, int offset, int length, boolean onCurve) {
- Vertex v = factory.create(coordsBuffer, offset, length);
- v.setOnCurve(onCurve);
- addVertex(v);
+ public final Vertex getVertex(int index){
+ return vertices.get(index);
}
- public Vertex getVertex(int index){
- return vertices.get(index);
+ /** Removes the {@link Vertex} element at the given {@code position}.
+ * <p>Sets the bounding box dirty, hence a next call to {@link #getBounds()} will validate it.</p>
+ *
+ * @param position of the to be removed Vertex
+ * @throws IndexOutOfBoundsException if position is out of range (position < 0 || position >= getVertexNumber())
+ */
+ public final Vertex removeVertex(int position) throws IndexOutOfBoundsException {
+ dirtyBBox = true;
+ return vertices.remove(position);
}
- public boolean isEmpty(){
+ public final boolean isEmpty(){
return (vertices.size() == 0);
}
- public Vertex getLastVertex(){
+
+ public final Vertex getLastVertex(){
if(isEmpty()){
return null;
}
return vertices.get(vertices.size()-1);
}
- public ArrayList<Vertex> getVertices() {
+ public final ArrayList<Vertex> getVertices() {
return vertices;
}
- public void setVertices(ArrayList<Vertex> vertices) {
+
+ /**
+ * Use the given outline loop/strip.
+ * <p>Validates the bounding box.</p>
+ *
+ * @param vertices the new outline loop/strip
+ */
+ public final void setVertices(ArrayList<Vertex> vertices) {
this.vertices = vertices;
+ validateBoundingBox();
}
- public AABBox getBox() {
- return box;
- }
- public boolean isClosed() {
+
+ public final boolean isClosed() {
return closed;
}
-
+
/** define if this outline is closed or not.
* if set to closed, checks if the last vertex is
* equal to the first vertex. If not Equal adds a
* vertex at the end to the list.
* @param closed
*/
- public void setClosed(boolean closed) {
+ public final void setClosed(boolean closed) {
this.closed = closed;
if(closed){
Vertex first = vertices.get(0);
@@ -162,9 +168,9 @@ public class Outline implements Comparable<Outline> {
* as criteria.
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
- public int compareTo(Outline outline) {
- float size = box.getSize();
- float newSize = outline.getBox().getSize();
+ public final int compareTo(Outline outline) {
+ float size = getBounds().getSize();
+ float newSize = outline.getBounds().getSize();
if(size < newSize){
return -1;
}
@@ -173,4 +179,61 @@ public class Outline implements Comparable<Outline> {
}
return 0;
}
+
+ private final void validateBoundingBox() {
+ dirtyBBox = false;
+ bbox.reset();
+ for (int i=0; i<vertices.size(); i++) {
+ bbox.resize(vertices.get(i).getCoord(), 0);
+ }
+ }
+
+ public final AABBox getBounds() {
+ if (dirtyBBox) {
+ validateBoundingBox();
+ }
+ return bbox;
+ }
+
+ /**
+ * @param obj the Object to compare this Outline with
+ * @return true if {@code obj} is an Outline, not null, equals bounds and equal vertices in the same order
+ */
+ public boolean equals(Object obj) {
+ if( obj == this) {
+ return true;
+ }
+ if( null == obj || !(obj instanceof Outline) ) {
+ return false;
+ }
+ final Outline o = (Outline) obj;
+ if(getVertexNumber() != o.getVertexNumber()) {
+ return false;
+ }
+ if( !getBounds().equals( o.getBounds() ) ) {
+ return false;
+ }
+ for (int i=getVertexNumber()-1; i>=0; i--) {
+ if( ! getVertex(i).equals( o.getVertex(i) ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return deep clone of this Outline
+ */
+ public Outline clone() {
+ Outline o;
+ try {
+ o = (Outline) super.clone();
+ } catch (CloneNotSupportedException e) { return null; /* never, ever */ }
+ o.bbox = bbox.clone();
+ o.vertices = new ArrayList<Vertex>(vertices.size());
+ for(int i=0; i<vertices.size(); i++) {
+ o.vertices.add(vertices.get(i).clone());
+ }
+ return o;
+ }
}
diff --git a/src/jogl/classes/com/jogamp/graph/geom/Vertex.java b/src/jogl/classes/com/jogamp/graph/geom/Vertex.java
index 859add943..3080f32cc 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/Vertex.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/Vertex.java
@@ -30,22 +30,21 @@ package com.jogamp.graph.geom;
/**
* A Vertex with custom memory layout using custom factory.
*/
-public interface Vertex extends Comparable<Vertex>, Cloneable {
+public interface Vertex extends Cloneable {
public static interface Factory <T extends Vertex> {
T create();
- T create(float x, float y);
+ T create(float x, float y, float z, boolean onCurve);
- T create(float x, float y, float z);
-
- T create(float[] coordsBuffer, int offset, int length);
+ T create(float[] coordsBuffer, int offset, int length, boolean onCurve);
}
- void setCoord(float x, float y);
-
void setCoord(float x, float y, float z);
+ /**
+ * @see System#arraycopy(Object, int, Object, int, int) for thrown IndexOutOfBoundsException
+ */
void setCoord(float[] coordsBuffer, int offset, int length);
float[] getCoord();
@@ -70,11 +69,23 @@ public interface Vertex extends Comparable<Vertex>, Cloneable {
void setId(int id);
- int compareTo(Vertex p);
-
float[] getTexCoord();
void setTexCoord(float s, float t);
+ /**
+ * @see System#arraycopy(Object, int, Object, int, int) for thrown IndexOutOfBoundsException
+ */
+ void setTexCoord(float[] texCoordsBuffer, int offset, int length);
+
+ /**
+ * @param obj the Object to compare this Vertex with
+ * @return true if {@code obj} is a Vertex and not null, on-curve flag is equal and has same vertex- and tex-coords.
+ */
+ boolean equals(Object obj);
+
+ /**
+ * @return deep clone of this Vertex
+ */
Vertex clone();
}
diff --git a/src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java b/src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java
index 6241d60df..9dade17e9 100644
--- a/src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java
+++ b/src/jogl/classes/com/jogamp/graph/geom/opengl/SVertex.java
@@ -27,7 +27,6 @@
*/
package com.jogamp.graph.geom.opengl;
-
import com.jogamp.graph.geom.Vertex;
import com.jogamp.graph.math.VectorUtil;
@@ -38,7 +37,7 @@ import com.jogamp.graph.math.VectorUtil;
public class SVertex implements Vertex {
private int id = Integer.MAX_VALUE;
protected float[] coord = new float[3];
- protected boolean onCurve = true;
+ protected boolean onCurve;
private float[] texCoord = new float[2];
static final Factory factory = new Factory();
@@ -46,133 +45,130 @@ public class SVertex implements Vertex {
public static Factory factory() { return factory; }
public static class Factory implements Vertex.Factory<SVertex> {
- @Override
public SVertex create() {
return new SVertex();
}
- @Override
- public SVertex create(float x, float y) {
- return new SVertex(x, y);
- }
-
- @Override
- public SVertex create(float x, float y, float z) {
- return new SVertex(x, y, z);
+ public SVertex create(float x, float y, float z, boolean onCurve) {
+ return new SVertex(x, y, z, onCurve);
}
- @Override
- public SVertex create(float[] coordsBuffer, int offset, int length) {
- return new SVertex(coordsBuffer, offset, length);
+ public SVertex create(float[] coordsBuffer, int offset, int length, boolean onCurve) {
+ return new SVertex(coordsBuffer, offset, length, onCurve);
}
}
public SVertex() {
}
- public SVertex(float x, float y) {
- setCoord(x, y);
- }
- public SVertex(float x, float y, float z) {
+ public SVertex(float x, float y, float z, boolean onCurve) {
setCoord(x, y, z);
- }
- public SVertex(float[] coordsBuffer, int offset, int length) {
+ setOnCurve(onCurve);
+ }
+
+ public SVertex(float[] coordsBuffer, int offset, int length, boolean onCurve) {
setCoord(coordsBuffer, offset, length);
+ setOnCurve(onCurve);
}
- public void setCoord(float x, float y) {
- this.coord[0] = x;
- this.coord[1] = y;
- this.coord[2] = 0f;
+ public SVertex(float[] coordsBuffer, int offset, int length,
+ float[] texCoordsBuffer, int offsetTC, int lengthTC, boolean onCurve) {
+ setCoord(coordsBuffer, offset, length);
+ setTexCoord(texCoordsBuffer, offsetTC, lengthTC);
+ setOnCurve(onCurve);
}
-
- public void setCoord(float x, float y, float z) {
+
+ public final void setCoord(float x, float y, float z) {
this.coord[0] = x;
this.coord[1] = y;
this.coord[2] = z;
}
- public void setCoord(float[] coordsBuffer, int offset, int length) {
- if(length > coordsBuffer.length - offset) {
- throw new IndexOutOfBoundsException("coordsBuffer too small: "+coordsBuffer.length+" - "+offset+" < "+length);
- }
- if(length > 3) {
- throw new IndexOutOfBoundsException("length too big: "+length+" > "+3);
- }
- int i=0;
- while(i<length) {
- this.coord[i++] = coordsBuffer[offset++];
- }
+ public final void setCoord(float[] coordsBuffer, int offset, int length) {
+ System.arraycopy(coordsBuffer, offset, coord, 0, length);
}
- public float[] getCoord() {
+ public final float[] getCoord() {
return coord;
}
- public void setX(float x) {
+ public final void setX(float x) {
this.coord[0] = x;
}
- public void setY(float y) {
+ public final void setY(float y) {
this.coord[1] = y;
}
- public void setZ(float z) {
+ public final void setZ(float z) {
this.coord[2] = z;
}
- public float getX() {
+ public final float getX() {
return this.coord[0];
}
- public float getY() {
+ public final float getY() {
return this.coord[1];
}
- public float getZ() {
+ public final float getZ() {
return this.coord[2];
}
- public boolean isOnCurve() {
+ public final boolean isOnCurve() {
return onCurve;
}
- public void setOnCurve(boolean onCurve) {
+ public final void setOnCurve(boolean onCurve) {
this.onCurve = onCurve;
}
- public int getId(){
+ public final int getId(){
return id;
}
- public void setId(int id){
+ public final void setId(int id){
this.id = id;
}
- public int compareTo(Vertex p) {
- if(VectorUtil.checkEquality(coord, p.getCoord())) {
- return 0;
+ public boolean equals(Object obj) {
+ if( obj == this) {
+ return true;
+ }
+ if( null == obj || !(obj instanceof Vertex) ) {
+ return false;
}
- return -1;
+ final Vertex v = (Vertex) obj;
+ return this == v ||
+ isOnCurve() == v.isOnCurve() &&
+ VectorUtil.checkEqualityVec2(getTexCoord(), v.getTexCoord()) &&
+ VectorUtil.checkEquality(getCoord(), v.getCoord()) ;
}
- public float[] getTexCoord() {
+ public final float[] getTexCoord() {
return texCoord;
}
- public void setTexCoord(float s, float t) {
+ public final void setTexCoord(float s, float t) {
this.texCoord[0] = s;
this.texCoord[1] = t;
}
-
+
+ public final void setTexCoord(float[] texCoordsBuffer, int offset, int length) {
+ System.arraycopy(texCoordsBuffer, offset, texCoord, 0, length);
+ }
+
+ /**
+ * @return deep clone of this Vertex, but keeping the id blank
+ */
public SVertex clone(){
- SVertex v = new SVertex(this.coord, 0, 3);
- v.setOnCurve(this.onCurve);
- return v;
+ return new SVertex(this.coord, 0, 3, this.texCoord, 0, 2, this.onCurve);
}
public String toString() {
- return "[ID: " + id + " X: " + coord[0]
- + " Y: " + coord[1] + " Z: " + coord[2] + "]";
+ return "[ID: " + id + ", onCurve: " + onCurve +
+ ": p " + coord[0] + ", " + coord[1] + ", " + coord[2] +
+ ", t " + texCoord[0] + ", " + texCoord[1] + "]";
}
}
diff --git a/src/jogl/classes/com/jogamp/graph/math/VectorUtil.java b/src/jogl/classes/com/jogamp/graph/math/VectorUtil.java
index 7cbb742e5..afab69f79 100755
--- a/src/jogl/classes/com/jogamp/graph/math/VectorUtil.java
+++ b/src/jogl/classes/com/jogamp/graph/math/VectorUtil.java
@@ -197,9 +197,22 @@ public class VectorUtil {
*/
public static boolean checkEquality(float[] v1, float[] v2)
{
- if(Float.compare(v1[0], v2[0]) == 0
- && Float.compare(v1[1] , v2[1]) == 0
- && Float.compare(v1[2], v2[2]) == 0 )
+ if(Float.compare(v1[0], v2[0]) == 0 &&
+ Float.compare(v1[1], v2[1]) == 0 &&
+ Float.compare(v1[2], v2[2]) == 0 )
+ return true;
+ return false;
+ }
+
+ /**Check equality of 2 vec2 vectors
+ * @param v1 vertex 1
+ * @param v2 vertex 2
+ * @return
+ */
+ public static boolean checkEqualityVec2(float[] v1, float[] v2)
+ {
+ if(Float.compare(v1[0], v2[0]) == 0 &&
+ Float.compare(v1[1], v2[1]) == 0)
return true;
return false;
}