// for all vertices in loopV, constrain to target // for all edges in loopV, disable flips and constrain to target public static void ConstrainVtxSpanTo(MeshConstraints cons, DMesh3 mesh, IList <int> spanV, IProjectionTarget target, int setID = -1) { VertexConstraint vc = new VertexConstraint(target); int N = spanV.Count; for (int i = 0; i < N; ++i) { cons.SetOrUpdateVertexConstraint(spanV[i], vc); } EdgeConstraint ec = new EdgeConstraint(EdgeRefineFlags.NoFlip, target); ec.TrackingSetID = setID; for (int i = 0; i < N - 1; ++i) { int v0 = spanV[i]; int v1 = spanV[i + 1]; int eid = mesh.FindEdge(v0, v1); Debug.Assert(eid != DMesh3.InvalidID); if (eid != DMesh3.InvalidID) { cons.SetOrUpdateEdgeConstraint(eid, ec); } } }
// 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, 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 != DMesh3.InvalidID); if (eid != DMesh3.InvalidID) { cons.SetOrUpdateEdgeConstraint(eid, ec); } } }
// used by collapse-edge to get projected position for new vertex protected virtual Vector3d get_projected_collapse_position(int vid, Vector3d vNewPos) { if (constraints != null) { VertexConstraint vc = constraints.GetVertexConstraint(vid); if (vc.Target != null) { return(vc.Target.Project(vNewPos, vid)); } if (vc.Fixed) { return(vNewPos); } } // no constraint applied, so if we have a target surface, project to that if (EnableInlineProjection && target != null) { if (VertexControlF == null || (VertexControlF(vid) & VertexControl.NoProject) == 0) { return(target.Project(vNewPos, vid)); } } return(vNewPos); }
protected bool vertex_is_constrained(int vid) { if (constraints != null) { VertexConstraint vc = constraints.GetVertexConstraint(vid); if (vc.Fixed || vc.Target != null) { return(true); } } return(false); }
void FullSmoothPass_InPlace(bool bParallel) { Func <DMesh3, int, double, Vector3d> smoothFunc = MeshUtil.UniformSmooth; if (SmoothType == SmoothTypes.MeanValue) { smoothFunc = MeshUtil.MeanValueSmooth; } else if (SmoothType == SmoothTypes.Cotan) { smoothFunc = MeshUtil.CotanSmooth; } Action <int> smooth = (vID) => { VertexConstraint vc = get_vertex_constraint(vID); if (vc.Fixed) { return; } Vector3d vSmoothed = smoothFunc(mesh, vID, SmoothSpeedT); Debug.Assert(vSmoothed.IsFinite); // this will really catch a lot of bugs... // project onto either vtx constraint target, or surface target if (vc.Target != null) { vSmoothed = vc.Target.Project(vSmoothed, vID); } else if (EnableInlineProjection && target != null) { vSmoothed = target.Project(vSmoothed, vID); } mesh.SetVertex(vID, vSmoothed); }; if (bParallel) { gParallel.ForEach <int>(mesh.VertexIndices(), smooth); } else { foreach (int vID in mesh.VertexIndices()) { smooth(vID); } } }
// 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, 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 splits public static void FixAllBoundaryEdges_AllowSplit(MeshConstraints cons, DMesh3 mesh, int setID) { EdgeConstraint edgeCons = new EdgeConstraint(EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse); 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); } } }
// used by collapse-edge to get projected position for new vertex protected Vector3d get_projected_collapse_position(int vid, Vector3d vNewPos) { if (constraints != null) { VertexConstraint vc = constraints.GetVertexConstraint(vid); if (vc.Target != null) { return(vc.Target.Project(vNewPos, vid)); } if (vc.Fixed) { return(vNewPos); } } // we don't need to do inline projection to target surface here because we // already did it in OptimalPoint() return(vNewPos); }
/// <summary> /// This computes smoothed positions w/ proper constraints/etc. /// Does not modify mesh. /// </summary> protected virtual Vector3d ComputeSmoothedVertexPos(int vID, Func <DMesh3, int, double, Vector3d> smoothFunc, out bool bModified) { bModified = false; VertexConstraint vConstraint = VertexConstraint.Unconstrained; get_vertex_constraint(vID, ref vConstraint); if (vConstraint.Fixed) { return(Mesh.GetVertex(vID)); } VertexControl vControl = (VertexControlF == null) ? VertexControl.AllowAll : VertexControlF(vID); if ((vControl & VertexControl.NoSmooth) != 0) { return(Mesh.GetVertex(vID)); } Vector3d vSmoothed = smoothFunc(mesh, vID, SmoothSpeedT); Debug.Assert(vSmoothed.IsFinite); // this will really catch a lot of bugs... // project onto either vtx constraint target, or surface target if (vConstraint.Target != null) { vSmoothed = vConstraint.Target.Project(vSmoothed, vID); } else if (EnableInlineProjection && target != null) { if ((vControl & VertexControl.NoProject) == 0) { vSmoothed = target.Project(vSmoothed, vID); } } bModified = true; return(vSmoothed); }
protected bool get_vertex_constraint(int vid, ref VertexConstraint vc) { return((constraints == null) ? false : constraints.GetVertexConstraint(vid, ref vc)); }
// resolve vertex constraints for collapsing edge eid=[a,b]. Generally we would // collapse a to b, and set the new position as 0.5*(v_a+v_b). However if a *or* b // are constrained, then we want to keep that vertex and collapse to its position. // This vertex (a or b) will be returned in collapse_to, which is -1 otherwise. // If a *and* b are constrained, then things are complicated (and documented below). protected bool can_collapse_vtx(int eid, int a, int b, out int collapse_to) { collapse_to = -1; if (constraints == null) { return(true); } VertexConstraint ca = constraints.GetVertexConstraint(a); VertexConstraint cb = constraints.GetVertexConstraint(b); // no constraint at all if (ca.Fixed == false && cb.Fixed == false && ca.Target == null && cb.Target == null) { return(true); } // handle a or b fixed if (ca.Fixed == true && cb.Fixed == false) { collapse_to = a; return(true); } if (cb.Fixed == true && ca.Fixed == false) { collapse_to = b; return(true); } // if both fixed, and options allow, treat this edge as unconstrained (eg collapse to midpoint) // [RMS] tried picking a or b here, but something weird happens, where // eg cylinder cap will entirely erode away. Somehow edge lengths stay below threshold?? if (AllowCollapseFixedVertsWithSameSetID && ca.FixedSetID >= 0 && ca.FixedSetID == cb.FixedSetID) { return(true); } // handle a or b w/ target if (ca.Target != null && cb.Target == null) { collapse_to = a; return(true); } if (cb.Target != null && ca.Target == null) { collapse_to = b; return(true); } // if both vertices are on the same target, and the edge is on that target, // then we can collapse to either and use the midpoint (which will be projected // to the target). *However*, if the edge is not on the same target, then we // cannot collapse because we would be changing the constraint topology! if (cb.Target != null && ca.Target != null && ca.Target == cb.Target) { if (constraints.GetEdgeConstraint(eid).Target == ca.Target) { return(true); } } return(false); }
public void SetOrUpdateVertexConstraint(int vid, VertexConstraint vc) { Vertices[vid] = vc; }
public bool GetVertexConstraint(int vid, ref VertexConstraint vc) { return(Vertices.TryGetValue(vid, out vc)); }