diff --git a/Plugin/SimplePartition.cpp b/Plugin/SimplePartition.cpp index 9495e425e748ee4cc11f5e4a0196b4d3128ee55a..62988f6463c20d03a081abf66a72a9714ba68f36 100644 --- a/Plugin/SimplePartition.cpp +++ b/Plugin/SimplePartition.cpp @@ -5,7 +5,10 @@ #include "SimplePartition.h" #include "GModel.h" +#include "partitionFace.h" +#include "partitionEdge.h" #include "MElement.h" +#include "MLine.h" #include "MFace.h" #include "MEdge.h" #if defined(HAVE_MESH) @@ -57,34 +60,40 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) GModel *m = GModel::current(); SBoundingBox3d bbox = m->bounds(); double pmin = bbox.min()[direction], pmax = bbox.max()[direction]; + std::vector<double> pp(numSlices + 1); + for(int p = 0; p <= numSlices; p++) + pp[p] = pmin + p * (pmax - pmin) / numSlices; int dim = m->getDim(); std::vector<GEntity*> entities; m->getEntities(entities); - std::map<int, std::set<MFace, Less_Face> > bndFaces; - std::map<int, std::set<MEdge, Less_Edge> > bndEdges; + std::vector<std::set<MFace, Less_Face> > bndFaces(numSlices); + std::vector<std::set<MEdge, Less_Edge> > bndEdges(numSlices); + std::vector<std::set<MElement*> > cutElements(numSlices); for(unsigned int i = 0; i < entities.size(); i++){ GEntity *ge = entities[i]; if(ge->dim() != dim) continue; for(int j = 0; j < ge->getNumMeshElements(); j++){ MElement *e = ge->getMeshElement(j); - double val = pmax; + double valmin = pmax; + double valmax = pmin; bool bnd = false; for(int k = 0; k < e->getNumVertices(); k++){ MVertex *v = e->getVertex(k); - val = std::min(val, v->point()[direction]); + valmin = std::min(valmin, v->point()[direction]); + valmax = std::max(valmax, v->point()[direction]); if(v->onWhat() && v->onWhat()->dim() != dim) bnd = true; } for(int p = 0; p < numSlices; p++){ - double p1 = pmin + p * (pmax - pmin) / numSlices; - double p2 = pmin + (p + 1) * (pmax - pmin) / numSlices; - if(val >= p1 && val < p2){ + if(valmin >= pp[p] && valmin < pp[p + 1]){ e->setPartition(p + 1); if(bnd){ for(int k = 0; k < e->getNumEdges(); k++) - bndEdges[p + 1].insert(e->getEdge(k)); + bndEdges[p].insert(e->getEdge(k)); for(int k = 0; k < e->getNumFaces(); k++) - bndFaces[p + 1].insert(e->getFace(k)); + bndFaces[p].insert(e->getFace(k)); } + if(valmax >= pp[p + 1]) + cutElements[p].insert(e); break; } } @@ -94,6 +103,8 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) // partition lower dimension elements Msg::Info("Partitioning lower dimension elements"); + std::set<MFace, Less_Face> allLowerDimFaces; + std::set<MEdge, Less_Edge> allLowerDimEdges; for(unsigned int i = 0; i < entities.size(); i++){ GEntity *ge = entities[i]; if(ge->dim() == dim) continue; @@ -101,8 +112,9 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) MElement *e = ge->getMeshElement(j); if(e->getDim() == 2){ MFace f = e->getFace(0); + if(createBoundaries) allLowerDimFaces.insert(f); for(int p = 0; p < numSlices; p++){ - if(bndFaces[p + 1].find(f) != bndFaces[p + 1].end()){ + if(bndFaces[p].find(f) != bndFaces[p].end()){ e->setPartition(p + 1); break; } @@ -110,8 +122,9 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) } else if(e->getDim() == 1){ MEdge f = e->getEdge(0); + if(createBoundaries) allLowerDimEdges.insert(f); for(int p = 0; p < numSlices; p++){ - if(bndEdges[p + 1].find(f) != bndEdges[p + 1].end()){ + if(bndEdges[p].find(f) != bndEdges[p].end()){ e->setPartition(p + 1); break; } @@ -121,13 +134,9 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) } if(createBoundaries){ -#if defined(HAVE_MESH) Msg::Info("Creating partition boundaries"); +#if 0 && defined(HAVE_MESH) // correct & general, but too slow CreatePartitionBoundaries(m, false, false); -#else - Msg::Error("Creating partition boundaries requires the mesh module"); -#endif - // renumber partition boundaries using the natural slicing order Msg::Info("Renumbering partition boundaries"); std::vector<std::pair<double, GFace*> > parFaces; std::vector<std::pair<double, GEdge*> > parEdges; @@ -136,22 +145,22 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) GEntity *ge = entities[i]; if(ge->geomType() == GEntity::PartitionSurface || ge->geomType() == GEntity::PartitionCurve){ - double val = pmax; + double valmin = pmax; for(int j = 0; j < ge->getNumMeshElements(); j++){ MElement *e = ge->getMeshElement(j); for(int k = 0; k < e->getNumVertices(); k++){ MVertex *v = e->getVertex(k); - val = std::min(val, v->point()[direction]); + valmin = std::min(valmin, v->point()[direction]); } } if(ge->dim() == 2){ GFace *gf = (GFace*)ge; - parFaces.push_back(std::pair<double, GFace*>(val, gf)); + parFaces.push_back(std::pair<double, GFace*>(valmin, gf)); m->remove(gf); } else{ GEdge *gc = (GEdge*)ge; - parEdges.push_back(std::pair<double, GEdge*>(val, gc)); + parEdges.push_back(std::pair<double, GEdge*>(valmin, gc)); m->remove(gc); } } @@ -170,6 +179,87 @@ PView *GMSH_SimplePartitionPlugin::execute(PView *v) ge->setMeshMaster(-i-1); m->add(ge); } +#else + for(int p = 0; p < numSlices - 1; p++){ + std::vector<int> v2(2); + v2[0] = p + 1; + v2[1] = p + 2; + if(dim == 2){ + // create partition edge + partitionEdge *pe = new partitionEdge(m, -(p + 1), 0, 0, v2); + m->add(pe); + // compute boundary of cut surface elements + std::set<MEdge, Less_Edge> myBndEdges; + for(std::set<MElement*>::iterator it = cutElements[p].begin(); + it != cutElements[p].end(); it++){ + for(int i = 0; i < (*it)->getNumEdges(); i++){ + MEdge e = (*it)->getEdge(i); + if(myBndEdges.find(e) == myBndEdges.end()) + myBndEdges.insert(e); + else + myBndEdges.erase(e); + } + } + // keep edges whose vertices are all >= than the plane, but are not on a + // curve of the original mesh + for(std::set<MEdge, Less_Edge>::iterator it = myBndEdges.begin(); + it != myBndEdges.end(); it++){ + bool bnd = true; + for(int j = 0; j < it->getNumVertices(); j++){ + if(it->getVertex(j)->point()[direction] < pp[p + 1]){ + bnd = false; + break; + } + } + if(bnd){ + if(allLowerDimEdges.find(*it) == allLowerDimEdges.end()){ + pe->lines.push_back(new MLine(it->getVertex(0), it->getVertex(1))); + } + } + } + } + if(dim == 3){ + // create partition face + partitionFace *pf = new partitionFace(m, -(p + 1), v2); + m->add(pf); + // compute boundary of cut elements + std::set<MFace, Less_Face> myBndFaces; + for(std::set<MElement*>::iterator it = cutElements[p].begin(); + it != cutElements[p].end(); it++){ + for(int i = 0; i < (*it)->getNumFaces(); i++){ + MFace f = (*it)->getFace(i); + if(myBndFaces.find(f) == myBndFaces.end()) + myBndFaces.insert(f); + else + myBndFaces.erase(f); + } + } + // keep faces whose vertices are all >= than the plane, but are not on a + // surface of the original mesh + for(std::set<MFace, Less_Face>::iterator it = myBndFaces.begin(); + it != myBndFaces.end(); it++){ + bool bnd = true; + for(int j = 0; j < it->getNumVertices(); j++){ + if(it->getVertex(j)->point()[direction] < pp[p + 1]){ + bnd = false; + break; + } + } + if(bnd){ + if(allLowerDimFaces.find(*it) == allLowerDimFaces.end()){ + if (it->getNumVertices() == 3) + pf->triangles.push_back + (new MTriangle(it->getVertex(0), it->getVertex(1), it->getVertex(2))); + else + pf->quadrangles.push_back + (new MQuadrangle(it->getVertex(0), it->getVertex(1), + it->getVertex(2), it->getVertex(3))); + } + } + } + } + } +#endif } return v;