void Graph::DeleteNode(pNode p) { while(!p->m_in_edges_list.empty()) { DeleteEdge(p->m_in_edges_list.front()->m_from,p); } while(!p->m_out_edges_list.empty()) { DeleteEdge(p,p->m_out_edges_list.front()->m_to); } m_nodes_list.remove(p); m_total_nodes_num--; FreeNode(p); }
void pvdb::ConceptMap::DeleteNode(const boost::shared_ptr<pvdb::Node> node) { #ifndef NDEBUG assert(node); assert(std::count(m_nodes.begin(),m_nodes.end(),node) == 1 && "Every node is unique"); const std::size_t n_nodes_before = m_nodes.size(); #endif //Delete all edges going to this node std::vector<boost::shared_ptr<pvdb::Edge> > to_be_deleted; std::copy_if(m_edges.begin(),m_edges.end(),std::back_inserter(to_be_deleted), [node](boost::shared_ptr<pvdb::Edge> edge) { return edge->GetFrom() == node || edge->GetTo() == node; } ); for (boost::shared_ptr<pvdb::Edge> edge: to_be_deleted) { DeleteEdge(edge); } //Delete the node itself //Copied from http://www.richelbilderbeek.nl/CppVector.htm m_nodes.erase(std::remove(m_nodes.begin(),m_nodes.end(),node),m_nodes.end()); #ifndef NDEBUG const std::size_t n_nodes_after = m_nodes.size(); assert(n_nodes_before - 1 == n_nodes_after); #endif }
void ribi::cmap::QtConceptMap::DeleteNode(QtNode * const qtnode) { #ifndef NDEBUG const int n_items_before = this->scene()->items().count(); #endif //Delete the edges connected to this node { const std::vector<QtEdge *> qtedges = GetQtEdges(); const std::size_t sz = qtedges.size(); for (std::size_t i=0; i!=sz; ++i) { QtEdge * const qtedge = qtedges[i]; assert(qtedge); if (qtedge->GetFrom() == qtnode || qtedge->GetTo() == qtnode) { DeleteEdge(qtedge); } } } //Remove from non-GUI, which removes the left-overs GetConceptMap()->DeleteNode(qtnode->GetNode()); //Remove node from GUI this->scene()->removeItem(qtnode); #ifndef NDEBUG const int n_items_after = this->scene()->items().count(); assert(n_items_before - n_items_after >= 1 && "At least one item is deleted: one node and x edges"); assert(Collect<QtNode>(this->scene()).size() == this->GetConceptMap()->GetNodes().size() && "GUI and non-GUI concept map must match"); #endif }
bool Graph::EdgeCollapse(long v1, long v2) { long edgeToDelete = GetEdgeID(v1, v2); if (edgeToDelete >= 0) { // delete the edge (v1, v2) DeleteEdge(edgeToDelete); // add v2 to v1 ancestors m_vertices[v1].m_ancestors.push_back(v2); // add v2's ancestors to v1's ancestors m_vertices[v1].m_ancestors.insert(m_vertices[v1].m_ancestors.begin(), m_vertices[v2].m_ancestors.begin(), m_vertices[v2].m_ancestors.end()); // update adjacency information SArray<long, SARRAY_DEFAULT_MIN_SIZE> & v1Edges = m_vertices[v1].m_edges; long b = -1; long idEdge; for(size_t ed = 0; ed < m_vertices[v2].m_edges.Size(); ++ed) { idEdge = m_vertices[v2].m_edges[ed]; if (m_edges[idEdge].m_v1 == v2) { b = m_edges[idEdge].m_v2; } else { b = m_edges[idEdge].m_v1; } if (GetEdgeID(v1, b) >= 0) { m_edges[idEdge].m_deleted = true; m_vertices[b].DeleteEdge(idEdge); m_nE--; } else { m_edges[idEdge].m_v1 = v1; m_edges[idEdge].m_v2 = b; v1Edges.Insert(idEdge); } } // delete the vertex v2 DeleteVertex(v2); return true; } return false; }
bool Graph::EdgeCollapse(long v1, long v2) { long edgeToDelete = GetEdgeID(v1, v2); if (edgeToDelete >= 0) { // delete the edge (v1, v2) DeleteEdge(edgeToDelete); // add v2 to v1 ancestors m_vertices[v1].m_ancestors.push_back(v2); // add v2's ancestors to v1's ancestors m_vertices[v1].m_ancestors.insert(m_vertices[v1].m_ancestors.begin(), m_vertices[v2].m_ancestors.begin(), m_vertices[v2].m_ancestors.end()); // update adjacency information std::set<long> & v1Edges = m_vertices[v1].m_edges; std::set<long>::const_iterator ed(m_vertices[v2].m_edges.begin()); std::set<long>::const_iterator itEnd(m_vertices[v2].m_edges.end()); long b = -1; for(; ed != itEnd; ++ed) { if (m_edges[*ed].m_v1 == v2) { b = m_edges[*ed].m_v2; } else { b = m_edges[*ed].m_v1; } if (GetEdgeID(v1, b) >= 0) { m_edges[*ed].m_deleted = true; m_vertices[b].DeleteEdge(*ed); m_nE--; } else { m_edges[*ed].m_v1 = v1; m_edges[*ed].m_v2 = b; v1Edges.insert(*ed); } } // delete the vertex v2 DeleteVertex(v2); return true; } return false; }
void Subdivision::InsertSite(const Point2d& x) // Inserts a new point into a subdivision representing a Delaunay // triangulation, and fixes the affected edges so that the result // is still a Delaunay triangulation. This is based on the // pseudocode from Guibas and Stolfi (1985) p.120, with slight // modifications and a bug fix. { Edge* e = Locate(x); if ((x == e->Org2d()) || (x == e->Dest2d())) // point is already in return; else if (OnEdge(x, e)) { e = e->Oprev(); DeleteEdge(e->Onext()); } // Connect the new point to the vertices of the containing // triangle (or quadrilateral, if the new point fell on an // existing edge.) Edge* base = MakeEdge(); base->EndPoints(e->Org(), new Point2d(x)); Splice(base, e); startingEdge = base; do { base = Connect(e, base->Sym()); e = base->Oprev(); } while (e->Lnext() != startingEdge); // Examine suspect edges to ensure that the Delaunay condition // is satisfied. do { Edge* t = e->Oprev(); if (RightOf(t->Dest2d(), e) && InCircle(e->Org2d(), t->Dest2d(), e->Dest2d(), x)) { Swap(e); e = e->Oprev(); } else if (e->Onext() == startingEdge) // no more suspect edges return; else // pop a suspect edge e = e->Onext()->Lprev(); } while (TRUE); }
int TopologicalGraph::Simplify() // returns the # o multiple edges + # loops {if(Set().exist(PROP_SIMPLE))return 0; if(debug())DebugPrintf(" Executing Simplify"); // Remove Loops int n = RemoveLoops(); if(!ne()){Prop1<int> simple(Set(),PROP_SIMPLE);return n;} svector<tedge>link(0,ne()); link.clear(); link.SetName("TG:Simplify:link"); svector<tedge>top1(1,nv()); top1.clear(); top1.SetName("TG:Simplify:top1"); svector<tedge>top2(1,nv()); top2.clear(); top2.SetName("TG:Simplify:top2"); tvertex u,v,w; tedge e,e0,next; //First sort with respect to biggest label for(e = ne();e >= 1;e--) {v = (vin[e] < vin[-e]) ? vin[-e] : vin[e]; link[e] = top1[v];top1[v] = e; } // Then sort with respect to smallest label for(u = nv();u > 1;u--) {e = top1[u]; while(e!=0) {next = link[e]; //as link is modified v = (vin[e] < vin[-e]) ? vin[e] : vin[-e]; link[e] = top2[v]; top2[v] = e; e = next; } } // Erase Multiple edges, but backup multiplicity Prop<int> multiplicity(Set(tedge()),PROP_MULTIPLICITY); for (e=1; e<=ne(); ++e) multiplicity[e]=1; for(v = nv()-1;v >= 1;v--) {e0 = top2[v]; u = vin[e0];if(u == v)u = vin[-e0]; e=link[e0]; link[e0]=0; while(e!=0) {next=link[e]; w = vin[e];if(w == v)w = vin[-e]; if(u == w) {++n; ++multiplicity[e0]; link[e] = 1; } else {u=w; link[e0=e] = 0; } e=next; } } bool erased = false; for(e = ne();e >= 1;e--) if(link[e]!=0){DeleteEdge(e);erased = true;} if(!erased)Set(tedge()).erase(PROP_MULTIPLICITY); Prop1<int> simple(Set(),PROP_SIMPLE); return n; }
SSHANDLE * CSSolid::MergeSameVertices(int& nDeleted) { int nMerged = 0; nDeleted = 0; static SSHANDLE hDeletedList[128]; DoVertices: for(int v1 = 0; v1 < m_nVertices; v1++) { for(int v2 = 0; v2 < m_nVertices; v2++) { if(v1 == v2) continue; // no! if(!VectorCompare(m_Vertices[v1].pos, m_Vertices[v2].pos)) { // no match continue; } ++nMerged; // same vertices - kill v1, set edge refs to use v2. SSHANDLE hV1 = m_Vertices[v1].id; SSHANDLE hV2 = m_Vertices[v2].id; hDeletedList[nDeleted++] = hV1; DeleteVertex(v1); int nAffected; CSSEdge **ppEdges = FindAffectedEdges(&hV1, 1, nAffected); // run through edges and change references for(int e = 0; e < nAffected; e++) { if(ppEdges[e]->hvStart == hV1) ppEdges[e]->hvStart = hV2; if(ppEdges[e]->hvEnd == hV1) ppEdges[e]->hvEnd = hV2; CalcEdgeCenter(ppEdges[e]); } goto DoVertices; } } if(!nMerged) return NULL; int e; // kill edges that have same vertices for(e = 0; e < m_nEdges; e++) { CSSEdge &edge = m_Edges[e]; if(edge.hvStart != edge.hvEnd) continue; // edge is OK hDeletedList[nDeleted++] = edge.id; DeleteEdge(e); --e; } // kill similar edges (replace in faces too) DoEdges: for(e = 0; e < m_nEdges; e++) { CSSEdge &edge = m_Edges[e]; for(int e2 = 0; e2 < m_nEdges; e2++) { if(e == e2) continue; CSSEdge &edge2 = m_Edges[e2]; if(!((edge2.hvStart == edge.hvStart && edge2.hvEnd == edge.hvEnd) || (edge2.hvEnd == edge.hvStart && edge2.hvStart == edge.hvEnd))) continue; // we're going to delete edge2. SSHANDLE id2 = edge2.id; SSHANDLE id1 = edge.id; for(int f = 0; f < m_nFaces; f++) { CSSFace& face = m_Faces[f]; for(int ef = 0; ef < face.nEdges; ef++) { if(face.Edges[ef] == id2) { face.Edges[ef] = id1; break; } } } hDeletedList[nDeleted++] = id2; DeleteEdge(e2); goto DoEdges; } } // delete concurrent edge references in face for(int f = 0; f < m_nFaces; f++) { CSSFace& face = m_Faces[f]; DoConcurrentEdges: for(int ef1 = 0; ef1 < face.nEdges; ef1++) { for(int ef2 = 0; ef2 < face.nEdges; ef2++) { if(ef2 == ef1) continue; if(face.Edges[ef1] != face.Edges[ef2]) continue; // delete this ref memcpy(&face.Edges[ef2], &face.Edges[ef2+1], (face.nEdges-ef2) * sizeof(face.Edges[0])); --face.nEdges; goto DoConcurrentEdges; } } if(face.nEdges < 3) { // kill this face hDeletedList[nDeleted++] = face.id; DeleteFace(f); --f; } } return hDeletedList; }
BOOL CSSolid::SplitFaceByEdges(CSSEdge *pEdge1, CSSEdge *pEdge2) { SSHANDLE hFace; // find the handle of the face if(pEdge1->Faces[0] == pEdge2->Faces[0] || pEdge1->Faces[0] == pEdge2->Faces[1]) { hFace = pEdge1->Faces[0]; } else if(pEdge1->Faces[1] == pEdge2->Faces[0] || pEdge1->Faces[1] == pEdge2->Faces[1]) { hFace = pEdge1->Faces[1]; } else return FALSE; // not the same face // get pointer to face CSSFace *pFace = (CSSFace*) GetHandleData(hFace); // create new objects CSSFace *pNewFace = AddFace(); CSSEdge *pNewEdgeMid = AddEdge(); int iNewVertex1, iNewVertex2; CSSVertex *pNewVertex1 = AddVertex(&iNewVertex1); CSSVertex *pNewVertex2 = AddVertex(&iNewVertex2); // assign faces to new edge AssignFace(pNewEdgeMid, pFace->id); AssignFace(pNewEdgeMid, pNewFace->id); // copy texture info from one face to the other memcpy(&pNewFace->texture, &pFace->texture, sizeof(TEXTURE)); // set vertex positions m_Vertices[iNewVertex1].pos = pEdge1->ptCenter; m_Vertices[iNewVertex2].pos = pEdge2->ptCenter; // set up middle edge pNewEdgeMid->hvStart = pNewVertex1->id; pNewEdgeMid->hvEnd = pNewVertex2->id; CalcEdgeCenter(pNewEdgeMid); // set up new side edges CSSEdge *pEdgeTmp = AddEdge(); pEdgeTmp->hvStart = pEdge1->hvStart; pEdgeTmp->hvEnd = pNewVertex1->id; CalcEdgeCenter(pEdgeTmp); pEdgeTmp = AddEdge(); pEdgeTmp->hvStart = pEdge1->hvEnd; pEdgeTmp->hvEnd = pNewVertex1->id; CalcEdgeCenter(pEdgeTmp); pEdgeTmp = AddEdge(); pEdgeTmp->hvStart = pEdge2->hvStart; pEdgeTmp->hvEnd = pNewVertex2->id; CalcEdgeCenter(pEdgeTmp); pEdgeTmp = AddEdge(); pEdgeTmp->hvStart = pEdge2->hvEnd; pEdgeTmp->hvEnd = pNewVertex2->id; CalcEdgeCenter(pEdgeTmp); /* FILE *fp = fopen("split", "w"); for(i = 0; i < nVertices; i++) { fprintf(fp, "%lu\n", phVertexList[i]); } fclose(fp); */ // set up edges - start with newvertex1 SSHANDLE hNewEdges[64]; int nNewEdges; BOOL bFirst = TRUE; CSSFace *pStoreFace = pFace; // ** do two new faces first ** int nv1index, nv2index; SSHANDLE *phVertexList = CreateNewVertexList(pFace, pEdge1, pEdge2, nv1index, nv2index, pNewVertex1, pNewVertex2); int nVertices = pFace->nEdges; if(nv1index != -1) ++nVertices; if(nv2index != -1) ++nVertices; // kill face references in edges first for(int i = 0; i < nVertices; i++) { int iNextVertex = GetNext(i, 1, nVertices); int iEdgeIndex = GetEdgeIndex(phVertexList[i], phVertexList[iNextVertex]); CSSEdge *pEdge = &m_Edges[iEdgeIndex]; ASSERT(pEdge->id != pEdge1->id); ASSERT(pEdge->id != pEdge2->id); AssignFace(pEdge, pFace->id, TRUE); } DoNextFace: nNewEdges = 0; for(i = nv1index; ; i++) { if(i == nVertices) i = 0; if(i == nv2index) break; int iNextVertex = GetNext(i, 1, nVertices); int iEdgeIndex = GetEdgeIndex(phVertexList[i], phVertexList[iNextVertex]); ASSERT(iEdgeIndex != -1); hNewEdges[nNewEdges++] = m_Edges[iEdgeIndex].id; AssignFace(&m_Edges[iEdgeIndex], pStoreFace->id); } // now add the middle edge hNewEdges[nNewEdges++] = pNewEdgeMid->id; // now set up in face pStoreFace->nEdges = nNewEdges; memcpy(pStoreFace->Edges, hNewEdges, sizeof(SSHANDLE) * nNewEdges); if(bFirst) { int tmp = nv1index; nv1index = nv2index; nv2index = tmp; pStoreFace = pNewFace; bFirst = FALSE; goto DoNextFace; } delete phVertexList; // ** now regular faces ** for(int iFace = 0; iFace < m_nFaces; iFace++) { CSSFace *pUpdFace = &m_Faces[iFace]; if(pUpdFace == pNewFace || pUpdFace == pFace) continue; SSHANDLE *phVertexList = CreateNewVertexList(pUpdFace, pEdge1, pEdge2, nv1index, nv2index, pNewVertex1, pNewVertex2); if(phVertexList == NULL) // don't need to update this face continue; nNewEdges = 0; nVertices = pUpdFace->nEdges; if(nv1index != -1) ++nVertices; if(nv2index != -1) ++nVertices; for(i = 0; i < nVertices; i++) { int iNextVertex = GetNext(i, 1, nVertices); int iEdgeIndex = GetEdgeIndex(phVertexList[i], phVertexList[iNextVertex]); ASSERT(iEdgeIndex != -1); AssignFace(&m_Edges[iEdgeIndex], pUpdFace->id); hNewEdges[nNewEdges++] = m_Edges[iEdgeIndex].id; } // now set up in face pUpdFace->nEdges = nNewEdges; memcpy(pUpdFace->Edges, hNewEdges, sizeof(SSHANDLE) * nNewEdges); delete phVertexList; } SSHANDLE id1 = pEdge1->id; SSHANDLE id2 = pEdge2->id; // delete old edges for(i = 0; i < m_nEdges; i++) { if(m_Edges[i].id == id1 || m_Edges[i].id == id2) { DeleteEdge(i); --i; } } return TRUE; }