typename PolygonMesh<PointType>::VertexIterator PolygonMesh<PointType>::splitFace(const typename PolygonMesh<PointType>::FaceIterator& faceIt,typename PolygonMesh<PointType>::Vertex* facePoint) { /* Link the face point to the mesh: */ facePoint->pred=lastVertex; facePoint->succ=0; if(lastVertex!=0) lastVertex->succ=facePoint; else vertices=facePoint; lastVertex=facePoint; /* Create a fan of triangles around the face point: */ Edge* firstOuterEdge=faceIt->getEdge(); deleteFace(faceIt.face); Edge* outerEdge=firstOuterEdge; Edge* firstInnerEdge; Edge* lastInnerEdge=0; do { Edge* nextOuterEdge=outerEdge->getFaceSucc(); /* Create a new triangle: */ Face* triangle=newFace(); Edge* innerEdge1=newEdge(); Edge* innerEdge2=newEdge(); facePoint->setEdge(innerEdge1); innerEdge1->set(facePoint,triangle,innerEdge2,outerEdge,lastInnerEdge); innerEdge1->sharpness=0; if(lastInnerEdge!=0) lastInnerEdge->setOpposite(innerEdge1); else firstInnerEdge=innerEdge1; innerEdge2->set(outerEdge->getEnd(),triangle,outerEdge,innerEdge1,0); innerEdge2->sharpness=0; outerEdge->setFace(triangle); outerEdge->setFacePred(innerEdge1); outerEdge->setFaceSucc(innerEdge2); triangle->setEdge(outerEdge); #ifndef NDEBUG triangle->checkFace(); #endif lastInnerEdge=innerEdge2; outerEdge=nextOuterEdge; } while(outerEdge!=firstOuterEdge); /* Close the fan by connecting the first and last inner edges: */ lastInnerEdge->setOpposite(firstInnerEdge); firstInnerEdge->setOpposite(lastInnerEdge); #ifndef NDEBUG facePoint->checkVertex(); #endif return VertexIterator(facePoint); }
void LookAlikeMainPrivate::processFaces() { if (m_facesToProcess.isEmpty()) { m_progressDialog->dismiss(); } else { QUrl toProcess = m_facesToProcess.first(); if (m_currentAction == m_confirmFaceAction) { confirmFace(toProcess, m_personSelected); } else { deleteFace(toProcess, m_personSelected); } m_facesToProcess.removeFirst(); m_progress->setValue(m_progress->value() + 1); } }
void BOP_Merge2::mergeVertex(BOP_Face3 *face, BOP_Index v1, BOP_Index v2) { BOP_Index next, prev; face->getNeighbours(v1,prev,next); // if new vertex is not already in the tri, make a new tri if( prev != v2 && next != v2 ) { m_mesh->addFace( new BOP_Face3(prev,v2,next, face->getPlane(),face->getOriginalFace()) ); #ifdef BOP_DEBUG cout << "mv3: add " << prev << "," << v2 << "," << next << endl; } else { cout << "mv3: vertex already in tri: doing nothing" << endl; #endif } deleteFace(m_mesh, face); }
void BOP_Merge2::mergeVertex(BOP_Face4 *face, BOP_Index v1, BOP_Index v2) { BOP_Index next, prev, opp; face->getNeighbours(v1,prev,next,opp); // if new vertex is already in the quad, replace quad with new tri if( prev == v2 || next == v2 ) { m_mesh->addFace( new BOP_Face3(prev,next,opp, face->getPlane(),face->getOriginalFace()) ); #ifdef BOP_DEBUG cout << "mv4a: add " << prev << "," << next << "," << opp << endl; #endif } // otherwise make a new quad else { m_mesh->addFace( new BOP_Face4(prev,v2,next,opp, face->getPlane(),face->getOriginalFace()) ); #ifdef BOP_DEBUG cout << "mv4b: add "<<prev<<","<<v2<<","<<next<<","<<opp<<endl; #endif } deleteFace(m_mesh, face); }
/** * Simplifies the mesh, merging the pairs of triangles that come frome the * same original face and define a quad. * @return true if a quad was added, false otherwise */ bool BOP_Merge2::createQuads() { BOP_Faces quads; // Get mesh faces BOP_Faces faces = m_mesh->getFaces(); // Merge mesh triangles const BOP_IT_Faces facesIEnd = (faces.end()-1); const BOP_IT_Faces facesJEnd = faces.end(); for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) { #ifdef OLD_QUAD if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue; for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) { if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 || (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue; BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ); if (faceK != NULL) { // Set triangles to BROKEN deleteFace(m_mesh, *faceI); deleteFace(m_mesh, *faceJ); #ifdef BOP_DEBUG cout << "createQuad: del " << *faceI << endl; cout << "createQuad: del " << *faceJ << endl; cout << "createQuad: add " << faceK << endl; #endif quads.push_back(faceK); break; } } #else if ((*faceI)->getTAG() == BROKEN ) continue; for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) { if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue; BOP_Face *faceK = NULL; if((*faceI)->size() == 3) { if((*faceJ)->size() == 3) faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ); else faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face4*)*faceJ); } else { if((*faceJ)->size() == 3) faceK = createQuad((BOP_Face3*)*faceJ,(BOP_Face4*)*faceI); else faceK = createQuad((BOP_Face4*)*faceI,(BOP_Face4*)*faceJ); } if (faceK != NULL) { // Set triangles to BROKEN deleteFace(m_mesh, *faceI); deleteFace(m_mesh, *faceJ); #ifdef BOP_DEBUG cout << "createQuad: del " << *faceI << endl; cout << "createQuad: del " << *faceJ << endl; cout << "createQuad: add " << faceK << endl; #endif quads.push_back(faceK); break; } } #endif } // Add quads to mesh const BOP_IT_Faces quadsEnd = quads.end(); for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad); return (quads.size() > 0); }
void clean_nonmanifold( BOP_Mesh *m ) { return; BOP_Edges nme; BOP_Edges e = m->getEdges(); for( BOP_IT_Edges it = e.begin(); it != e.end(); ++it ) { BOP_Indexs faces = (*it)->getFaces(); if( faces.size() & ~2 ) nme.push_back(*it); } if (nme.size() == 0) return; for( BOP_IT_Edges it = nme.begin(); it != nme.end(); ++it ) { if( (*it)->getFaces().size() > 1 ) { BOP_Indexs faces = (*it)->getFaces(); for( BOP_IT_Indexs face = faces.begin(); face != faces.end(); ++face ) { MT_Point3 vertex1 = m->getVertex(m->getFace(*face)->getVertex(0))->getPoint(); MT_Point3 vertex2 = m->getVertex(m->getFace(*face)->getVertex(1))->getPoint(); MT_Point3 vertex3 = m->getVertex(m->getFace(*face)->getVertex(2))->getPoint(); if (BOP_collinear(vertex1,vertex2,vertex3)) // collinear triangle deleteFace(m,m->getFace(*face)); } continue; } BOP_Face *oface1 = m->getFace((*it)->getFaces().front()); BOP_Face *oface2, *tmpface; BOP_Index first =(*it)->getVertex1(); BOP_Index next =(*it)->getVertex2(); BOP_Index last = first; unsigned short facecount = 0; bool found = false; BOP_Indexs vertList; #ifdef BOP_DEBUG cout << " first edge is " << (*it) << endl; #endif vertList.push_back(first); BOP_Edge *edge; while(true) { BOP_Vertex *vert = m->getVertex(next); BOP_Indexs edges = vert->getEdges(); edge = NULL; for( BOP_IT_Indexs eit = edges.begin(); eit != edges.end(); ++eit) { edge = m->getEdge(*eit); if( edge->getFaces().size() > 1) { edge = NULL; continue; } if( edge->getVertex1() == next && edge->getVertex2() != last ) { last = next; next = edge->getVertex2(); break; } if( edge->getVertex2() == next && edge->getVertex1() != last ) { last = next; next = edge->getVertex1(); break; } edge = NULL; } if( !edge ) break; #ifdef BOP_DEBUG cout << " next edge is " << edge << endl; #endif tmpface = m->getFace(edge->getFaces().front()); if( oface1->getOriginalFace() != tmpface->getOriginalFace() ) oface2 = tmpface; else ++facecount; vertList.push_back(last); if( vertList.size() > 3 ) break; if( next == first ) { found = true; break; } } if(found) { edge = *it; #ifdef BOP_DEBUG cout << " --> found a loop" << endl; #endif if( vertList.size() == 3 ) { BOP_Face3 *face = (BOP_Face3 *)m->getFace(edge->getFaces().front()); face->getNeighbours(first,last,next); } else if( vertList.size() == 4 ) { BOP_Face4 *face = (BOP_Face4 *)m->getFace(edge->getFaces().front()); face->getNeighbours(first,last,next,last); } else { #ifdef BOP_DEBUG cout << "loop has " << vertList.size() << "verts"; #endif continue; } if(facecount == 1) oface1 = oface2; next = vertList[1]; last = vertList[2]; if( edge->getVertex2() == next ) { BOP_Face3 *f = new BOP_Face3(next,first,last, oface1->getPlane(),oface1->getOriginalFace()); m->addFace( f ); #ifdef BOP_DEBUG cout << " face is backward: " << f << endl; #endif } else { BOP_Face3 *f = new BOP_Face3(last,first,next, oface1->getPlane(),oface1->getOriginalFace()); m->addFace( f ); #ifdef BOP_DEBUG cout << " face is forward: " << f << endl; #endif } } } }
VertexIter HalfedgeMesh::collapseEdge( EdgeIter e ) { // TODO This method should collapse the given edge and return an iterator to the new vertex created by the collapse. //1. collect elements EdgeIter e4 = e; //Halfedges HalfedgeIter h1 = e4->halfedge(); HalfedgeIter h5 = h1->twin(); //Faces FaceIter f0 = h1->face(); FaceIter f1 = h5->face(); //Early Exit #1: Ignore requests to collapse boundary edges if(f0->isBoundary() || f1->isBoundary()) return verticesEnd(); //Halfedges, cont' HalfedgeIter h2 = h1->next(); HalfedgeIter h0 = h2->next(); HalfedgeIter h3 = h5->next(); HalfedgeIter h4 = h3->next(); HalfedgeIter h7 = h0->twin(); HalfedgeIter h12 = h3->twin(); HalfedgeIter h20 = h2->twin(); HalfedgeIter h15 = h4->twin(); //Edges EdgeIter e0 = h0->edge(); EdgeIter e1 = h3->edge(); EdgeIter e2 = h4->edge(); EdgeIter e3 = h2->edge(); //EdgeIter e4 //Faces //Vertices VertexIter v0 = h0->vertex(); VertexIter v1 = h3->vertex(); VertexIter v2 = h4->vertex(); VertexIter v3 = h2->vertex(); //Early Exit #2: The number of the joint neighbor vertices of the two merging vertices //must be EXACTLY TWO std::vector<VertexIter> v1_neighbors; std::vector<VertexIter> v3_neighbors; HalfedgeIter h = h3; do { h = h->twin(); if(h->vertex() != v1) v1_neighbors.push_back(h->vertex()); h = h->next(); } while(h != h3); h = h2; do { h = h->twin(); if(h->vertex() != v3) v3_neighbors.push_back(h->vertex()); h = h->next(); } while(h != h2); std::sort(v1_neighbors.begin(), v1_neighbors.end()); std::sort(v3_neighbors.begin(), v3_neighbors.end()); std::vector<VertexIter> joint_neighbors; std::set_intersection(v1_neighbors.begin(), v1_neighbors.end(), v3_neighbors.begin(), v3_neighbors.end(), std::back_inserter(joint_neighbors)); if(joint_neighbors.size() != 2) return verticesEnd(); //Early Exit #3: mesh must have more than 4 vertices if neither v1 nor v3 is boundary vertex, //and more than 3 vertices if either v1 or v3 is boundary vertex if(!v1->isBoundary() && !v3->isBoundary() && nVertices() <= 4) return verticesEnd(); if((v1->isBoundary() || v3->isBoundary()) && nVertices() <= 3) return verticesEnd(); //Early Exit #4: v1, v3 cannot be both boundary vertex if(v1->isBoundary() && v3->isBoundary()) return verticesEnd(); //Early Exit #5: boundary vertex needs at least one triangle //By convention, Vertex::degree() returns the face degree if(v0->isBoundary() && v0->degree() <= 1) return verticesEnd(); if(v1->isBoundary() && v1->degree() <= 1) return verticesEnd(); if(v2->isBoundary() && v2->degree() <= 1) return verticesEnd(); if(v3->isBoundary() && v3->degree() <= 1) return verticesEnd(); //Early Exit #6: degenerated case: v0/v1/v2/v3 are duplicated if(v0 == v1 || v0 == v2 || v0 == v3 || v1 == v2 || v1 == v3 || v2 == v3) return verticesEnd(); VertexIter output = verticesEnd(); if(v3->isBoundary()) { std::vector<HalfedgeIter> v1_out; HalfedgeIter h = v1->halfedge(); do { v1_out.push_back(h); h = h->next()->next()->twin(); } while(h != v1->halfedge()); //2. reassign elements //Halfedges h7->twin() = h20; h7->edge() = e3; h20->twin() = h7; h12->twin() = h15; h12->edge() = e2; h15->twin() = h12; for(auto h = v1_out.begin(); h!= v1_out.end(); ++h) (*h)->vertex() = v3; //Vertices v0->halfedge() = h20; v3->halfedge() = h15; v3->position = 0.5f * (v1->position + v3->position); v2->halfedge() = h12; //Edges e3->halfedge() = h20; e2->halfedge() = h15; //Faces //3. delete elements //Halfedges deleteHalfedge(h0); deleteHalfedge(h1); deleteHalfedge(h2); deleteHalfedge(h3); deleteHalfedge(h4); deleteHalfedge(h5); //Vertices deleteVertex(v1); //Edges deleteEdge(e0); deleteEdge(e1); deleteEdge(e4); //Faces deleteFace(f0); deleteFace(f1); output = v3; } else { std::vector<HalfedgeIter> v3_out; HalfedgeIter h = v3->halfedge(); do { v3_out.push_back(h); h = h->next()->next()->twin(); } while(h != v3->halfedge()); //2. reassign elements //Halfedges h7->twin() = h20; h20->twin() = h7; h20->edge() = e0; h12->twin() = h15; h15->twin() = h12; h15->edge() = e1; for(auto h = v3_out.begin(); h!= v3_out.end(); ++h) (*h)->vertex() = v1; //Vertices v0->halfedge() = h20; v1->halfedge() = h15; v1->position = 0.5f * (v1->position + v3->position); v2->halfedge() = h12; //Edges e0->halfedge() = h20; e1->halfedge() = h15; //Faces //3. delete elements //Halfedges deleteHalfedge(h0); deleteHalfedge(h1); deleteHalfedge(h2); deleteHalfedge(h3); deleteHalfedge(h4); deleteHalfedge(h5); //Vertices deleteVertex(v3); //Edges deleteEdge(e2); deleteEdge(e3); deleteEdge(e4); //Faces deleteFace(f0); deleteFace(f1); output = v1; } return output; }
void HMesh::collapseEdge(Edge* edgy) { Vertex* v1 = edgy->start; Vertex* v2 = edgy->end; if(v1 == v2) return; *v1 = (*v1 + *v2) * 0.5; edgy->start = v1; if (edgy->face) { if(edgy->next->next->pair != NULL) { edgy->next->next->pair->pair = edgy->next->pair; if(edgy->next->pair != NULL) { edgy->next->pair->pair = edgy->next->next->pair; Edge* e1 = edgy->next->next; Edge* e2 = edgy->next; //delete old edges deleteEdge(e1, false); deleteEdge(e2, false); } } } if(edgy->pair != NULL) { if (edgy->pair->face) { if(edgy->pair->next->next->pair != NULL) { edgy->pair->next->next->pair->pair = edgy->pair->next->pair; if(edgy->pair->next->pair != NULL) { edgy->pair->next->pair->pair = edgy->pair->next->next->pair; //delete old edges Edge* e1 = edgy->pair->next->next; Edge* e2 = edgy->pair->next; deleteEdge(e1, false); deleteEdge(e2, false); } } } // Now really delete faces if(edgy->pair->face) { deleteFace(edgy->pair->face); edgy->pair = 0; } } if(edgy->face) { deleteFace(edgy->face); edgy->face = 0; } deleteEdge(edgy); auto it =v2->out_edges.begin(); while(it !=v2->out_edges.end()) { (*it)->start = v1; v1->out_edges.push_back(*it); it++; } auto it2 = v2->in_edges.begin(); while(it2 != v2->in_edges.end()) { (*it2)->end = v1; v1->in_edges.push_back(*it2); it2++; } //v2->out_edges.clear(); //v2->in_edges.clear(); }
bool AutoTriangleMesh<PointType>::collapseEdge(const typename AutoTriangleMesh<PointType>::EdgeIterator& edge) { /* Get triangle topology: */ Edge* e1=&(*edge); Edge* e2=e1->getFaceSucc(); Edge* e3=e1->getFacePred(); Edge* e4=e1->getOpposite(); if(e4==0) return false; Edge* e5=e4->getFaceSucc(); Edge* e6=e4->getFacePred(); Edge* e7=e2->getOpposite(); Edge* e8=e3->getOpposite(); Edge* e9=e5->getOpposite(); Edge* e10=e6->getOpposite(); Vertex* v1=e1->getStart(); Vertex* v2=e2->getStart(); Vertex* v3=e3->getStart(); Vertex* v4=e6->getStart(); Face* f1=e1->getFace(); Face* f2=e4->getFace(); /* Check if v3 has valence of at least 4: */ if(e7->getFacePred()->getOpposite()->getFacePred()==e8) return false; /* Check if v4 has valence of at least 4: */ if(e9->getFacePred()->getOpposite()->getFacePred()==e10) return false; /* Check if v1 and v2 together have at least valence 7 (then collapsed v1 will have at least valence 3): */ if(e7->getFaceSucc()==e10&&e9->getFaceSucc()==e8) return false; /* Check if platelets of v1 and v2 have common vertices (except each other, of course): */ /* Currently highly inefficient at O(n^2); need to optimize! */ for(Edge* ve1=e10->getFacePred();ve1!=e7;ve1=ve1->getOpposite()->getFacePred()) for(Edge* ve2=e8->getFacePred();ve2!=e9;ve2=ve2->getOpposite()->getFacePred()) if(ve1->getStart()==ve2->getStart()) return false; assert(v2->getEdge()!=0); assert(f1->getEdge()!=0); assert(f2->getEdge()!=0); assert(e2->getFaceSucc()==e3&&e3->getFacePred()==e2); assert(e5->getFaceSucc()==e6&&e6->getFacePred()==e5); assert(e4->getStart()==v2); assert(e5->getStart()==v1); assert(e7->getOpposite()==e2); assert(e8->getOpposite()==e3); assert(e9->getOpposite()==e5); assert(e10->getOpposite()==e6); assert(e7->getStart()==v3); assert(e8->getStart()==v1); assert(e9->getStart()==v4); assert(e10->getStart()==v2); assert(e2->getFace()==f1); assert(e3->getFace()==f1); assert(e5->getFace()==f2); assert(e6->getFace()==f2); assert(f1->getEdge()==e1||f1->getEdge()==e2||f1->getEdge()==e3); assert(f2->getEdge()==e4||f2->getEdge()==e5||f2->getEdge()==e6); /* Move v1 to edge midpoint: */ Point p=Point::zero(); p.add(*v1); p.add(*v2); p.normalize(2); p.index=v1->index; v1->setPoint(p); /* Remove both faces from mesh: */ e7->setOpposite(e8); e8->setOpposite(e7); if(e7->sharpness<e8->sharpness) e7->sharpness=e8->sharpness; else e8->sharpness=e7->sharpness; e9->setOpposite(e10); e10->setOpposite(e9); if(e9->sharpness<e10->sharpness) e9->sharpness=e10->sharpness; else e10->sharpness=e9->sharpness; v1->setEdge(e8); v3->setEdge(e7); v4->setEdge(e9); /* Remove v2 from mesh: */ /* Note: Works currently only for closed meshes! */ for(Edge* e=e10;e!=e8;e=e->getVertexSucc()) { assert(e->getStart()==v2); e->setStart(v1); } assert(e7->getOpposite()==e8); assert(e8->getOpposite()==e7); assert(e9->getOpposite()==e10); assert(e10->getOpposite()==e9); assert(e7->getStart()==v3); assert(e8->getStart()==v1); assert(e9->getStart()==v4); assert(e10->getStart()==v1); /* Delete removed objects: */ v2->setEdge(0); f1->setEdge(0); f2->setEdge(0); deleteEdge(e1); deleteEdge(e2); deleteEdge(e3); deleteEdge(e4); deleteEdge(e5); deleteEdge(e6); deleteVertex(v2); deleteFace(f1); deleteFace(f2); /* Update version numbers of all involved vertices: */ ++version; v1->version=version; Edge* e=v1->getEdge(); do { e->getEnd()->version=version; e=e->getVertexSucc(); } while(e!=v1->getEdge()); return true; }
typename PolygonMesh<PointType>::FaceIterator PolygonMesh<PointType>::splitFaceDooSabin(const typename PolygonMesh<PointType>::FaceIterator& faceIt) { /* Calculate the face's centroid: */ PointType centroid=PointType::zero(); int numVertices=0; for(FaceEdgeIterator feIt=faceIt.beginEdges();feIt!=faceIt.endEdges();++feIt,++numVertices) centroid.add(*feIt->getStart()); centroid.normalize(numVertices); /* Walk around the face again and create the inner face: */ Face* innerFace=newFace(); Edge* lastInnerEdge=0; Edge* outerEdge=faceIt->getEdge(); for(int i=0;i<numVertices;++i,outerEdge=outerEdge->getFaceSucc()) { /* Create a new vertex and a new edge: */ PointType newPoint=PointType::zero(); newPoint.add(centroid); newPoint.add(*outerEdge->getStart()); newPoint.normalize(2); Vertex* newV=newVertex(newPoint); Edge* newE=newEdge(); newV->setEdge(newE); newE->set(newV,innerFace,lastInnerEdge,0,0); newE->sharpness=0; if(lastInnerEdge!=0) lastInnerEdge->setFaceSucc(newE); else innerFace->setEdge(newE); lastInnerEdge=newE; } lastInnerEdge->setFaceSucc(innerFace->getEdge()); innerFace->getEdge()->setFacePred(lastInnerEdge); /* Walk around the face again and create one quad face for each edge: */ Edge* innerEdge=innerFace->getEdge(); outerEdge=faceIt->getEdge(); Edge* lastCrossEdge=0; Edge* firstCrossEdge; for(int i=0;i<numVertices;++i,innerEdge=innerEdge->getFaceSucc()) { Edge* nextOuterEdge=outerEdge->getFaceSucc(); /* Create a new face and three new edges: */ Face* quad=newFace(); quad->setEdge(outerEdge); Edge* e1=newEdge(); Edge* e2=newEdge(); Edge* e3=newEdge(); e1->set(innerEdge->getEnd(),quad,e3,e2,innerEdge); e1->sharpness=0; innerEdge->setOpposite(e1); e2->set(innerEdge->getStart(),quad,e1,outerEdge,lastCrossEdge); e2->sharpness=0; if(lastCrossEdge!=0) lastCrossEdge->setOpposite(e2); else firstCrossEdge=e2; e3->set(outerEdge->getEnd(),quad,outerEdge,e1,0); e3->sharpness=0; lastCrossEdge=e3; outerEdge->set(outerEdge->getStart(),quad,e2,e3,outerEdge->getOpposite()); outerEdge=nextOuterEdge; } lastCrossEdge->setOpposite(firstCrossEdge); firstCrossEdge->setOpposite(lastCrossEdge); /* Delete the old face and return the inner one: */ deleteFace(faceIt.face); return FaceIterator(innerFace); }
typename PolygonMesh<PointType>::FaceIterator PolygonMesh<PointType>::removeEdge(const typename PolygonMesh<PointType>::EdgeIterator& edgeIt) { Edge* edge2=edgeIt->getOpposite(); if(edge2!=0) { /* Have all edges of the second face point to the first instead: */ Face* newFace=edgeIt->getFace(); for(Edge* ePtr=edge2->getFaceSucc();ePtr!=edge2;ePtr=ePtr->getFaceSucc()) ePtr->setFace(newFace); /* Fix up the edge's start vertex: */ edgeIt->getFacePred()->setFaceSucc(edge2->getFaceSucc()); edge2->getFaceSucc()->setFacePred(edgeIt->getFacePred()); edgeIt->getStart()->setEdge(edge2->getFaceSucc()); /* Fix up the edge's end vertex: */ edgeIt->getFaceSucc()->setFacePred(edge2->getFacePred()); edge2->getFacePred()->setFaceSucc(edgeIt->getFaceSucc()); edge2->getStart()->setEdge(edgeIt->getFaceSucc()); /* Remove the edge and the second face: */ newFace->setEdge(edgeIt->getFaceSucc()); deleteFace(edge2->getFace()); deleteEdge(edgeIt.edge); deleteEdge(edge2); return FaceIterator(newFace); } else { /* Fix up all vertices around the face: */ Edge* ePtr=edgeIt.edge; do { /* Fix up the edge's start vertex: */ if(ePtr->getVertexSucc()!=0) ePtr->getStart()->setEdge(ePtr->getVertexSucc()); else ePtr->getStart()->setEdge(ePtr->getVertexPred()); /* Go to the next edge: */ ePtr=ePtr->getFaceSucc(); } while(ePtr!=edgeIt.edge); /* Delete the face: */ deleteFace(ePtr->getFace()); /* Delete all edges: */ ePtr=edgeIt.edge; ePtr->getFacePred()->setFaceSucc(0); while(ePtr!=0) { Edge* next=ePtr->getFaceSucc(); deleteEdge(ePtr); ePtr=next; } return FaceIterator(0); } }
typename PolygonMesh<PointType>::FaceIterator PolygonMesh<PointType>::vertexToFace(const typename PolygonMesh<PointType>::VertexIterator& vertexIt) { /* Remove solitary vertices: */ if(vertexIt->getEdge()==0) { deleteVertex(vertexIt.vertex); return FaceIterator(0); } /* Walk around the vertex and flip its edges: */ Face* vertexFace=newFace(); Edge* lastEdge=0; Edge* ePtr=vertexIt->getEdge(); do { Edge* nextEdge=ePtr->getFacePred()->getOpposite(); /* Remove the edge from its current face and add it to the vertex face: */ Edge* pred=ePtr->getFacePred(); Edge* succ=ePtr->getFaceSucc(); /* Test for the dangerous special case of a triangle: */ if(succ->getFaceSucc()==pred) { /* Remove the triangle completely: */ deleteFace(succ->getFace()); deleteEdge(ePtr); deleteEdge(pred); /* Put the outside edge into the new face loop: */ succ->set(succ->getStart(),vertexFace,lastEdge,0,succ->getOpposite()); ePtr=succ; } else { pred->setFaceSucc(succ); succ->setFacePred(pred); ePtr->set(succ->getStart(),vertexFace,lastEdge,0,pred); pred->setOpposite(ePtr); ePtr->sharpness=pred->sharpness=0; pred->getFace()->setEdge(pred); #ifndef NDEBUG pred->getFace()->checkFace(); #endif } if(lastEdge!=0) { lastEdge->setFaceSucc(ePtr); #ifndef NDEBUG ePtr->getStart()->checkVertex(); #endif } else vertexFace->setEdge(ePtr); lastEdge=ePtr; ePtr=nextEdge; } while(ePtr!=vertexIt->getEdge()); lastEdge->setFaceSucc(vertexFace->getEdge()); vertexFace->getEdge()->setFacePred(lastEdge); #ifndef NDEBUG ePtr->getStart()->checkVertex(); vertexFace->checkFace(); #endif /* Delete the vertex and return the new face: */ vertexIt->setEdge(0); deleteVertex(vertexIt.vertex); return FaceIterator(vertexFace); }
typename PolygonMesh<PointType>::FaceIterator PolygonMesh<PointType>::removeVertex(const typename PolygonMesh<PointType>::VertexIterator& vertexIt) { if(vertexIt->isInterior()) { /* Combine all surrounding faces into a single face: */ Face* vertexFace=newFace(); Edge* lastEdge=0; Edge* ePtr=vertexIt->getEdge(); ePtr->getOpposite()->setOpposite(0); while(ePtr!=0) { /* Re-arrange all face pointers: */ Edge* vePtr=ePtr->getFaceSucc(); while(vePtr!=ePtr->getFacePred()) { vePtr->setFace(vertexFace); vePtr=vePtr->getFaceSucc(); } /* Fix up the vertex: */ ePtr->getEnd()->setEdge(ePtr->getFaceSucc()); /* Delete the outgoing and incoming edges: */ Edge* nextEptr=ePtr->getVertexSucc(); ePtr->getFaceSucc()->setFacePred(lastEdge); if(lastEdge!=0) lastEdge->setFacePred(ePtr->getFaceSucc()); else vertexFace->setEdge(ePtr->getFaceSucc()); lastEdge=ePtr->getFacePred()->getFacePred(); deleteFace(ePtr->getFace()); deleteEdge(ePtr->getFacePred()); deleteEdge(ePtr); /* Go to the next face: */ ePtr=nextEptr; } /* Close the face loop: */ lastEdge->setFaceSucc(vertexFace->getEdge()); vertexFace->getEdge()->setFacePred(lastEdge); deleteVertex(vertexIt.vertex); return vertexFace; } else if(vertexIt->getEdge()!=0) { /* Go backwards until border edge is hit: */ Edge* ePtr; for(ePtr=vertexIt->getEdge();ePtr->getOpposite()!=0;ePtr=ePtr->getVertexPred()) ; /* Remove all surrounding faces: */ while(ePtr!=0) { Edge* nextEptr=ePtr->getVertexSucc(); deleteFace(ePtr->getFace()); Edge* fePtr=ePtr; do { Edge* nextFePtr=fePtr->getFaceSucc(); /* Fix up the vertex: */ if(nextFePtr!=ePtr) { if(nextFePtr->getVertexPred()!=0) nextFePtr->getStart()->setEdge(nextFePtr->getVertexPred()); else nextFePtr->getStart()->setEdge(fePtr->getOpposite()->getFacePred()); } /* Remove the edge: */ if(fePtr->getOpposite()!=0) fePtr->getOpposite()->setOpposite(0); deleteEdge(fePtr); } while(fePtr!=ePtr); ePtr=nextEptr; } deleteVertex(vertexIt.vertex); return FaceIterator(0); } else // Dangling vertex { deleteVertex(vertexIt.vertex); return FaceIterator(0); } }