All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jeometry.geom3D.Geom3D Maven / Gradle / Ivy

There is a newer version: 1.0.5
Show newest version
package org.jeometry.geom3D;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.jeometry.Jeometry;
import org.jeometry.factory.JeometryFactory;
import org.jeometry.geom3D.mesh.Edge;
import org.jeometry.geom3D.mesh.Face;
import org.jeometry.geom3D.mesh.Mesh;
import org.jeometry.geom3D.point.ArrayListPoint3DContainer;
import org.jeometry.geom3D.point.Point3D;
import org.jeometry.geom3D.point.Point3DContainer;
import org.jeometry.geom3D.primitive.Box;
import org.jeometry.geom3D.primitive.Polygon3D;
import org.jeometry.geom3D.primitive.Triangle;


/**
 * This classes provides various 3D geometry algorithm and functions.
*
* @author Julien Seinturier - COMEX S.A. - [email protected] - https://github.com/jorigin/jeometry * @version {@value Jeometry#version} * @since 1.0.0 */ public class Geom3D { /** * The 0 limit. Under this value, a value is considered as equal to 0 */ public static double ZERO_LIMIT = 0.00000001d; /** * The numeric precision used in value comparison. */ public static double NUMERIC_PRECISION = 0.000001d; /** * The 0 limit. Under this value, a value is considered as equal to 0 */ public static double EPSILON = 0.00000001d; /** * Return true if the three points given in parameter are collinear. * @param p1 the first point. * @param p2 the second point. * @param p3 the third point. * @return true if the three points are collinear and false otherwise. */ public static boolean collinear(Point3D p1, Point3D p2, Point3D p3){ double x1 = p1.getX(); double y1 = p1.getY(); double z1 = p1.getZ(); double x2 = p2.getX(); double y2 = p2.getY(); double z2 = p2.getZ(); double x3 = p3.getX(); double y3 = p3.getY(); double z3 = p3.getZ(); return (z3 - z1) * (y2 - y1) - (z2 - z1) * (y3 - y1) == 0 && (z2 - z1) * (x3 - x1) - (x2 - x1) * (z3 - z1) == 0 && (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1) == 0; } /** * Check if the given two points are equals (i-e) are at the same location. * points coordinates are considered as equals if their difference lies under the {@link #NUMERIC_PRECISION numeric precision}. * @param p1 the first point. * @param p2 the second point. * @return true is the two points are considered as equals and false otherwise. * @see #equals(Point3D, Point3D, double) * @see #NUMERIC_PRECISION */ public static boolean equals(Point3D p1, Point3D p2){ return equals(p1, p2, NUMERIC_PRECISION); } /** * Check if the given two points are equals (i-e) are at the same location. * points coordinates are considered as equals if their difference lies under the given precision. * @param p1 the first point. * @param p2 the second point. * @param precision the numeric precision to use. * @return true is the two points are considered as equals and false otherwise. * @see #equals(Point3D, Point3D) */ public static boolean equals(Point3D p1, Point3D p2, double precision){ boolean r = p1 == p2; if (!r) { r = ( (Math.abs(p1.getX() - p2.getX())) < precision) && ( (Math.abs(p1.getY() - p2.getY())) < precision) && ( (Math.abs(p1.getZ() - p2.getZ())) < precision); } return r; } /** * Compute and return the normal vector for the polygon given in parameter. * This method need three points for the computation of the normal. The points used are: * - P1: The first vertex of the polygon.
* - P2: The vertex in the middle of the vertices list obtained by polygon.getVertices().get(polygon.getVertices()/2)
* - P3: The last vertex of the polygon.
* The normal is the vector obtained by the computation of the vectorial product of P1P2 and P2P3. * @param polygon IPolygone3D A planar polygon * @return IPoint3D The normal vector of the polygon */ public static Point3D normal(Polygon3D polygon){ Point3D normal = null; Point3D p1p2 = null; Point3D p2p3 = null; // Si le polygone est nul ou compte moins de 3 points, il n'y a pas de normale if ((polygon == null)||(polygon.getVertices().size() < 3)){ return null; } // Calcul du vecteur formé par le premier points du polygone et le point du milieu // de la liste des sommets p1p2 = polygon.getVertices().get(polygon.getVertices().size() / 2).minus(polygon.getVertices().get(0)); // Calcul du vecteur formé par le point du milieu de la liste des sommets et // le dernier sommet du polygone p2p3 = polygon.getVertices().get(polygon.getVertices().size() - 1).minus(polygon.getVertices().get(polygon.getVertices().size() / 2)); // Calcul du produit vectoriel normal = p1p2.cross(p2p3); return normal; } /** * Compute and return the barycenter of the given {@link Point3D points} collection. * @param points the {@link Point3D points} collection to process * @return the barycenter of the points collection. */ public static Point3D computeBarycenter(Point3DContainer points){ Point3D barycenter = null; if ((points != null)&&(points.size() >= 1)){ barycenter = JeometryFactory.createPoint3D(); barycenter.setX(0.0d); barycenter.setY(0.0d); barycenter.setZ(0.0d); Iterator iter = points.iterator(); while(iter.hasNext()){ barycenter = barycenter.plus(iter.next()); } barycenter = barycenter.divide(points.size()); } return barycenter; } /** * Compute and return the volume of a box given in parameter. * @param box the box to use * @return the volume of the box, 0 if the parameter is null */ public static double volume(Box box){ if (box == null){ return 0.0d; } else { return box.getHeight()*box.getWidth()*box.getHeight(); } } /** * Compute and return the volume of the mesh given in parameter. The mesh * must be convex and each face must be a convex polygon. * @param mesh the convex mesh. * @return double the volume of the mesh given in parameter */ public static double volume(Mesh mesh){ // Volume du polthedre double volume = 0.0d; // Points composant une face (les faces doivent être triangulaires) Point3D p1 = null; Point3D p2 = null; Point3D p3 = null; double bxdx = 0.0d; double bydy = 0.0d; double bzdz = 0.0d; double cxdx = 0.0d; double cydy = 0.0d; double czdz = 0.0d; // Barycentre du polygone Point3D barycenter = null; // Iterateur pour parcourir la liste de face Iterator> iter = null; // La face courante Face currentFace = null; // La methode consiste à ajouter tous les volumes de tétrahèdres formés par // une face du polyhedre et son barycentre. Ceci est valable seulement si les // faces sont des triangles. Point3DContainer vertices = null; // Le polyhedre doit être non null et avoir au moins 4 faces. if ((mesh != null)&&(mesh.getFaces().size() > 3)){ // System.out.println("Faces: "+polyhedron.getFaces().size()); // Calcul du barycentre du polyhedre barycenter = Geom3D.computeBarycenter(mesh.getVertices()); // Parcours itéré de la liste des faces iter = mesh.getFaces().iterator(); while(iter.hasNext()){ // Recuperation de la face courante currentFace = iter.next(); vertices = currentFace.getVertices(); // Une face doit avoir au moins 3 points if (vertices.size() < 3){ volume = -1.0d; break; } p1 = vertices.get(0); // On parcours les sommets par groupe de 3 avec le premier for (int i = 1; i < vertices.size() - 1; i++){ p2 = vertices.get(i); p3 = vertices.get(i+1); // Calcul du volume pour le tetrahedre formé par p1, p2, p3, barycentre bxdx = p2.getX() - barycenter.getX(); bydy = p2.getY() - barycenter.getY(); bzdz = p2.getZ() - barycenter.getZ(); cxdx = p3.getX() - barycenter.getX(); cydy = p3.getY() - barycenter.getY(); czdz = p3.getZ() - barycenter.getZ(); // Le volume est la somme des volumes des tetrahedres volume += ( (p1.getZ() - barycenter.getZ())*(bxdx*cydy-bydy*cxdx) + (p1.getY() - barycenter.getY())*(bzdz*cxdx-bxdx*czdz) + (p1.getX() - barycenter.getX())*(bydy*czdz-bzdz*cydy)) / 6; p2 = null; p3 = null; } p1 = null; vertices = null; currentFace = null; } iter = null; barycenter = null; } return volume; } /** * Compute if a 3D point p3d given in parameter is inside a convex polyhedron represented by the given mesh. * A point is inside a convex polyhedron if it is on the invisible side of all its faces. * The computation of all the normals of the face and the scalar product with the vector given by the point * p3d and the barycenter of the face show if the point is on the visible side. * @param polyhedron the mesh that represents a convex polyhedron. * @param p3d the point 3D to check. * @return boolean true if the point is inside the polyhedron, false otherwise */ public static boolean contains(Mesh polyhedron, Point3D p3d){ boolean contains = true; // Vecteur composé par le point donné en paramêtre et le barycentre de // de la face courante du polyhedre. Point3D vector; // Variables de parcours de la liste des faces Iterator> iter = null; Face currentFace = null; if ((polyhedron != null) && (polyhedron.getFaces().size() > 0)){ // Pour chaque face du polyhedre, le produit scalaire entre le vecteur normal // de la face est le vecteur donné par le barycenytre des points de la face // et le point donné en paramêtre est calculé. Si le produit scalaire est // positif le point est du coté de la face visible (et donc en dehors) // du polyhedre. Si le produit scalaire est négatif ou nul, le point est à // l'intérieur. iter = polyhedron.getFaces().iterator(); while(iter.hasNext() && (contains == true)){ currentFace = iter.next(); // Calcul du vector par rapport au point pour cette face vector = Geom3D.computeBarycenter(currentFace.getVertices()).minus(p3d); contains = contains && (vector.dot(Geom3D.normal(currentFace)) >= 0); } } else{ contains = false; } return contains; } /** * Check if the given {@link Box box} contains * the given {@link SpatialLocalization3D spatial localization}. * @param box box the {@link Box box} to check. * @param spatial the {@link SpatialLocalization3D spatial localization} to check. * @return true if the box contains the {@link SpatialLocalization3D spatial localization}, false otherwise. */ public static boolean contains(Box box, SpatialLocalization3D spatial){ if (spatial != null){ if (spatial instanceof Point3D){ return contains(box, (Point3D) spatial); } else if (spatial instanceof Triangle){ Point3DContainer pts = ((Triangle) spatial).getVertices(); return contains(box, pts); } } return false; } /** * Check if the given {@link Box box} contains the given {@link Point3D point}.

* Please not that to conform to algebric semantic of contains, a null box cannot contains any points, on the other hand, a not null box * always contains the null point. * @param box the {@link Box box} to check. * @param p3d the {@link Point3D point} to check. * @return true if the box contains the point, false otherwise. */ public static boolean contains(Box box, Point3D p3d){ if (box != null){ if (p3d != null){ Point3D max = box.getMax(); Point3D min = box.getMin(); return p3d.getX() >= min.getX() && p3d.getX() <= max.getX() && p3d.getY() >= min.getY() && p3d.getY() <= max.getY() && p3d.getZ() >= min.getZ() && p3d.getZ() <= max.getZ(); } else { return true; } } else { return false; } } /** * Check if the given {@link Box box} contains all the points presents * within the given {@link Point3DContainer point manager}. * @param box the {@link Box box} to check. * @param points the {@link Point3DContainer point manager} to check. * @return true if the box contains all the points, false otherwise. */ public static boolean contains(Box box, Point3DContainer points){ if (points != null){ boolean ok = true; Iterator iter = points.iterator(); while(iter.hasNext()&&ok){ ok = contains(box, iter.next()); } return ok; } return false; } /** * Compute if a 3D point cloud points given in parameter is inside the convex polyhedron represented by the given mesh. * A point is inside a convex polyhedron if it is on the invisible side of all the faces of the polyhedron. The computation of all the * normals of the face and the scalar product with the vector given by the point p3d and the barycenter of the face show if the point is on the * visible side. * @param polyhedron the polyhedron * @param points the points that should all be in the polyedron * @return true if all points are in the polyhedron, false otherwise. */ public static boolean contains(Mesh polyhedron, Point3DContainer points){ boolean contains = true; Point3D[] normals = null; Point3D[] barycenters = null; Iterator> iter = null; Face currentFace = null; Point3D p3d = null; int i = 0; int j = 0; if (polyhedron == null){ return false; } if ((points == null) || (points.size() == 0)){ return true; } // Calcul des normales et des barycentres des faces. normals = new Point3D[polyhedron.getFaces().size()]; barycenters = new Point3D[polyhedron.getFaces().size()]; i = 0; iter = polyhedron.getFaces().iterator(); while(iter.hasNext()){ currentFace = iter.next(); normals[i] = Geom3D.normal(currentFace); barycenters[i] = Geom3D.computeBarycenter(currentFace.getVertices()); i++; currentFace = null; } // Parcours de la liste des points et calcul du scalaire j = 0; while((j < points.size()) && (contains)){ // Parcours de la liste des normales / barycentres i = 0; while((i < normals.length) &&(contains)){ contains = contains && (barycenters[i].minus(p3d).dot(normals[i]) >= 0); } j++; } return contains; } /** * Check if the given {@link Box box} intersects the given * {@link SpatialLocalization3D spatial localization}. This method is computed at this time for the following * items: *
    *
  • {@link Point3D Point3D}
  • *
  • {@link Triangle triangle}
  • *
* @param box {@link Box box} the box to check. * @param spatial the {@link SpatialLocalization3D spatial localization} to check. * @return true if the given {@link Box box} geometry intersects the given * {@link SpatialLocalization3D spatial localization} geometry and false otherwise. */ public static boolean isIntersect(Box box, SpatialLocalization3D spatial){ if ((box != null)&&(spatial != null)){ if (spatial instanceof Point3D){ return isIntersect(box, (Point3D) spatial); } else if (spatial instanceof Triangle){ return isIntersect(box, (Triangle) spatial); } } return false; } /** * Check if the given {@link Triangle triangle} intersect * the given {@link Box box}. * @param box the box to check. * @param triangle the triangle to check. * @return true if the given triangle intersect the box and false otherwise. */ public static boolean isIntersect(Box box, Triangle triangle){ if ((box != null)||(triangle != null)){ // Triangle is on the "right" of the box if ( (triangle.getVertex1().getX() > box.getMax().getX()) && (triangle.getVertex2().getX() > box.getMax().getX()) && (triangle.getVertex3().getX() > box.getMax().getX())){ return false; } // Triangle is on the "left" of the box if ( (triangle.getVertex1().getX() < box.getMin().getX()) && (triangle.getVertex2().getX() < box.getMin().getX()) && (triangle.getVertex3().getX() < box.getMin().getX())){ return false; } // Triangle is in "above" the box if ( (triangle.getVertex1().getY() > box.getMax().getY()) && (triangle.getVertex2().getY() > box.getMax().getY()) && (triangle.getVertex3().getY() > box.getMax().getY())){ return false; } // Triangle is "below" the box if ( (triangle.getVertex1().getZ() < box.getMin().getZ()) && (triangle.getVertex2().getZ() < box.getMin().getZ()) && (triangle.getVertex3().getZ() < box.getMin().getZ())){ return false; } // Triangle is in "front" of the box if ( (triangle.getVertex1().getZ() > box.getMax().getZ()) && (triangle.getVertex2().getZ() > box.getMax().getZ()) && (triangle.getVertex3().getZ() > box.getMax().getZ())){ return false; } // Triangle is "behind" the box if ( (triangle.getVertex1().getY() < box.getMin().getY()) && (triangle.getVertex2().getY() < box.getMin().getY()) && (triangle.getVertex3().getY() < box.getMin().getY())){ return false; } // The first vertex of the triangle lies within the box if ( (triangle.getVertex1().getX() <= box.getMax().getX()) && (triangle.getVertex1().getX() >= box.getMin().getX()) && (triangle.getVertex1().getY() <= box.getMax().getY()) && (triangle.getVertex1().getY() >= box.getMin().getY()) && (triangle.getVertex1().getZ() <= box.getMax().getZ()) && (triangle.getVertex1().getZ() >= box.getMin().getZ())){ return true; // The second vertex of the triangle lies within the box } else if ( (triangle.getVertex2().getX() <= box.getMax().getX()) && (triangle.getVertex2().getX() >= box.getMin().getX()) && (triangle.getVertex2().getY() <= box.getMax().getY()) && (triangle.getVertex2().getY() >= box.getMin().getY()) && (triangle.getVertex2().getZ() <= box.getMax().getZ()) && (triangle.getVertex2().getZ() >= box.getMin().getZ())){ return true; // The third vertex of the triangle lies within the box } else if ( (triangle.getVertex3().getX() <= box.getMax().getX()) && (triangle.getVertex3().getX() >= box.getMin().getX()) && (triangle.getVertex3().getY() <= box.getMax().getY()) && (triangle.getVertex3().getY() >= box.getMin().getY()) && (triangle.getVertex3().getZ() <= box.getMax().getZ()) && (triangle.getVertex3().getZ() >= box.getMin().getZ())){ return true; } Collection boxpoints = new ArrayList(8); Point3D boxCenter = JeometryFactory.createPoint3D((box.getMin().getX()+box.getMax().getX())/2.0d, (box.getMin().getY()+box.getMax().getY())/2.0d, (box.getMin().getZ()+box.getMax().getZ())/2.0d); //IPoint3D boxCenter = Geometry.newPoint3D(0.0, 0.0, 0.0); Point3D translatedBoxMin = box.getMin().minus(boxCenter); Point3D translatedBoxMax = box.getMax().minus(boxCenter); boxpoints.add(JeometryFactory.createPoint3D(box.getMax().minus(boxCenter).getX(), box.getMax().minus(boxCenter).getY(), box.getMax().minus(boxCenter).getZ())); boxpoints.add(JeometryFactory.createPoint3D(box.getMax().minus(boxCenter).getX(), box.getMax().minus(boxCenter).getY(), box.getMin().minus(boxCenter).getZ())); boxpoints.add(JeometryFactory.createPoint3D(box.getMax().minus(boxCenter).getX(), box.getMin().minus(boxCenter).getY(), box.getMax().minus(boxCenter).getZ())); boxpoints.add(JeometryFactory.createPoint3D(box.getMax().minus(boxCenter).getX(), box.getMin().minus(boxCenter).getY(), box.getMin().minus(boxCenter).getZ())); boxpoints.add(JeometryFactory.createPoint3D(box.getMin().minus(boxCenter).getX(), box.getMax().minus(boxCenter).getY(), box.getMax().minus(boxCenter).getZ())); boxpoints.add(JeometryFactory.createPoint3D(box.getMin().minus(boxCenter).getX(), box.getMax().minus(boxCenter).getY(), box.getMin().minus(boxCenter).getZ())); boxpoints.add(JeometryFactory.createPoint3D(box.getMin().minus(boxCenter).getX(), box.getMin().minus(boxCenter).getY(), box.getMax().minus(boxCenter).getZ())); boxpoints.add(JeometryFactory.createPoint3D(box.getMin().minus(boxCenter).getX(), box.getMin().minus(boxCenter).getY(), box.getMin().minus(boxCenter).getZ())); List tripoints = new ArrayList(3); tripoints.add(triangle.getVertex1().minus(boxCenter)); tripoints.add(triangle.getVertex2().minus(boxCenter)); tripoints.add(triangle.getVertex3().minus(boxCenter)); // test the x, y, and z axes if (!isIntersect(boxpoints, tripoints, JeometryFactory.createPoint3D(translatedBoxMax.getX() - translatedBoxMin.getX(), 0, 0))){ return false; } if (!isIntersect(boxpoints, tripoints, JeometryFactory.createPoint3D(0, translatedBoxMax.getY() - translatedBoxMin.getY(), 0))){ return false; } if (!isIntersect(boxpoints, tripoints, JeometryFactory.createPoint3D(0, 0, translatedBoxMax.getZ() - translatedBoxMin.getZ()))){ return false; } // test the triangle normal Point3D triedge1 = tripoints.get(1).minus(tripoints.get(0)); Point3D triedge2 = tripoints.get(2).minus(tripoints.get(1)); Point3D trinormal = cross(triedge1, triedge2); if (!isIntersect(boxpoints, tripoints, trinormal)){ return false; } // test the 9 edge cross products Point3D triedge3 = tripoints.get(0).minus(tripoints.get(2)); Point3D boxedge1 = JeometryFactory.createPoint3D(translatedBoxMax.getX() - translatedBoxMin.getX(), 0, 0); Point3D boxedge2 = JeometryFactory.createPoint3D(0, translatedBoxMax.getY() - translatedBoxMin.getY(), 0); Point3D boxedge3 = JeometryFactory.createPoint3D(0, 0, translatedBoxMax.getZ() - translatedBoxMin.getZ()); if (!isIntersect(boxpoints, tripoints, cross(boxedge1, triedge1))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge1, triedge2))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge1, triedge3))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge2, triedge1))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge2, triedge2))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge2, triedge3))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge3, triedge1))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge3, triedge2))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge3, triedge3))) return false; // Inverted normals triedge1 = tripoints.get(2).minus(tripoints.get(0)); triedge2 = tripoints.get(1).minus(tripoints.get(2)); trinormal = cross(triedge1, triedge2); if (!isIntersect(boxpoints, tripoints, trinormal)){ return false; } // test the 9 edge cross products with inverted normals triedge3 = tripoints.get(0).minus(tripoints.get(1)); if (!isIntersect(boxpoints, tripoints, cross(boxedge1, triedge1))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge1, triedge2))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge1, triedge3))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge2, triedge1))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge2, triedge2))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge2, triedge3))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge3, triedge1))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge3, triedge2))) return false; if (!isIntersect(boxpoints, tripoints, cross(boxedge3, triedge3))) return false; return true; } return false; } /** * This method check if a {@link Point3D 3D point} intersects * the given {@link Box box}. * From a formal point of view, checking if a point intersects a box is equivalent to checking if the bonx contains the point. * For this reason this method delegates to {@link #contains(Box, Point3D)} method for computation. * @param box the {@link Box box} to check. * @param point the {@link Point3D 3D point} to check. * @return true if the point intersect the box and false otherwise. * @see #contains(Box, Point3D) */ public static boolean isIntersect(Box box, Point3D point){ return contains(box, point); } /** * Compute a return a set of convex polyhedra which are the convex decomposition * of the polyhedron given in parameter. A convex decomposition is a set of * polyhedron that their disjunction compose the initial polyhedron. The algoritm * used for the computation is given by Wang Fei, LIU Wen-Yu, Li Huain
* A Algorithm for Convex Decomposition for polyedral object
* Proceeding of the Seventh International conference on computer aided Design * and Computer Graphics
* International Academic Publishers, August 22-24 2001
* @param The type of underlying 3D points * @param polyhedron the polyhedron to decompose * @return the list of convex polyedra composing the initial polyhedron */ public static List> computeConvexDecomposition(Mesh polyhedron){ List> convexPolyhedrons = null; List> concaveEdges = null; List> edges = new ArrayList>(polyhedron.getEdges().size()); List> faces = new ArrayList>(polyhedron.getFaces().size()); int faceCpt = 0; // table de correspondance arrête / face. Les lignes du tableaux correspondent // aux indices des arrêtes du polyhedre. Les colonnes sont les indices des faces // du polyhedre attaché à l'arrête. int[][] edgeFaces = new int[polyhedron.getEdges().size()][2]; // Recuperation des tableaux des faces et des arrêtes edges = polyhedron.getEdges(); faces = polyhedron.getFaces(); // 1 - Calcul des sommets et arêtes concaves // A) Calcul des faces attach�es à chaque arrêtes. for(int i = 0; i < edges.size(); i++){ for(int j = 0; j < faces.size(); j++){ faceCpt = 0; for(int k = 0; k < faces.get(j).getEdges().size(); k++) { if (faces.get(j).getEdges().get(k).equals(edges.get(i))){ // La jieme face du polyedre est adjacente à l'arrête i. edgeFaces[i][faceCpt] = j; faceCpt++; // Si deux faces on été trouvées pour l'arrête, inutile de chercher plus if (faceCpt >= 2){ break; } } } } } // B) D�termination de la concavité des arrêtes. // Une arr�te est concave ssi pour une arr�te (P1,P2) reliant 2 faces // A et B avec P3 un point de A et P4 un point de B la matrice: // // [ x1 y1 z1 1 ] // [ x2 y2 z2 1 ] // [ x3 y3 z3 1 ] avec (xi, yi, zi) sont les coordonn�es de Pi // [ x4 y4 z4 1 ] // // on a det(M) < 0. Dans le cas contraire l'arrête est convexe. Point3D p1 = null; Point3D p2 = null; Point3D p3 = null; Point3D p4 = null; concaveEdges = new ArrayList>(); double[][] matrice = new double[4][4]; double det = 0.0d; for(int i = 0; i < edgeFaces.length; i++){ // Recuperation des sommets de l'arrête p1 = edges.get(i).getVertices().get(0); p2 = edges.get(i).getVertices().get(1); // Utilisation des barycentres des faces comme référence. p3 = Geom3D.computeBarycenter(faces.get(edgeFaces[i][0]).getVertices()); p4 = Geom3D.computeBarycenter(faces.get(edgeFaces[i][1]).getVertices()); // Remplissage de la matrice 4*4 avant calcul du déterminant matrice[0][0] = p1.getX(); matrice[0][1] = p1.getY(); matrice[0][2] = p1.getZ(); matrice[0][3] = 1; matrice[1][0] = p2.getX(); matrice[1][1] = p2.getY(); matrice[1][2] = p3.getZ(); matrice[1][3] = 1; matrice[2][0] = p3.getX(); matrice[2][1] = p3.getY(); matrice[2][2] = p3.getZ(); matrice[2][3] = 1; matrice[4][0] = p4.getX(); matrice[4][1] = p4.getY(); matrice[4][2] = p4.getZ(); matrice[4][3] = 1; det = matrice[2][0] * matrice[3][1] + matrice[1][0] * matrice[2][1] * matrice[3][2] + matrice[0][0] * matrice[1][1] * matrice[2][2] * matrice[3][3] + matrice[0][1] * matrice[1][2] * matrice[2][3] + matrice[0][2] * matrice[1][3] - matrice[0][1] * matrice[1][0] - matrice[0][2] * matrice[1][1] * matrice[2][0] - matrice[0][3] * matrice[1][2] * matrice[2][1] * matrice[3][0] - matrice[1][3] * matrice[2][2] * matrice[3][1] - matrice[2][3] * matrice[3][2]; // Si le déterminant est strictement positif, l'arrête est concave if (det > 0){ concaveEdges.add(edges.get(i)); } } // 2 - Selection d'une arrête convexe et sauvegarde des deux sommets qui seront // arbitrairemenbt le départ et la fin d'une boucle Edge concaveEdge = concaveEdges.get(0); T start = concaveEdge.getVertices().get(0); T end = concaveEdge.getVertices().get(1); // 3 - Recherche d'une boucle dont les points de départ et d'arrivée sont les // sommets de l'arrête choisie. Point3DContainer loop = new ArrayListPoint3DContainer(); while(Geom3D.equals(start, end)){ // 3.1> Pour le sommet d'une arrête, recupération de tous les points avec // lesquels le sommet forme une face. Point3DContainer linkedVertices = new ArrayListPoint3DContainer(); boolean isVertexInFace = false; for(int j = 0; j < polyhedron.getFaces().size(); j++){ // Recherche si la face contient le point d�sir� for(int k = 0; k < faces.get(j).getVertices().size(); k++){ if (Geom3D.equals(start, faces.get(j).getVertices().get(k))){ isVertexInFace = true; } } // Si la face contient bien le sommet, les autres points de la face sont // ajoutés à liste des sommets liés. Un sommet ne peut apparaitre qu'une // seule fois dans la liste. if (isVertexInFace){ for(int k = 0; k < faces.get(j).getVertices().size(); k++){ linkedVertices.add(faces.get(j).getVertices().get(k)); } } // Si les sommets liés contiennent un sommet concave (sommet d'une arrête concave) // alors ce sommet devient le premier sommet de la suite de la boucle. for(int lk = 0; lk < linkedVertices.size(); lk++){ for(int ce = 0; ce < concaveEdges.size(); ce++){ if ((Geom3D.equals(linkedVertices.get(lk), concaveEdges.get(ce).getVertices().get(0))) ||(Geom3D.equals(linkedVertices.get(lk), concaveEdges.get(ce).getVertices().get(1)))){ loop.add(linkedVertices.get(lk)); } } } isVertexInFace = false; } } return convexPolyhedrons; } /** * Compute the cross product between two vectors represented by the two given points.

* The result is computed using the formula:
* x = v1.getY()*v2.getZ() - v2.getY()*v1.getZ();
* y = v1.getZ()*v2.getX() - v1.getX()*v2.getZ();
* z = v1.getX()*v2.getY() - v1.getY()*v2.getX();
* * @param v1 the first vector represented by a point. * @param v2 the second vector represented by a point. * @return the cross product of the two vectors. */ public static Point3D cross(Point3D v1, Point3D v2){ return JeometryFactory.createPoint3D(v1.getY()*v2.getZ() - v2.getY()*v1.getZ(), v1.getZ()*v2.getX() - v1.getX()*v2.getZ(), v1.getX()*v2.getY() - v1.getY()*v2.getX()); } /** * Compute the dot product between two vectors by the two given points.

* The result is computed using the formula:
* r = v1.getX()*v2.getX() + v2.getY()*v1.getY() + v2.getZ()*v1.getZ();
* @param v1 the first vector represented by a point * @param v2 the second vector represented by a point. * @return the cross product of the two vectors. */ public static double dot(Point3D v1, Point3D v2){ return ( v1.getX()*v2.getX() + v1.getY()*v2.getY() + v1.getZ()*v2.getZ()); } /** * Test if a the points given in parameter are coplanar. * @param p3dm Point3DManagerI the set of points to test * @return boolean true if the points are coplanar, false otherwise */ public static boolean coplanar(Point3DContainer p3dm) { boolean test = false; Point3D point = null; Point3D vector1 = null; Point3D vector2 = null; Point3D vector3 = null; double norm = 0.0d; double d = 0.0d; // Trois points sont forcement coplanaires if (p3dm.size() < 4){ return true; } // Calcul du vecteur entre le premier et le deuxième point point = p3dm.get(0); vector1 = p3dm.get(1).minus(point); // Recherche d'un vecteur normal de référence for(int i=2;iZERO_LIMIT){ break; } } // Calcul du produit scalaire entre le vecteur normal de reference et le premier point d = Math.abs(vector3.dot(point)); //System.out.println("d = "+d); test = true; for(int i=1;iZERO_LIMIT){ test = false; break; } } return test; } /** * Compute the farthest points in the point manager given in parameter. If the point manager * is null or if it contains less than 2 points, null is returned. * @param p3dm the point manager used for computation * @return an array containing the farthest points of the manager. */ public static Point3D[] farthestPoints(Point3DContainer p3dm){ Point3D[] result = null; Point3D p1 = null; Point3D p2 = null; double distance = 0.0d; double distanceMax = 0.0d; if ((p3dm == null) || (p3dm.size() < 2)){ return null; } else { result = new Point3D[2]; p1 = null; p2 = null; // Toutes les distances sont calculées et comparées for(int i = 0; i < p3dm.size(); i++){ p1 = p3dm.get(i); for(int j = i+1; j < p3dm.size(); j++){ p2 = p3dm.get(j); if (p1 != p2){ distance = p1.distance(p2); if (distance > distanceMax){ distanceMax = distance; result[0] = p1; result[1] = p2; } } } } } p1 = null; p2 = null; return result; } /** * Return the point of the manager given in parameter that is the furthest from the polygon * given in parameter. The distance is computed between the barycenter of the polygon and a * point. * @param polygon IPolygon3D a polygon * @param points Point3DManagerI the set of points * @return IPoint3D the furthest point from the polygon */ public static Point3D furthest(Polygon3D polygon, Point3DContainer points){ // Le point courant Point3D current = null; // Le point le plus éloigné du polygone Point3D furthest = null; // Le barycentre du polygone Point3D barycenter = null; double currentDistance = 0.0d; double maxDistance = 0.0d; if ((polygon == null)||(points == null)){ return null; } barycenter = computeBarycenter(polygon.getVertices()); // Initialisation avec le premier point considéré comme le plus éloigné furthest = points.get(0); currentDistance = barycenter.distance(furthest); maxDistance = currentDistance; // Calcul des distances et verification du maximum for(int i = 1; i < points.size(); i++){ current = points.get(i); currentDistance = barycenter.distance(current); // Si la distance courant est supérieure à la distance maximale, // le point courant devient le point le plus eloigne if (currentDistance > maxDistance){ furthest = current; maxDistance = currentDistance; } } return furthest; } /** * Compute the axis aligned bounding box for the points given in parameter. If the point * manager is null or empty, null is returned. * @param points the points to englobe in the box * @return the axis aligned bounding box */ public static Box computeAxisAlignedBoundingBox(Point3DContainer points){ Point3D pMax = null; Point3D pMin = null; Point3D pt = null; Box polyhedron = null; // Une boite englobante n'est retournée que s'il existe des points à englober. if ((points == null) || (points.size() < 3)){ polyhedron = null; } else { // On calcule les sommets de la boite englobante pMax = JeometryFactory.createPoint3D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); pMin = JeometryFactory.createPoint3D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); for(int i = 0; i < points.size(); i++){ pt = points.get(i); if (pMin.getX() > pt.getX()){ pMin.setX(pt.getX()); } if (pMin.getY() > pt.getY()){ pMin.setY(pt.getY()); } if (pMin.getZ() > pt.getZ()){ pMin.setZ(pt.getZ()); } if (pMax.getX() < pt.getX()){ pMax.setX(pt.getX()); } if (pMax.getY() < pt.getY()){ pMax.setY(pt.getY()); } if (pMax.getZ() < pt.getZ()){ pMax.setZ(pt.getZ()); } pt = null; } // Creation d'un boite parallele aux axes. polyhedron = JeometryFactory.createBox(pMin, pMax); } return polyhedron; } /** * Compute the axis aligned bounding box for the points given in parameter. If the point * manager is null or empty, null is returned. * @param points the points to englobe in the box * @return the axis aligned bounding box */ public static Box computeAxisAlignedBoundingBox(Collection points){ Point3D pMax = null; Point3D pMin = null; Point3D pt = null; Box polyhedron = null; // Une boite englobante n'est retournée que s'il existe des points à englober. if ((points == null) || (points.size() < 3)){ polyhedron = null; } else { // On calcule les sommets de la boite englobante pMax = JeometryFactory.createPoint3D(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); pMin = JeometryFactory.createPoint3D(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); Iterator iter = points.iterator(); while(iter.hasNext()){ pt = iter.next(); if (pMin.getX() > pt.getX()){ pMin.setX(pt.getX()); } if (pMin.getY() > pt.getY()){ pMin.setY(pt.getY()); } if (pMin.getZ() > pt.getZ()){ pMin.setZ(pt.getZ()); } if (pMax.getX() < pt.getX()){ pMax.setX(pt.getX()); } if (pMax.getY() < pt.getY()){ pMax.setY(pt.getY()); } if (pMax.getZ() < pt.getZ()){ pMax.setZ(pt.getZ()); } pt = null; } // Creation d'un boite parallele aux axes. polyhedron = JeometryFactory.createBox(pMin, pMax); } return polyhedron; } /** * Compute an axis oriented bounding box for the polyhedron given in parameter. If the polyhedron * is null or if it contains no vertices, null is returned. * @param polyhedron the polyhedron to fit in the bounding box * @return the axis aligned bounding box for the polyhedron. */ public static Box computeAxisAlignedBoundingBox(Mesh polyhedron){ if (polyhedron == null){ return null; } else { return computeAxisAlignedBoundingBox(polyhedron.getVertices()); } } /** * Compute the euclidean distance between the two given {@link SpatialLocalization3D spatial localization}. * The distance computation method depends on the nature of the items. In most of the case, the returned value is * the minimal distance between the two items. It is assumed that if one the item contains the second or if the two items intersects, * the distance should be considered as 0. * @param item1 the first {@link SpatialLocalization3D spatial localization}. * @param item2 the second {@link SpatialLocalization3D spatial localization}. * @return the euclidean distance between the two items. */ public static double computeDistance(SpatialLocalization3D item1, SpatialLocalization3D item2){ return 0.0d; } /** * Compute the euclidean distance between the two given 3D coordinates. * @param x1 the X coordinate of the point 1. * @param y1 the Y coordinate of the point 1. * @param z1 the Z coordinate of the point 1. * @param x2 the X coordinate of the point 2. * @param y2 the Y coordinate of the point 2. * @param z2 the Z coordinate of the point 2. * @return the euclidean distance between the two given 3D coordinates. */ public static double computeDistance(double x1, double y1, double z1, double x2, double y2, double z2){ return Math.sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1) + (z2 - z1)*(z2 - z1)); } /** * Compute the intersection between the given {@link Triangle triangle} and the ray represented * by the given direction and the given origin.

* This method is an implementation of "Fast, Minimum Storage Ray / Triangle Intersection", Journal of Graphics Tools, 2(1):21--28, 1997 * published by Tomas Muller and Ben Trumbore. * @param triangle triangle the {@link Triangle triangle} to check. * @param dir the direction of the ray. * @param orig the origin of the ray. * @return the intersection point or null if no intersection is detected. * @see #computeIntersection(Triangle, Point3D, Point3D, boolean) */ public static Point3D computeIntersection(Triangle triangle, Point3D dir, Point3D orig){ return computeIntersection(triangle, dir, orig, false); } /** * Compute the intersection between the given {@link Triangle triangle} and the ray represented by the given direction and the given origin.

* This method is an implementation of "Fast, Minimum Storage Ray / Triangle Intersection", Journal of Graphics Tools, 2(1):21--28, 1997 published by Tomas Muller and Ben Trumbore.

* Lets a triangle defined by its 3 vertices (V0, V1, V2). Lets R a ray defined by its origin O and its direction D. A point within a triangle is denoted T(u, v) where u and v are the barycentric coordinates of the point such that:
* T(u, v) = (1 - u - v)V0 + uV1 + vV2
* The intersection between the triangle and the ray is given by the following formula:
* O + tD = T(u, v)
* where t is the distance of the intersection from the ray origin along the ray direction.
* @param triangle the {@link Triangle triangle} to check. * @param dir the direction of the ray. * @param orig the origin of the ray. * @param cullback is the facing of the triangle is determinant (if true, intersection is discarded if triangle visible face is not facing the ray origin.) * @return the intersection point or null if no intersection is detected. * @see #computeIntersection(Triangle, Point3D, Point3D) */ public static Point3D computeIntersection(Triangle triangle, Point3D dir, Point3D orig, boolean cullback){ Point3D result = null; Point3D edge1 = null; Point3D edge2 = null; Point3D tvec = null; Point3D pvec = null; Point3D qvec = null; double det = 0.0d; double invDet = 0.0d; double u = 0.0d; double v = 0.0d; double t = 0.0d; /* find vectors for two edges sharing vertO */ edge1 = triangle.getVertex2().minus(triangle.getVertex1()); edge2 = triangle.getVertex3().minus(triangle.getVertex1()); /* begin calculating determinant - also used to calculate U parameter */ pvec = cross(dir, edge2); /* if determinant is near zero, ray lies in plane of triangle */ det = dot(edge1, pvec); /* If the back culling is used */ if (cullback){ if (det < EPSILON){ return null; } /* calculate distance from vertex 1 to ray origin */ tvec = orig.minus(triangle.getVertex1()); /* calculate U parameter and test bounds */ u = dot(tvec, pvec); if ((u < 0.0) || (u > det)){ return null; } /* prepare to test V parameter */ qvec = cross(tvec, edge1); /* calculate V parameter and test bounds */ v = dot(dir, qvec); if ((v < 0.0) || ((u + v) > det)){ return null; } /* calculate t, scale parameters, ray intersects triangle */ t = dot(edge2, qvec); invDet = 1.0 / det; t *= invDet; u *= invDet; v *= invDet; } else { if (det > -EPSILON && det < EPSILON){ return null; } invDet = 1.0 / det; /* calculate distance from vertO to ray origin */ tvec = orig.minus(triangle.getVertex1()); /* calculate U parameter and test bounds */ u = dot(tvec, pvec) * invDet; if ((u < 0.0) || (u > 1.0)){ return null; } /* prepare to test V parameter */ qvec = cross(tvec, edge1); /* calculate V parameter and test bounds */ v = dot(dir, qvec) * invDet; if ((v < 0.0) || ((u + v) > 1.0)){ return null; } /* calculate t, ray intersects triangle */ t = dot(edge2, qvec) * invDet; } // Translating barycentric coordinates into cartesian coordinates. /* double factor = (1-u-v); result = GeometryFactory.createPoint3D(factor*triangle.getVertex1().getX() + u*triangle.getVertex2().getX() + v*triangle.getVertex3().getX(), factor*triangle.getVertex1().getY() + u*triangle.getVertex2().getY() + v*triangle.getVertex3().getY(), factor*triangle.getVertex1().getZ() + u*triangle.getVertex2().getZ() + v*triangle.getVertex3().getZ()); */ result = orig.plus(dir.multiply(t)); return result; } /** * Get the minimum scalar product (dot product) for the given point collection following the given axis. * @param points the points collection to test. * @param axis the direction of the axis to check. * @return the minimum scalar product (dot product) for the given point collection following the given axis. * @see #getMaxScalar(Collection, Point3D) */ public static double getMinScalar(Collection points, Point3D axis){ double min = Double.POSITIVE_INFINITY; Iterator iter = points.iterator(); Point3D point = null; double dotprod = 0.0d; while(iter.hasNext()){ point = iter.next(); dotprod = point.dot(axis); if (dotprod < min){ min = dotprod; } } return min; } /** * Get the maximum scalar product (dot product) for the given point collection following the given axis. * @param points the points collection to test. * @param axis the direction of the axis to check. * @return the maximum scalar product (dot product) for the given point collection following the given axis. * @see #getMinScalar(Collection, Point3D) */ public static double getMaxScalar(Collection points, Point3D axis){ double max = Double.NEGATIVE_INFINITY; Iterator iter = points.iterator(); Point3D point = null; double dotprod = 0.0d; while(iter.hasNext()){ point = iter.next(); dotprod = point.dot(axis); if (dotprod > max){ max = dotprod; } } return max; } /** * Check if the two given point collections are intersecting following the given axis. * @param ref the first point collection considered as reference. * @param check the second collection. * @param axis the axis for the check. * @return true if the collections are intersecting and false otherwise. */ public static boolean isIntersect(Collection ref, Collection check, Point3D axis){ if (getMinScalar(ref, axis) > getMaxScalar(check, axis)){ return false; } if (getMaxScalar(ref, axis) < getMinScalar(check, axis)){ return false; } return true; } /* public static void computeFaceOrientation(IMeshIndexed mesh, IFaceIndexed start) { if (mesh != null){ List faces = mesh.getFacesIndexes(); List wavefront = new LinkedList(); List wavefront2 = new LinkedList(); if ((start != null)&&(start.getMesh() == mesh)){ wavefront.add(start); } else { wavefront.add(faces.get(0)); } HashMap flag = new HashMap(); boolean oneflagactive=(faces.size() > 0); int processedTriangles = 0; int orientedFaces = 1; int lastIterationOrientedFaces = 0; List[] adjacentsArray = null; List[] incidentsArray = null; int commonPoint1IndexOnAdj = -1; int commonPoint2IndexOnAdj = -1; int tmp = -1; int invertedEdge = -1; while (oneflagactive==true) { Iterator wavefrontIter = wavefront.iterator(); IFaceIndexed wave = null; IFaceIndexed adjacent = null; while(wavefrontIter.hasNext()){ wave = wavefrontIter.next(); IFaceIndexed[] adjacents={wave.getAdjacent(0), wave.getAdjacent(1), wave.getAdjacent(2)}; for(int i = 0; i < 3; i++){ adjacent = adjacents[i]; // We check each adjacent of the wave if ((adjacent!=null) &&(flag.get(adjacent) == null)){ int[] waveIndices = wave.getIndice(); int[] adjacentIndices = adjacent.getIndice(); // We retrieve the indices of the vertices forming the edge of adjacency for the wave triangle // within the adjacent triangle. for an edge i, the attached vertices indices are (i, (i+1)%3) // ie: edge 0: (0, 1), edge 1: (1, 2), edge 2: (2, 0) if (adjacentIndices[0] == waveIndices[i]){ commonPoint1IndexOnAdj = 0; } else if (adjacentIndices[1] == waveIndices[i]){ commonPoint1IndexOnAdj = 1; } else if (adjacentIndices[2] == waveIndices[i]){ commonPoint1IndexOnAdj = 2; } else { commonPoint1IndexOnAdj = -1; } if (adjacentIndices[0] == waveIndices[(i+1)%3]){ commonPoint2IndexOnAdj = 0; } else if (adjacentIndices[1] == waveIndices[(i+1)%3]){ commonPoint2IndexOnAdj = 1; } else if (adjacentIndices[2] == waveIndices[(i+1)%3]){ commonPoint2IndexOnAdj = 2; } else { commonPoint1IndexOnAdj = -1; } // We check if the common points are in the same order (natural ordering relation on indices is the same // within wave and its adjacent.) boolean samedir = (adjacentIndices[(commonPoint1IndexOnAdj+1)%3] == adjacentIndices[commonPoint2IndexOnAdj]); // If the edge is listed within the same order for the two triangle, the adjacent edge has to be // inverted. The adjacents relative to the inverted edge have also to be inverted. if (samedir){ // Saving actual neighborhood for each edge (adjacent) and each vertex (incident) adjacentsArray = new List[]{adjacent.getAdjacents(0), adjacent.getAdjacents(1), adjacent.getAdjacents(2)}; incidentsArray = new List[]{ adjacent.getIncidents(0), adjacent.getIncidents(1), adjacent.getIncidents(2)}; // Inverting vertices tmp = adjacentIndices[commonPoint1IndexOnAdj]; adjacentIndices[commonPoint1IndexOnAdj] = adjacentIndices[commonPoint2IndexOnAdj]; adjacentIndices[commonPoint2IndexOnAdj] = tmp; adjacent.setIndice(adjacentIndices); // Inverting incidents attached to inverted vertices adjacent.setIncidents(commonPoint1IndexOnAdj, incidentsArray[commonPoint2IndexOnAdj]); adjacent.setIncidents(commonPoint2IndexOnAdj, incidentsArray[commonPoint1IndexOnAdj]); // Inverting adjacency to match the new edges order. if (commonPoint1IndexOnAdj == 0){ if (commonPoint2IndexOnAdj == 1){ invertedEdge = 0; } else if (commonPoint2IndexOnAdj == 2){ invertedEdge = 2; } } else if (commonPoint1IndexOnAdj == 1){ if (commonPoint2IndexOnAdj == 0){ invertedEdge = 0; } else if (commonPoint2IndexOnAdj == 2){ invertedEdge = 1; } } else if (commonPoint1IndexOnAdj == 2){ if (commonPoint2IndexOnAdj == 0){ invertedEdge = 2; } else if (commonPoint2IndexOnAdj == 1){ invertedEdge = 1; } } if (invertedEdge == 0){ adjacent.setAdjacents(1, adjacentsArray[2]); adjacent.setAdjacents(2, adjacentsArray[1]); } else if (invertedEdge == 1){ adjacent.setAdjacents(0, adjacentsArray[2]); adjacent.setAdjacents(2, adjacentsArray[0]); } else if (invertedEdge == 2){ adjacent.setAdjacents(1, adjacentsArray[0]); adjacent.setAdjacents(0, adjacentsArray[1]); } adjacentsArray = null; incidentsArray = null; tmp = -1; invertedEdge = -1; } // Compute the adjacent normal adjacent.computeAndSetNormal(); processedTriangles++; // Mark the adjacent as processed. flag.put(adjacent, 1); // Set the adjacent as part of the next wave front. wavefront2.add(adjacent); // Update the processed faces count. orientedFaces++; } } wave.computeAndSetNormal(); processedTriangles++; } if (processedTriangles < faces.size()){ processedTriangles = faces.size(); } wavefront.clear(); wavefront.addAll(wavefront2); wavefront2.clear(); // Check if all the faces are oriented or if the face orientation does not provide // new computation if (orientedFaces == faces.size() || (lastIterationOrientedFaces == orientedFaces)){ oneflagactive = false; } lastIterationOrientedFaces = orientedFaces; } // // Computation of vertices normals // HashMap normalescalculees = new HashMap(); Iterator triangleIter = faces.iterator(); Triangle triangle = null; Collection pointNeighborhood = new LinkedList(); Point3DManager vertices = null; IPoint3D vertex = null; while(triangleIter.hasNext()){ triangle = triangleIter.next(); if (triangle.getNormale() == null){ triangle.computeAndSetNormal(); } vertices = triangle.getVertices(); if (vertices != null){ Iterator vertexIter = vertices.iterator(); int cpt = 0; while(vertexIter.hasNext()){ vertex = vertexIter.next(); if ((vertex instanceof HasNormal)&&(normalescalculees.get(vertex) == null)){ ((HasNormal) vertex).setNormal(GeometryFactory.createPoint3D( triangle.getNormale().getX(), triangle.getNormale().getY(), triangle.getNormale().getZ())); // Get adjacent from the first edge containing the vertex if (triangle.getAdjacents(cpt) != null){ pointNeighborhood.addAll(triangle.getAdjacents(cpt)); } // Get adjacent from the second edge containing the vertex if (triangle.getAdjacents((cpt+2)%3) != null){ pointNeighborhood.addAll(triangle.getAdjacents((cpt+2)%3)); } // Get incidents faces linked to the current vertex if (triangle.getIncidents(cpt) != null){ pointNeighborhood.addAll(triangle.getIncidents(cpt)); } // Summing all neighbors faces normal to compute the vertex normal. Iterator faceIter = pointNeighborhood.iterator(); IPoint3D tmpNormal = null; while(faceIter.hasNext()){ tmpNormal = faceIter.next().getNormale(); ((HasNormal) vertex).getNormal().plusAffect(tmpNormal); } ((HasNormal) vertex).getNormal().normalize(); cpt++; normalescalculees.put(vertex, true); pointNeighborhood.clear(); tmpNormal = null; vertex = null; } } vertexIter = null; } vertices = null; triangle = null; processedTriangles++; } normalescalculees.clear(); normalescalculees = null; triangleIter = null; } } */ } //////////////////////////////////////////////////////////////////////////////// // FIN COMPATIBILITE AVEC LES CLASSES DE GEOMETRIE DE HAUT NIVEAU D'ARPENTEUR // ////////////////////////////////////////////////////////////////////////////////




© 2015 - 2024 Weber Informatics LLC | Privacy Policy