package ProGAL.geom3d.complex; import java.awt.Color; import ProGAL.geom3d.LineSegment; import ProGAL.geom3d.Plane; import ProGAL.geom3d.Point; //import ProGAL.geom3d.viewer.J3DScene; import ProGAL.geom3d.complex.delaunayComplex.RegularComplex; import ProGAL.geom3d.kineticDelaunay.Tet; import ProGAL.geom3d.volumes.Tetrahedron; /** * An extension of the normal Tetrahedron that is used in complexes. In addition to the four * corner-points, pointers to the triangular faces (of the type CTriangle) and the four * neighboring tetrahedra are maintained. * * @author R.Fonseca */ public class CTetrahedron extends Tetrahedron{ private CTetrahedron[] neighbours = new CTetrahedron[4]; private CTriangle[] triangles = new CTriangle[4]; private boolean modified = false; private boolean flat = false; public CTetrahedron(CVertex p0, CVertex p1, CVertex p2, CVertex p3) { super(p0,p1,p2,p3); } protected CTetrahedron(){ this(null,null,null,null); } public void setFlat(boolean flat) { this.flat = flat; } public void setModified(boolean modified) { this.modified = modified; } public void setPoint(CVertex p, int i){ super.corners[i] = p; } public void setNeighbour(int index, CTetrahedron t){ neighbours[index] = t; } public void setTriangle(int index, CTriangle t){ triangles[index] = t; } public CVertex getPoint(int i){ return (CVertex)corners[i]; } public CTetrahedron getNeighbour(int index) { return neighbours[index]; } public CTriangle getTriangle(int index){ return triangles[index]; } public boolean isModified() { return modified; } public boolean isFlat() { return flat; } /** * For computational convenience, the representation of a complex is based on a big tetrahedron * that encloses all vertices. It has 4 so-called 'big points' as corners. This method indicates * if this tetrahedron has one of these 'big points' as corners. * @see RegularComplex */ public boolean containsBigPoint() { if(getPoint(0).isBigpoint() || getPoint(1).isBigpoint() || getPoint(2).isBigpoint() || getPoint(3).isBigpoint()) return true; return false; } public int getNumberBigPoints() { int count = 0; for (int i = 0; i < 4; i++) { if (getPoint(i).isBigpoint()) count++; } return count; } /** returns neighbour tetrahedron containing specified vertex */ public CTetrahedron getNeighbour(CVertex v) { for (int i = 0; i < 4; i++) { CTetrahedron tetr = getNeighbour(i); if (tetr.containsPoint(v)) return tetr; } return null; } public boolean hasNeighbor(CTetrahedron t) { for (int i = 0; i < 4; i++) if (neighbours[i] == t) return true; return false; } public int getID(CVertex v) { if (v == getPoint(0)) return 0; else { if (v == getPoint(1)) return 1; else { if (v == getPoint(2)) return 2; else { if (v == getPoint(3)) return 3; else return -1; } } } } /** returns the vertices shared by two tetrahedra. */ public CVertex[] getCommonVertices(CTetrahedron tetr) { CVertex[] points = new CVertex[4]; int n = 0; for (int i = 0; i < 4; i++) { if (tetr.containsPoint(getPoint(i))) { points[n] = new CVertex(getPoint(i), getPoint(i).idx); for (int k = 0; k < 3; k++) if (Math.abs(points[n].get(k)) > 100.0) points[n].set(k, points[n].get(k)/1); n++; } } return points; } /** returns plane through common triangle of this and another tetrahedron. The apex of this tetrahedron * is below the plane. */ public Plane getPlane(CTetrahedron tetr) { CVertex[] points = new CVertex[3]; CVertex v = null; int i = 0; int j = 0; while ( i < 3) { if (tetr.containsPoint(getPoint(j))) { points[i] = getPoint(j); i++; } else v = getPoint(j); j++; } Plane plane; if (!points[0].isBigpoint()) plane = new Plane(points[0], points[1], points[2]); else { if (!points[1].isBigpoint()) plane = new Plane(points[1], points[2], points[0]); else plane = new Plane(points[2], points[0], points[1]); } if (plane.above(v) == 1) plane.setNormal(plane.getNormal().multiplyThis(-1)); return plane; } public void updateNeighbour(CTetrahedron lookfor, CTetrahedron replacement){ for(int i=0; i<4;i++){ if(neighbours[i]==lookfor){ neighbours[i]=replacement; break; } } } //find id of point public int findpoint(CVertex p){ for(int i = 0; i<4; i++){ if(getPoint(i)==p) { return i; } } System.out.println("Problemer med findpoint\n"); //never happens: return -1; } /** returns neighbouring tetrahedron containing v as the oppposite vertex */ public CTetrahedron findNeighbour(CVertex v) { for (int i = 0; i < 4; i++) { if (getNeighbour(i).containsPoint(v)) return getNeighbour(i); } return null; } /* this tetrahedron and tetr must be neighbours. Return the vertex of this tetrahedron not in tetr */ public CVertex findVertex(CTetrahedron tetr) { CVertex p; for (int i = 0; i < 4; i++) { p = getPoint(i); if (!tetr.containsPoint(p)) return p; } return null; } public boolean containsPoint(CVertex p) { for (int i = 0; i < 4; i++) { if (getPoint(i) == p) return true; } return false; } public boolean containsTriangle(CTriangle t){ for(int tp=0;tp<3;tp++){ boolean found = false; for(int p=0;p<4;p++) if(this.getPoint(p)==t.getPoint(tp)) { found=true; break; } if(!found) return false; } return true; } /** TODO: Copy to Tetrahedron */ public CVertex oppositeVertex(CTriangle base){ for(int p=0;p<4;p++){ if(!base.containsPoint(getPoint(p))) return getPoint(p); } throw new RuntimeException("The triangle is not part of this tetrahedron"); } public CTriangle oppositeTriangle(CVertex v) { for(CTriangle t: triangles){ if(t!=null && !t.containsPoint(v)) return t; } throw new RuntimeException("The vertex is not part of this tetrahedron"); } //given a point index this method finds the index of the apex - meaning the opposite point id that is in //the tetrahedron opposite the given point id //input: point index //output: point index of the point opposite public int apexid(int index){ //Point ap0,ap1,ap2,ap3; CTetrahedron apex_tet= getNeighbour(index); if(apex_tet!= null){ for(int i=0;i<4;i++){ if(apex_tet.getNeighbour(i)== this){ return i; } } } //never happens: return -1; } // public void toScene(J3DScene scene, double rad, Color clr) { // double newRad = rad; // Color newClr = clr; //// if (containsBigPoint()) { newRad = 0.005; newClr = Color.red; } // for (int i = 0; i < 3; i++) { // Point u = getPoint(i).clone(); // for (int k = 0; k < 3; k++) if (Math.abs(u.get(k)) > 100.0) u.set(k, u.get(k)/1); // for (int j = i+1; j < 4; j++) { // Point v = getPoint(j).clone(); // for (int k = 0; k < 3; k++) if (Math.abs(v.get(k)) > 100.0) v.set(k, v.get(k)/1); // LineSegment seg = new LineSegment(u, v); // seg.toScene(scene, newRad, newClr); // } // } // } }