/// <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); } }
/// <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); }
/// <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); } } }