/// <summary> /// Calculates the midpoint of the specified edge. /// </summary> /// <returns>The point.</returns> /// <param name="edge">Edge.</param> public static Point3d MidPoint(MeshEdge edge) { var halfEdge = edge.HalfEdge; Point3d a = halfEdge.Vertex; Point3d b = halfEdge.Twin.Vertex; return((a + b) / 2); }
/// <summary> /// Calculates the length of the specified edge. /// </summary> /// <returns>The length.</returns> /// <param name="edge">Edge.</param> public static double Length(MeshEdge edge) => Vector(edge.HalfEdge).Length;
// Takes a List containing another List per face with the vertex indexes belonging to that face private bool CreateFaces(IEnumerable <List <int> > faceIndexes) { var edgeCount = new Dictionary <string, int>(); var existingHalfEdges = new Dictionary <string, MeshHalfEdge>(); var hasTwinHalfEdge = new Dictionary <MeshHalfEdge, bool>(); // Create the faces, edges and half-edges, non-boundary loops and link references when possible; foreach (var indexes in faceIndexes) { var f = new MeshFace(); this.Faces.Add(f); var tempHEdges = new List <MeshHalfEdge>(indexes.Count); // Create empty half-edges for (var i = 0; i < indexes.Count; i++) { var h = new MeshHalfEdge(); tempHEdges.Add(h); } // Fill out each half edge for (var i = 0; i < indexes.Count; i++) { // Edge goes from v0 to v1 var v0 = indexes[i]; var v1 = indexes[(i + 1) % indexes.Count]; var 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 = this.Vertices[v0]; this.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) { var temp = v0; v0 = v1; v1 = temp; } var key = v0 + " " + v1; if (existingHalfEdges.ContainsKey(key)) { // If this half-edge key already exists, it is the twin of this current half-edge var twin = existingHalfEdges[key]; h.Twin = twin; twin.Twin = h; h.Edge = twin.Edge; hasTwinHalfEdge[h] = true; hasTwinHalfEdge[twin] = true; edgeCount[key]++; } else { // Create an edge and set its half-edge var e = new MeshEdge(); this.Edges.Add(e); h.Edge = e; e.HalfEdge = h; // Record the newly created half-edge existingHalfEdges.Add(key, h); edgeCount.Add(key, 1); } } this.HalfEdges.AddRange(tempHEdges); } // Create boundary edges for (var i = 0; i < this.HalfEdges.Count; i++) { var h = this.HalfEdges[i]; if (!hasTwinHalfEdge[h]) { var f = new MeshFace(); this.Boundaries.Add(f); var boundaryCycle = new List <MeshHalfEdge>(); var halfEdge = h; do { var boundaryHalfEdge = new MeshHalfEdge(); this.HalfEdges.Add(boundaryHalfEdge); boundaryCycle.Add(boundaryHalfEdge); var nextHalfEdge = halfEdge.Next; while (hasTwinHalfEdge[nextHalfEdge]) { nextHalfEdge = nextHalfEdge.Twin.Next; } boundaryHalfEdge.Vertex = nextHalfEdge.Vertex; boundaryHalfEdge.Edge = halfEdge.Edge; boundaryHalfEdge.OnBoundary = true; boundaryHalfEdge.Face = f; f.HalfEdge = boundaryHalfEdge; boundaryHalfEdge.Twin = halfEdge; halfEdge.Twin = boundaryHalfEdge; halfEdge = nextHalfEdge; } while (halfEdge != h); var n = boundaryCycle.Count; for (var 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) { continue; } var corner = new MeshCorner { HalfEdge = h }; h.Corner = corner; this.Corners.Add(corner); } // Check mesh for common errors if (this.HasIsolatedFaces() || this.HasIsolatedVertices() || this.HasNonManifoldEdges()) { return(false); } // Index elements this.IndexElements(); return(true); }