diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp index 6c81e9ef1ab2a2acee0a605480489dee4b6db14c..66f2a059ca7f8480e4ae19160ec3b6d95f86d5f2 100644 --- a/Geo/GModel.cpp +++ b/Geo/GModel.cpp @@ -38,6 +38,66 @@ std::vector<GModel*> GModel::list; int GModel::_current = -1; +static void recur_connect(MVertex *v, + std::multimap<MVertex*,MEdge> &v2e, + std::set<MEdge,Less_Edge> &group, + std::set<MVertex*> &touched) +{ + if (touched.find(v) != touched.end())return; + + touched.insert(v); + for (std::multimap <MVertex*,MEdge>::iterator it = v2e.lower_bound(v); + it != v2e.upper_bound(v) ; ++it){ + group.insert(it->second); + for (int i=0;i<it->second.getNumVertices();++i){ + recur_connect (it->second.getVertex(i),v2e,group,touched); + } + } + +} + +// starting form a list of elements, returns +// lists of lists that are all simply connected +static void recur_connect_e (const MEdge &e, + std::multimap<MEdge,MElement*,Less_Edge> &e2e, + std::set<MElement*> &group, + std::set<MEdge,Less_Edge> &touched){ + if (touched.find(e) != touched.end())return; + touched.insert(e); + for (std::multimap <MEdge,MElement*,Less_Edge>::iterator it = e2e.lower_bound(e); + it != e2e.upper_bound(e) ; ++it){ + group.insert(it->second); + for (int i=0;i<it->second->getNumEdges();++i){ + recur_connect_e (it->second->getEdge(i),e2e,group,touched); + } + } +} + + +static int connected_bounds (std::set<MEdge, Less_Edge> &edges, std::vector<std::vector<MEdge> > &boundaries) +{ + + std::multimap<MVertex*,MEdge> v2e; + for(std::set<MEdge, Less_Edge>::iterator it = edges.begin(); it != edges.end(); it++){ + for (int j=0;j<it->getNumVertices();j++){ + v2e.insert(std::make_pair(it->getVertex(j),*it)); + } + } + + while (!v2e.empty()){ + std::set<MEdge, Less_Edge> group; + std::set<MVertex*> touched; + recur_connect (v2e.begin()->first,v2e,group,touched); + std::vector<MEdge> temp; + temp.insert(temp.begin(), group.begin(), group.end()); + boundaries.push_back(temp); + for (std::set<MVertex*>::iterator it = touched.begin() ; it != touched.end();++it) + v2e.erase(*it); + } + + return boundaries.size(); +} + GModel::GModel(std::string name) : _name(name), _visible(1), _octree(0), _geo_internals(0), _occ_internals(0), _fm_internals(0), @@ -1105,7 +1165,7 @@ void GModel::createTopologyFromMesh() //check for closed faces createTopologyFromFaces(discFaces); - + double t2 = Cpu(); Msg::Info("Creating topology from mesh done (%g s)", t2-t1); @@ -1132,45 +1192,41 @@ void GModel::createTopologyFromFaces(std::vector<discreteFace*> &discFaces) //return if no boundary edges (torus, sphere, ...) if (map_edges.empty()) return; - + // create reverse map, for each face find set of MEdges that are // candidate for new discrete Edges std::map<int, std::vector<int> > face2Edges; while (!map_edges.empty()){ - - std::vector<MEdge> myEdges; + std::set<MEdge, Less_Edge> myEdges; + myEdges.clear(); std::vector<int> tagFaces = map_edges.begin()->second; - myEdges.push_back(map_edges.begin()->first); + myEdges.insert(map_edges.begin()->first); map_edges.erase(map_edges.begin()); std::map<MEdge, std::vector<int>, Less_Edge >::iterator itmap = map_edges.begin(); while (itmap != map_edges.end()){ std::vector<int> tagFaces2 = itmap->second; if (tagFaces2 == tagFaces){ - myEdges.push_back(itmap->first); + myEdges.insert(itmap->first); map_edges.erase(itmap++); } else itmap++; } - //printf("*** %d Edges that bound \n", myEdges.size()); - //for(std::vector<int>::iterator itFace = tagFaces.begin(); itFace != tagFaces.end(); itFace++) - // printf("face %d \n", *itFace); - // if the loaded mesh already contains discrete Edges, check if // the candidate discrete Edge does contain any of those; if not, // create discreteEdges and create a map face2Edges that associate // for each face the boundary discrete Edges - for (std::vector<discreteEdge*>::iterator itE = discEdges.begin(); - itE != discEdges.end(); itE++){ + for (std::vector<discreteEdge*>::iterator itE = discEdges.begin(); itE != discEdges.end(); itE++){ bool candidate = true; for (unsigned int i = 0; i < (*itE)->getNumMeshElements(); i++){ MEdge me = (*itE)->getMeshElement(i)->getEdge(0); - if (std::find(myEdges.begin(), myEdges.end(), me) == myEdges.end()){ + std::set<MEdge, Less_Edge >::iterator itset = myEdges.find(me); + if (itset == myEdges.end()){ candidate = false; break; } @@ -1180,11 +1236,10 @@ void GModel::createTopologyFromFaces(std::vector<discreteFace*> &discFaces) std::vector<int> tagEdges; tagEdges.push_back((*itE)->tag()); - //printf("Push back edge %d\n", (*itE)->tag()); for (unsigned int i = 0; i < (*itE)->getNumMeshElements(); i++){ MEdge me = (*itE)->getMeshElement(i)->getEdge(0); - std::vector<MEdge>::iterator itME = std::find(myEdges.begin(), myEdges.end(), me); - myEdges.erase(itME); + std::set<MEdge, Less_Edge >::iterator itset = myEdges.find(me); + myEdges.erase(itset); } for (std::vector<int>::iterator itFace = tagFaces.begin(); @@ -1201,44 +1256,12 @@ void GModel::createTopologyFromFaces(std::vector<discreteFace*> &discFaces) } } - - while (!myEdges.empty()) { - std::vector<MEdge> myLines; - myLines.clear(); - std::vector<MEdge>::iterator it = myEdges.begin(); - - MVertex *vB = (*it).getVertex(0); - MVertex *vE = (*it).getVertex(1); - myLines.push_back(*it); - myEdges.erase(it); - it++; - for (int i = 0; i < 2; i++) { - std::vector<MEdge>::iterator it= myEdges.begin(); - while (it != myEdges.end()){ - MVertex *v1 = (*it).getVertex(0); - MVertex *v2 = (*it).getVertex(1); - std::vector<MEdge>::iterator itp; - if (v1 == vE){ - myLines.push_back(*it); - myEdges.erase(it); - vE = v2; - i = -1; - } - else if (v2 == vE){ - myLines.push_back(*it); - myEdges.erase(it); - vE = v1; - i = -1; - } - else it++; - } - if (vB == vE) break; - if (myEdges.empty()) break; - MVertex *temp = vB; - vB = vE; - vE = temp; - } + std::vector<std::vector<MEdge> > boundaries; + double nbBounds = connected_bounds(myEdges, boundaries); + + for (int ib = 0; ib < nbBounds; ib++){ + std::vector<MEdge> myLines = boundaries[ib]; int numE = maxEdgeNum()+1; discreteEdge *e = new discreteEdge(this, numE, 0, 0); @@ -1259,18 +1282,16 @@ void GModel::createTopologyFromFaces(std::vector<discreteFace*> &discFaces) } e->mesh_vertices.insert(e->mesh_vertices.begin(), allV.begin(),allV.end()); - for (std::vector<int>::iterator itFace = tagFaces.begin(); - itFace != tagFaces.end(); itFace++) { + for (std::vector<int>::iterator itFace = tagFaces.begin(); itFace != tagFaces.end(); itFace++) { //delete new mesh vertices of edge from adjacent faces GFace *dFace = getFaceByTag(*itFace); - for (std::vector<MVertex*>::iterator itv = allV.begin(); - itv != allV.end(); itv++) { + for (std::vector<MVertex*>::iterator itv = allV.begin();itv != allV.end(); itv++) { std::vector<MVertex*>::iterator itve = std::find(dFace->mesh_vertices.begin(), dFace->mesh_vertices.end(), *itv); if (itve != dFace->mesh_vertices.end()) dFace->mesh_vertices.erase(itve); } - + //fill face2Edges with the new edge std::map<int, std::vector<int> >::iterator f2e = face2Edges.find(*itFace); if (f2e == face2Edges.end()){ @@ -1285,27 +1306,96 @@ void GModel::createTopologyFromFaces(std::vector<discreteFace*> &discFaces) } } - + } + if (map_edges.empty()) break; } // set boundary edges for each face - for (std::vector<discreteFace*>::iterator it = discFaces.begin(); - it != discFaces.end(); it++){ + for (std::vector<discreteFace*>::iterator it = discFaces.begin(); it != discFaces.end(); it++){ //printf("set boundary edge for face =%d \n", (*it)->tag()); std::map<int, std::vector<int> >::iterator ite = face2Edges.find((*it)->tag()); if (ite != face2Edges.end()){ - std::vector<int> myEdges = ite->second; - (*it)->setBoundEdges(myEdges); + std::vector<int> bcEdges = ite->second; + (*it)->setBoundEdges(bcEdges); } } // for each discreteEdge, create Topology - for (std::vector<discreteEdge*>::iterator it = discEdges.begin(); - it != discEdges.end(); it++){ + std::map<MVertex*, MVertex*, std::less<MVertex*> > old2new; + for (std::vector<discreteEdge*>::iterator it = discEdges.begin(); it != discEdges.end(); it++){ + double t1 = Cpu(); (*it)->createTopo(); - (*it)->parametrize(); + double t2 = Cpu(); + (*it)->parametrize(old2new); + double t3 = Cpu(); + } + + //we need to recreate lines, triangles and tets + //that contain those new MEdgeVertices + double t5 = Cpu(); + for (std::vector<discreteFace*>::iterator iFace = discFaces.begin(); iFace != discFaces.end(); iFace++){ + std::vector<MTriangle*> newTriangles; + std::vector<MQuadrangle*> newQuadrangles; + for (unsigned int i = 0; i < (*iFace)->getNumMeshElements(); ++i){ + MElement *e = (*iFace)->getMeshElement(i); + int N = e->getNumVertices(); + std::vector<MVertex *> v(N); + for(int j = 0; j < N; j++) v[j] = e->getVertex(j); + for (int j = 0; j < N; j++){ + std::map<MVertex*, MVertex*, std::less<MVertex*> >::iterator itmap = old2new.find(v[j]); + if (itmap != old2new.end()) { + MVertex *vNEW; + vNEW = itmap->second; + v[j]=vNEW; + } + } + if (N == 3) newTriangles.push_back(new MTriangle(v[0], v[1], v[2])); + else if ( N == 4) newQuadrangles.push_back(new MQuadrangle(v[0], v[1], v[2], v[3])); + + } + (*iFace)->deleteVertexArrays(); + (*iFace)->triangles.clear(); + (*iFace)->triangles = newTriangles; + (*iFace)->quadrangles.clear(); + (*iFace)->quadrangles = newQuadrangles; } + + for(GModel::riter iRegion = firstRegion(); iRegion != lastRegion(); iRegion++){ + std::vector<MTetrahedron*> newTetrahedra; + std::vector<MHexahedron*> newHexahedra; + std::vector<MPrism*> newPrisms; + std::vector<MPyramid*> newPyramids; + for (unsigned int i = 0; i < (*iRegion)->getNumMeshElements(); ++i){ + MElement *e = (*iRegion)->getMeshElement(i); + int N = e->getNumVertices(); + std::vector<MVertex *> v(N); + for(int j = 0; j < N; j++) v[j] = e->getVertex(j); + for (int j = 0; j < N; j++){ + std::map<MVertex*, MVertex*, std::less<MVertex*> >::iterator itmap = old2new.find(v[j]); + MVertex *vNEW; + if (itmap != old2new.end()) { + vNEW = itmap->second; + v[j]=vNEW; + } + } + if (N == 4) newTetrahedra.push_back(new MTetrahedron(v[0], v[1], v[2], v[3])); + else if (N == 5) newPyramids.push_back(new MPyramid(v[0], v[1], v[2], v[3], v[4])); + else if (N == 6) newPrisms.push_back(new MPrism(v[0], v[1], v[2], v[3], v[4], v[5])); + else if (N == 8) newHexahedra.push_back(new MHexahedron(v[0], v[1], v[2], v[3], + v[4], v[5], v[6], v[7])); + } + (*iRegion)->deleteVertexArrays(); + (*iRegion)->tetrahedra.clear(); + (*iRegion)->tetrahedra = newTetrahedra; + (*iRegion)->pyramids.clear(); + (*iRegion)->pyramids = newPyramids; + (*iRegion)->prisms.clear(); + (*iRegion)->prisms = newPrisms; + (*iRegion)->hexahedra.clear(); + (*iRegion)->hexahedra = newHexahedra; + } + } GModel *GModel::buildCutGModel(gLevelset *ls, bool cutElem) diff --git a/Geo/discreteEdge.cpp b/Geo/discreteEdge.cpp index baa8ee5e7cd6373341e61c7f6344a62a6055ea32..877cea98d94de044014ae7ee18b14ca7729c6039 100644 --- a/Geo/discreteEdge.cpp +++ b/Geo/discreteEdge.cpp @@ -18,6 +18,7 @@ #include "MHexahedron.h" #include "MPyramid.h" #include "Geo.h" +#include "OS.h" discreteEdge::discreteEdge(GModel *model, int num, GVertex *_v0, GVertex *_v1) : GEdge(model, num, _v0, _v1) @@ -242,19 +243,18 @@ void discreteEdge::setBoundVertices() +---------------+--------------+----------- ... ----------+ _pars[0]=0 _pars[1]=1 _pars[2]=2 _pars[N+1]=N+1 */ -void discreteEdge::parametrize() +void discreteEdge::parametrize(std::map<MVertex*, MVertex*, std::less<MVertex*> > &old2new) { for (unsigned int i = 0; i < lines.size() + 1; i++){ _pars.push_back(i); } //Replace MVertex by MedgeVertex - //we need to recreate lines, triangles and tets - //that contain those new MEdgeVertices - std::map<MVertex*, MVertex*> old2new; - - std::vector<MVertex*> newVertices; + + std::vector<MVertex* > newVertices; std::vector<MLine*> newLines; + + double t1 = Cpu(); MVertex *vL = getBeginVertex()->mesh_vertices[0]; int i = 0; @@ -282,98 +282,35 @@ void discreteEdge::parametrize() lines.clear(); lines = newLines; - for(std::list<GFace*>::iterator iFace = l_faces.begin(); iFace != l_faces.end(); ++iFace){ - std::vector<MTriangle*> newTriangles; - std::vector<MQuadrangle*> newQuadrangles; - for (unsigned int i = 0; i < (*iFace)->getNumMeshElements(); ++i){ - MElement *e = (*iFace)->getMeshElement(i); - int N = e->getNumVertices(); - std::vector<MVertex *> v(N); - for(int j = 0; j < N; j++){ - v[j] = e->getVertex(j); - } - for (int j = 0; j < N; j++){ - std::map<MVertex*, MVertex*>::iterator itmap = old2new.find(v[j]); - MVertex *vNEW; - if (itmap != old2new.end()) { - vNEW = itmap->second; - v[j]=vNEW; - } - } - if (N == 3) newTriangles.push_back(new MTriangle(v[0], v[1], v[2])); - else if ( N == 4) newQuadrangles.push_back(new MQuadrangle(v[0], v[1], v[2], v[3])); - - } - (*iFace)->deleteVertexArrays(); - (*iFace)->triangles.clear(); - (*iFace)->triangles = newTriangles; - (*iFace)->quadrangles.clear(); - (*iFace)->quadrangles = newQuadrangles; - } - - for(GModel::riter iRegion = model()->firstRegion(); - iRegion != model()->lastRegion(); iRegion++){ - std::vector<MTetrahedron*> newTetrahedra; - std::vector<MHexahedron*> newHexahedra; - std::vector<MPrism*> newPrisms; - std::vector<MPyramid*> newPyramids; - for (unsigned int i = 0; i < (*iRegion)->getNumMeshElements(); ++i){ - MElement *e = (*iRegion)->getMeshElement(i); - int N = e->getNumVertices(); - std::vector<MVertex *> v(N); - for(int j = 0; j < N; j++){ - v[j] = e->getVertex(j); - } - for (int j = 0; j < N; j++){ - std::map<MVertex*, MVertex*>::iterator itmap = old2new.find(v[j]); - MVertex *vNEW; - if (itmap != old2new.end()) { - vNEW = itmap->second; - v[j]=vNEW; - } - } - if (N == 4) newTetrahedra.push_back(new MTetrahedron(v[0], v[1], v[2], v[3])); - else if (N == 5) newPyramids.push_back(new MPyramid(v[0], v[1], v[2], v[3], v[4])); - else if (N == 6) newPrisms.push_back(new MPrism(v[0], v[1], v[2], v[3], v[4], v[5])); - else if (N == 8) newHexahedra.push_back(new MHexahedron(v[0], v[1], v[2], v[3], - v[4], v[5], v[6], v[7])); - } - (*iRegion)->deleteVertexArrays(); - (*iRegion)->tetrahedra.clear(); - (*iRegion)->tetrahedra = newTetrahedra; - (*iRegion)->pyramids.clear(); - (*iRegion)->pyramids = newPyramids; - (*iRegion)->prisms.clear(); - (*iRegion)->prisms = newPrisms; - (*iRegion)->hexahedra.clear(); - (*iRegion)->hexahedra = newHexahedra; - } - - computeNormals(); -} + computeNormals(); + } void discreteEdge::computeNormals () const { _normals.clear(); + for (int i= 0; i < mesh_vertices.size(); i++) _normals[mesh_vertices[i]] = SVector3(0.0,0.0,0.0); + _normals[getBeginVertex()->mesh_vertices[0]] = SVector3(0.0,0.0,0.0); + _normals[getBeginVertex()->mesh_vertices[0]] = SVector3(0.0,0.0,0.0); double J[3][3]; for(std::list<GFace*>::const_iterator iFace = l_faces.begin(); iFace != l_faces.end(); ++iFace){ for (unsigned int i = 0; i < (*iFace)->triangles.size(); ++i){ MTriangle *t = (*iFace)->triangles[i]; - t->getJacobian(0, 0, 0, J); - SVector3 d1(J[0][0], J[0][1], J[0][2]); - SVector3 d2(J[1][0], J[1][1], J[1][2]); - SVector3 n = crossprod(d1, d2); - n.normalize(); for (int j = 0; j < 3; j++){ - std::map<MVertex*, SVector3>::iterator itn = _normals.find(t->getVertex(j)); - if (itn == _normals.end())_normals[t->getVertex(j)] = n; - else itn->second += n; + std::map<MVertex*, SVector3, std::less<MVertex*> >::iterator itn = _normals.find(t->getVertex(j)); + if (itn != _normals.end()){ + t->getJacobian(0, 0, 0, J); + SVector3 d1(J[0][0], J[0][1], J[0][2]); + SVector3 d2(J[1][0], J[1][1], J[1][2]); + SVector3 n = crossprod(d1, d2); + n.normalize(); + _normals[t->getVertex(j)] += n; + } } } } - std::map<MVertex*,SVector3>::iterator itn = _normals.begin(); + std::map<MVertex*,SVector3, std::less<MVertex*> >::iterator itn = _normals.begin(); for ( ; itn != _normals.end(); ++itn){ itn->second.normalize(); } diff --git a/Geo/discreteEdge.h b/Geo/discreteEdge.h index ab8f5301b3f7c8c7481d8bb62d650b5b5f0b9004..63d8de1d9a6110e63dd228d8e82d4d264c3cebb6 100644 --- a/Geo/discreteEdge.h +++ b/Geo/discreteEdge.h @@ -15,7 +15,7 @@ class discreteEdge : public GEdge { std::vector<double> _pars; std::vector<int> _orientation; std::map<MVertex*,MLine*> boundv; - mutable std::map<MVertex*,SVector3> _normals; + mutable std::map<MVertex*,SVector3, std::less<MVertex*> > _normals; bool createdTopo; public: discreteEdge(GModel *model, int num, GVertex *_v0, GVertex *_v1); @@ -25,7 +25,7 @@ class discreteEdge : public GEdge { virtual GPoint point(double p) const; virtual SVector3 firstDer(double par) const; virtual Range<double> parBounds(int) const; - void parametrize(); + void parametrize(std::map<MVertex*, MVertex*, std::less<MVertex*> > &old2new); void orderMLines(); void setBoundVertices(); void createTopo(); diff --git a/benchmarks/stl/pelvis.geo b/benchmarks/stl/pelvis.geo index 0a3ac76140b1dd521923479b98b070705d406e30..534f8ecc7ee8de0917a8c96503dc430780cac771 100644 --- a/benchmarks/stl/pelvis.geo +++ b/benchmarks/stl/pelvis.geo @@ -4,7 +4,7 @@ Mesh.Algorithm3D = 4; //Frontal (4) Delaunay(1) Merge "pelvis.stl"; -Compound Surface(200)={1}; +Compound Surface(200)={1} Conformal; Surface Loop(300)={200}; Volume(301)={300};