public void FindCells() { // First we construct "wedges", which are pairs of sequential edges around each vtx. // we then put all in a hash set, we will iterate until we use up all the available wedges. // Edges are sorted by positive angle, so they are in clockwise order // Hence, going from edge n to n+1 is a left-turn, and so "inside" cells are oriented clockwise int NV = Graph.MaxVertexID; var wedges = new Index2i[NV][]; var remaining = new HashSet <Index2i>(); foreach (int vid in Graph.VertexIndices()) { int[] sorted = Graph.SortedVtxEdges(vid); wedges[vid] = new Index2i[sorted.Length]; for (int k = 0; k < sorted.Length; ++k) { wedges[vid][k] = new Index2i(sorted[k], sorted[(k + 1) % sorted.Length]); remaining.Add(new Index2i(vid, k)); } } CellLoops = new List <int[]>(); var loopv = new List <int>(); while (remaining.Count > 0) { Index2i idx = remaining.First(); remaining.Remove(idx); int start_vid = idx.a; int wid = idx.b; int e0 = wedges[start_vid][wid].a; e0 = e0 + 1 - 1; // get rid of unused variable warning, want to keep this for debugging int e1 = wedges[start_vid][wid].b; loopv.Clear(); loopv.Add(start_vid); int cur_v = start_vid; int outgoing_e = e1; // walk around loop taking immediate left-turns bool done = false; while (!done) { // find outgoing edge and vtx at far end Index2i ev = Graph.GetEdgeV(outgoing_e); int next_v = (ev.a == cur_v) ? ev.b : ev.a; if (next_v == start_vid) { done = true; continue; } // now find wedge at that vtx where this is incoming edge Index2i[] next_wedges = wedges[next_v]; int use_wedge_idx = -1; for (int k = 0; k < next_wedges.Length; ++k) { if (next_wedges[k].a == outgoing_e) { use_wedge_idx = k; break; } } if (use_wedge_idx == -1) { throw new Exception("could not find next wedge?"); } remaining.Remove(new Index2i(next_v, use_wedge_idx)); loopv.Add(next_v); cur_v = next_v; outgoing_e = next_wedges[use_wedge_idx].b; } CellLoops.Add(loopv.ToArray()); } }