00001 /******************************************************************************* 00002 * Copyright (c) 2014 Andrei Stoica. All rights reserved. This program and the accompanying 00003 * materials are made available under the terms of the GNU Public License v3.0 which accompanies 00004 * this distribution, and is available at http://www.gnu.org/licenses/gpl.html 00005 * 00006 * Contributors: Andrei Stoica - initial API and implementation during Google Summer of Code 2014 00007 ******************************************************************************/ 00008 00009 package edu.tum.cs.vis.model.util; 00010 00011 import javax.vecmath.Vector3f; 00012 00019 public class Edge { 00020 00024 private final Vector3f edge = new Vector3f(); 00025 00029 private final Vector3f invertedEdge = new Vector3f(); 00030 00034 private final Vertex[] vertices = new Vertex[2]; 00035 00039 private boolean isSharpEdge = false; 00040 00044 public Edge() { 00045 return; 00046 } 00047 00052 public Edge(Vertex position1, Vertex position2) { 00053 this.edge.set(position1); 00054 this.edge.sub(position2); 00055 this.invertedEdge.negate(edge); 00056 this.vertices[0] = position1; 00057 this.vertices[1] = position2; 00058 } 00059 00066 public Vector3f getEdgeValue() { 00067 return this.edge; 00068 } 00069 00076 public Vector3f getInvertedEdgeValue() { 00077 return this.invertedEdge; 00078 } 00079 00086 public Vertex[] getVerticesOfEdge() { 00087 return this.vertices; 00088 } 00089 00095 public boolean isSharpEdge() { 00096 return this.isSharpEdge; 00097 } 00098 00110 public boolean hasVertex(Vertex v) { 00111 if (v != null && (vertices[0].sameCoordinates(v) || vertices[1].sameCoordinates(v))) { 00112 return true; 00113 } 00114 return false; 00115 } 00116 00121 public void setEdgeValue() { 00122 if (this.vertices[0] == null || this.vertices[1] == null) { 00123 return; 00124 } 00125 this.edge.set(this.vertices[0]); 00126 this.edge.sub(this.vertices[1]); 00127 } 00128 00133 public void setInvertedEdgeValue() { 00134 this.invertedEdge.negate(this.edge); 00135 } 00136 00146 public void setVerticesOfEdge(final Vertex position1, final Vertex position2) { 00147 this.vertices[0] = position1; 00148 this.vertices[1] = position2; 00149 this.setEdgeValue(); 00150 this.setInvertedEdgeValue(); 00151 } 00152 00159 public void isSharpEdge(final boolean value) { 00160 this.isSharpEdge = value; 00161 } 00162 00171 public boolean isEqualTo(Edge edge) { 00172 if (this.vertices[0].sameCoordinates(edge.vertices[0]) 00173 && this.vertices[1].sameCoordinates(edge.vertices[1])) { 00174 return true; 00175 } 00176 if (this.vertices[0].sameCoordinates(edge.vertices[1]) 00177 && this.vertices[1].sameCoordinates(edge.vertices[0])) { 00178 return true; 00179 } 00180 return false; 00181 } 00182 00194 public boolean isCollinear(Edge edge) { 00195 // compute angle between the two edges in DEG (will result a value in [0,180] DEG) 00196 float angle = this.edge.angle(edge.edge) * 180.f / (float) Math.PI; 00197 // if the angle is in [0,angleTolerance] || [180-angleTolerance,180] then edges are 00198 // collinear 00199 if (angle <= Thresholds.ANGLE_TOLERANCE || angle >= (180.0f - Thresholds.ANGLE_TOLERANCE)) { 00200 return true; 00201 } 00202 return false; 00203 } 00204 00212 public boolean containsVertex(Vertex v) { 00213 if (vertices[0].sameCoordinates(v)) { 00214 return true; 00215 } 00216 if (vertices[1].sameCoordinates(v)) { 00217 return true; 00218 } 00219 Vector3f sideEdge = new Vector3f(v); 00220 sideEdge.sub(vertices[0]); 00221 sideEdge.cross(sideEdge, edge); 00222 if (sideEdge.length() == 0.0f) { 00223 return true; 00224 } 00225 return false; 00226 } 00227 00238 public boolean containsVertexInside(Vertex v) { 00239 Vector3f edgeRef = new Vector3f(invertedEdge); 00240 // create edge given the vertex to be compared 00241 Vector3f edgeCmp = new Vector3f(v); 00242 edgeCmp.sub(vertices[0]); 00243 if (edgeCmp.length() <= Thresholds.DISTANCE_TOLERANCE) { 00244 return false; 00245 } 00246 // get the angle (in DEG) between the two edges (in [0,180]) 00247 float angle = edgeRef.angle(edgeCmp) * 180.0f / (float) Math.PI; 00248 // check if the angle is bigger than the tolerance 00249 if (angle > Thresholds.ANGLE_TOLERANCE && angle < (180.f - Thresholds.ANGLE_TOLERANCE)) { 00250 return false; 00251 } 00252 // now the edges are parallel so v is on the ref edge 00253 // check if it is inside using dot product 00254 float dotProd = edgeCmp.dot(edgeRef); 00255 // the vertex is inside if dotProd in between the edgeRef with the tolerance levels 00256 // discounted for the edge vertices 00257 if (dotProd <= Thresholds.DISTANCE_TOLERANCE) { 00258 return false; 00259 } 00260 if (dotProd >= (edge.length() * (edge.length() - Thresholds.DISTANCE_TOLERANCE))) { 00261 return false; 00262 } 00263 return true; 00264 } 00265 00277 public boolean isDirectNeighbor(Edge nEdge) { 00278 if (this.isCollinear(nEdge)) { 00279 if ((this.vertices[0].sameCoordinates(nEdge.vertices[0]) && this.vertices[1] 00280 .sameCoordinates(nEdge.vertices[1])) 00281 || (this.vertices[1].sameCoordinates(nEdge.vertices[0]) && this.vertices[0] 00282 .sameCoordinates(nEdge.vertices[1]))) { 00283 return true; 00284 } else if ((this.containsVertexInside(nEdge.vertices[0])) 00285 || (this.containsVertexInside(nEdge.vertices[1])) 00286 || (nEdge.containsVertexInside(this.vertices[0])) 00287 || (nEdge.containsVertexInside(this.vertices[1]))) { 00288 return true; 00289 } 00290 } 00291 return false; 00292 } 00293 00294 @Override 00295 public String toString() { 00296 String print = "Edge: " + this.edge + "\n"; 00297 print = print + "Vertex1: " + this.vertices[0] + ", Vertex2: " + this.vertices[1]; 00298 return print; 00299 } 00300 }