private string DebugHalfedge(Halfedge he) { if (he == null) { return("null"); } else if (he.IsDestroyed()) { return("not null " + he.id + " (destroyed)"); } else { return(he.id.ToString()); } }
public List <Halfedge> Circulate() { Debug.Assert(!IsDestroyed()); List <Halfedge> res = new List <Halfedge>(); Halfedge iter = halfedge; Debug.Assert(iter != null); Debug.Assert(!iter.IsDestroyed()); bool first = true; while (iter != halfedge || first) { res.Add(iter); first = false; iter = iter.next; } return(res); }
public bool Destroy(Halfedge halfedge) { Debug.Assert(halfedge != null); Debug.Assert(halfedge.hmesh == this); Debug.Assert(!halfedge.IsDestroyed(), "Halfedge already destroyed"); bool res = halfedges.Remove(halfedge); if (res) { halfedge.face = null; halfedge.next = null; halfedge.opp = null; halfedge.prev = null; halfedge.vert = null; halfedge.SetDestroyed(); } else { Debug.Log("Already destroyed"); } return(res); }
private static bool PreconditionLegalCollapse(Halfedge he, Vector3D pos) { if (he.IsDestroyed()) { return(false); } if (he.CollapsePrecondition(pos, Halfedge.CollapsePreconditionReason.NormalFlipped) != Halfedge.CollapsePreconditionReason.Ok) { return(false); } HMesh hmesh = he.hmesh; HashSet <int> uniqueLabels = new HashSet <int>(); List <Vector3D> vertexPositions = new List <Vector3D>(); int index = 0; int indexOfHe = 0; var prevVertCirculated = he.prev.vert.Circulate(); // Check that all normals (of same label) are facing the same way var prev = he.prev; int thisLabel = he.face.label; Vector3D normal = he.face.GetNormal(); Vector3D otherNormal = Vector3D.zero; foreach (var vHe in prev.vert.Circulate()) { uniqueLabels.Add(vHe.face.label); if (vHe.face.label != thisLabel) { otherNormal = vHe.face.GetNormal(); } } if (uniqueLabels.Count > 2) { // currently not simplified return(false); } // 2. all face normals of the same label must be equal when having the same label foreach (var vHe in prev.vert.Circulate()) { var circulateFaceNormal = vHe.face.GetNormal(); if (vHe.face.label == thisLabel) { if (!hmesh.AreNormalsEqual(circulateFaceNormal, normal)) { return(false); } } else { if (!hmesh.AreNormalsEqual(circulateFaceNormal, otherNormal)) { return(false); } } } // if more labels, make sure that the collapse does not change any boundary between labels if (uniqueLabels.Count == 2) { if (he.opp != null && he.face.label == he.opp.face.label) { return(false); } foreach (var otherHe in prevVertCirculated) { bool compareToSelf = otherHe.id == he.id; if (compareToSelf) { continue; } bool isLabelBoundary = otherHe.opp != null && otherHe.opp.face.label != otherHe.face.label; if (isLabelBoundary) { var dir1 = he.GetDirection(); var dir2 = otherHe.GetDirection(); bool oppositeDir = Vector3D.Dot(dir1, dir2) > 0; // if boundary between labels then they must be parallel in same direction if (Vector3D.IsParallelDist(dir1, dir2, hmesh.zeroMagnitudeTresholdSqr) == false || oppositeDir) { return(false); } } } } return(true); }