Example #1
0
        void find_cut_paths(HashSet <int> CutEdges)
        {
            Spans = new List <EdgeSpan>();
            Loops = new List <EdgeLoop>();

            // [TODO] what about if vert appears more than twice in list? we should check for that!

            var Remaining = new HashSet <int>(CutEdges);

            while (Remaining.Count > 0)
            {
                int start_edge = Remaining.First();
                Remaining.Remove(start_edge);
                Index2i start_edge_v = Mesh.GetEdgeV(start_edge);

                bool       isLoop;
                List <int> forwardSpan = walk_edge_span_forward(Mesh, start_edge, start_edge_v.a, Remaining, out isLoop);
                if (isLoop == false)
                {
                    List <int> backwardSpan = walk_edge_span_forward(Mesh, start_edge, start_edge_v.b, Remaining, out isLoop);
                    if (isLoop)
                    {
                        throw new Exception("find_cut_paths: how did this possibly happen?!?");
                    }

                    if (backwardSpan.Count > 1)
                    {
                        backwardSpan.Reverse();
                        backwardSpan.RemoveAt(backwardSpan.Count - 1);
                        backwardSpan.AddRange(forwardSpan);
                        Index2i start_ev = Mesh.GetEdgeV(backwardSpan[0]);
                        Index2i end_ev   = Mesh.GetEdgeV(backwardSpan[backwardSpan.Count - 1]);
                        // [RMS] >2 check here catches two-edge span case, where we do have shared vert but
                        //   can never be loop unless we have duplicate edge (!)
                        isLoop      = backwardSpan.Count > 2 && IndexUtil.find_shared_edge_v(ref start_ev, ref end_ev) != DMesh3.InvalidID;
                        forwardSpan = backwardSpan;
                    }
                }

                if (isLoop)
                {
                    var loop = EdgeLoop.FromEdges(Mesh, forwardSpan);
                    Util.gDevAssert(loop.CheckValidity());
                    Loops.Add(loop);
                }
                else
                {
                    var span = EdgeSpan.FromEdges(Mesh, forwardSpan);
                    Util.gDevAssert(span.CheckValidity());
                    Spans.Add(span);
                }
            }
        }
        // Walk along edge loop and collapse to inserted curve vertices.
        EdgeLoop simplify(EdgeLoop loop)
        {
            HashSet <int> curve_verts = new HashSet <int>(CurveVertices);

            List <int> remaining_edges = new List <int>();

            for (int li = 0; li < loop.EdgeCount; ++li)
            {
                int     eid = loop.Edges[li];
                Index2i ev  = Mesh.GetEdgeV(eid);

                // cannot collapse edge between two "original" polygon verts (ie created by face pokes)
                if (curve_verts.Contains(ev.a) && curve_verts.Contains(ev.b))
                {
                    remaining_edges.Add(eid);
                    continue;
                }

                // if we have an original vert, we need to keep it (and its position!)
                int      keep = ev.a, discard = ev.b;
                Vector3d set_to = Vector3d.Zero;
                if (curve_verts.Contains(ev.b))
                {
                    keep    = ev.b;
                    discard = ev.a;
                    set_to  = Mesh.GetVertex(ev.b);
                }
                else if (curve_verts.Contains(ev.a))
                {
                    set_to = Mesh.GetVertex(ev.a);
                }
                else
                {
                    set_to = 0.5 * (Mesh.GetVertex(ev.a) + Mesh.GetVertex(ev.b));
                }

                // make sure we are not going to flip any normals
                // [OPTIMIZATION] May be possible to do this more efficiently because we know we are in
                //   2D and each tri should have same cw/ccw orientation. But we don't quite "know" we
                //   are in 2D here, as CollapseEdge function is operating on the mesh coordinates...
                if (MeshUtil.CheckIfCollapseCreatesFlip(Mesh, eid, set_to))
                {
                    remaining_edges.Add(eid);
                    continue;
                }

                // cannot collapse if the 'other' edges we would discard are OnCutEdges. This would
                // result in loop potentially being broken. bad!
                Index4i einfo = Mesh.GetEdge(eid);
                int     c     = IndexUtil.find_tri_other_vtx(keep, discard, Mesh.GetTriangle(einfo.c));
                int     d     = IndexUtil.find_tri_other_vtx(keep, discard, Mesh.GetTriangle(einfo.d));
                int     ec    = Mesh.FindEdge(discard, c);
                int     ed    = Mesh.FindEdge(discard, d);
                if (OnCutEdges.Contains(ec) || OnCutEdges.Contains(ed))
                {
                    remaining_edges.Add(eid);
                    continue;
                }

                // do collapse and update internal data structures
                DMesh3.EdgeCollapseInfo collapse;
                MeshResult result = Mesh.CollapseEdge(keep, discard, out collapse);
                if (result == MeshResult.Ok)
                {
                    Mesh.SetVertex(collapse.vKept, set_to);
                    OnCutEdges.Remove(collapse.eCollapsed);
                }
                else
                {
                    remaining_edges.Add(eid);
                }
            }

            return(EdgeLoop.FromEdges(Mesh, remaining_edges));
        }