/** checks the combinatorial validity of the triangulation. */ public boolean isValid() { boolean result = true; System.out.print("Checking combinatorial validity..."); for (TriangulationDSVertex_2<X> p : this.vertices) { if (p == null) { result = false; System.out.println("\n vertex with null point"); } if (p != null && p.getFace() == null) { result = false; System.out.println("\n vertex with null associated triangle"); } if (p != null && !hasFace(p.getFace())) { result = false; System.out.println("\n vertex with non-existing associated triangle"); } } for (TriangulationDSFace_2<X> c : this.faces) { if (c == null) { result = false; System.out.println("null face"); } if (c != null && (c.vertex(0) == null || c.vertex(1) == null || c.vertex(2) == null)) { result = false; System.out.println("\n face with null vertex"); } if (c != null && (!hasVertex(c.vertex(0)) || !hasVertex(c.vertex(1)) || !hasVertex(c.vertex(2)))) { result = false; System.out.println("\n face with non-existing vertex"); } // check for the coherence of the 3 neighbors of a given face if (c != null) { for (int i = 0; i < 3; i++) { TriangulationDSFace_2<X> adjacentFace = c.neighbor(i); if (adjacentFace != null && adjacentFace.neighbors.contains(c) == false) { System.out.println("\n adjacent face error"); result = false; } } } } if (result == true) System.out.println(" ok"); else System.out.println("errors in combinatorial validity"); return result; }
/** * checks whether an edge is shared by two faces f1 and f2: the function check whether the * corresponding vertices appear both in f1 and f2, in the correct order. LCA: a' tester */ public boolean areEqual( TriangulationDSFace_2<X> face1, int i1, TriangulationDSFace_2<X> face2, int i2) { HalfedgeHandle<X> edge1 = new HalfedgeHandle<X>(face1, i1); HalfedgeHandle<X> edge2 = new HalfedgeHandle<X>(face2, i2); TriangulationDSVertex_2<X> v1 = edge1.getVertex(0); // first vertex of edge1 TriangulationDSVertex_2<X> v2 = edge1.getVertex(1); // second vertex of edge1 boolean contained = edge2.hasVertex(v1); if (contained == false) return false; contained = edge2.hasVertex(v2); if (contained == false) return false; if (v1.equals(edge2.getVertex(0))) return false; return true; }
/** Inserts point p in face c. Face c is split into 3 triangles. */ public TriangulationDSVertex_2<X> insertInTriangle(X p, TriangulationDSFace_2<X> t) { if (t == null) throw new Error("Trying to star a null cell"); TriangulationDSFace_2<X> f1 = t.neighbor(1); TriangulationDSFace_2<X> f2 = t.neighbor(2); TriangulationDSFace_2<X> f0 = t.neighbor(0); TriangulationDSVertex_2<X> v0 = t.vertex(0); TriangulationDSVertex_2<X> v1 = t.vertex(1); TriangulationDSVertex_2<X> v2 = t.vertex(2); // create new vertex TriangulationDSVertex_2<X> v = new TriangulationDSVertex_2<X>(p); vertices.add(v); // create and set two new faces TriangulationDSFace_2<X> newFace2 = createFace(v0, v1, v, t, null, f2); TriangulationDSFace_2<X> newFace1 = createFace(v0, v, v2, t, f1, newFace2); newFace2.setNeighbor(1, newFace1); // set new vertex and neighbors of old triangle t.setVertex(0, v); t.setNeighbor(1, newFace1); t.setNeighbor(2, newFace2); // set the faces incident to v and v0 v.setFace(t); v0.setFace(newFace1); // restore the marks of the initial triangle edges for (int i = 0; i < 3; i++) t.unmark(i); if (t.neighbor(0) != null) { HalfedgeHandle<X> e = new HalfedgeHandle<X>(t, 0); e.setMark(e.getOpposite().isMarked()); } if (newFace1.neighbor(1) != null) { HalfedgeHandle<X> e = new HalfedgeHandle<X>(newFace1, 1); e.setMark(e.getOpposite().isMarked()); } if (newFace2.neighbor(2) != null) { HalfedgeHandle<X> e = new HalfedgeHandle<X>(newFace2, 2); e.setMark(e.getOpposite().isMarked()); } // return the new vertex return v; }
/** creates a triangle with vertices p1, p2, p3. */ public TriangulationDSFace_2<X> makeTriangle(X p1, X p2, X p3) { TriangulationDSVertex_2<X> v1 = new TriangulationDSVertex_2<X>(p1); TriangulationDSVertex_2<X> v2 = new TriangulationDSVertex_2<X>(p2); TriangulationDSVertex_2<X> v3 = new TriangulationDSVertex_2<X>(p3); TriangulationDSFace_2<X> c = createFace(v1, v2, v3, null, null, null); v1.setFace(c); v2.setFace(c); v3.setFace(c); this.vertices.add(v1); this.vertices.add(v2); this.vertices.add(v3); return c; }
/** * Create a new triangulation from the face-vertex incidence relations It takes linear space and * linear time. */ public TriangulationDS_2(X[] points, int[][] neighbors) { if (points == null || neighbors == null || points[0] == null) throw new Error("error: null vertices or null faces"); System.out.print("Creating triangulated 3D mesh... "); this.faces = new ArrayList<TriangulationDSFace_2<X>>(); this.vertices = new ArrayList<TriangulationDSVertex_2<X>>(); for (int i = 0; i < points.length; i++) { if (points[i] == null) throw new Error("null vertex error"); TriangulationDSVertex_2<X> v = new TriangulationDSVertex_2<X>(points[i]); this.vertices.add(v); } // first pair (the key) represents the edges of the triangulation // second pair (the associated value) represents the two neighboring faces (sharing an edge) HashMap<Pair<Integer>, Pair<Integer>> edges = new HashMap<Pair<Integer>, Pair<Integer>>(); for (int i = 0; i < neighbors.length; i++) { int i0 = neighbors[i][0], i1 = neighbors[i][1], i2 = neighbors[i][2]; createFace(this.vertices.get(i0), vertices.get(i1), vertices.get(i2), null, null, null); for (int j = 0; j < 3; j++) { int index1 = neighbors[i][(j + 1) % 3]; int index2 = neighbors[i][(j + 2) % 3]; Pair<Integer> edge; if (index1 <= index2) edge = new Pair<Integer>(index1, index2); else edge = new Pair<Integer>(index2, index1); if (edges.containsKey(edge) == false) { Pair<Integer> face; if (index1 <= index2) face = new Pair<Integer>(i, -1); else face = new Pair<Integer>(-1, i); edges.put(edge, face); } else { Pair<Integer> face = edges.get(edge); if (face.getFirst() == -1) face.setFirst(i); else face.setSecond(i); } } } // System.out.println("setting neighboring faces"); for (int i = 0; i < neighbors.length; i++) { TriangulationDSFace_2<X> currentFace = this.faces.get(i); for (int j = 0; j < 3; j++) { // setting vertex adjacent face TriangulationDSVertex_2<X> v = this.vertices.get(neighbors[i][j]); v.setFace(this.faces.get(i)); int index1 = neighbors[i][(j + 1) % 3]; int index2 = neighbors[i][(j + 2) % 3]; Pair<Integer> edge; if (index1 <= index2) edge = new Pair<Integer>(index1, index2); else edge = new Pair<Integer>(index2, index1); if (edges.containsKey(edge) == false) throw new Error("error: edge not found"); else { Pair<Integer> face = edges.get(edge); if (face.getFirst() == -1 && face.getSecond() == -1) throw new Error("error: wrong adjacent faces"); if (face.getFirst() == -1 || face.getSecond() == -1) ; // boundary edge else { int neighborFace; if (index1 <= index2) neighborFace = face.getSecond(); else neighborFace = face.getFirst(); if (neighborFace < 0 || neighborFace >= this.faces.size()) throw new Error("error neighbor face index"); currentFace.setNeighbor(j, this.faces.get(neighborFace)); } } } } System.out.println("done"); }