/// <summary>
        /// Remove vertices that are colinear w/ their two neighbours, within angle tolerance
        /// </summary>
        public void CollapseFlatVertices(double fMaxDeviationDeg = 5)
        {
            bool done       = false;
            int  max_passes = 200;
            int  pass_count = 0;

            while (done == false && pass_count++ < max_passes)
            {
                done = true;

                // [RMS] do modulo-indexing here to avoid pathological cases where we do things like
                // continually collapse a short edge adjacent to a long edge (which will result in crazy over-collapse)
                int       N       = Graph.MaxVertexID;
                const int nPrime  = 31337;                    // any prime will do...
                int       cur_vid = 0;
                do
                {
                    int vid = cur_vid;
                    cur_vid = (cur_vid + nPrime) % N;

                    if (!Graph.IsVertex(vid))
                    {
                        continue;
                    }

                    if (Graph.GetVtxEdgeCount(vid) != 2)
                    {
                        continue;
                    }

                    double open = Math.Abs(Graph.OpeningAngle(vid));
                    if (open < 180 - fMaxDeviationDeg)
                    {
                        continue;
                    }

                    var edges = Graph.GetVtxEdges(vid);
                    int eid   = edges.First();
                    int eid2  = edges.Last();
                    if (FixedEdgeFilterF(eid) || FixedEdgeFilterF(eid2))
                    {
                        continue;
                    }

                    Index2i ev      = Graph.GetEdgeV(eid);
                    int     other_v = (ev.a == vid) ? ev.b : ev.a;

                    DGraph2.EdgeCollapseInfo collapseInfo;
                    MeshResult result = Graph.CollapseEdge(other_v, vid, out collapseInfo);
                    if (result == MeshResult.Ok)
                    {
                        done = false;
                    }
                    else
                    {
                        throw new Exception("DGraph2Resampler.CollapseFlatVertices: failed!");
                    }
                } while (cur_vid != 0);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Find and remove any junction (ie valence>2) vertices of the graph.
        /// At a junction, the pair of best-aligned (ie straightest) edges are left
        /// connected, and all the other edges are disconnected
        ///
        /// [TODO] currently there is no DGraph2.SetEdge(), so the 'other' edges
        /// are deleted and new edges inserted. Hence, edge IDs are not preserved.
        /// </summary>
        public static int DisconnectJunctions(DGraph2 graph)
        {
            var junctions = new List <int>();

            // find all junctions
            foreach (int vid in graph.VertexIndices())
            {
                if (graph.IsJunctionVertex(vid))
                {
                    junctions.Add(vid);
                }
            }


            foreach (int vid in junctions)
            {
                Vector2d v         = graph.GetVertex(vid);
                int[]    nbr_verts = graph.VtxVerticesItr(vid).ToArray();

                // find best-aligned pair of edges connected to vid
                Index2i best_aligned = Index2i.Max; double max_angle = 0;
                for (int i = 0; i < nbr_verts.Length; ++i)
                {
                    for (int j = i + 1; j < nbr_verts.Length; ++j)
                    {
                        double angle = Vector2d.AngleD(
                            (graph.GetVertex(nbr_verts[i]) - v).Normalized,
                            (graph.GetVertex(nbr_verts[j]) - v).Normalized);
                        angle = Math.Abs(angle);
                        if (angle > max_angle)
                        {
                            max_angle    = angle;
                            best_aligned = new Index2i(nbr_verts[i], nbr_verts[j]);
                        }
                    }
                }

                // for nbr verts that are not part of the best_aligned edges,
                // we remove those edges and add a new one connected to a new vertex
                for (int k = 0; k < nbr_verts.Length; ++k)
                {
                    if (nbr_verts[k] == best_aligned.a || nbr_verts[k] == best_aligned.b)
                    {
                        continue;
                    }

                    int eid = graph.FindEdge(vid, nbr_verts[k]);
                    graph.RemoveEdge(eid, true);
                    if (graph.IsVertex(nbr_verts[k]))
                    {
                        var newpos = Vector2d.Lerp(graph.GetVertex(nbr_verts[k]), v, 0.99);
                        int newv   = graph.AppendVertex(newpos);
                        graph.AppendEdge(nbr_verts[k], newv);
                    }
                }
            }

            return(junctions.Count);
        }
Beispiel #3
0
        /// <summary>
        /// foreach edge [vid,b] connected to junction vertex vid, remove, add new vertex c,
        /// and then add new edge [b,c]. Optionally move c a bit back along edge from vid.
        /// </summary>
        public static void DisconnectJunction(DGraph2 graph, int vid, double shrinkFactor = 1.0)
        {
            Vector2d v = graph.GetVertex(vid);

            int[] nbr_verts = graph.VtxVerticesItr(vid).ToArray();
            for (int k = 0; k < nbr_verts.Length; ++k)
            {
                int eid = graph.FindEdge(vid, nbr_verts[k]);
                graph.RemoveEdge(eid, true);
                if (graph.IsVertex(nbr_verts[k]))
                {
                    Vector2d newpos = Vector2d.Lerp(graph.GetVertex(nbr_verts[k]), v, shrinkFactor);
                    int      newv   = graph.AppendVertex(newpos);
                    graph.AppendEdge(nbr_verts[k], newv);
                }
            }
        }