Triangle.java
Go to the documentation of this file.
00001 /*******************************************************************************
00002  * Copyright (c) 2012 Stefan Profanter. 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: Stefan Profanter - initial API and implementation, Year: 2012
00007  ******************************************************************************/
00008 package edu.tum.cs.vis.model.util;
00009 
00010 import java.util.HashSet;
00011 import java.util.Set;
00012 import java.util.concurrent.locks.Lock;
00013 
00014 import javax.vecmath.Point2f;
00015 import javax.vecmath.Point3f;
00016 import javax.vecmath.Tuple3f;
00017 import javax.vecmath.Vector3d;
00018 import javax.vecmath.Vector3f;
00019 
00020 import org.apache.log4j.Logger;
00021 
00022 import processing.core.PConstants;
00023 import processing.core.PGraphics;
00024 
00031 public class Triangle extends DrawObject {
00032 
00036         private static final long       serialVersionUID        = -5164768039180386782L;
00037 
00041         private static Logger           logger                          = Logger.getLogger(Triangle.class);
00042 
00046         protected Point2f                       texPosition[];
00047 
00051         protected Vector3f                      normalVector            = null;
00052 
00056         protected Vector3f                      cornerarea                      = null;
00057 
00061         protected Point3f                       centroid;
00062 
00066         protected Set<Triangle>         neighbors                       = new HashSet<Triangle>(3);
00067 
00072         public Triangle() {
00073                 super(3);
00074         }
00075 
00086         public Triangle(Tuple3f p1, Tuple3f p2, Tuple3f p3) {
00087                 this(new Vertex(p1), new Vertex(p2), new Vertex(p3));
00088         }
00089 
00106         public Triangle(Tuple3f p1, Vector3f normP1, Tuple3f p2, Vector3f normP2, Tuple3f p3,
00107                         Vector3f normP3) {
00108                 super(3);
00109                 position[0] = new Vertex(p1, normP1);
00110                 position[1] = new Vertex(p2, normP2);
00111                 position[2] = new Vertex(p3, normP3);
00112         }
00113 
00124         public Triangle(Vertex p1, Vertex p2, Vertex p3) {
00125                 super(3);
00126                 position[0] = p1;
00127                 position[1] = p2;
00128                 position[2] = p3;
00129         }
00130 
00146         public boolean addNeighbor(Triangle neighbor, Lock lock) {
00147                 boolean add = false;
00148 
00149                 if (neighbors.size() >= 3) // for better performance skip if triangle has already all
00150                                                                         // neighbors set
00151                         return false;
00152 
00153                 add = isDirectNeighbor(neighbor);
00154 
00155                 if (add) {
00156                         if (lock != null)
00157                                 lock.lock();
00158                         // to make sure neighbors is not cached
00159                         synchronized (neighbors) {
00160                                 neighbors.add(neighbor);
00161                         }
00162                         synchronized (neighbor.neighbors) {
00163                                 neighbor.neighbors.add(this);
00164                         }
00165                         if (lock != null)
00166                                 lock.unlock();
00167                 }
00168                 return add;
00169         }
00170 
00178         public void removeNeighbor(Triangle n) {
00179                 if (neighbors != null) {
00180                         synchronized (neighbors) {
00181                                 neighbors.remove(n);
00182                         }
00183                 }
00184                 if (n.neighbors != null) {
00185                         synchronized (n.neighbors) {
00186                                 n.neighbors.remove(this);
00187                         }
00188                 }
00189         }
00190 
00200         public void draw(PGraphics g, DrawSettings drawSettings) {
00201                 applyColor(g, drawSettings);
00202 
00203                 if (drawSettings != null && drawSettings.drawType == DrawType.POINTS) {
00204 
00205                         for (int i = 0; i < position.length; i++) {
00206                                 if (position[i].overrideColor != null) {
00207                                         g.stroke(position[i].overrideColor.getRed(),
00208                                                         position[i].overrideColor.getGreen(),
00209                                                         position[i].overrideColor.getBlue());
00210                                         g.noFill();
00211                                 } else if (drawSettings.getOverrideColor() == null && position[i].color != null) {
00212                                         g.stroke(position[i].color.getRed(), position[i].color.getGreen(),
00213                                                         position[i].color.getBlue());
00214                                         g.noFill();
00215                                 }
00216                                 g.point(position[i].x, position[i].y, position[i].z);
00217                         }
00218                 } else {
00219                         g.beginShape(PConstants.TRIANGLES);
00220                         if (appearance == null || appearance.getImageReference() == null /*no appearance*/
00221                                         || drawSettings.getOverrideColor() != null /*override*/
00222                                         || position[0].overrideColor != null /* points have colors */) {
00223                                 // no texture only color
00224 
00225                                 for (int i = 0; i < position.length; i++) {
00226 
00227                                         if (drawSettings != null && drawSettings.drawType == DrawType.LINES) {
00228                                                 if (position[i].overrideColor != null) {
00229                                                         g.stroke(position[i].overrideColor.getRed(),
00230                                                                         position[i].overrideColor.getGreen(),
00231                                                                         position[i].overrideColor.getBlue());
00232                                                         g.noFill();
00233                                                 } else if (drawSettings.getOverrideColor() == null
00234                                                                 && position[i].color != null) {
00235                                                         g.stroke(position[i].color.getRed(), position[i].color.getGreen(),
00236                                                                         position[i].color.getBlue());
00237                                                         g.noFill();
00238                                                 }
00239                                         } else {
00240                                                 if (position[i].overrideColor != null) {
00241                                                         g.fill(position[i].overrideColor.getRed(),
00242                                                                         position[i].overrideColor.getGreen(),
00243                                                                         position[i].overrideColor.getBlue());
00244                                                 } else if ((drawSettings == null || drawSettings.getOverrideColor() == null)
00245                                                                 && position[i].color != null) {
00246                                                         g.fill(position[i].color.getRed(), position[i].color.getGreen(),
00247                                                                         position[i].color.getBlue());
00248                                                 }
00249                                         }
00250 
00251                                         if (position[i].getNormalVector() != null)
00252                                                 g.normal(position[i].getNormalVector().x, position[i].getNormalVector().y,
00253                                                                 position[i].getNormalVector().z);
00254                                         g.vertex(position[i].x, position[i].y, position[i].z);
00255                                 }
00256 
00257                         } else {
00258                                 // has texture
00259                                 g.texture(appearance.getImageReference());
00260 
00261                                 for (int i = 0; i < position.length; i++) {
00262 
00263                                         g.vertex(position[i].x, position[i].y, position[i].z, texPosition[i].x,
00264                                                         texPosition[i].y);
00265 
00266                                 }
00267 
00268                         }
00269                         g.endShape();
00270                 }
00271         }
00272 
00278         public float getArea() {
00279                 if (position.length == 3) {
00280 
00281                         Point3f v = (Point3f) position[1].clone();
00282                         v.sub(position[0]);
00283                         Point3f w = (Point3f) position[2].clone();
00284                         w.sub(position[0]);
00285 
00286                         Vector3f v1 = new Vector3f(v);
00287                         Vector3f w1 = new Vector3f(w);
00288 
00289                         Vector3f cross = new Vector3f();
00290                         cross.cross(v1, w1);
00291                         return cross.length() / 2f;
00292                 }
00293 
00294                 logger.error("getArea not implemented for " + position.length + "-Triangle");
00295                 return 0;
00296         }
00297 
00303         public Point3f getCentroid() {
00304                 return centroid;
00305         }
00306 
00312         public Vector3f getCornerarea() {
00313                 return cornerarea;
00314         }
00315 
00321         public Set<Triangle> getNeighbors() {
00322                 return neighbors;
00323         }
00324 
00333         public double getDihedralAngle(Triangle t) {
00334                 double dot = this.getNormalVector().dot(t.getNormalVector());
00335                 dot = Math.max(-1, dot);
00336                 dot = Math.min(1, dot);
00337                 return Math.acos(dot);
00338         }
00339 
00345         public Vector3f getNormalVector() {
00346                 return normalVector;
00347         }
00348 
00354         public Point2f[] getTexPosition() {
00355                 return texPosition;
00356         }
00357 
00368         public boolean intersectsRay(Point3f rayStart, Point3f rayEnd) {
00369                 return intersectsRay(rayStart, rayEnd, null);
00370         }
00371 
00377         public boolean calculateNormalVector() {
00378                 // Calculate normal vector for triangle
00379                 Vector3f avgVertexNorm = new Vector3f();
00380                 for (int i = 0; i < 3; i++) {
00381                         if (position[i].getNormalVector() == null) {
00382                                 avgVertexNorm = null;
00383                                 break;
00384                         }
00385                         avgVertexNorm.add(position[i].getNormalVector());
00386                 }
00387                 if (avgVertexNorm != null) {
00388                         avgVertexNorm.scale(1f / 3f);
00389                 }
00390 
00391                 Vector3f a = new Vector3f(position[0]);
00392                 a.sub(position[1]);
00393                 Vector3f b = new Vector3f(position[1]);
00394                 b.sub(position[2]);
00395 
00396                 /*Vector3f a = new Vector3f(position[1]);
00397                 a.sub(position[0]);
00398                 Vector3f b = new Vector3f(position[2]);
00399                 b.sub(position[0]);*/
00400                 Vector3f norm = new Vector3f();
00401                 norm.cross(a, b);
00402                 if (norm.lengthSquared() == 0) {
00403                         return false;
00404                 }
00405                 norm.normalize();
00406 
00407                 if (avgVertexNorm != null && avgVertexNorm.dot(norm) < 0)
00408                         norm.scale(-1f);
00409 
00410                 this.normalVector = norm;
00411                 return true;
00412         }
00413 
00431         public boolean intersectsRay(Point3f p1, Point3f p2, Point3f intersectionPoint) {
00432 
00433                 if (position.length != 3) {
00434                         System.out.println("intersectRay not implemented for not triangles!!");
00435                         return false;
00436                 }
00437 
00438                 Vector3d u, v, n; // triangle vectors
00439                 Vector3d dir, w0, w; // ray vectors
00440                 double r, a, b; // params to calc ray-plane intersect
00441 
00442                 // get triangle edge vectors and plane normal
00443                 u = new Vector3d(position[1]);
00444                 u.sub(new Vector3d(position[0]));
00445                 v = new Vector3d(position[2]);
00446                 v.sub(new Vector3d(position[0]));
00447 
00448                 n = new Vector3d();
00449                 n.cross(u, v); // Normal vector
00450                 if (n.equals(new Vector3d(0, 0, 0))) // triangle is degenerate
00451                         return false; // do not deal with this case
00452 
00453                 dir = new Vector3d(p2);// ray direction vector
00454                 dir.sub(new Vector3d(p1));
00455 
00456                 w0 = new Vector3d(p1);
00457                 w0.sub(new Vector3d(position[0]));
00458 
00459                 a = -n.dot(w0);
00460                 b = n.dot(dir);
00461                 // SMALL_NUM 0.00000001 // anything that avoids division overflow
00462                 if (Math.abs(b) < 0.00000001) { // ray is parallel to triangle plane
00463                         if (a == 0) // ray lies in triangle plane
00464                                 return false;
00465 
00466                         return false; // ray disjoint from plane
00467                 }
00468 
00469                 // get intersect point of ray with triangle plane
00470                 r = a / b;
00471 
00472                 // if (r < 0.0) // ray goes away from triangle
00473                 // return false; // => no intersect
00474                 // for a segment, also test if (r > 1.0) => no intersect
00475 
00476                 Point3f intersect = intersectionPoint;
00477 
00478                 if (intersect == null)
00479                         intersect = new Point3f();
00480 
00481                 intersect.set(dir); // intersect point of ray and plane
00482                 intersect.scale((float) r);
00483                 intersect.add(p1);
00484 
00485                 // is I inside T?
00486                 double uu, uv, vv, wu, wv, D;
00487                 uu = new Vector3d(u).dot(u);
00488                 uv = new Vector3d(u).dot(v);
00489                 vv = new Vector3d(v).dot(v);
00490                 w = new Vector3d(intersect);
00491                 w.sub(new Vector3d(position[0]));
00492                 wu = new Vector3d(w).dot(u);
00493                 wv = new Vector3d(w).dot(v);
00494                 D = uv * uv - uu * vv;
00495 
00496                 // get and test parametric coords
00497                 double s, t;
00498                 s = (uv * wv - vv * wu) / D;
00499                 if (s < 0.0 || s > 1.0) // I is outside T
00500                         return false;
00501                 t = (uv * wu - uu * wv) / D;
00502                 if (t < 0.0 || (s + t) > 1.0) // I is outside T
00503                         return false;
00504 
00505                 return true; // I is in T
00506         }
00507 
00516         public boolean isDirectNeighbor(Triangle tr) {
00517 
00518                 int eqCnt = 0;
00519                 boolean isNeighbor = false;
00520 
00521                 for (int i = 0; i < 3; i++) {
00522                         if (i == 2 && eqCnt == 0)
00523                                 break; // if 2 of 3 points aren't equal, it is no neighbor
00524                         Point3f p1 = position[i];
00525                         for (Point3f p2 : tr.position) {
00526                                 if (p1.x == p2.x && p1.y == p2.y && p1.z == p2.z) {
00527                                         eqCnt++;
00528                                         if (eqCnt == 2) {
00529                                                 isNeighbor = true;
00530                                         } else if (eqCnt == 3) {
00531                                                 // if triangle has same position but is backface
00532                                                 return false;
00533                                         }
00534                                         break;
00535                                 }
00536 
00537                         }
00538                 }
00539                 return isNeighbor;
00540         }
00541 
00550         public boolean isAdjacentNeighbor(Triangle tr) {
00551 
00552                 int eqCnt = 0;
00553                 boolean isNeighbor = false;
00554 
00555                 for (int i = 0; i < 3; i++) {
00556                         if (i == 2 && eqCnt == 0)
00557                                 break; // if 2 of 3 points aren't equal, it is no neighbor
00558                         Point3f p1 = position[i];
00559                         for (Point3f p2 : tr.position) {
00560                                 if (p1 == p2) {
00561                                         eqCnt++;
00562                                         if (eqCnt == 2) {
00563                                                 isNeighbor = true;
00564                                         }
00565                                         if (eqCnt == 3) {
00566                                                 // if triangle has same position but is backface
00567                                                 isNeighbor = false;
00568                                         }
00569                                         break;
00570                                 }
00571 
00572                         }
00573                 }
00574                 return isNeighbor;
00575         }
00576 
00581         public void setCornerarea(Vector3f cornerarea) {
00582                 this.cornerarea = cornerarea;
00583         }
00584 
00591         public void setNeighbors(Set<Triangle> neighbors) {
00592                 this.neighbors = neighbors;
00593         }
00594 
00601         public void setNormalVector(Vector3f normalVector) {
00602                 this.normalVector = normalVector;
00603         }
00604 
00611         public void setTexPosition(Point2f[] texPosition) {
00612                 this.texPosition = texPosition;
00613         }
00614 
00615         @Override
00616         public void updateCentroid() {
00617                 centroid = new Point3f(0, 0, 0);
00618 
00619                 for (int i = 0; i < position.length; i++) {
00620                         centroid.add(position[i]);
00621                 }
00622                 centroid.scale(1f / position.length);
00623         }
00624 
00625 }


knowrob_cad_parser
Author(s): Stefan Profanter
autogenerated on Sat Dec 28 2013 17:09:45