// loop through submesh border edges on basemesh, map to submesh, and // pin those edges / vertices public static void FixSubmeshBoundaryEdges(MeshConstraints cons, DSubmesh3 sub) { Debug.Assert(sub.BaseBorderE != null); foreach (int base_eid in sub.BaseBorderE) { Index2i base_ev = sub.BaseMesh.GetEdgeV(base_eid); Index2i sub_ev = sub.MapVerticesToSubmesh(base_ev); int sub_eid = sub.SubMesh.FindEdge(sub_ev.a, sub_ev.b); Debug.Assert(sub_eid != NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID); Debug.Assert(sub.SubMesh.IsBoundaryEdge(sub_eid)); cons.SetOrUpdateEdgeConstraint(sub_eid, EdgeConstraint.FullyConstrained); cons.SetOrUpdateVertexConstraint(sub_ev.a, VertexConstraint.Pinned); cons.SetOrUpdateVertexConstraint(sub_ev.b, VertexConstraint.Pinned); } }
// for all mesh boundary edges, disable flip/split/collapse // for all mesh boundary vertices, pin in current position public static void FixAllBoundaryEdges(MeshConstraints cons, NGonsCore.geometry3Sharp.mesh.DMesh3 mesh) { int NE = mesh.MaxEdgeID; for (int ei = 0; ei < NE; ++ei) { if (mesh.IsEdge(ei) && mesh.IsBoundaryEdge(ei)) { cons.SetOrUpdateEdgeConstraint(ei, EdgeConstraint.FullyConstrained); Index2i ev = mesh.GetEdgeV(ei); cons.SetOrUpdateVertexConstraint(ev.a, VertexConstraint.Pinned); cons.SetOrUpdateVertexConstraint(ev.b, VertexConstraint.Pinned); } } }
// for all vertices in loopV, constrain to target // for all edges in loopV, disable flips and constrain to target public static void ConstrainVtxLoopTo(MeshConstraints cons, NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int[] loopV, IProjectionTarget target, int setID = -1) { VertexConstraint vc = new VertexConstraint(target); for (int i = 0; i < loopV.Length; ++i) { cons.SetOrUpdateVertexConstraint(loopV[i], vc); } EdgeConstraint ec = new EdgeConstraint(EdgeRefineFlags.NoFlip, target); ec.TrackingSetID = setID; for (int i = 0; i < loopV.Length; ++i) { int v0 = loopV[i]; int v1 = loopV[(i + 1) % loopV.Length]; int eid = mesh.FindEdge(v0, v1); Debug.Assert(eid != NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID); if (eid != NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID) { cons.SetOrUpdateEdgeConstraint(eid, ec); } } }
// After we split an edge, we have created a new edge and a new vertex. // The edge needs to inherit the constraint on the other pre-existing edge that we kept. // In addition, if the edge vertices were both constrained, then we /might/ // want to also constrain this new vertex, possibly project to constraint target. void update_after_split(int edgeID, int va, int vb, NGonsCore.geometry3Sharp.mesh.DMesh3.EdgeSplitInfo splitInfo) { bool bPositionFixed = false; if (constraints != null && constraints.HasEdgeConstraint(edgeID)) { // inherit edge constraint constraints.SetOrUpdateEdgeConstraint(splitInfo.eNewBN, constraints.GetEdgeConstraint(edgeID)); // [RMS] update vertex constraints. Note that there is some ambiguity here. // Both verts being constrained doesn't inherently mean that the edge is on // a constraint, that's why these checks are only applied if edge is constrained. // But constrained edge doesn't necessarily mean we want to inherit vert constraints!! // // although, pretty safe to assume that we would at least disable flips // if both vertices are constrained to same line/curve. So, maybe this makes sense... // // (perhaps edge constraint should be explicitly tagged to resolve this ambiguity??) // vert inherits Fixed if both orig edge verts Fixed, and both tagged with same SetID VertexConstraint ca = constraints.GetVertexConstraint(va); VertexConstraint cb = constraints.GetVertexConstraint(vb); if (ca.Fixed && cb.Fixed) { int nSetID = (ca.FixedSetID > 0 && ca.FixedSetID == cb.FixedSetID) ? ca.FixedSetID : VertexConstraint.InvalidSetID; constraints.SetOrUpdateVertexConstraint(splitInfo.vNew, new VertexConstraint(true, nSetID)); bPositionFixed = true; } // vert inherits Target if both source verts and edge have same Target if (ca.Target != null && ca.Target == cb.Target && constraints.GetEdgeConstraint(edgeID).Target == ca.Target) { constraints.SetOrUpdateVertexConstraint(splitInfo.vNew, new VertexConstraint(ca.Target)); project_vertex(splitInfo.vNew, ca.Target); bPositionFixed = true; } } if (EnableInlineProjection && bPositionFixed == false && target != null) { project_vertex(splitInfo.vNew, target); } }
// for all mesh boundary vertices, pin in current position, but allow collapses public static void FixAllBoundaryEdges_AllowCollapse(MeshConstraints cons, NGonsCore.geometry3Sharp.mesh.DMesh3 mesh, int setID) { EdgeConstraint edgeCons = new EdgeConstraint(EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoSplit); VertexConstraint vertCons = new VertexConstraint(true, setID); int NE = mesh.MaxEdgeID; for (int ei = 0; ei < NE; ++ei) { if (mesh.IsEdge(ei) && mesh.IsBoundaryEdge(ei)) { cons.SetOrUpdateEdgeConstraint(ei, edgeCons); Index2i ev = mesh.GetEdgeV(ei); cons.SetOrUpdateVertexConstraint(ev.a, vertCons); cons.SetOrUpdateVertexConstraint(ev.b, vertCons); } } }