private void CGI_Cut() { // -- mark verteices on strokes -- int n = mesh.VertexCount, label = 0; bool[] labeled = new bool[n]; bool[] tag = new bool[n]; foreach (int v in this.sourceVertices) { vnode[v].label = label; labeled[v] = true; tag[v] = true; } label = 1; foreach (int v in this.sinkVertices) { vnode[v].label = label; labeled[v] = true; tag[v] = true; } // -- push to priority queue -- PriorityQueue iQue = new PriorityQueue(); foreach (int v in this.sourceVertices) { foreach (int adj in mesh.AdjVV[v]) { GraphNode node = vnode[adj]; node.label = vnode[v].label; node.dis = Vrt_wij(v, adj); tag[adj] = true; iQue.Insert(node); } } foreach (int v in this.sinkVertices) { foreach (int adj in mesh.AdjVV[v]) { GraphNode node = vnode[adj]; node.label = vnode[v].label; node.dis = Vrt_wij(v, adj); tag[adj] = true; iQue.Insert(node); } } // -- region growing -- while (!iQue.IsEmpty()) { GraphNode node = iQue.DeleteMin() as GraphNode; int v = node.index; labeled[v] = true; foreach (int adj in mesh.AdjVV[v]) { if (labeled[adj]) // -- already labeled -- { continue; } else { double cost = Vrt_wij(v, adj); GraphNode adjNode = vnode[adj]; adjNode.label = node.label; if (tag[adj]) // -- already in the queue -- { if (adjNode.dis > cost) { adjNode.dis = cost; iQue.Update(adjNode); } } else // -- a fresh vertex -- { adjNode.dis = cost; tag[adj] = true; iQue.Insert(adjNode); } } } } // -- convert to facets -- List<int> risidual = new List<int>(); for (int i = 0, j = 0; i < mesh.FaceCount; ++i, j+=3) { int c0 = mesh.FaceIndex[j]; int c1 = mesh.FaceIndex[j+1]; int c2 = mesh.FaceIndex[j+2]; if (vnode[c0].label == vnode[c1].label && vnode[c0].label == vnode[c2].label) { fnode[i].label = vnode[c0].label; } else { fnode[i].label = -1; risidual.Add(i); } } // -- deal with boundary faces -- while (risidual.Count > 0) { List<int> vlist = new List<int>(); vlist.AddRange(risidual); risidual.Clear(); foreach (int f in vlist) { double min = double.MaxValue; int minid = -1; foreach (int adj in mesh.AdjFF[f]) { if (fnode[adj].label < 0) continue; double c = Face_wij1(f, adj); if (c < min) { min = c; minid = adj; } } if (minid != -1) fnode[f].label = fnode[minid].label; else risidual.Add(f); } } // -- patch the results -- int index = this.patches.Count + 1; Patch p = new Patch(index); if (patchid == null) patchid = new byte[mesh.FaceCount]; for (int i = 0; i < mesh.FaceCount; ++i) { if (fnode[i].label == 0) { patchid[i] = (byte)index; p.faces.Add(i); } } this.all_patches.Add(p); }
private void patch_type_decompose() { int n = mesh.FaceCount; for (int i = 0; i < n; ++i) // -- reset the labels -- fnode[i].label = -1; // -- label seed faces -- bool[] visited = new bool[n]; bool[] labeled = new bool[n]; if (patchid == null) patchid = new byte[n]; List<int> sources = new List<int>(); List<int> targets = new List<int>(); foreach (List<int> flist in this.facesOnStrokes) { if (flist.Count < 1) continue; sources.Add(flist[0]); targets.Add(flist[flist.Count - 1]); } byte pid = patchid[sources[0]]; // -- the patch strokes lies on -- foreach (int f in sources) { fnode[f].label = 0; visited[f] = true; labeled[f] = true; } int label = 1; foreach (int f in targets) { fnode[f].label = label; visited[f] = true; labeled[f] = true; } // -- region growing -- PriorityQueue iQue = new PriorityQueue(); foreach (int f in sources) { foreach (int adj in mesh.AdjFF[f]) { if (patchid[adj] != pid) continue; fnode[adj].label = fnode[f].label; fnode[adj].dis = Face_wij(f, adj); iQue.Insert(fnode[adj]); visited[adj] = true; } } foreach (int f in targets) { foreach (int adj in mesh.AdjFF[f]) { if (patchid[adj] != pid) continue; fnode[adj].label = fnode[f].label; fnode[adj].dis = Face_wij(f, adj); iQue.Insert(fnode[adj]); visited[adj] = true; } } while (!iQue.IsEmpty()) { GraphNode node = iQue.DeleteMin() as GraphNode; int f = node.index; labeled[f] = true; foreach (int adj in mesh.AdjFF[f]) { if (patchid[adj] != pid) continue; if (labeled[adj]) { continue; } else if (visited[adj]) { double wij = Face_wij(f, adj); if (fnode[adj].dis > wij) { fnode[adj].label = fnode[f].label; fnode[adj].dis = wij; iQue.Update(fnode[adj]); } } else { fnode[adj].label = fnode[f].label; fnode[adj].dis = Face_wij(f, adj); iQue.Insert(fnode[adj]); visited[adj] = true; } } } // -- patch the results -- int index = this.all_patches.Count+1; Patch p = new Patch(index); p.prev_label = (int)pid; for (int i = 0; i < n; ++i) { if (fnode[i].label == 0) { patchid[i] = (byte)index; p.faces.Add(i); } } this.patches.Add(p); this.all_patches.Add(p); // -- global patches -- }