public EdgeMesh(Mesh m) { this.Verticies = new List<Vector3>(); this.Faces = new List<EMFace>(); this.Edges = new List<EMEdge>(); foreach (var v in m.verticies) this.Verticies.Add(v.Position); for (int i = 0; i < m.indicies.Length; i += 3) { var face = new EMFace(m.indicies[i + 0], m.indicies[i + 1], m.indicies[i + 2]); foreach (var edge in face.edges) face.Centroid += this.Verticies[edge.Verticies[0]]; face.Centroid /= face.edges.Count; this.Faces.Add(face); for (int e = 0; e < face.edges.Count; ++e) { var foundEdge = FindEdge(face.edges[e].Verticies[0], face.edges[e].Verticies[1]); if (foundEdge != -1) { face.edges[e] = this.Edges[foundEdge]; face.edges[e].ParentFace.SetRecipricalNeighbor(face.edges[e], face); } else this.Edges.Add(face.edges[e]); } } }
private EMFace MergeFaces(EMFace A, EMFace B) { if (Object.ReferenceEquals(A, B)) { throw new InvalidOperationException("Attempt to merge face with itself"); } EMEdge sharedEdge = null; foreach (var e in A.edges) { if (e.Neighbors.Contains(B)) { sharedEdge = e; } } if (sharedEdge == null) { throw new InvalidOperationException("Attempt to merge faces with no shared edge."); } var newFace = new EMFace(); newFace.edges = new List <EMEdge>(A.edges); newFace.edges.InsertRange(0, B.edges); newFace.edges.RemoveAll((e) => Object.ReferenceEquals(e, sharedEdge)); if (newFace.edges.Count <= 2) { throw new InvalidOperationException("Degenerate face generated"); } return(newFace); }
private EMFace OtherNeighbor(EMEdge e, EMFace f) { if (Object.ReferenceEquals(e.Neighbors[0], f)) { return(e.Neighbors[1]); } else { return(e.Neighbors[0]); } }
private void VisitEdgePairsInSequence(EMFace face, Func <EMEdge, EMEdge, VEPISReturnCode> callback) { short?endpoint = null; var currentEdge = face.edges[0]; var terminalCheck = false; while (true) { if (!endpoint.HasValue) { endpoint = currentEdge.Verticies[1]; } if (terminalCheck) { if (Object.ReferenceEquals(currentEdge, face.edges[0])) { break; //We've looped through the entire polygon } } else { terminalCheck = true; } var nextEdge = FindNextEdgeInSequence(face, currentEdge, endpoint.Value); short nextEndpoint = -1; if (nextEdge.Verticies[0] == endpoint) { nextEndpoint = nextEdge.Verticies[1]; } else { nextEndpoint = nextEdge.Verticies[0]; } var callbackResult = callback(currentEdge, nextEdge); if (callbackResult == VEPISReturnCode.Advance) { currentEdge = nextEdge; } else if (callbackResult == VEPISReturnCode.Abort) { break; } else { terminalCheck = false; } endpoint = nextEndpoint; } }
public static EMEdge FindSharedEdge(EMFace a, EMFace b) { foreach (var e in a.edges) { if (b.edges.Contains(e)) { return(e); } } return(null); }
internal void SetRecipricalNeighbor(EMEdge edge, EMFace neighbor) { foreach (var e in edges) { if (Object.ReferenceEquals(e, edge)) { e.Neighbors[1] = neighbor; } } //for (int i = 0; i < 3; ++i) // if (Object.ReferenceEquals(Edges[i],edge)) Neighbors[i] = neighbor; }
public List<Vector3> ExtractPerimeter(EMFace face) { var r = new List<Vector3>(); VisitEdgePairsInSequence(face, (a, b) => { //Record the un-shared end point of a. if (b.Verticies.Contains(a.Verticies[0])) r.Add(Verticies[a.Verticies[1]]); else r.Add(Verticies[a.Verticies[0]]); return VEPISReturnCode.Advance; }); return r; }
private EMEdge FindNextEdgeInSequence(EMFace of, EMEdge after, short endpoint) { foreach (var e in of.edges) { if (Object.ReferenceEquals(e, after)) { continue; } if (e.Verticies.Contains(endpoint)) { return(e); } } throw new InvalidOperationException("Malformed edge mesh"); }
public bool IsPointOnFace(Vector3 p, EMFace face) { var accumulatedAngle = 0.0f; foreach (var edge in face.edges) { var v0 = Verticies[edge.Verticies[0]] - p; var v1 = Verticies[edge.Verticies[1]] - p; var angle = AngleBetweenVectors(v0, v1); if (angle < 0) angle *= -1; accumulatedAngle += angle; } return Gem.Math.Utility.NearlyEqual(accumulatedAngle, Gem.Math.Angle.PI2); }
private Plane ConstructPlane(EMFace face) { Plane? r = null; //Choose the first two edges of the face that are not colinear, and create a plane from them. VisitEdgePairsInSequence(face, (A, B) => { if (EdgesAreColinear(A, B)) return VEPISReturnCode.Advance; var points = ExtractPointSequence(A, B); r = new Plane(Verticies[points[0]], Verticies[points[1]], Verticies[points[2]]); return VEPISReturnCode.Abort; }); //If we made it here, there are no non-colinear edge pairs. if (!r.HasValue) throw new InvalidOperationException("Attempt to construct plane from degenerate face"); return r.Value; }
public bool IsPointOnFace(Vector3 p, EMFace face) { var accumulatedAngle = 0.0f; foreach (var edge in face.edges) { var v0 = Verticies[edge.Verticies[0]] - p; var v1 = Verticies[edge.Verticies[1]] - p; var angle = AngleBetweenVectors(v0, v1); if (angle < 0) { angle *= -1; } accumulatedAngle += angle; } return(Gem.Math.Utility.NearlyEqual(accumulatedAngle, Gem.Math.Angle.PI2)); }
public List <Vector3> ExtractPerimeter(EMFace face) { var r = new List <Vector3>(); VisitEdgePairsInSequence(face, (a, b) => { //Record the un-shared end point of a. if (b.Verticies.Contains(a.Verticies[0])) { r.Add(Verticies[a.Verticies[1]]); } else { r.Add(Verticies[a.Verticies[0]]); } return(VEPISReturnCode.Advance); }); return(r); }
public EdgeMesh(Mesh m) { this.Verticies = new List <Vector3>(); this.Faces = new List <EMFace>(); this.Edges = new List <EMEdge>(); foreach (var v in m.verticies) { this.Verticies.Add(v.Position); } for (int i = 0; i < m.indicies.Length; i += 3) { var face = new EMFace(m.indicies[i + 0], m.indicies[i + 1], m.indicies[i + 2]); foreach (var edge in face.edges) { face.Centroid += this.Verticies[edge.Verticies[0]]; } face.Centroid /= face.edges.Count; this.Faces.Add(face); for (int e = 0; e < face.edges.Count; ++e) { var foundEdge = FindEdge(face.edges[e].Verticies[0], face.edges[e].Verticies[1]); if (foundEdge != -1) { face.edges[e] = this.Edges[foundEdge]; face.edges[e].ParentFace.SetRecipricalNeighbor(face.edges[e], face); } else { this.Edges.Add(face.edges[e]); } } } }
private bool IsConvex(EMFace face) { var accumulatedAngle = 0.0f; VisitEdgePairsInSequence(face, (a, b) => { var points = ExtractPointSequence(a, b); var v0 = Verticies[points[0]] - Verticies[points[1]]; var v1 = Verticies[points[2]] - Verticies[points[1]]; var angle = AngleBetweenVectors(v0, v1); accumulatedAngle += angle; return(VEPISReturnCode.Advance); }); if (accumulatedAngle < 0) { accumulatedAngle *= -1; } return(Gem.Math.Utility.NearlyEqual(accumulatedAngle, (face.edges.Count - 2) * Gem.Math.Angle.PI)); }
private Plane ConstructPlane(EMFace face) { Plane?r = null; //Choose the first two edges of the face that are not colinear, and create a plane from them. VisitEdgePairsInSequence(face, (A, B) => { if (EdgesAreColinear(A, B)) { return(VEPISReturnCode.Advance); } var points = ExtractPointSequence(A, B); r = new Plane(Verticies[points[0]], Verticies[points[1]], Verticies[points[2]]); return(VEPISReturnCode.Abort); }); //If we made it here, there are no non-colinear edge pairs. if (!r.HasValue) { throw new InvalidOperationException("Attempt to construct plane from degenerate face"); } return(r.Value); }
private void VisitEdgePairsInSequence(EMFace face, Func<EMEdge, EMEdge, VEPISReturnCode> callback) { short? endpoint = null; var currentEdge = face.edges[0]; var terminalCheck = false; while (true) { if (!endpoint.HasValue) endpoint = currentEdge.Verticies[1]; if (terminalCheck) { if (Object.ReferenceEquals(currentEdge, face.edges[0])) break; //We've looped through the entire polygon } else terminalCheck = true; var nextEdge = FindNextEdgeInSequence(face, currentEdge, endpoint.Value); short nextEndpoint = -1; if (nextEdge.Verticies[0] == endpoint) nextEndpoint = nextEdge.Verticies[1]; else nextEndpoint = nextEdge.Verticies[0]; var callbackResult = callback(currentEdge, nextEdge); if (callbackResult == VEPISReturnCode.Advance) currentEdge = nextEdge; else if (callbackResult == VEPISReturnCode.Abort) break; else terminalCheck = false; endpoint = nextEndpoint; } }
public static EMEdge FindSharedEdge(EMFace a, EMFace b) { foreach (var e in a.edges) if (b.edges.Contains(e)) return e; return null; }
private EMFace OtherNeighbor(EMEdge e, EMFace f) { if (Object.ReferenceEquals(e.Neighbors[0], f)) return e.Neighbors[1]; else return e.Neighbors[0]; }
private EMFace MergeFaces(EMFace A, EMFace B) { if (Object.ReferenceEquals(A, B)) throw new InvalidOperationException("Attempt to merge face with itself"); EMEdge sharedEdge = null; foreach (var e in A.edges) if (e.Neighbors.Contains(B)) sharedEdge = e; if (sharedEdge == null) throw new InvalidOperationException("Attempt to merge faces with no shared edge."); var newFace = new EMFace(); newFace.edges = new List<EMEdge>(A.edges); newFace.edges.InsertRange(0, B.edges); newFace.edges.RemoveAll((e) => Object.ReferenceEquals(e, sharedEdge)); if (newFace.edges.Count <= 2) throw new InvalidOperationException("Degenerate face generated"); return newFace; }
private bool IsConvex(EMFace face) { var accumulatedAngle = 0.0f; VisitEdgePairsInSequence(face, (a, b) => { var points = ExtractPointSequence(a, b); var v0 = Verticies[points[0]] - Verticies[points[1]]; var v1 = Verticies[points[2]] - Verticies[points[1]]; var angle = AngleBetweenVectors(v0, v1); accumulatedAngle += angle; return VEPISReturnCode.Advance; }); if (accumulatedAngle < 0) accumulatedAngle *= -1; return Gem.Math.Utility.NearlyEqual(accumulatedAngle, (face.edges.Count - 2) * Gem.Math.Angle.PI); }
private EMEdge FindNextEdgeInSequence(EMFace of, EMEdge after, short endpoint) { foreach (var e in of.edges) { if (Object.ReferenceEquals(e, after)) continue; if (e.Verticies.Contains(endpoint)) return e; } throw new InvalidOperationException("Malformed edge mesh"); }
internal void SetRecipricalNeighbor(EMEdge edge, EMFace neighbor) { foreach (var e in edges) if (Object.ReferenceEquals(e, edge)) e.Neighbors[1] = neighbor; //for (int i = 0; i < 3; ++i) // if (Object.ReferenceEquals(Edges[i],edge)) Neighbors[i] = neighbor; }
public bool FacesAreCoplanar(EMFace A, EMFace B) { return true; //In current test case, all faces that are connected are coplanar. }
private void CalculateCentroid(EMFace face) { var perimeterPoints = ExtractPerimeter(face); face.Centroid = Sum(perimeterPoints) / perimeterPoints.Count; }
public bool FacesAreCoplanar(EMFace A, EMFace B) { return(true); //In current test case, all faces that are connected are coplanar. }