/** * @param newTriangleIndexes [out] Indexes of new triangles added to convex hull * @param removedTriangleIndexes [out] Indexes of removed triangles from convex hull * @return Returns index of point added. If point doesn't make part of convex, result is zero. */ template<class T> unsigned int ConvexHull3D<T>::addNewPoint(const Point3<T> &newPoint, std::vector<unsigned int> &newTriangleIndexes, std::vector<unsigned int> &removedTriangleIndexes) { std::map<long long, std::pair<unsigned int, unsigned int>> edges; constexpr int HALF_SIZE_INDEX = (sizeof(unsigned int) * 8) / 2; //deletes all triangles visible by the new point for(typename std::map<unsigned int, IndexedTriangle3D<T>>::iterator itTriangle=indexedTriangles.begin(); itTriangle!=indexedTriangles.end();) { const IndexedTriangle3D<T> indexedTriangle = itTriangle->second; const Vector3<T> &triangleNormal = indexedTriangle.computeNormal(points); const Point3<T> &point0 = points.find(indexedTriangle.getIndexes()[0])->second; const Vector3<T> &triangleToPoint = point0.vector(newPoint); if(triangleNormal.dotProduct(triangleToPoint) > 0.0) { for(int i=0; i<3; i++) { //each edge int index1 = indexedTriangle.getIndexes()[i]; int index2 = indexedTriangle.getIndexes()[(i+1)%3]; long long idEdge = (std::min(index1, index2) << HALF_SIZE_INDEX) | std::max(index1, index2); std::map<long long, std::pair<unsigned int, unsigned int>>::iterator itEdge = edges.find(idEdge); if(itEdge==edges.end()) { edges[idEdge] = std::make_pair(index1, index2); }else { edges.erase(itEdge); } } removedTriangleIndexes.push_back(itTriangle->first); removeTriangle(itTriangle++); }else { ++itTriangle; } } //adds the new triangles if(edges.size()>0) { newTriangleIndexes.reserve(edges.size()); unsigned int pointIndex = nextPointIndex++; points[pointIndex] = newPoint; for(std::map<long long, std::pair<unsigned int, unsigned int>>::iterator it = edges.begin(); it!=edges.end(); ++it) { unsigned int triangleIndex = addTriangle(IndexedTriangle3D<T>(it->second.first, it->second.second, pointIndex)); newTriangleIndexes.push_back(triangleIndex); } return pointIndex; } return 0; }
QWidget *WalkmeshManager::buildWalkmeshPage() { QWidget *ret = new QWidget(this); ListWidget *listWidget = new ListWidget(ret); listWidget->addAction(ListWidget::Add, tr("Ajouter triangle"), this, SLOT(addTriangle())); listWidget->addAction(ListWidget::Rem, tr("Supprimer triangle"), this, SLOT(removeTriangle())); idToolbar = listWidget->toolBar(); idList = listWidget->listWidget(); idVertices[0] = new VertexWidget(ret); idVertices[1] = new VertexWidget(ret); idVertices[2] = new VertexWidget(ret); idAccess[0] = new QSpinBox(ret); idAccess[1] = new QSpinBox(ret); idAccess[2] = new QSpinBox(ret); idAccess[0]->setRange(-32768, 32767); idAccess[1]->setRange(-32768, 32767); idAccess[2]->setRange(-32768, 32767); QHBoxLayout *accessLayout0 = new QHBoxLayout; accessLayout0->addWidget(new QLabel(tr("Triangle accessible via la ligne 1-2 :"))); accessLayout0->addWidget(idAccess[0]); QHBoxLayout *accessLayout1 = new QHBoxLayout; accessLayout1->addWidget(new QLabel(tr("Triangle accessible via la ligne 2-3 :"))); accessLayout1->addWidget(idAccess[1]); QHBoxLayout *accessLayout2 = new QHBoxLayout; accessLayout2->addWidget(new QLabel(tr("Triangle accessible via la ligne 3-1 :"))); accessLayout2->addWidget(idAccess[2]); QGridLayout *layout = new QGridLayout(ret); layout->addWidget(listWidget, 0, 0, 7, 1, Qt::AlignLeft); layout->addWidget(new QLabel(tr("Point 1 :")), 0, 1); layout->addWidget(idVertices[0], 0, 2); layout->addWidget(new QLabel(tr("Point 2 :")), 1, 1); layout->addWidget(idVertices[1], 1, 2); layout->addWidget(new QLabel(tr("Point 3 :")), 2, 1); layout->addWidget(idVertices[2], 2, 2); layout->addLayout(accessLayout0, 3, 1, 1, 2); layout->addLayout(accessLayout1, 4, 1, 1, 2); layout->addLayout(accessLayout2, 5, 1, 1, 2); layout->setRowStretch(6, 1); connect(idList, SIGNAL(currentRowChanged(int)), SLOT(setCurrentId(int))); connect(idVertices[0], SIGNAL(valuesChanged(Vertex_s)), SLOT(editIdTriangle(Vertex_s))); connect(idVertices[1], SIGNAL(valuesChanged(Vertex_s)), SLOT(editIdTriangle(Vertex_s))); connect(idVertices[2], SIGNAL(valuesChanged(Vertex_s)), SLOT(editIdTriangle(Vertex_s))); connect(idAccess[0], SIGNAL(valueChanged(int)), SLOT(editIdAccess(int))); connect(idAccess[1], SIGNAL(valueChanged(int)), SLOT(editIdAccess(int))); connect(idAccess[2], SIGNAL(valueChanged(int)), SLOT(editIdAccess(int))); return ret; }
void cMesh::clean() { int nbFaces = getFacesNumber(); for(int i=0 ; i < nbFaces; i++) { cTriangle * Triangle = getTriangle(i); if (Triangle->getEdgesNumber() < 3 && !Triangle->isTextured()) { //cout <<"remove triangle " << Triangle->getIdx() << " with " << Triangle->getEdgesNumber() << " edges" << endl; //cout <<"sommets = " << Triangle->getVertex(0) << " " << Triangle->getVertex(1) << " " << Triangle->getVertex(2) << endl; removeTriangle(*Triangle); nbFaces--; i--; } /*else if (!Triangle->isTextured()) cout << "triangle " << i << " nb edges = " << Triangle->getEdgesNumber() << " textured= " << Triangle->isTextured() << endl;*/ } //suppression des points n'appartenant à aucun triangle for(int aK=0; aK < getVertexNumber();++aK) { bool found = false; for(int i=0 ; i < nbFaces; i++) { int vertex1, vertex2, vertex3; getTriangle(i)->getVertexesIndexes(vertex1, vertex2, vertex3); if ((aK==vertex1) || (aK==vertex2) || (aK==vertex3)) { found = true; break; } } if (!found) //remove this point { mVertexes.erase(std::remove(mVertexes.begin(), mVertexes.end(), mVertexes[aK]), mVertexes.end()); for(int i=0 ; i < nbFaces; i++) { cTriangle * tri= getTriangle(i); int vertex1, vertex2, vertex3; tri->getVertexesIndexes(vertex1, vertex2, vertex3); if (vertex1>aK) tri->setVertexIndex(0, vertex1-1); if (vertex2>aK) tri->setVertexIndex(1, vertex2-1); if (vertex3>aK) tri->setVertexIndex(2, vertex3-1); } } } }
void Mesh::assertManifold() { std::map<Vertex*, std::vector<Triangle *> > triRing; // for each triangle for( std::vector<Triangle *>::iterator tit = triangles.begin(); tit != triangles.end(); ++tit ) { Triangle *t = *tit; for( size_t i=0; i<3; ++i ) triRing[ t->v[i] ].push_back( t ); } for( std::map<Vertex*, std::vector<Triangle *> >::iterator it = triRing.begin(); it != triRing.end(); ++it ) { Vertex *v = it->first; if( it->second.size() < 3 ) { printf( "degenerated vertex detected (referenced by less then 3 triangles) -> removed\n" ); // remove all triangles referencing v for( std::vector<Triangle *>::iterator tit = it->second.begin(); tit != it->second.end(); ++tit ) { Triangle *t = *tit; // remove triangle from triangleRings from all reference vertices for( size_t i =0;i<3; ++i ) if( t->v[i] != v ) { triRing[t->v[i]].erase( std::find( triRing[t->v[i]].begin(), triRing[t->v[i]].end(), t ) ); // TODO: check if new degenerate vertices are created } // remove the triangle removeTriangle( t ); } // remove v itsself removeVertex( v ); } } }