void Face <T> ::print ( std::ostream * output ) const { //Print Face if ( edge != NULL ) { //Get next edge in cell HalfEdge <T> *e = edge; //Proces all edges of the Face do { //Print edge e->print ( output ); //Add new line *output << '\n'; //Increment edge e = e->getNextEdge(); } while ( e != edge ); } std::cout << std::endl; }
bool Face::include_edge(Edge *e) { HalfEdge * he = m_halfedge; if(he->edge () == e || he->he_next ()->edge () == e || he->he_prev ()->edge () == e) return true; return false; }
// Return whether a point is inside, on, or outside the cell: // -1: point is outside the perimeter of the cell // 0: point is on the perimeter of the cell // 1: point is inside the perimeter of the cell // int Cell::pointIntersection(double x, double y) { // Check if point in polygon. Since all polygons of a Voronoi // diagram are convex, then: // http://paulbourke.net/geometry/polygonmesh/ // Solution 3 (2D): // "If the polygon is convex then one can consider the polygon // "as a 'path' from the first vertex. A point is on the interior // "of this polygons if it is always on the same side of all the // "line segments making up the path. ... // "(y - y0) (x1 - x0) - (x - x0) (y1 - y0) // "if it is less than 0 then P is to the right of the line segment, // "if greater than 0 it is to the left, if equal to 0 then it lies // "on the line segment" HalfEdge* he; size_t edgeCount = halfEdges.size(); Point2 p0; Point2 p1; double r; while (edgeCount--) { he = halfEdges[edgeCount]; p0 = *he->startPoint(); p1 = *he->endPoint(); r = (y - p0.y)*(p1.x - p0.x) - (x - p0.x)*(p1.y - p0.y); if (r == 0) { return 0; } if (r > 0) { return -1; } } return 1; }
void Face <T>::removeAdjacency() { //Set twin edges of Faces adjacent to actual Face to NULL if ( edge != NULL ) { //Get actual edge in cell HalfEdge <T> *e = edge; //Proces all edges of the Face do { //Get twin edge HalfEdge <T> *e_twin = e->getTwinEdge(); //Adjacent cell exists if ( e_twin != NULL ) { //Set pointer to NULL e_twin -> setTwinEdge ( NULL ); } //Increment edge e = e->getNextEdge(); } while ( e != edge ); } }
int TriangleAdjacencyGraph::fillIndexFromFan( std::vector<Index> &indexVec, HalfEdge &firstEdge ) { int count = 0; HalfEdge *halfEdge(&firstEdge); HalfEdge *gateEdge = 0; if (halfEdge) { count = 3; indexVec.resize(2); indexVec[0] = halfEdge->vertexStart(); indexVec[1] = halfEdge->vertexEnd(); for ( gateEdge = halfEdge->next->next->twin; gateEdge != halfEdge; gateEdge = gateEdge->next->next->twin ) { indexVec.push_back(gateEdge->vertexEnd()); count++; } indexVec.push_back(halfEdge->vertexEnd()); } else { cerr << "Invalid fac in fillIndexFromFan()" << endl; } return count; }
int TriangleAdjacencyGraph::calcEgdeLines ( vector<Index> & indexVec, bool codeBorder ) { unsigned int i, nN, j, nE, halfEdgeCount = 0; Index startVertexIndex, endVertexIndex; HalfEdge *halfEdge; bool isBorder; indexVec.clear(); nN = _temporaryVector.size(); for (i = 0; i < nN; i++) { nE = _temporaryVector[i].size(); for ( j = 0; j < nE; j++) { halfEdge = _temporaryVector[i][j].second; startVertexIndex = halfEdge->vertexStart(); endVertexIndex = halfEdge->vertexEnd(); if ((isBorder = (halfEdge->twin == 0)) || (startVertexIndex < endVertexIndex)) { indexVec.push_back(startVertexIndex); indexVec.push_back(endVertexIndex); if (codeBorder) indexVec.push_back(isBorder ? 0 : 1); halfEdgeCount++; } } } return halfEdgeCount; }
unsigned int Face <T> ::countVertices() const { //Count vertices of the Face unsigned int vertices = 0; //There is a valid edge if ( edge != NULL ) { //Get next edge in cell HalfEdge <T> *e = edge; //Proces all edges of the Face do { //Increment vertices vertices ++; //Increment edge e = e->getNextEdge(); } while ( e != edge ); } return vertices; }
void DigraphL::print(void) { // Wagi krawedzi od 'v' do kazdego z V wierzcholkow (moga byc nieskonczone) int matrix[V]; HalfEdge* edge; for (int v = 0; v < V; v++) { edges[v]->rewind(); // Inicjujemy tablice nieskonczonymi wagami for (int w = 0; w < V; w++) matrix[w] = INF; // Uaktualniamy wagi odpowadajace istniejacym krawedziom while (edges[v]->hasMoreElements()) { edge = edges[v]->getNext(); matrix[edge->getEndingVertexIndex()] = edge->getWeight(); } // Wypisujemy wagi na ekran for (int w = 0; w < V; w++) { cout << "\t"; if (matrix[w] != INF) cout << matrix[w]; else cout << "-"; } cout << endl; } cout << endl; }
//---------------------------------------------------------------------- // Method: fillPrimFromFan // Author: jbehr // Date: Tue Feb 15 18:16:59 2000 // Description: // //---------------------------------------------------------------------- Int32 HalfEdgeGraph::fillIndexFromFan(std::vector<HalfEdgeGraph::IndexT> &indexVec, HalfEdge &firstEdge ) { Int32 count = 0; HalfEdge *halfEdge(&firstEdge); HalfEdge *gateEdge = 0; if(halfEdge) { count = 3; indexVec.resize(2); indexVec[0] = halfEdge->vertexStart(); indexVec[1] = halfEdge->vertexEnd(); for(gateEdge = halfEdge->next->next->twin; gateEdge != halfEdge; gateEdge = gateEdge->next->next->twin) { indexVec.push_back(gateEdge->vertexEnd()); ++count; } indexVec.push_back(halfEdge->vertexEnd()); } else { SWARNING << "Invalid fac in fillIndexFromFan()" << endl; } return count; }
//---------------------------------------------------------------------- // Method: calcEdgeLines // Author: jbehr // Date: Tue Feb 15 18:16:59 2000 // Description: // //---------------------------------------------------------------------- Int32 HalfEdgeGraph::calcEgdeLines(vector<HalfEdgeGraph::IndexT> & indexVec, bool codeBorder ) { UInt32 i, nN, j, nE, halfEdgeCount = 0; HalfEdgeGraph::IndexT startVertexIndex, endVertexIndex; HalfEdge *halfEdge; bool isBorder; indexVec.clear(); nN = _edgeLinkVec.size(); for (i = 0; i < nN; ++i) { nE = _edgeLinkVec[i].size(); for ( j = 0; j < nE; ++j) { halfEdge = _edgeLinkVec[i][j].second; startVertexIndex = halfEdge->vertexStart(); endVertexIndex = halfEdge->vertexEnd(); if ((isBorder = (halfEdge->twin == 0)) || (startVertexIndex < endVertexIndex)) { indexVec.push_back(startVertexIndex); indexVec.push_back(endVertexIndex); if(codeBorder) indexVec.push_back(isBorder ? 0 : 1); ++halfEdgeCount; } } } return halfEdgeCount; }
T FacePerimeter:: getFacePerimeter ( const HalfEdge <T> *e_start ) { //Get perimeter of the Face given by start half edge T perimeter = 0; HalfEdge <T> *e = const_cast <HalfEdge <T> *> ( e_start ); //There is a valid edge if ( e_start != NULL ) { //Get point Node3DCartesian <T> *pi = e->getPoint(); //Proces all edges of the Face do { //Get point Node3DCartesian <T> *pii = e->getNextEdge()->getPoint(); //Compute area perimeter += EuclDistance::getEuclDistance2D ( pi->getX(), pi->getY(), pii->getX(), pii->getY() ); //Assign point pi = pii; //Assign edge e = e->getNextEdge(); } while ( e != e_start ); } //Get area return perimeter; }
QVector3D Slice::linePLaneIntersection(HalfEdge edge, QVector3D planeOrigin, QVector3D planeNormal){ QVector3D u=edge.getStart()->toVector3D()-edge.getStop()->toVector3D(); QVector3D w=edge.getStop()->toVector3D()-planeOrigin; QVector3D normal=planeNormal; float d=QVector3D::dotProduct(normal,u); float n=-QVector3D::dotProduct(normal,w); //line is parallel to plane if(fabs(d)<0.00000001){ if(n==0){ qDebug() << "line is on plane"; return QVector3D(edge.getStart()->toVector3D()); } else{ qDebug() << "no intersection"; return QVector3D(); } } //line croses plane float sI = n/d; if(sI<0 || sI>1){ qDebug() << "no intersection"; return QVector3D(); } return edge.getStop()->toVector3D() + u*sI; }
//fill list of edges crossing plane on some z height void Slice::fillEdgeLayer(){ QList<Face*> currentLayer; Face* currentFace; HalfEdge* currentEdge; for(int i=0; i<this->triLayer.size(); i++){ currentLayer=*this->triLayer.at(i); //take first face from list if(currentLayer.size()>0){ while(currentLayer.size()>0){ currentFace=currentLayer.takeFirst(); currentEdge=currentFace->getEdgesCrossingPlane(this->layerHeight*i).at(0); //create list for firts edge loop this->edgeLayer.at(i)->append(new QList<HalfEdge*>); this->pointLayer.at(i)->append(new QList<QVector3D>); this->edgeLayer.at(i)->last()->append(currentEdge); //while all faces are processed do{ currentLayer.removeAt(currentLayer.indexOf(currentFace)); //take his twin currentEdge=currentEdge->getTwin(); currentFace=currentEdge->getFaces().at(0); //qDebug() << currentFace->getNeighbors().size(); if(currentFace->getEdgesCrossingPlane(this->layerHeight*i,currentEdge).size()!=1){ //qDebug() << "dupa" <<currentFace->getEdgesCrossingPlane(this->layerHeight*i,currentEdge).size(); } currentEdge=currentFace->getEdgesCrossingPlane(this->layerHeight*i,currentEdge).first(); this->edgeLayer.at(i)->last()->append(currentEdge); }while(currentLayer.contains(currentFace)); } } } }
void Curve::ReplaceSections(Vertex * startV, Vertex * endV, std::vector<HalfEdge *> & replaceList) { int i,j; int startInd, endInd; startInd = endInd = -1; for (i=0;i<helist.size(); ++i) { HalfEdge * he = helist[i]; if (he->source() == startV) { startInd = i; break; } } assert(startInd != -1); for (j=i; j<helist.size();++j) { HalfEdge * he = helist[j]; if (he->target() == endV) { endInd = j; break; } } assert(endInd != -1); ReplaceSections(startInd, endInd, replaceList); }
/** Return node no ix from triangle. * \param ix is either 0, 1 or 2. */ Node* getNode(size_t ix) { HalfEdge *he = m_he_; for(size_t i=0; i<ix; i++) { he = he->getNext(); } return he->getSourceNode(); }
Curve::Curve(std::list<Edge *> edges) { std::list<Edge *>::iterator eiter = edges.begin(); Edge * e = *eiter; HalfEdge * he = e->halfedge(0); Vertex * v = he->source(); BuildList(edges, v); }
bool Face::include_vertex(Vertex *v) { HalfEdge * he = m_halfedge; if(he->target () == v || he->source () == v || he->he_next ()->target () == v) return true; return false; }
void TriMesh::buildConnectivity() { // skip // Use the algorithm from the lecture to categorize the edges into inner, boundary or non-manifold // Set the twin edge appropriately to the category of the current edge // For each node take its leading halfedge and rewind (using getVtxRingPrev) until: // - We get the one that we started with (no need to do anything) // - We get NULL - then the previous choice should be used as the nodes leading halfedge // unskip std::vector<SortElement> helper = std::vector<SortElement>(); for(int i = 0; i < m_halfedges.size(); i++){ helper.push_back(m_halfedges[i]); } std::sort(helper.begin(), helper.end()); int i,j; //Loop through all edges for(j=0; j<helper.size(); j++){ //Find i so that i and i+1 are different edges for(i=j; i<helper.size()-1; i++){ if(helper[i].m_a != helper[i+1].m_a || helper[i].m_b != helper[i+1].m_b){ break; } } if(i==j){ helper[j].m_he->m_twin_ = NULL; // helper[j] points to a boundary edge } else if (i==j+1){ helper[i].m_he->m_twin_ = helper[j].m_he; helper[j].m_he->m_twin_ = helper[i].m_he; // connect the triangles of helper[i] and helper[j] } else{ std::cout << "Non-manifold mesh!" << std::endl; } j = i; } for (int i = 0; i < m_nodes.size(); i++){ HalfEdge* beginLead = m_nodes[i].getLeadingHalfEdge(); HalfEdge* tempLead = m_nodes[i].getLeadingHalfEdge(); while(true){ HalfEdge* rewindHe = tempLead->getVtxRingPrev(); if (rewindHe == NULL){ m_nodes[i].m_he_ = tempLead; break; } else if (rewindHe == beginLead) break; tempLead = rewindHe; } } }
Point Face::norm() { HalfEdge * he = m_halfedge; Point p1 = he->target ()->point () - he->source ()->point (); Point p2 = he->he_next ()->target ()->point () - he->target ()->point (); Point n = p1 ^ p2; n /= n.norm (); return n; }
void writePly(Interface& interface) { QFile file(saveToFileName); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); QVector<Face *> faces = interface.getFaces(); out << "ply" << "\n"; out << "format ascii 1.0" << "\n"; int vertex_count = interface.getVertices().size(); int faces_count = faces.size(); out << "element vertex " << vertex_count << "\n"; out << "property float x" << "\n"; out << "property float y" << "\n"; out << "element face " << faces_count << "\n"; out << "property list uchar int vertex_index" << "\n"; out << "end_header" << "\n"; QList<Vertex*> points = interface.getVertices().values(); for (int i = 0; i < points.size(); i++) { QPointF p = points[i]->getPoint(); qDebug() << "adicionando ponto: (" << p.x() << "," << p.y() << ")\n"; //out << i << " "; out << p.x() << " " << p.y() << "\n"; } for (int i = 0; i < faces.size(); i++) { HalfEdge* start = faces.at(i)->getOuterComp(); HalfEdge* aux = start; //out << i << " "; qDebug() << "### Face: " << i << "\n"; int vertex_per_face_counter = 0; QString tempStr; do { QTextStream tempStream(&tempStr); Vertex* vertex = aux->getOrigem(); int index = points.indexOf(vertex); tempStream << index << " "; aux = aux->getProx(); vertex_per_face_counter++; } while (aux != start); out << vertex_per_face_counter << " " << tempStr << "\n"; } }
HalfEdge* Face::MaxEdge() { HalfEdge* MaxEdge = OuterEdge; MaxEdge = OuterEdge->Next->Lenght() > MaxEdge->Lenght() ? OuterEdge->Next : MaxEdge; MaxEdge = OuterEdge->Prev->Lenght() > MaxEdge->Lenght() ? OuterEdge->Prev : MaxEdge; return MaxEdge; }
HalfEdge* Face::MinEdge() { HalfEdge* MinEdge = OuterEdge; MinEdge = OuterEdge->Next->Lenght() < MinEdge->Lenght() ? OuterEdge->Next : MinEdge; MinEdge = OuterEdge->Prev->Lenght() < MinEdge->Lenght() ? OuterEdge->Prev : MinEdge; return MinEdge; }
int Curve::CreateBoundaryLoop(Vertex * startV) { HalfEdge * he = startV->most_ccw_out_halfedge(); if (!he->edge()->boundary()) { he = startV->most_clw_out_halfedge(); assert(he->edge()->boundary()); } return CreateBoundaryLoop(he); }
bool MyObject::buildHalfEdges(THalfEdgeList& lst) { int pli, i; TPointPairHash m_pntmap; m_pntmap.reserve(150); // the pointer is the half edge already between these points for(pli = 0; pli < nPolys; ++pli) { MyPolygon *pol = poly[pli]; HalfEdge *he = nullptr, *lasthe = nullptr; for(i = 3; i >= 0; --i) { //he = new HalfEdge(pol, pol->vtx[i], he); HalfEdge *prevhe = he; he = m_alloc->m_hePool.allocate(); he->init(pol, pol->vtx[i], prevhe); lst.push_back(he); if (lasthe == nullptr) lasthe = he; if (pol->vtx[i]->he == nullptr) pol->vtx[i]->he = he; } lasthe->next = he; pol->he = he; for(i = 3; i >= 0; --i) { PointPair pp(he->point, he->next->point); TPointPairHash::iterator it = m_pntmap.find(pp); if (it == m_pntmap.end()) // its not there, add it m_pntmap.insert(make_pair(pp, he)); else { HalfEdge *she = it->second; M_ASSERT((she->next->point == he->point) && (he->next->point == she->point)); he->pair = she; she->pair = he; m_pntmap.erase(it); // no longer needed in the map } he = he->next; } // maximum size of m_pntmap is 134 } M_ASSERT(m_pntmap.empty()); return true; }
void TetrahedMesh::deconnect(vector<unsigned int> adjecentList, arma::Mat<double> v, unsigned int vIndex) { unsigned int vInd; Vertex temp; temp.setPosition(v); mVertices->push_back(temp); vInd = mVertices->size()-1; for (int j = 0; j < adjecentList.size(); j++) { vector<unsigned int> faceIndices = mTetraheds->at(adjecentList.at(j)).getFaceInd(); for (int i = 0; i< faceIndices.size();i++) { Face & face = mFaces->at(faceIndices[i]); HalfEdge* edge = &mHalfEdges->at(face.getEdgeInd()); Vertex & v1 = mVertices->at(edge->getVertexInd()); if(vecEquals(v1.getPosition(),v)) { //mFaces->at(faceIndices[i]).setOppositeFaceInd(-1); edge->setVertexInd(vInd); break; } edge = &mHalfEdges->at(edge->getNextInd()); Vertex & v2 = mVertices->at(edge->getVertexInd()); if(vecEquals(v2.getPosition(),v)) { //mFaces->at(faceIndices[i]).setOppositeFaceInd(-1); edge->setVertexInd(vInd); break; } edge = &mHalfEdges->at(edge->getNextInd()); Vertex & v3 = mVertices->at(edge->getVertexInd()); if(vecEquals(v3.getPosition(),v)) { edge->setVertexInd(vInd); break; } } } }
void Interface::addFace(QVector<QPointF> in) { Face *f = new Face(); HalfEdge *ant = NULL; HalfEdge *first, *twin, *temp; for(int i = 0; i < in.size(); i++) { HalfEdge *e = new HalfEdge(); if (i == 0) first = e; temp = findTwin(in[i],in[(i+1)%in.size()]); if (temp != NULL) e = temp; else map[qMakePair(in[i], in[(i+1)%in.size()])] = e; twin = e->getTwin(); if (twin == NULL) twin = findTwin(in[(i+1)%in.size()],in[i]); minX = MIN(minX, in[i].x()); maxX = MAX(maxX, in[i].x()); minY = MIN(minY, in[i].y()); maxY = MAX(maxY, in[i].y()); Vertex *v = addVertex(in[i]); v->setEdge(e); e->setOrigem(v); e->setFace(f); e->setAnt(ant); if (ant!= NULL) { ant->setProx(e); } e->setTwin(twin); if (twin!= NULL) { twin->setTwin(e); } ant = e; } first->setAnt(ant); ant->setProx(first); f->setOuterComp(first); faces.push_back(f); }
long DigraphL::getWeight(int v, int w) { if (v >= 0 && w >=0 && v < V && w < V) { HalfEdge* edge; edges[v]->rewind(); while (edges[v]->hasMoreElements()) { edge = edges[v]->getNext(); if (edge->getEndingVertexIndex() == w) return edge->getWeight(); } return INF; } else return INF; }
double Face::S() { HalfEdge* tmpHalfEdge = OuterEdge; double a = tmpHalfEdge->Lenght(); tmpHalfEdge = tmpHalfEdge->Next; double b = tmpHalfEdge->Lenght(); tmpHalfEdge = tmpHalfEdge->Next; double c = tmpHalfEdge->Lenght(); tmpHalfEdge = tmpHalfEdge->Next; return sqrt( (a + b + c)*(b + c - a)*(a + c - b)*(a + b - c) ); }
int Curve::TraceFeatureCurve(Mesh * mesh, HalfEdge * heStart) { helist.clear(); MeshUtility::MarkSharpEdges(mesh); HalfEdge * che = heStart; Edge * ce = che->edge(); if (!ce->sharp()) { std::cerr << "Error: the input halfedge is not a feature edge!" << std::endl; return 0; } helist.push_back(che); Vertex * startV = che->source(); Vertex * cv = che->target(); while (cv!=startV) { bool flag = false; for (VertexOutHalfedgeIterator vhe(mesh, cv); !vhe.end(); ++vhe) { HalfEdge * he = *vhe; if (he->edge()->sharp() && he->edge() != ce) { che = he; cv = che->target(); ce = che->edge(); flag = true; break; } } if (!flag) { std::cerr << "Cannot find a circle!" << std::endl; helist.clear(); return 0; } helist.push_back(che); if (che->target() == startV) { //succeed return helist.size(); } } return helist.size(); }
Face <T> :: Face ( const Container <Node3DCartesian <T> *, destructable> &nl, Container <HalfEdge <T> *> &hl ) { //Create Face from the list of nodes this->vertices_count = nl.size(); this->edge = NULL; //Nodes list contains some points if ( this->vertices_count > 2 ) { //Create first half edge HalfEdge <T> *h = new HalfEdge <T> ( nl [0], NULL, NULL, NULL ); //Create first edge HalfEdge <T> *h_start = h; hl.push_back ( h ); //Create other half edges HalfEdge <T> *h_old = h; //Process all vertices for ( unsigned int i = 1; i < this->vertices_count; i++, h_old = h ) { //Create new edge and set previous edge h = new HalfEdge <T> ( nl [i], h_old, NULL, NULL ); //Set next edge h_old->setNextEdge ( h ); //Set face for each edge h->setFace ( this ); //Add half edge to the list hl.push_back ( h ); } //Set previous edge of the first edge h_start->setPreviousEdge ( h ); //Set next edge for the last edge h->setNextEdge ( h_start ); //Set face for h start h_start->setFace ( this ); //Set start edge of the Face this->edge = h_start; } }