/// <summary> /// Compute the orthonormal bases of the specified face /// </summary> /// <returns>Array containing the 2 Vector3d.</returns> /// <param name="face">Face.</param> public static Vector3d[] OrthonormalBases(HE_Face face) { Vector3d e1 = Vector(face.HalfEdge).Unit(); Vector3d normal = FaceNormal(face); Vector3d e2 = normal.Cross(e1); return(new Vector3d[] { e1, e2 }); }
// get clone public HE_Mesh get() { HE_Mesh result = new HE_Mesh(); reindex(); for (int i = 0; i < vertices.Count; i++) { result.vertices.Add((vertices [i]).getClone()); } for (int i = 0; i < faces.Count; i++) { result.faces.Add(new HE_Face()); } for (int i = 0; i < halfEdges.Count; i++) { result.halfEdges.Add(new HE_HalfEdge()); } for (int i = 0; i < edges.Count; i++) { result.edges.Add(new HE_Edge()); } // for (int i = 0; i < vertices.Count; i++) { HE_Vertex sv = vertices [i]; HE_Vertex tv = result.vertices [i]; tv.halfEdge = result.halfEdges [sv.halfEdge.id]; } for (int i = 0; i < faces.Count; i++) { HE_Face sf = faces [i]; HE_Face tf = result.faces [i]; tf.id = i; tf.halfEdge = result.halfEdges [sf.halfEdge.id]; } for (int i = 0; i < edges.Count; i++) { HE_Edge se = edges [i]; HE_Edge te = result.edges [i]; te.halfEdge = result.halfEdges [se.halfEdge.id]; te.id = i; } for (int i = 0; i < halfEdges.Count; i++) { HE_HalfEdge she = halfEdges [i]; HE_HalfEdge the = result.halfEdges [i]; the.pair = result.halfEdges [she.pair.id]; the.next = result.halfEdges [she.next.id]; the.prev = result.halfEdges [she.prev.id]; the.vert = result.vertices [she.vert.id]; the.face = result.faces [she.face.id]; the.edge = result.edges [she.edge.id]; the.id = i; } return(result); }
public HE_MeshPoint(Point3d point, HE_Face face) { List <HE_Vertex> adj = face.adjacentVertices(); double[] bary = Convert.Point3dToBarycentric(point, adj[0], adj[1], adj[2]); U = bary[0]; V = bary[1]; W = bary[2]; }
HE_Mesh getDual() { HE_Mesh result = new HE_Mesh(); reindex(); for (int i = 0; i < faces.Count; i++) { HE_Face f = faces [i]; HE_HalfEdge he = f.halfEdge; PVector faceCenter = new PVector(); int n = 0; do { faceCenter.add(he.vert); he = he.next; n++; } while(he != f.halfEdge); faceCenter.div(n); result.vertices.Add(new HE_Vertex(faceCenter.x, faceCenter.y, faceCenter.z, i)); } //for(int i=0;i<vertices.Count;i++){ //HE_Vertex v=getVertex(i); foreach (HE_Vertex v in vertices) { HE_HalfEdge he = v.halfEdge; HE_Face f = he.face; List <HE_HalfEdge> faceHalfEdges = new List <HE_HalfEdge> (); HE_Face nf = new HE_Face(); result.faces.Add(nf); do { HE_HalfEdge hen = new HE_HalfEdge(); faceHalfEdges.Add(hen); hen.face = nf; hen.vert = result.vertices [f.id]; if (hen.vert.halfEdge == null) { hen.vert.halfEdge = hen; } if (nf.halfEdge == null) { nf.halfEdge = hen; } he = he.pair.next; f = he.face; } while(he != v.halfEdge); cycleHalfEdges(faceHalfEdges, false); result.halfEdges.AddRange(faceHalfEdges); } result.pairHalfEdges(result.halfEdges); result.createEdges(result.halfEdges, result.edges); result.reindex(); return(result); }
/// <summary> /// Computes the area of the specified face /// </summary> /// <returns>The face area</returns> /// <param name="face">Face.</param> public static double Area(HE_Face face) { if (face.isBoundaryLoop()) { return(0.0); } Vector3d u = Vector(face.HalfEdge); Vector3d v = -Vector(face.HalfEdge.Prev); return(0.5 * u.Cross(v).Length); }
/// <summary> /// Compute the normal vector of the specified face /// </summary> /// <returns>The normal.</returns> /// <param name="face">Face.</param> public static Vector3d FaceNormal(HE_Face face) { if (face.isBoundaryLoop()) { return(null); } Vector3d u = Vector(face.HalfEdge); Vector3d v = -Vector(face.HalfEdge.Prev); return(u.Cross(v).Unit()); }
public void buildMesh(float[][] simpleVertices, int[][] simpleFaces) { /* * vertices = new List<HE_Vertex>(); * faces=new List<HE_Face>(); * halfEdges=new List<HE_HalfEdge>(); * edges=new List<HE_Edge>(); */ vertices.Clear(); faces.Clear(); halfEdges.Clear(); edges.Clear(); //Add all input vertices to the mesh, the original index of the vertex is stored as an id. for (int i = 0; i < simpleVertices.Length; i++) { vertices.Add(new HE_Vertex(simpleVertices [i] [0], simpleVertices [i] [1], simpleVertices [i] [2], i)); } //Create a loop of halfedges for each face. We assume the vertices are given in a consistent order. // To extend this for a non-ordered list, sort the vertices of the input vertices here. HE_HalfEdge he; for (int i = 0; i < simpleFaces.Length; i++) { List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> (); HE_Face hef = new HE_Face(); faces.Add(hef); //TODO: sort face vertices here for (int j = 0; j < simpleFaces[i].Length; j++) { he = new HE_HalfEdge(); faceEdges.Add(he); he.face = hef; if (hef.halfEdge == null) { hef.halfEdge = he; } he.vert = vertices [simpleFaces [i] [j]]; if (he.vert.halfEdge == null) { he.vert.halfEdge = he; } } cycleHalfEdges(faceEdges, false); halfEdges.AddRange(faceEdges); } //associate each halfedge with its pair (belonging to adjacent face) pairHalfEdges(halfEdges); //associate each pair of halfedges to a physical edge createEdges(halfEdges, edges); reindex(); }
/// <summary> /// Compute the centroid of the specified face /// </summary> /// <returns>The centroid.</returns> /// <param name="face">Face.</param> public static Point3d Centroid(HE_Face face) { HE_HalfEdge hE = face.HalfEdge; Point3d a = hE.Vertex; Point3d b = hE.Next.Vertex; Point3d c = hE.Prev.Vertex; if (face.isBoundaryLoop()) { return((a + b) / 2); } return((a + b + c) / 3); }
/// <summary> /// Compute the level on a specified face. /// </summary> /// <param name="valueKey">Key of the value to be computed per vertex.</param> /// <param name="level">Level value to be computed.</param> /// <param name="face">Face to computee the level in.</param> /// <param name="line">Resulting level line on the face</param> /// <returns>True if successful, false if not.</returns> public static bool GetFaceLevel(string valueKey, double level, HE_Face face, out Line line) { List <HE_Vertex> adj = face.adjacentVertices(); List <double> vertexValues = new List <double> { adj[0].UserValues[valueKey], adj[1].UserValues[valueKey], adj[2].UserValues[valueKey] }; List <int> above = new List <int>(); List <int> below = new List <int>(); for (int i = 0; i < vertexValues.Count; i++) { if (vertexValues[i] < level) { below.Add(i); } else { above.Add(i); } } if (above.Count == 3 || below.Count == 3) { // Triangle is above or below level line = new Line(new Point3d(), new Point3d()); return(false); } else { // Triangle intersects level List <Point3d> intersectionPoints = new List <Point3d>(); foreach (int i in above) { foreach (int j in below) { double diff = vertexValues[i] - vertexValues[j]; double desiredDiff = level - vertexValues[j]; double unitizedDistance = desiredDiff / diff; Vector3d edgeV = adj[i] - adj[j]; Point3d levelPoint = (Point3d)adj[j] + (edgeV * unitizedDistance); intersectionPoints.Add(levelPoint); } } line = new Line(intersectionPoints[0], intersectionPoints[1]); return(true); } }
/// <summary> /// Compute the intersection between a mesh face perimeter and a ray tangent to the face. /// </summary> /// <param name="ray">The tangent ray.</param> /// <param name="Face">The mesh face.</param> /// <param name="result">The resulting intersection point.</param> /// <param name="halfEdge">The half-edge on where the intersection lies.</param> /// <returns></returns> public static ISRayFacePerimeter RayFacePerimeter(Ray ray, HE_Face Face, out Point3d result, out HE_HalfEdge halfEdge) { Vector3d faceNormal = HE_MeshGeometry.FaceNormal(Face); Vector3d biNormal = Vector3d.CrossProduct(ray.Direction, faceNormal); Plane perpPlane = new Plane(ray.Origin, ray.Direction, faceNormal, biNormal); List <HE_Vertex> vertices = Face.adjacentVertices(); Point3d temp = new Point3d(); Line line = new Line(vertices[0], vertices[1]); if (LinePlane(line, perpPlane, out temp) != ISLinePlane.Point) { result = null; halfEdge = null; return(ISRayFacePerimeter.Point); } // No intersection found if (temp != ray.Origin && temp != null) { result = temp; halfEdge = null; return(ISRayFacePerimeter.Point); } // Intersection found line = new Line(vertices[1], vertices[2]); if (LinePlane(line, perpPlane, out temp) != ISLinePlane.Point) { result = null; halfEdge = null; return(ISRayFacePerimeter.NoIntersection); } // No intersection found if (temp != ray.Origin && temp != null) { result = temp; halfEdge = null; return(ISRayFacePerimeter.Point); } // Intersection found line = new Line(vertices[2], vertices[0]); if (LinePlane(line, perpPlane, out temp) != ISLinePlane.Point) { result = null; halfEdge = null; return(ISRayFacePerimeter.NoIntersection); } if (temp != ray.Origin && temp != null) { result = temp; halfEdge = null; return(ISRayFacePerimeter.Point); } else { result = null; halfEdge = null; return(ISRayFacePerimeter.Error); } }
/// <summary> /// Computes a geodesic on a mesh given a starting point and an initial direction. /// Returns true if successfull and false if something went wrong. /// </summary> public static bool StartDir(HE_MeshPoint meshPoint, Vector3d vector, HE_Mesh mesh, int maxIter, out List <Point3d> geodesic) { // Get initial face on the mesh HE_Face initialFace = mesh.Faces[meshPoint.FaceIndex]; // Start iteration // Create variables for current iteration step HE_Face thisFace = initialFace; Point3d thisPoint = new Point3d(); Vector3d thisDirection = vector; int iter = 0; List <Point3d> geodPoints = new List <Point3d>(); do { Ray ray = new Ray(thisPoint, thisDirection); // Find intersection between ray and boundary AR_Lib.Intersect3D.RayFacePerimeter(ray, thisFace, out Point3d nextPoint, out HE_HalfEdge halfEdge); // Intersection method should check for correct direction using sign of dot product // Add point to pointlist geodPoints.Add(nextPoint); // Walk to next face HE_Face nextFace = halfEdge.Twin.Face; // Flip vector to next face Vector3d perpVector = Vector3d.CrossProduct(thisDirection, HE_MeshGeometry.FaceNormal(thisFace)); Vector3d nextVector = Vector3d.CrossProduct(HE_MeshGeometry.FaceNormal(nextFace), perpVector); // Assign iteration variables to current thisPoint = nextPoint; thisFace = nextFace; thisDirection = nextVector; // Increase counter iter++; } while (iter < maxIter); // Assign outputs geodesic = geodPoints; return(true); }
/// <summary> /// Compute the gradient on a given mesh face given some per-vertex values /// </summary> /// <param name="valueKey">Key of the values in the vertex.UserData dictionary</param> /// <param name="face">Face to compute thee gradient.</param> /// <returns>A vector representing the gradient on that mesh face</returns> public static Vector3d ComputeFaceGradient(string valueKey, HE_Face face) { List <HE_Vertex> adjacentVertices = face.adjacentVertices(); Point3d i = adjacentVertices[0]; Point3d j = adjacentVertices[1]; Point3d k = adjacentVertices[2]; double gi = adjacentVertices[0].UserValues[valueKey]; double gj = adjacentVertices[1].UserValues[valueKey]; double gk = adjacentVertices[2].UserValues[valueKey]; Vector3d faceNormal = face.Normal / (2 * face.Area); Vector3d rotatedGradient = (gi * (k - j) + gj * (i - k) + gk * (j - i)) / (2 * face.Area); Vector3d gradient = rotatedGradient.Cross(faceNormal); return(gradient); }
/// <summary> /// Compute the circumcenter the specified face. /// </summary> /// <returns>The circumcenter.</returns> /// <param name="face">Face.</param> public static Point3d Circumcenter(HE_Face face) { HE_HalfEdge hE = face.HalfEdge; Point3d a = hE.Vertex; Point3d b = hE.Next.Vertex; Point3d c = hE.Prev.Vertex; if (face.isBoundaryLoop()) { return((a + b) / 2); } Vector3d ac = c - a; Vector3d ab = b - a; Vector3d w = ab.Cross(ac); Vector3d u = (w.Cross(ab)) * ac.Length2; Vector3d v = (ac.Cross(w)) * ab.Length2; Point3d x = (u + v) / (2 * w.Length2); return(x + a); }
// Takes a List containing another List per face with the vertex indexes belonging to that face private bool createFaces(List <List <int> > faceIndexes) { Dictionary <string, int> edgeCount = new Dictionary <string, int>(); Dictionary <string, HE_HalfEdge> existingHalfEdges = new Dictionary <string, HE_HalfEdge>(); Dictionary <HE_HalfEdge, bool> hasTwinHalfEdge = new Dictionary <HE_HalfEdge, bool>(); // Create the faces, edges and half-edges, non-boundary loops and link references when possible; foreach (List <int> indexes in faceIndexes) { HE_Face f = new HE_Face(); Faces.Add(f); List <HE_HalfEdge> tempHEdges = new List <HE_HalfEdge>(indexes.Count); //Create empty half-edges for (int i = 0; i < indexes.Count; i++) { HE_HalfEdge h = new HE_HalfEdge(); tempHEdges.Add(h); } //Fill out each half edge for (int i = 0; i < indexes.Count; i++) { //Edge goes from v0 to v1 int v0 = indexes[i]; int v1 = indexes[(i + 1) % indexes.Count]; HE_HalfEdge h = tempHEdges[i]; // Set previous and next h.Next = tempHEdges[(i + 1) % indexes.Count]; h.Prev = tempHEdges[(i + indexes.Count - 1) % indexes.Count]; h.onBoundary = false; hasTwinHalfEdge.Add(h, false); // Set half-edge & vertex mutually h.Vertex = Vertices[v0]; Vertices[v0].HalfEdge = h; // Set half-edge face & vice versa h.Face = f; f.HalfEdge = h; // Reverse v0 and v1 if v0 > v1 if (v0 > v1) { int temp = v0; v0 = v1; v1 = temp; } string key = v0 + " " + v1; if (existingHalfEdges.ContainsKey(key)) { // If this half-edge key already exists, it is the twin of this current half-edge HE_HalfEdge twin = existingHalfEdges[key]; h.Twin = twin; twin.Twin = h; h.Edge = twin.Edge; hasTwinHalfEdge[h] = true; hasTwinHalfEdge[twin] = true; edgeCount[key] += 1; } else { // Create an edge and set its half-edge HE_Edge e = new HE_Edge(); Edges.Add(e); h.Edge = e; e.HalfEdge = h; // Record the newly created half-edge existingHalfEdges.Add(key, h); edgeCount.Add(key, 1); } } HalfEdges.AddRange(tempHEdges); } // Create boundary edges for (int i = 0; i < HalfEdges.Count; i++) { HE_HalfEdge h = HalfEdges[i]; if (!hasTwinHalfEdge[h]) { HE_Face f = new HE_Face(); Boundaries.Add(f); List <HE_HalfEdge> boundaryCycle = new List <HE_HalfEdge>(); HE_HalfEdge hE = h; do { HE_HalfEdge bH = new HE_HalfEdge(); HalfEdges.Add(bH); boundaryCycle.Add(bH); HE_HalfEdge nextHE = hE.Next; while (hasTwinHalfEdge[nextHE]) { nextHE = nextHE.Twin.Next; } bH.Vertex = nextHE.Vertex; bH.Edge = hE.Edge; bH.onBoundary = true; bH.Face = f; f.HalfEdge = bH; bH.Twin = hE; hE.Twin = bH; hE = nextHE; } while (hE != h); int n = boundaryCycle.Count; for (int j = 0; j < n; j++) { boundaryCycle[j].Next = boundaryCycle[(j + n - 1) % n]; boundaryCycle[j].Prev = boundaryCycle[(j + 1) % n]; hasTwinHalfEdge[boundaryCycle[j]] = true; hasTwinHalfEdge[boundaryCycle[j].Twin] = true; } } if (!h.onBoundary) { HE_Corner corner = new HE_Corner(); corner.HalfEdge = h; h.Corner = corner; Corners.Add(corner); } } // Check mesh for common errors if (HasIsolatedFaces() || HasIsolatedVertices() || HasNonManifoldEdges()) { return(false); } // Index elements indexElements(); return(true); }
// Split the mesh in half, retain the part on the same side as the point "center". // Works only on a convex mesh !!! public void cutMesh(Plane P, PVector center) { float centerside = P.side(center); if (centerside != 0) // if center is on the plane, we can't decide which part to keep, ignore. { List <HE_Vertex> newVertices = new List <HE_Vertex> (); List <HE_Face> newFaces = new List <HE_Face> (); List <HE_HalfEdge> newHalfEdges = new List <HE_HalfEdge> (); List <HE_Edge> newEdges = new List <HE_Edge> (); // get all split edges List <SplitEdge> splitEdges = retrieveSplitEdges(P); //check if the plane cuts the mesh at all, at least one point should be on the other side of the plane. //compared to the first point float[] sides = new float[vertices.Count]; //bool cut = false;// add inok for (int i = 0; i < vertices.Count; i++) { HE_Vertex v = vertices [i]; sides [i] = P.side(v); //if(sides[0]*sides[i]<=0f) cut=true;// add inok } //loop through all faces. for (int i = 0; i < faces.Count; i++) { HE_Face face = faces [i]; HE_HalfEdge halfEdge = face.halfEdge; List <HE_Vertex> newFaceVertices1 = new List <HE_Vertex> (); // vertices on the correct side. List <HE_Vertex> newFaceVertices2 = new List <HE_Vertex> (); // vertices on the wrong side, not used right now. //for each face, loop through all vertices and retain the vertices on the correct side. If the edge //is cut, insert the new point in the appropriate place. do { if (sides [halfEdge.vert.id] * centerside >= 0f) { newFaceVertices1.Add(halfEdge.vert); } if (sides [halfEdge.vert.id] * centerside <= 0f) { newFaceVertices2.Add(halfEdge.vert); } for (int j = 0; j < splitEdges.Count; j++) // loop through all split edges to check for the current edge. { SplitEdge se = splitEdges [j]; if (halfEdge.edge == se.edge) { newFaceVertices1.Add(se.splitVertex); newFaceVertices2.Add(se.splitVertex); break; } } halfEdge = halfEdge.next; } while(halfEdge != face.halfEdge); //Create a new face form the vertices we retained,ignore degenerate faces with less than 3 vertices. //Add all face-related information to the data-structure. if (newFaceVertices1.Count > 2) { HE_Face newFace = new HE_Face(); newFaces.Add(newFace); List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> (); for (int j = 0; j < newFaceVertices1.Count; j++) { HE_Vertex v = newFaceVertices1 [j]; if (!newVertices.Contains(v)) { newVertices.Add(v); } HE_HalfEdge newHalfEdge = new HE_HalfEdge(); faceEdges.Add(newHalfEdge); newHalfEdge.vert = v; v.halfEdge = newHalfEdge; newHalfEdge.face = newFace; if (newFace.halfEdge == null) { newFace.halfEdge = newHalfEdge; } } cycleHalfEdges(faceEdges, false); newHalfEdges.AddRange(faceEdges); } } //Add missing information to the datastructure int n = newHalfEdges.Count; pairHalfEdges(newHalfEdges); createEdges(newHalfEdges, newEdges); //Cutting the mesh not only cuts the faces, it also creates one new planar face looping through all new cutpoints(in a convex mesh). //This hole in the mesh is identified by unpaired halfedges remaining after the pairibg operation. //This part needs to rethought to extend to concave meshes!!! List <HE_HalfEdge> unpairedEdges = new List <HE_HalfEdge> (); for (int i = 0; i < n; i++) { HE_HalfEdge he = newHalfEdges [i]; if (he.pair == null) { unpairedEdges.Add(he); } } if (unpairedEdges.Count > 0) { //Create a closed loop out of the collection of unpaired halfedges and associate a new face with this. //Easy to explain with a drawing, beyond my skill with words. HE_Face cutFace = new HE_Face(); List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> (); HE_HalfEdge he = unpairedEdges [0]; HE_HalfEdge hen = he; do { HE_HalfEdge _hen = he.next; HE_HalfEdge _hep = he.next.pair; if (_hep != null) //add inok { hen = he.next.pair.next; while (!unpairedEdges.Contains(hen)) { hen = hen.pair.next; } } else { hen = hen.next; Debug.LogWarning("LogWarning: null"); } HE_HalfEdge newhe = new HE_HalfEdge(); faceEdges.Add(newhe); if (cutFace.halfEdge == null) { cutFace.halfEdge = newhe; } newhe.vert = hen.vert; newhe.pair = he; he.pair = newhe; HE_Edge e = new HE_Edge(); e.halfEdge = newhe; he.edge = e; newhe.edge = e; newEdges.Add(e); newhe.face = cutFace; he = hen; } while(hen != unpairedEdges[0]); cycleHalfEdges(faceEdges, true); newHalfEdges.AddRange(faceEdges); newFaces.Add(cutFace); } // update the mesh vertices = newVertices; faces = newFaces; halfEdges = newHalfEdges; edges = newEdges; reindex(); } }
void splitSurface(Plane P) { List <HE_Vertex> newVertices = new List <HE_Vertex> (); List <HE_Face> newFaces = new List <HE_Face> (); List <HE_HalfEdge> newHalfEdges = new List <HE_HalfEdge> (); List <HE_Edge> newEdges = new List <HE_Edge> (); // get all split edges List <SplitEdge> splitEdges = retrieveSplitEdges(P); //check if the plane cuts the mesh at all, at least one point should be on the other side of the plane. //compared to the first point float[] sides = new float[vertices.Count]; //bool cut=false; for (int i = 0; i < vertices.Count; i++) { HE_Vertex v = vertices [i]; sides [i] = P.side(v); //if(sides[0]*sides[i]<=0f) cut=true; } //loop through all faces. for (int i = 0; i < faces.Count; i++) { HE_Face face = faces [i]; HE_HalfEdge halfEdge = face.halfEdge; List <HE_Vertex> newFaceVertices1 = new List <HE_Vertex> (); List <HE_Vertex> newFaceVertices2 = new List <HE_Vertex> (); List <HE_Vertex> currentFace = newFaceVertices1; //for each face, loop through all vertices and retain the vertices on the correct side. If the edge //is cut, insert the new point in the appropriate place. do { currentFace.Add(halfEdge.vert); for (int j = 0; j < splitEdges.Count; j++) // loop through all split edges to check for the current edge. { SplitEdge se = (SplitEdge)splitEdges [j]; if (halfEdge.edge == se.edge) { newFaceVertices1.Add(se.splitVertex); newFaceVertices2.Add(se.splitVertex); if (currentFace == newFaceVertices1) { currentFace = newFaceVertices2; } else { currentFace = newFaceVertices1; } break; } } halfEdge = halfEdge.next; } while(halfEdge != face.halfEdge); //Create a new face form the vertices we retained,ignore degenerate faces with less than 3 vertices. //Add all face-related information to the data-structure. HE_Face newFace = new HE_Face(); newFaces.Add(newFace); List <HE_HalfEdge> faceEdges = new List <HE_HalfEdge> (); for (int j = 0; j < newFaceVertices1.Count; j++) { HE_Vertex v = newFaceVertices1 [j]; if (!newVertices.Contains(v)) { newVertices.Add(v); } HE_HalfEdge newHalfEdge = new HE_HalfEdge(); faceEdges.Add(newHalfEdge); newHalfEdge.vert = v; v.halfEdge = newHalfEdge; newHalfEdge.face = newFace; if (newFace.halfEdge == null) { newFace.halfEdge = newHalfEdge; } } cycleHalfEdges(faceEdges, false); newHalfEdges.AddRange(faceEdges); if (newFaceVertices2.Count > 0) { newFace = new HE_Face(); newFaces.Add(newFace); faceEdges = new List <HE_HalfEdge> (); for (int j = 0; j < newFaceVertices2.Count; j++) { HE_Vertex v = newFaceVertices2 [j]; if (!newVertices.Contains(v)) { newVertices.Add(v); } HE_HalfEdge newHalfEdge = new HE_HalfEdge(); faceEdges.Add(newHalfEdge); newHalfEdge.vert = v; v.halfEdge = newHalfEdge; newHalfEdge.face = newFace; if (newFace.halfEdge == null) { newFace.halfEdge = newHalfEdge; } } cycleHalfEdges(faceEdges, false); newHalfEdges.AddRange(faceEdges); //}//test } //Add missing information to the datastructure pairHalfEdges(newHalfEdges); createEdges(newHalfEdges, newEdges); } // update the mesh vertices = newVertices; faces = newFaces; halfEdges = newHalfEdges; edges = newEdges; reindex(); }
// draw as a triangular mesh. public Triangle3D draw() { Triangle3D triangle3d = new Triangle3D(); for (int i = 0; i < faces.Count; i++) { HE_Face face = faces [i]; HE_HalfEdge halfEdge = face.halfEdge; HE_Vertex midFace = new HE_Vertex(0, 0, 0, 0); int c = 0; do { HE_Vertex v = halfEdge.vert; midFace.x += v.x; midFace.y += v.y; midFace.z += v.z; halfEdge = halfEdge.next; c++; } while(halfEdge != face.halfEdge); midFace.x /= c; midFace.y /= c; midFace.z /= c; halfEdge = face.halfEdge; HE_Vertex vv; do { HE_Vertex v0 = halfEdge.vert; HE_Vertex v1 = halfEdge.next.vert; triangle3d.vertices.Add(midFace); triangle3d.vertices.Add(v1); triangle3d.vertices.Add(v0); halfEdge = halfEdge.next; } while(halfEdge != face.halfEdge); //beginShape(TRIANGLE_STRIP); /* * GL.Begin(GL.TRIANGLE_STRIP); * HE_Vertex vv; * do{ * vv=halfEdge.vert; * GL.Vertex3(vv.x,vv.y,vv.z); * GL.Vertex3(midFace.x,midFace.y,midFace.z); * halfEdge= halfEdge.next; * } * while(halfEdge!=face.halfEdge); * vv=halfEdge.vert; * GL.Vertex3(vv.x,vv.y,vv.z); * //endShape(); * GL.End(); */ /* * HE_Vertex vv; * do{ * vv=halfEdge.vert; * //GL.Vertex3(vv.x,vv.y,vv.z); * //GL.Vertex3(midFace.x,midFace.y,midFace.z); * triangle3d.vertices.Add(vv); * triangle3d.vertices.Add(midFace); * * halfEdge= halfEdge.next; * } * while(halfEdge!=face.halfEdge); * vv=halfEdge.vert; * * //GL.Vertex3(vv.x,vv.y,vv.z); * triangle3d.vertices.Add(vv); */ } return(triangle3d); }