From 82ad0b39b964741a743f03a4bd1c488ae46ac4d1 Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Thu, 27 Aug 2009 21:42:29 +0000 Subject: [PATCH] rewrote gmsh2DMeshGenerator to make it thread-safe *** PLEASE TEST THAT THE 2D MESH GENERATORS BEHAVE EXACTLY AS BEFORE *** --- Mesh/meshGFace.cpp | 794 ++++++++++++++-------------------- Mesh/meshGFace.h | 6 - Mesh/meshGFaceTransfinite.cpp | 52 +++ 3 files changed, 370 insertions(+), 482 deletions(-) diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp index aec0afa95e..b959b082c9 100644 --- a/Mesh/meshGFace.cpp +++ b/Mesh/meshGFace.cpp @@ -31,59 +31,6 @@ #include "OS.h" #include "HighOrder.h" -void computeEdgeLoops(const GFace *gf, - std::vector<MVertex*> &all_mvertices, - std::vector<int> &indices) -{ - std::list<GEdge*> edges = gf->edges(); - std::list<int> ori = gf->orientations(); - std::list<GEdge*>::iterator it = edges.begin(); - std::list<int>::iterator ito = ori.begin(); - - indices.push_back(0); - GVertex *start = ((*ito) == 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); - GVertex *v_end = ((*ito) != 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); - all_mvertices.push_back(start->mesh_vertices[0]); - if (*ito == 1) - for (unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++) - all_mvertices.push_back((*it)->mesh_vertices[i]); - else - for (int i = (*it)->mesh_vertices.size() - 1; i >= 0; i--) - all_mvertices.push_back((*it)->mesh_vertices[i]); - - GVertex *v_start = start; - while(1){ - ++it; - ++ito; - if(v_end == start){ - indices.push_back(all_mvertices.size()); - if(it == edges.end ()) break; - start = ((*ito) == 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); - v_end = ((*ito) != 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); - v_start = start; - } - else{ - if(it == edges.end ()){ - Msg::Error("Something wrong in edge loop computation"); - return; - } - v_start = ((*ito) == 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); - if(v_start != v_end){ - Msg::Error("Something wrong in edge loop computation"); - return; - } - v_end = ((*ito) != 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); - } - all_mvertices.push_back(v_start->mesh_vertices[0]); - if(*ito == 1) - for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++) - all_mvertices.push_back((*it)->mesh_vertices[i]); - else - for (int i = (*it)->mesh_vertices.size()-1; i >= 0; i--) - all_mvertices.push_back((*it)->mesh_vertices[i]); - } -} - void fourthPoint(double *p1, double *p2, double *p3, double *p4) { double c[3]; @@ -107,24 +54,25 @@ static bool noseam(GFace *gf) while (it != edges.end()){ GEdge *ge = *it ; bool seam = ge->isSeam(gf); - if (seam) return false; + if(seam) return false; ++it; } return true; } -static void remeshUnrecoveredEdges(std::set<EdgeToRecover> &edgesNotRecovered, +static void remeshUnrecoveredEdges(std::map<MVertex*, BDS_Point*> &recoverMapInv, + std::set<EdgeToRecover> &edgesNotRecovered, std::list<GFace*> &facesToRemesh) { facesToRemesh.clear(); deMeshGFace dem; std::set<EdgeToRecover>::iterator itr = edgesNotRecovered.begin(); - for (; itr != edgesNotRecovered.end(); ++itr){ + for(; itr != edgesNotRecovered.end(); ++itr){ std::list<GFace*> l_faces = itr->ge->faces(); - // Un-mesh model faces adjacent to the model edge + // un-mesh model faces adjacent to the model edge for(std::list<GFace*>::iterator it = l_faces.begin(); it != l_faces.end(); ++it){ - if ((*it)->triangles.size() ||(*it)->quadrangles.size()){ + if((*it)->triangles.size() || (*it)->quadrangles.size()){ facesToRemesh.push_back(*it); dem(*it); } @@ -134,21 +82,22 @@ static void remeshUnrecoveredEdges(std::set<EdgeToRecover> &edgesNotRecovered, int p1 = itr->p1; int p2 = itr->p2; int N = itr->ge->lines.size(); - GVertex * g1 = itr->ge->getBeginVertex(); - GVertex * g2 = itr->ge->getEndVertex(); + GVertex *g1 = itr->ge->getBeginVertex(); + GVertex *g2 = itr->ge->getEndVertex(); Range<double> bb = itr->ge->parBounds(0); std::vector<MLine*> newLines; - for (int i = 0; i < N; i++){ + for(int i = 0; i < N; i++){ MVertex *v1 = itr->ge->lines[i]->getVertex(0); MVertex *v2 = itr->ge->lines[i]->getVertex(1); - if ((v1->getIndex() == p1 && v2->getIndex() == p2) || - (v1->getIndex() == p2 && v2->getIndex() == p1)){ + BDS_Point *pp1 = recoverMapInv[v1]; + BDS_Point *pp2 = recoverMapInv[v2]; + if((pp1->iD == p1 && pp2->iD == p2) || (pp1->iD == p2 && pp2->iD == p1)){ double t1; double lc1 = -1; - if (v1->onWhat() == g1) t1 = bb.low(); - else if (v1->onWhat() == g2) t1 = bb.high(); + if(v1->onWhat() == g1) t1 = bb.low(); + else if(v1->onWhat() == g2) t1 = bb.high(); else { MEdgeVertex *ev1 = (MEdgeVertex*)v1; lc1 = ev1->getLc(); @@ -156,8 +105,8 @@ static void remeshUnrecoveredEdges(std::set<EdgeToRecover> &edgesNotRecovered, } double t2; double lc2 = -1; - if (v2->onWhat() == g1) t2 = bb.low(); - else if (v2->onWhat() == g2) t2 = bb.high(); + if(v2->onWhat() == g1) t2 = bb.low(); + else if(v2->onWhat() == g2) t2 = bb.high(); else { MEdgeVertex *ev2 = (MEdgeVertex*)v2; lc2 = ev2->getLc(); @@ -165,14 +114,14 @@ static void remeshUnrecoveredEdges(std::set<EdgeToRecover> &edgesNotRecovered, } // periodic - if (v1->onWhat() == g1 && v1->onWhat() == g2) + if(v1->onWhat() == g1 && v1->onWhat() == g2) t1 = fabs(t2-bb.low()) < fabs(t2-bb.high()) ? bb.low() : bb.high(); - if (v2->onWhat() == g1 && v2->onWhat() == g2) + if(v2->onWhat() == g1 && v2->onWhat() == g2) t2 = fabs(t1-bb.low()) < fabs(t1-bb.high()) ? bb.low() : bb.high(); - if (lc1 == -1) + if(lc1 == -1) lc1 = BGM_MeshSize(v1->onWhat(), 0, 0, v1->x(), v1->y(), v1->z()); - if (lc2 == -1) + if(lc2 == -1) lc2 = BGM_MeshSize(v2->onWhat(), 0, 0, v2->x(), v2->y(), v2->z()); // should be better, i.e. equidistant double t = 0.5 * (t2 + t1); @@ -190,7 +139,7 @@ static void remeshUnrecoveredEdges(std::set<EdgeToRecover> &edgesNotRecovered, itr->ge->lines = newLines; itr->ge->mesh_vertices.clear(); N = itr->ge->lines.size(); - for (int i = 1; i < N; i++){ + for(int i = 1; i < N; i++){ itr->ge->mesh_vertices.push_back(itr->ge->lines[i]->getVertex(0)); } } @@ -223,44 +172,49 @@ void computeElementShapes(GFace *gf, double &worst, double &avg, double &best, avg /= nT; } -static bool recover_medge(BDS_Mesh *m, GEdge *ge, std::set<EdgeToRecover> *e2r, +static bool recover_medge(BDS_Mesh *m, GEdge *ge, + std::map<MVertex*, BDS_Point*> &recoverMapInv, + std::set<EdgeToRecover> *e2r, std::set<EdgeToRecover> *not_recovered, int pass_) { BDS_GeomEntity *g = 0; - if (pass_ == 2){ - m->add_geom (ge->tag(), 1); - g = m->get_geom(ge->tag(),1); + if(pass_ == 2){ + m->add_geom(ge->tag(), 1); + g = m->get_geom(ge->tag(), 1); } - for (unsigned int i = 0; i < ge->lines.size(); i++){ + for(unsigned int i = 0; i < ge->lines.size(); i++){ MVertex *vstart = ge->lines[i]->getVertex(0); - MVertex *vend = ge->lines[i]->getVertex(1); - if (pass_ == 1) e2r->insert(EdgeToRecover(vstart->getIndex(), vend->getIndex(), ge)); + MVertex *vend = ge->lines[i]->getVertex(1); + BDS_Point *pstart = recoverMapInv[vstart]; + BDS_Point *pend = recoverMapInv[vend]; + if(pass_ == 1) + e2r->insert(EdgeToRecover(pstart->iD, pend->iD, ge)); else{ - BDS_Edge *e = m->recover_edge(vstart->getIndex(), vend->getIndex(), e2r, not_recovered); - if (e) e->g = g; - else { - // Msg::Error("Unable to recover an edge %g %g && %g %g (%d/%d)", - // vstart->x(), vstart->y(), vend->x(), vend->y(), i, - // ge->mesh_vertices.size()); - // return false; - } + BDS_Edge *e = m->recover_edge(pstart->iD, pend->iD, e2r, not_recovered); + if(e) e->g = g; + // else { + // Msg::Error("Unable to recover an edge %g %g && %g %g (%d/%d)", + // vstart->x(), vstart->y(), vend->x(), vend->y(), i, + // ge->mesh_vertices.size()); + // return false; + // } } } - if (pass_ == 2 && ge->getBeginVertex()){ + if(pass_ == 2 && ge->getBeginVertex()){ MVertex *vstart = *(ge->getBeginVertex()->mesh_vertices.begin()); MVertex *vend = *(ge->getEndVertex()->mesh_vertices.begin()); - BDS_Point *pstart = m->find_point(vstart->getIndex()); - BDS_Point *pend = m->find_point(vend->getIndex()); + BDS_Point *pstart = recoverMapInv[vstart]; + BDS_Point *pend = recoverMapInv[vend]; if(!pstart->g){ - m->add_geom (vstart->getIndex(), 0); - BDS_GeomEntity *g0 = m->get_geom(vstart->getIndex(), 0); + m->add_geom(pstart->iD, 0); + BDS_GeomEntity *g0 = m->get_geom(pstart->iD, 0); pstart->g = g0; } if(!pend->g){ - m->add_geom (vend->getIndex(), 0); - BDS_GeomEntity *g0 = m->get_geom(vend->getIndex(), 0); + m->add_geom(pend->iD, 0); + BDS_GeomEntity *g0 = m->get_geom(pend->iD, 0); pend->g = g0; } } @@ -268,151 +222,41 @@ static bool recover_medge(BDS_Mesh *m, GEdge *ge, std::set<EdgeToRecover> *e2r, return true; } -static bool recover_medge_old(BDS_Mesh *m, GEdge *ge, std::set<EdgeToRecover> *e2r, - std::set<EdgeToRecover> *not_recovered, int pass_) -{ - BDS_GeomEntity *g = 0; - if (pass_ == 2){ - m->add_geom (ge->tag(), 1); - g = m->get_geom(ge->tag(),1); - } - - if(ge->mesh_vertices.size() == 0){ - MVertex *vstart = *(ge->getBeginVertex()->mesh_vertices.begin()); - MVertex *vend = *(ge->getEndVertex()->mesh_vertices.begin()); - if(pass_ == 1){ - e2r->insert(EdgeToRecover(vstart->getIndex(), vend->getIndex(), ge)); - return true; - } - else{ - BDS_Point *pstart = m->find_point(vstart->getIndex()); - BDS_Point *pend = m->find_point(vend->getIndex()); - if(!pstart->g){ - m->add_geom (vstart->getIndex(), 0); - BDS_GeomEntity *g0 = m->get_geom(vstart->getIndex(), 0); - pstart->g = g0; - } - if(!pend->g){ - m->add_geom(vend->getIndex(), 0); - BDS_GeomEntity *g0 = m->get_geom(vend->getIndex(), 0); - pend->g = g0; - } - BDS_Edge * e = m->recover_edge(vstart->getIndex(), vend->getIndex(), e2r, not_recovered); - if (e) e->g = g; - else { - // Msg::Error("The unrecoverable edge is on model edge %d", ge->tag()); - return false; - } - return true; - } - } - - BDS_Edge *e; - MVertex *vstart = *(ge->getBeginVertex()->mesh_vertices.begin()); - MVertex *vend = *(ge->mesh_vertices.begin()); - - if (pass_ == 1) e2r->insert(EdgeToRecover(vstart->getIndex(), vend->getIndex(), ge)); - else{ - BDS_Point *pstart = m->find_point(vstart->getIndex()); - if(!pstart->g){ - m->add_geom (vstart->getIndex(), 0); - BDS_GeomEntity *g0 = m->get_geom(vstart->getIndex(), 0); - pstart->g = g0; - } - e = m->recover_edge(vstart->getIndex(), vend->getIndex(), e2r, not_recovered); - if (e) e->g = g; - else { - // Msg::Error("The unrecoverable edge is on model edge %d", ge->tag()); - // return false; - } - } - - for (unsigned int i = 1; i < ge->mesh_vertices.size(); i++){ - vstart = ge->mesh_vertices[i - 1]; - vend = ge->mesh_vertices[i]; - if (pass_ == 1) e2r->insert(EdgeToRecover(vstart->getIndex(), vend->getIndex(), ge)); - else{ - e = m->recover_edge(vstart->getIndex(), vend->getIndex(), e2r, not_recovered); - if (e) e->g = g; - else { - // Msg::Error("Unable to recover an edge %g %g && %g %g (%d/%d)", - // vstart->x(), vstart->y(), vend->x(), vend->y(), i, - // ge->mesh_vertices.size()); - // return false; - } - } - } - vstart = vend; - vend = *(ge->getEndVertex()->mesh_vertices.begin()); - if (pass_ == 1) e2r->insert(EdgeToRecover(vstart->getIndex(), vend->getIndex(), ge)); - else{ - e = m->recover_edge(vstart->getIndex(), vend->getIndex(), e2r, not_recovered); - if (e)e->g = g; - else { - // Msg::Error("Unable to recover an edge %g %g && %g %g (%d/%d)", - // vstart->x(), vstart->y(), vend->x(), vend->y(), - // ge->mesh_vertices.size(), ge->mesh_vertices.size()); - // return false; - } - BDS_Point *pend = m->find_point(vend->getIndex()); - if(!pend->g){ - m->add_geom (vend->getIndex(), 0); - BDS_GeomEntity *g0 = m->get_geom(vend->getIndex(), 0); - pend->g = g0; - } - } - return true; -} - - // Builds An initial triangular mesh that respects the boundaries of // the domain, including embedded points and surfaces -// FIXME: to make the algorithm thread-safe, we need to change the way -// we renumber the boundary vertices (and the associated u/v reparam): -// using setIndex leads to unpredicatbel results if meshing -// concurrently two surfaces that share a common edge! - static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, - bool repairSelfIntersecting1dMesh, bool debug = true) + bool repairSelfIntersecting1dMesh, + bool debug = true) { - BDS_GeomEntity CLASS_F (1, 2); - typedef std::set<MVertex*> v_container; - v_container all_vertices; - std::map<int, MVertex*>numbered_vertices; + BDS_GeomEntity CLASS_F(1, 2); + std::map<BDS_Point*, MVertex*> recoverMap; + std::map<MVertex*, BDS_Point*> recoverMapInv; std::list<GEdge*> edges = gf->edges(); - // here, we will replace edges by their compounds - if (gf->geomType() == GEntity::CompoundSurface){ - //printf("replace edges by compound lines \n"); + // replace edges by their compounds + if(gf->geomType() == GEntity::CompoundSurface){ std::set<GEdge*> mySet; std::list<GEdge*>::iterator it = edges.begin(); while(it != edges.end()){ - if ((*it)->getCompound()){ + if((*it)->getCompound()) mySet.insert((*it)->getCompound()); - //printf("compound edge %d found in edge %d\n",(*it)->getCompound()->tag(), (*it)->tag()); - } else mySet.insert(*it); ++it; } - //printf("replacing %d edges by %d in the GFaceCompound %d\n",edges.size(),mySet.size(),gf->tag()); edges.clear(); edges.insert(edges.begin(), mySet.begin(), mySet.end()); } - - - std::list<GEdge*> emb_edges = gf->embeddedEdges(); - std::list<GVertex*> emb_vertx = gf->embeddedVertices(); - std::list<GEdge*>::iterator it = edges.begin(); - std::list<GVertex*>::iterator itvx = emb_vertx.begin(); // build a set with all points of the boundaries - it = edges.begin(); + std::set<MVertex*> all_vertices; + + std::list<GEdge*>::iterator it = edges.begin(); while(it != edges.end()){ - if ((*it)->isSeam(gf)) return false; + if((*it)->isSeam(gf)) return false; if(!(*it)->isMeshDegenerated()){ - for (unsigned int i = 0; i< (*it)->lines.size(); i++){ + for(unsigned int i = 0; i< (*it)->lines.size(); i++){ all_vertices.insert((*it)->lines[i]->getVertex(0)); all_vertices.insert((*it)->lines[i]->getVertex(1)); } @@ -420,6 +264,7 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, ++it; } + std::list<GEdge*> emb_edges = gf->embeddedEdges(); it = emb_edges.begin(); while(it != emb_edges.end()){ if(!(*it)->isMeshDegenerated()){ @@ -434,13 +279,15 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, } // add embedded vertices + std::list<GVertex*> emb_vertx = gf->embeddedVertices(); + std::list<GVertex*>::iterator itvx = emb_vertx.begin(); while(itvx != emb_vertx.end()){ all_vertices.insert((*itvx)->mesh_vertices.begin(), - (*itvx)->mesh_vertices.end() ); + (*itvx)->mesh_vertices.end()); ++itvx; } - if (all_vertices.size() < 3){ + if(all_vertices.size() < 3){ Msg::Warning("Mesh Generation of Model Face %d Skipped: " "Only %d Mesh Vertices on The Contours", gf->tag(), all_vertices.size()); @@ -448,136 +295,116 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, return true; } - double *U_ = new double[all_vertices.size()]; - double *V_ = new double[all_vertices.size()]; - - v_container::iterator itv = all_vertices.begin(); + // Buid a BDS_Mesh structure that is convenient for doing the actual + // meshing procedure + BDS_Mesh *m = new BDS_Mesh; + m->scalingU = 1; + m->scalingV = 1; - int count = 0; + std::vector<BDS_Point*> points(all_vertices.size()); + std::vector<MVertex*> indexed_vertices(all_vertices.size()); SBoundingBox3d bbox; - while(itv != all_vertices.end()){ - MVertex *here = *itv; + int count = 0; + for(std::set<MVertex*>::iterator it = all_vertices.begin(); + it != all_vertices.end(); it++){ + MVertex *here = *it; + GEntity *ge = here->onWhat(); SPoint2 param; reparamMeshVertexOnFace(here, gf, param); - U_[count] = param[0]; - V_[count] = param[1]; - //printf("-->> meshGFace : %g %g -> u,v = %g %g\n",here->x(),here->y(), param.x(),param.y() ); - (*itv)->setIndex(count); - numbered_vertices[(*itv)->getIndex()] = *itv; - bbox += SPoint3(param.x(), param.y(), 0); + BDS_Point *pp = m->add_point(count, param[0], param[1], gf); + m->add_geom(ge->tag(), ge->dim()); + BDS_GeomEntity *g = m->get_geom(ge->tag(), ge->dim()); + pp->g = g; + recoverMap[pp] = here; + recoverMapInv[here] = pp; + points[count] = pp; + bbox += SPoint3(param[0], param[1], 0); count++; - ++itv; } + all_vertices.clear(); - // compute the bounding box in parametric space. I do not have - // SBoundingBox, so I use a 3D one... At the same time, number the - // vertices locally. - SVector3 dd (bbox.max(), bbox.min()); + // compute the bounding box in parametric space + SVector3 dd(bbox.max(), bbox.min()); double LC2D = norm(dd); - // Buid a BDS_Mesh structure that is convenient for doing the actual - // meshing procedure - BDS_Mesh *m = new BDS_Mesh; - m->scalingU = 1; - m->scalingV = 1; - - - // Use a divide & conquer type algorithm to create a triangulation. + // use a divide & conquer type algorithm to create a triangulation. // We add to the triangulation a box with 4 points that encloses the // domain. { - - DocRecord doc(all_vertices.size() + 4); - itv = all_vertices.begin(); - int j = 0; - while(itv != all_vertices.end()){ - MVertex *here = *itv; - double XX = CTX::instance()->mesh.randFactor * LC2D * (double)rand() / (double)RAND_MAX; - double YY = CTX::instance()->mesh.randFactor * LC2D * (double)rand() / (double)RAND_MAX; - doc.points[j].where.h = U_[j] + XX; - doc.points[j].where.v = V_[j] + YY; - doc.points[j].adjacent = NULL; - doc.points[j].data = here; - j++; - ++itv; + DocRecord doc(points.size() + 4); + for(unsigned int i = 0; i < points.size(); i++){ + double XX = CTX::instance()->mesh.randFactor * LC2D * (double)rand() / + (double)RAND_MAX; + double YY = CTX::instance()->mesh.randFactor * LC2D * (double)rand() / + (double)RAND_MAX; + doc.points[i].where.h = points[i]->u + XX; + doc.points[i].where.v = points[i]->v + YY; + doc.points[i].data = points[i]; + doc.points[i].adjacent = NULL; } - // Increase the size of the bounding box + // increase the size of the bounding box bbox *= 2.5; + // add 4 points than encloses the domain (use negative number to - // distinguish thos fake vertices) - MVertex *bb[4]; - bb[0] = new MVertex(bbox.min().x(), bbox.min().y(), 0, gf, -1); - bb[1] = new MVertex(bbox.min().x(), bbox.max().y(), 0, gf, -2); - bb[2] = new MVertex(bbox.max().x(), bbox.min().y(), 0, gf, -3); - bb[3] = new MVertex(bbox.max().x(), bbox.max().y(), 0, gf, -4); - + // distinguish those fake vertices) + double bb[4][2] = {{bbox.min().x(), bbox.min().y()}, + {bbox.min().x(), bbox.max().y()}, + {bbox.max().x(), bbox.min().y()}, + {bbox.max().x(), bbox.max().y()}}; for(int ip = 0; ip < 4; ip++){ - doc.points[all_vertices.size() + ip].where.h = bb[ip]->x(); - doc.points[all_vertices.size() + ip].where.v = bb[ip]->y(); - doc.points[all_vertices.size() + ip].adjacent = 0; - doc.points[all_vertices.size() + ip].data = bb[ip]; + BDS_Point *pp = m->add_point(-ip - 1, bb[ip][0], bb[ip][1], gf); + m->add_geom(gf->tag(), 2); + BDS_GeomEntity *g = m->get_geom(gf->tag(), 2); + pp->g = g; + doc.points[points.size() + ip].where.h = bb[ip][0]; + doc.points[points.size() + ip].where.v = bb[ip][1]; + doc.points[points.size() + ip].adjacent = 0; + doc.points[points.size() + ip].data = pp; } - // Use "fast" inhouse recursive algo to generate the triangulation + // Use "fast" inhouse recursive algo to generate the triangulation. // At this stage the triangulation is not what we need // -) It does not necessary recover the boundaries // -) It contains triangles outside the domain (the first edge // loop is the outer one) - Msg::Debug("Meshing of the convex hull (%d points)", all_vertices.size()); + Msg::Debug("Meshing of the convex hull (%d points)", points.size()); doc.MakeMeshWithPoints(); - Msg::Debug("Meshing of the convex hull (%d points) done", all_vertices.size()); - - for(int i = 0; i < doc.numPoints; i++){ - MVertex *here = (MVertex *)doc.points[i].data; - int num = here->getIndex(); - double U, V; - if(num < 0){ // fake bbox points - U = bb[-1 - num]->x(); - V = bb[-1 - num]->y(); - } - else{ - U = U_[num]; - V = V_[num]; - } - m->add_point(num, U, V, gf); - } - + Msg::Debug("Meshing of the convex hull (%d points) done", points.size()); for(int i = 0; i < doc.numTriangles; i++) { - MVertex *V1 = (MVertex*)doc.points[doc.triangles[i].a].data; - MVertex *V2 = (MVertex*)doc.points[doc.triangles[i].b].data; - MVertex *V3 = (MVertex*)doc.points[doc.triangles[i].c].data; - m->add_triangle(V1->getIndex(), V2->getIndex(), V3->getIndex()); + BDS_Point *p1 = (BDS_Point*)doc.points[doc.triangles[i].a].data; + BDS_Point *p2 = (BDS_Point*)doc.points[doc.triangles[i].b].data; + BDS_Point *p3 = (BDS_Point*)doc.points[doc.triangles[i].c].data; + m->add_triangle(p1->iD, p2->iD, p3->iD); } - // Recover the boundary edges and compute characteristic lenghts - // using mesh edge spacing - if( debug && RECUR_ITER == 0){ + if(debug && RECUR_ITER == 0){ char name[245]; sprintf(name, "surface%d-initial-real.pos", gf->tag()); outputScalarField(m->triangles, name, 0); sprintf(name, "surface%d-initial-param.pos", gf->tag()); outputScalarField(m->triangles, name, 1); } - + + // Recover the boundary edges and compute characteristic lenghts + // using mesh edge spacing. If two of these edges intersect, then + // the 1D mesh have to be densified Msg::Debug("Recovering %d model Edges", edges.size()); - - // build a structure with all mesh edges that have to be - // recovered. If two of these edges intersect, then the 1D mesh have - // to be densified std::set<EdgeToRecover> edgesToRecover; std::set<EdgeToRecover> edgesNotRecovered; it = edges.begin(); while(it != edges.end()){ if(!(*it)->isMeshDegenerated()) - recover_medge(m, *it, &edgesToRecover, &edgesNotRecovered, 1); + recover_medge + (m, *it, recoverMapInv, &edgesToRecover, &edgesNotRecovered, 1); ++it; } it = emb_edges.begin(); while(it != emb_edges.end()){ if(!(*it)->isMeshDegenerated()) - recover_medge(m, *it, &edgesToRecover, &edgesNotRecovered, 1); + recover_medge + (m, *it, recoverMapInv, &edgesToRecover, &edgesNotRecovered, 1); ++it; } @@ -587,40 +414,42 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, it = edges.begin(); while(it != edges.end()){ if(!(*it)->isMeshDegenerated()){ - recover_medge(m, *it, &edgesToRecover, &edgesNotRecovered, 2); + recover_medge + (m, *it, recoverMapInv, &edgesToRecover, &edgesNotRecovered, 2); } ++it; } - if (edgesNotRecovered.size()){ + if(edgesNotRecovered.size()){ std::ostringstream sstream; - for (std::set<EdgeToRecover>::iterator itr = edgesNotRecovered.begin(); + for(std::set<EdgeToRecover>::iterator itr = edgesNotRecovered.begin(); itr != edgesNotRecovered.end(); ++itr) sstream << " " << itr->ge->tag(); Msg::Warning(":-( There are %d intersections in the 1D mesh (curves%s)", edgesNotRecovered.size(), sstream.str().c_str()); Msg::Warning("8-| Gmsh splits those edges and tries again"); - if (debug){ + if(debug){ char name[245]; - sprintf(name, "surface%d-not_yet_recovered-real-%d.msh", gf->tag(),RECUR_ITER); + sprintf(name, "surface%d-not_yet_recovered-real-%d.msh", gf->tag(), + RECUR_ITER); gf->model()->writeMSH(name); } std::list<GFace *> facesToRemesh; - if (repairSelfIntersecting1dMesh) - remeshUnrecoveredEdges(edgesNotRecovered, facesToRemesh); + if(repairSelfIntersecting1dMesh) + remeshUnrecoveredEdges(recoverMapInv, edgesNotRecovered, facesToRemesh); else{ std::set<EdgeToRecover>::iterator itr = edgesNotRecovered.begin(); - int *_error = new int[3*edgesNotRecovered.size()]; + int *_error = new int[3 * edgesNotRecovered.size()]; int I = 0; - for (; itr != edgesNotRecovered.end(); ++itr){ + for(; itr != edgesNotRecovered.end(); ++itr){ int p1 = itr->p1; int p2 = itr->p2; int tag = itr->ge->tag(); - _error[3*I+0] = p1; - _error[3*I+1] = p2; - _error[3*I+2] = tag; + _error[3 * I + 0] = p1; + _error[3 * I + 1] = p2; + _error[3 * I + 2] = tag; I++; } throw _error; @@ -628,20 +457,20 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, // delete the mesh delete m; - delete [] U_; - delete [] V_; - if (RECUR_ITER < 10 && facesToRemesh.size() == 0) - return gmsh2DMeshGenerator(gf, RECUR_ITER+1, repairSelfIntersecting1dMesh, debug); + if(RECUR_ITER < 10 && facesToRemesh.size() == 0) + return gmsh2DMeshGenerator + (gf, RECUR_ITER + 1, repairSelfIntersecting1dMesh, debug); return false; } if(RECUR_ITER > 0) - Msg::Warning(":-) Gmsh was able to recover all edges after %d iterations", RECUR_ITER); + Msg::Warning(":-) Gmsh was able to recover all edges after %d iterations", + RECUR_ITER); Msg::Debug("Boundary Edges recovered for surface %d", gf->tag()); - // Look for an edge that is on the boundary for which one of the two - // neighbors has a negative number node. The other triangle is + // Look for an edge that is on the boundary for which one of the + // two neighbors has a negative number node. The other triangle is // inside the domain and, because all edges were recovered, // triangles inside the domain can be recovered using a simple // recursive algorithm @@ -652,11 +481,11 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, if(e->g && e->numfaces() == 2){ BDS_Point *oface[2]; e->oppositeof(oface); - if (oface[0]->iD < 0){ + if(oface[0]->iD < 0){ recur_tag(e->faces(1), &CLASS_F); break; } - else if (oface[1]->iD < 0){ + else if(oface[1]->iD < 0){ recur_tag(e->faces(0), &CLASS_F); break; } @@ -668,37 +497,39 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, it = emb_edges.begin(); while(it != emb_edges.end()){ if(!(*it)->isMeshDegenerated()) - recover_medge(m, *it, &edgesToRecover, &edgesNotRecovered, 2); + recover_medge + (m, *it, recoverMapInv, &edgesToRecover, &edgesNotRecovered, 2); ++it; } + // compute characteristic lengths at vertices - Msg::Debug("Computing mesh size field at mesh vertices %d", edgesToRecover.size()); + Msg::Debug("Computing mesh size field at mesh vertices %d", + edgesToRecover.size()); for(int i = 0; i < doc.numPoints; i++){ - MVertex *here = (MVertex *)doc.points[i].data; - int num = here->getIndex(); - GEntity *ge = here->onWhat(); - BDS_Point *pp = m->find_point(num); - if(ge->dim() == 0){ - pp->lcBGM() = BGM_MeshSize(ge, 0, 0, here->x(), here->y(), here->z()); - } - else if(ge->dim() == 1){ - double u; - here->getParameter(0,u); - pp->lcBGM() = BGM_MeshSize(ge, u, 0, here->x(), here->y(), here->z()); + BDS_Point *pp = (BDS_Point*)doc.points[i].data; + if(recoverMap.count(pp)){ + MVertex *here = recoverMap[pp]; + GEntity *ge = here->onWhat(); + if(ge->dim() == 0){ + pp->lcBGM() = BGM_MeshSize(ge, 0, 0, here->x(), here->y(), here->z()); + } + else if(ge->dim() == 1){ + double u; + here->getParameter(0, u); + pp->lcBGM() = BGM_MeshSize(ge, u, 0, here->x(), here->y(), here->z()); + } + else + pp->lcBGM() = MAX_LC; + pp->lc() = pp->lcBGM(); } - else - pp->lcBGM() = MAX_LC; - pp->lc() = pp->lcBGM(); } - for(int ip = 0; ip < 4; ip++) delete bb[ip]; } // delete useless stuff std::list<BDS_Face*>::iterator itt = m->triangles.begin(); while (itt != m->triangles.end()){ BDS_Face *t = *itt; - if (!t->g) - m->del_face (t); + if(!t->g) m->del_face(t); ++itt; } m->cleanup(); @@ -707,13 +538,15 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, std::list<BDS_Edge*>::iterator ite = m->edges.begin(); while (ite != m->edges.end()){ BDS_Edge *e = *ite; - if (e->numfaces() == 0) + if(e->numfaces() == 0) m->del_edge(e); else{ - if (!e->g) + if(!e->g) e->g = &CLASS_F; - if (!e->p1->g || e->p1->g->classif_degree > e->g->classif_degree)e->p1->g = e->g; - if (!e->p2->g || e->p2->g->classif_degree > e->g->classif_degree)e->p2->g = e->g; + if(!e->p1->g || e->p1->g->classif_degree > e->g->classif_degree) + e->p1->g = e->g; + if(!e->p2->g || e->p2->g->classif_degree > e->g->classif_degree) + e->p2->g = e->g; } ++ite; } @@ -724,7 +557,7 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, m->del_point(m->find_point(-3)); m->del_point(m->find_point(-4)); - if (debug){ + if(debug){ char name[245]; sprintf(name, "surface%d-recovered-real.pos", gf->tag()); outputScalarField(m->triangles, name, 0); @@ -756,12 +589,13 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, // fill the small gmsh structures { - std::set<BDS_Point*,PointLessThan>::iterator itp = m->points.begin(); + std::set<BDS_Point*,PointLessThan>::iterator itp = m->points.begin(); while (itp != m->points.end()){ BDS_Point *p = *itp; - if (numbered_vertices.find(p->iD) == numbered_vertices.end()){ - MVertex *v = new MFaceVertex (p->X, p->Y, p->Z, gf, p->u, p->v); - numbered_vertices[p->iD]=v; + if(recoverMap.find(p) == recoverMap.end()){ + MVertex *v = new MFaceVertex + (p->X, p->Y, p->Z, gf, m->scalingU * p->u, m->scalingV * p->v); + recoverMap[p] = v; gf->mesh_vertices.push_back(v); } ++itp; @@ -771,16 +605,21 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, std::list<BDS_Face*>::iterator itt = m->triangles.begin(); while (itt != m->triangles.end()){ BDS_Face *t = *itt; - if (!t->deleted){ + if(!t->deleted){ BDS_Point *n[4]; t->getNodes(n); - MVertex *v1 = numbered_vertices[n[0]->iD]; - MVertex *v2 = numbered_vertices[n[1]->iD]; - MVertex *v3 = numbered_vertices[n[2]->iD]; - if (!n[3]) - gf->triangles.push_back(new MTriangle(v1, v2, v3)); + MVertex *v1 = recoverMap[n[0]]; + MVertex *v2 = recoverMap[n[1]]; + MVertex *v3 = recoverMap[n[2]]; + if(!n[3]){ + // when a singular point is present, degenerated triangles + // may be created, for example on a sphere that contains one + // pole + if(v1 != v2 && v1 != v3 && v2 != v3) + gf->triangles.push_back(new MTriangle(v1, v2, v3)); + } else{ - MVertex *v4 = numbered_vertices[n[3]->iD]; + MVertex *v4 = recoverMap[n[3]]; gf->quadrangles.push_back(new MQuadrangle(v1, v2, v3, v4)); } } @@ -792,14 +631,14 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, // BDS mesh is passed in order not to recompute local coordinates of // vertices if(AlgoDelaunay2D(gf)){ - if (CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL) + if(CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL) gmshBowyerWatsonFrontal(gf); else gmshBowyerWatson(gf); - for (int i = 0; i < CTX::instance()->mesh.nbSmoothing; i++) + for(int i = 0; i < CTX::instance()->mesh.nbSmoothing; i++) laplaceSmoothing(gf); } - else if (debug){ + else if(debug){ char name[256]; sprintf(name, "real%d.pos", gf->tag()); outputScalarField(m->triangles, name, 0, gf); @@ -809,10 +648,8 @@ static bool gmsh2DMeshGenerator(GFace *gf, int RECUR_ITER, // delete the mesh delete m; - delete [] U_; - delete [] V_; - if (gf->meshAttributes.recombine) + if(gf->meshAttributes.recombine) gmshRecombineIntoQuads(gf); computeElementShapes(gf, gf->meshStatistics.worst_element_shape, @@ -832,21 +669,21 @@ static inline double dist2(const SPoint2 &p1, const SPoint2 &p2) { const double dx = p1.x() - p2.x(); const double dy = p1.y() - p2.y(); - return dx*dx+dy*dy; + return dx * dx + dy * dy; } static void printMesh1d(int iEdge, int seam, std::vector<SPoint2> &m) { printf("Mesh1D for edge %d seam %d\n", iEdge, seam); - for (unsigned int i = 0; i < m.size(); i++){ + for(unsigned int i = 0; i < m.size(); i++){ printf("%12.5E %12.5E\n", m[i].x(), m[i].y()); } } -static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, +static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, std::vector<BDS_Point*> &result, SBoundingBox3d &bbox, BDS_Mesh *m, - std::map<BDS_Point*, MVertex*> &recover_map_global, + std::map<BDS_Point*, MVertex*> &recoverMap, int &count, int countTot, double tol, bool seam_the_first = false) { @@ -854,19 +691,19 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, // the edge points on the face for seams, we build the list for // every side for closed loops, we build it on both senses - std::map<GEntity*,std::vector<SPoint2> > meshes; - std::map<GEntity*,std::vector<SPoint2> > meshes_seam; + std::map<GEntity*, std::vector<SPoint2> > meshes; + std::map<GEntity*, std::vector<SPoint2> > meshes_seam; const int MYDEBUG = false; - std::map<BDS_Point*,MVertex*> recover_map; + std::map<BDS_Point*, MVertex*> recoverMapLocal; result.clear(); count = 0; GEdgeLoop::iter it = gel.begin(); - if (MYDEBUG) + if(MYDEBUG) printf("face %d with %d edges case %d\n", gf->tag(), (int)gf->edges().size(), seam_the_first); @@ -880,23 +717,23 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, Range<double> range = ges.ge->parBounds(0); MVertex *here = ges.ge->getBeginVertex()->mesh_vertices[0]; - mesh1d.push_back(ges.ge->reparamOnFace(gf,range.low(),1)); - if (seam) mesh1d_seam.push_back(ges.ge->reparamOnFace(gf, range.low(), -1)); - for (unsigned int i = 0; i < ges.ge->mesh_vertices.size(); i++){ + mesh1d.push_back(ges.ge->reparamOnFace(gf, range.low(), 1)); + if(seam) mesh1d_seam.push_back(ges.ge->reparamOnFace(gf, range.low(), -1)); + for(unsigned int i = 0; i < ges.ge->mesh_vertices.size(); i++){ double u; here = ges.ge->mesh_vertices[i]; here->getParameter(0, u); mesh1d.push_back(ges.ge->reparamOnFace(gf, u, 1)); - if ( seam ) mesh1d_seam.push_back(ges.ge->reparamOnFace(gf, u, -1)); + if(seam) mesh1d_seam.push_back(ges.ge->reparamOnFace(gf, u, -1)); } here = ges.ge->getEndVertex()->mesh_vertices[0]; mesh1d.push_back(ges.ge->reparamOnFace(gf, range.high(), 1)); - if ( seam ) mesh1d_seam.push_back(ges.ge->reparamOnFace(gf, range.high(), -1)); + if(seam) mesh1d_seam.push_back(ges.ge->reparamOnFace(gf, range.high(), -1)); meshes.insert(std::pair<GEntity*,std::vector<SPoint2> >(ges.ge, mesh1d)); if(seam) meshes_seam.insert(std::pair<GEntity*,std::vector<SPoint2> > (ges.ge, mesh1d_seam)); - // printMesh1d (ges.ge->tag(), seam, mesh1d); - // if (seam)printMesh1d (ges.ge->tag(), seam, mesh1d_seam); + // printMesh1d(ges.ge->tag(), seam, mesh1d); + // if(seam) printMesh1d (ges.ge->tag(), seam, mesh1d_seam); it++; } @@ -908,7 +745,7 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, int counter = 0; while (unordered.size()){ - if (MYDEBUG) + if(MYDEBUG) printf("unordered.size() = %d\n", (int)unordered.size()); std::list<GEdgeSigned>::iterator it = unordered.begin(); std::vector<SPoint2> coords; @@ -921,13 +758,13 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, GEdge *ge = (*it).ge; bool seam = ge->isSeam(gf); mesh1d = meshes[ge]; - if (seam){ mesh1d_seam = meshes_seam[ge]; } + if(seam){ mesh1d_seam = meshes_seam[ge]; } mesh1d_reversed.insert(mesh1d_reversed.begin(), mesh1d.rbegin(), mesh1d.rend()); - if (seam) mesh1d_seam_reversed.insert(mesh1d_seam_reversed.begin(), - mesh1d_seam.rbegin(),mesh1d_seam.rend()); - if (!counter){ + if(seam) mesh1d_seam_reversed.insert(mesh1d_seam_reversed.begin(), + mesh1d_seam.rbegin(),mesh1d_seam.rend()); + if(!counter){ counter++; - if (seam && seam_the_first){ + if(seam && seam_the_first){ coords = ((*it)._sign == 1) ? mesh1d_seam : mesh1d_seam_reversed; found = (*it); Msg::Info("This test case would have failed in previous Gmsh versions ;-)"); @@ -937,19 +774,19 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, found = (*it); } unordered.erase(it); - if (MYDEBUG) + if(MYDEBUG) printf("Starting with edge = %d seam %d\n", (*it).ge->tag(), seam); break; } else{ - if (MYDEBUG) + if(MYDEBUG) printf("Followed by edge = %d\n", (*it).ge->tag()); SPoint2 first_coord = mesh1d[0]; double d = -1, d_reversed = -1, d_seam = -1, d_seam_reversed = -1; d = dist2(last_coord, first_coord); - if (MYDEBUG) + if(MYDEBUG) printf("%g %g dist = %12.5E\n", first_coord.x(), first_coord.y(), d); - if (d < tol){ + if(d < tol){ coords.clear(); coords = mesh1d; found = GEdgeSigned(1,ge); @@ -958,22 +795,22 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, } SPoint2 first_coord_reversed = mesh1d_reversed[0]; d_reversed = dist2(last_coord, first_coord_reversed); - if (MYDEBUG) + if(MYDEBUG) printf("%g %g dist_reversed = %12.5E\n", - first_coord_reversed.x(), first_coord_reversed.y(),d_reversed); - if (d_reversed < tol){ + first_coord_reversed.x(), first_coord_reversed.y(), d_reversed); + if(d_reversed < tol){ coords.clear(); coords = mesh1d_reversed; found = (GEdgeSigned(-1,ge)); unordered.erase(it); goto Finalize; } - if (seam){ + if(seam){ SPoint2 first_coord_seam = mesh1d_seam[0]; SPoint2 first_coord_seam_reversed = mesh1d_seam_reversed[0]; d_seam = dist2(last_coord,first_coord_seam); - if (MYDEBUG) printf("dist_seam = %12.5E\n", d_seam); - if (d_seam < tol){ + if(MYDEBUG) printf("dist_seam = %12.5E\n", d_seam); + if(d_seam < tol){ coords.clear(); coords = mesh1d_seam; found = (GEdgeSigned(1,ge)); @@ -981,8 +818,8 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, goto Finalize; } d_seam_reversed = dist2(last_coord, first_coord_seam_reversed); - if (MYDEBUG) printf("dist_seam_reversed = %12.5E\n", d_seam_reversed); - if (d_seam_reversed < tol){ + if(MYDEBUG) printf("dist_seam_reversed = %12.5E\n", d_seam_reversed); + if(d_seam_reversed < tol){ coords.clear(); coords = mesh1d_seam_reversed; found = GEdgeSigned(-1, ge); @@ -995,27 +832,27 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, ++it; } Finalize: - if (MYDEBUG) printf("Finalize, found %d points\n", (int)coords.size()); - if (coords.size() == 0){ + if(MYDEBUG) printf("Finalize, found %d points\n", (int)coords.size()); + if(coords.size() == 0){ // It has not worked : either tolerance is wrong or the first seam edge // has to be taken with the other parametric coordinates (because it is // only present once in the closure of the domain). - for (std::map<BDS_Point*, MVertex*>::iterator it = recover_map.begin(); - it != recover_map.end(); ++it){ + for(std::map<BDS_Point*, MVertex*>::iterator it = recoverMapLocal.begin(); + it != recoverMapLocal.end(); ++it){ m->del_point(it->first); } return false; } std::vector<MVertex*> edgeLoop; - if (found._sign == 1){ + if(found._sign == 1){ edgeLoop.push_back(found.ge->getBeginVertex()->mesh_vertices[0]); - for (unsigned int i = 0; i <found.ge->mesh_vertices.size(); i++) + for(unsigned int i = 0; i <found.ge->mesh_vertices.size(); i++) edgeLoop.push_back(found.ge->mesh_vertices[i]); } else{ edgeLoop.push_back(found.ge->getEndVertex()->mesh_vertices[0]); - for (int i = found.ge->mesh_vertices.size() - 1; i >= 0; i--) + for(int i = found.ge->mesh_vertices.size() - 1; i >= 0; i--) edgeLoop.push_back(found.ge->mesh_vertices[i]); } @@ -1024,7 +861,7 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, found.ge->tag(), (int)edgeLoop.size(), (int)coords.size()); std::vector<BDS_Point*> edgeLoop_BDS; - for (unsigned int i = 0; i < edgeLoop.size(); i++){ + for(unsigned int i = 0; i < edgeLoop.size(); i++){ MVertex *here = edgeLoop[i]; GEntity *ge = here->onWhat(); double U, V; @@ -1035,7 +872,7 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, if(ge->dim() == 0){ pp->lcBGM() = BGM_MeshSize(ge, 0, 0, here->x(), here->y(), here->z()); } - else if (ge->dim() == 1){ + else if(ge->dim() == 1){ double u; here->getParameter(0, u); pp->lcBGM() = BGM_MeshSize(ge, u, 0,here->x(), here->y(), here->z()); @@ -1047,29 +884,29 @@ static bool buildConsecutiveListOfVertices(GFace *gf, GEdgeLoop &gel, m->add_geom (ge->tag(), ge->dim()); BDS_GeomEntity *g = m->get_geom(ge->tag(), ge->dim()); pp->g = g; - if (MYDEBUG) + if(MYDEBUG) printf("point %3d (%8.5f %8.5f : %8.5f %8.5f) (%2d,%2d)\n", count, pp->u, pp->v, param.x(), param.y(), pp->g->classif_tag, pp->g->classif_degree); bbox += SPoint3(U, V, 0); edgeLoop_BDS.push_back(pp); - recover_map[pp] = here; + recoverMapLocal[pp] = here; count++; } last_coord = coords[coords.size() - 1]; - if (MYDEBUG) printf("last coord %g %g\n", last_coord.x(), last_coord.y()); + if(MYDEBUG) printf("last coord %g %g\n", last_coord.x(), last_coord.y()); result.insert(result.end(), edgeLoop_BDS.begin(), edgeLoop_BDS.end()); } // It has worked, so we add all the points to the recover map - recover_map_global.insert(recover_map.begin(),recover_map.end()); + recoverMap.insert(recoverMapLocal.begin(), recoverMapLocal.end()); return true; } static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) { - std::map<BDS_Point*,MVertex*> recover_map; + std::map<BDS_Point*, MVertex*> recoverMap; Range<double> rangeU = gf->parBounds(0); Range<double> rangeV = gf->parBounds(1); @@ -1082,27 +919,28 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) // Buid a BDS_Mesh structure that is convenient for doing the actual // meshing procedure BDS_Mesh *m = new BDS_Mesh; - m->scalingU = 1;//fabs(du); - m->scalingV = 1;//fabs(dv); + m->scalingU = 1; + m->scalingV = 1; + std::vector<std::vector<BDS_Point*> > edgeLoops_BDS; SBoundingBox3d bbox; int nbPointsTotal = 0; { - for (std::list<GEdgeLoop>::iterator it = gf->edgeLoops.begin(); - it != gf->edgeLoops.end(); it++){ + for(std::list<GEdgeLoop>::iterator it = gf->edgeLoops.begin(); + it != gf->edgeLoops.end(); it++){ std::vector<BDS_Point* > edgeLoop_BDS; int nbPointsLocal; const double fact[4] = {1.e-12, 1.e-7, 1.e-5, 1.e-3}; bool ok = false; for(int i = 0; i < 4; i++){ if(buildConsecutiveListOfVertices(gf, *it, edgeLoop_BDS, bbox, m, - recover_map, nbPointsLocal, + recoverMap, nbPointsLocal, nbPointsTotal, fact[i] * LC2D)){ ok = true; break; } if(buildConsecutiveListOfVertices(gf, *it, edgeLoop_BDS, bbox, m, - recover_map, nbPointsLocal, + recoverMap, nbPointsLocal, nbPointsTotal, fact[i] * LC2D, true)){ ok = true; break; @@ -1125,18 +963,16 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) { DocRecord doc(nbPointsTotal + 4); int count = 0; - for (unsigned int i = 0; i < edgeLoops_BDS.size(); i++){ + for(unsigned int i = 0; i < edgeLoops_BDS.size(); i++){ std::vector<BDS_Point*> &edgeLoop_BDS = edgeLoops_BDS[i]; - for (unsigned int j = 0; j < edgeLoop_BDS.size(); j++){ + for(unsigned int j = 0; j < edgeLoop_BDS.size(); j++){ BDS_Point *pp = edgeLoop_BDS[j]; - const double U = pp->u; - const double V = pp->v; - double XX = CTX::instance()->mesh.randFactor * LC2D * - (double)rand() / (double)RAND_MAX; - double YY = CTX::instance()->mesh.randFactor * LC2D * - (double)rand() / (double)RAND_MAX; - doc.points[count].where.h = U + XX; - doc.points[count].where.v = V + YY; + double XX = CTX::instance()->mesh.randFactor * LC2D * (double)rand() / + (double)RAND_MAX; + double YY = CTX::instance()->mesh.randFactor * LC2D * (double)rand() / + (double)RAND_MAX; + doc.points[count].where.h = pp->u + XX; + doc.points[count].where.v = pp->v + YY; doc.points[count].adjacent = NULL; doc.points[count].data = pp; count++; @@ -1152,7 +988,7 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) bb[1] = new MVertex(bbox.min().x(), bbox.max().y(), 0, 0, -2); bb[2] = new MVertex(bbox.max().x(), bbox.min().y(), 0, 0, -3); bb[3] = new MVertex(bbox.max().x(), bbox.max().y(), 0, 0, -4); - for (int ip = 0; ip < 4; ip++){ + for(int ip = 0; ip < 4; ip++){ BDS_Point *pp = m->add_point(-ip - 1, bb[ip]->x(), bb[ip]->y(), gf); m->add_geom(gf->tag(), 2); BDS_GeomEntity *g = m->get_geom(gf->tag(), 2); @@ -1162,7 +998,7 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) doc.points[nbPointsTotal+ip].adjacent = 0; doc.points[nbPointsTotal+ip].data = pp; } - for (int ip = 0; ip < 4; ip++) delete bb[ip]; + for(int ip = 0; ip < 4; ip++) delete bb[ip]; // Use "fast" inhouse recursive algo to generate the triangulation // At this stage the triangulation is not what we need @@ -1185,7 +1021,7 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) BDS_GeomEntity CLASS_F(1, 2); BDS_GeomEntity CLASS_E(1, 1); - if (debug){ + if(debug){ char name[245]; sprintf(name, "surface%d-initial-real.pos", gf->tag()); outputScalarField(m->triangles, name, 0); @@ -1193,14 +1029,14 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) outputScalarField(m->triangles, name, 1); } - for (unsigned int i = 0; i < edgeLoops_BDS.size(); i++){ + for(unsigned int i = 0; i < edgeLoops_BDS.size(); i++){ std::vector<BDS_Point*> &edgeLoop_BDS = edgeLoops_BDS[i]; - for (unsigned int j = 0; j < edgeLoop_BDS.size(); j++){ - BDS_Edge * e = m->recover_edge(edgeLoop_BDS[j]->iD, - edgeLoop_BDS[(j + 1) % edgeLoop_BDS.size()]->iD); - if (!e){ - Msg::Error("Impossible to recover the edge %d %d", - edgeLoop_BDS[j]->iD, edgeLoop_BDS[(j + 1) % edgeLoop_BDS.size()]->iD); + for(unsigned int j = 0; j < edgeLoop_BDS.size(); j++){ + BDS_Edge * e = m->recover_edge + (edgeLoop_BDS[j]->iD, edgeLoop_BDS[(j + 1) % edgeLoop_BDS.size()]->iD); + if(!e){ + Msg::Error("Impossible to recover the edge %d %d", edgeLoop_BDS[j]->iD, + edgeLoop_BDS[(j + 1) % edgeLoop_BDS.size()]->iD); gf->meshStatistics.status = GFace::FAILED; return false; } @@ -1221,11 +1057,11 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) if(e->g && e->numfaces () == 2){ BDS_Point *oface[2]; e->oppositeof(oface); - if (oface[0]->iD < 0){ + if(oface[0]->iD < 0){ recur_tag(e->faces(1), &CLASS_F); break; } - else if (oface[1]->iD < 0){ + else if(oface[1]->iD < 0){ recur_tag(e->faces(0), &CLASS_F); break; } @@ -1239,7 +1075,7 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) std::list<BDS_Face*>::iterator itt = m->triangles.begin(); while (itt != m->triangles.end()){ BDS_Face *t = *itt; - if (!t->g){ + if(!t->g){ m->del_face (t); } ++itt; @@ -1252,13 +1088,15 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) std::list<BDS_Edge*>::iterator ite = m->edges.begin(); while (ite != m->edges.end()){ BDS_Edge *e = *ite; - if (e->numfaces() == 0) + if(e->numfaces() == 0) m->del_edge(e); else{ - if (!e->g) + if(!e->g) e->g = &CLASS_F; - if (!e->p1->g || e->p1->g->classif_degree > e->g->classif_degree)e->p1->g = e->g; - if (!e->p2->g || e->p2->g->classif_degree > e->g->classif_degree)e->p2->g = e->g; + if(!e->p1->g || e->p1->g->classif_degree > e->g->classif_degree) + e->p1->g = e->g; + if(!e->p2->g || e->p2->g->classif_degree > e->g->classif_degree) + e->p2->g = e->g; } ++ite; } @@ -1269,7 +1107,7 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) m->del_point(m->find_point(-3)); m->del_point(m->find_point(-4)); - if (debug){ + if(debug){ char name[245]; sprintf(name, "surface%d-recovered-real.pos", gf->tag()); outputScalarField(m->triangles, name, 0); @@ -1278,11 +1116,11 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) } // start mesh generation - if (!AlgoDelaunay2D(gf)){ + if(!AlgoDelaunay2D(gf)){ gmshRefineMeshBDS(gf, *m, CTX::instance()->mesh.refineSteps, true); gmshOptimizeMeshBDS(gf, *m, 2); gmshRefineMeshBDS (gf, *m, -CTX::instance()->mesh.refineSteps, false); - gmshOptimizeMeshBDS(gf, *m, 2, &recover_map); + gmshOptimizeMeshBDS(gf, *m, 2, &recoverMap); // compute mesh statistics computeMeshSizeFieldAccuracy(gf, *m, gf->meshStatistics.efficiency_index, gf->meshStatistics.longest_edge_length, @@ -1297,9 +1135,10 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) std::set<BDS_Point*,PointLessThan>::iterator itp = m->points.begin(); while (itp != m->points.end()){ BDS_Point *p = *itp; - if (recover_map.find(p) == recover_map.end()){ - MVertex *v = new MFaceVertex (p->X,p->Y,p->Z,gf,m->scalingU*p->u,m->scalingV*p->v); - recover_map[p] = v; + if(recoverMap.find(p) == recoverMap.end()){ + MVertex *v = new MFaceVertex + (p->X, p->Y, p->Z, gf, m->scalingU * p->u, m->scalingV * p->v); + recoverMap[p] = v; gf->mesh_vertices.push_back(v); } ++itp; @@ -1310,21 +1149,21 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) std::list<BDS_Face*>::iterator itt = m->triangles.begin(); while (itt != m->triangles.end()){ BDS_Face *t = *itt; - if (!t->deleted){ + if(!t->deleted){ BDS_Point *n[4]; t->getNodes(n); - MVertex *v1 = recover_map[n[0]]; - MVertex *v2 = recover_map[n[1]]; - MVertex *v3 = recover_map[n[2]]; - if (!n[3]){ + MVertex *v1 = recoverMap[n[0]]; + MVertex *v2 = recoverMap[n[1]]; + MVertex *v3 = recoverMap[n[2]]; + if(!n[3]){ // when a singular point is present, degenerated triangles // may be created, for example on a sphere that contains one // pole - if (v1 != v2 && v1 != v3 && v2 != v3) + if(v1 != v2 && v1 != v3 && v2 != v3) gf->triangles.push_back(new MTriangle(v1, v2, v3)); } else{ - MVertex *v4 = recover_map[n[3]]; + MVertex *v4 = recoverMap[n[3]]; gf->quadrangles.push_back(new MQuadrangle(v1, v2, v3, v4)); } } @@ -1332,7 +1171,7 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) } } - if (debug){ + if(debug){ char name[245]; sprintf(name, "surface%d-final-real.pos", gf->tag()); outputScalarField(m->triangles, name, 0, gf); @@ -1340,19 +1179,19 @@ static bool gmsh2DMeshGeneratorPeriodic(GFace *gf, bool debug = true) outputScalarField(m->triangles, name, 1); } - if (AlgoDelaunay2D(gf)){ - if (CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL) + if(AlgoDelaunay2D(gf)){ + if(CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL) gmshBowyerWatsonFrontal(gf); else gmshBowyerWatson(gf); - for (int i = 0; i < CTX::instance()->mesh.nbSmoothing; i++) + for(int i = 0; i < CTX::instance()->mesh.nbSmoothing; i++) laplaceSmoothing(gf); } // delete the mesh delete m; - if (gf->meshAttributes.recombine) + if(gf->meshAttributes.recombine) gmshRecombineIntoQuads(gf); computeElementShapes(gf, gf->meshStatistics.worst_element_shape, @@ -1375,15 +1214,13 @@ void deMeshGFace::operator() (GFace *gf) gf->meshStatistics.nbTriangle = gf->meshStatistics.nbEdge = 0; } -const int debugSurface = -1;//-100; -//const int debugSurface = -100; +const int debugSurface = -1; void meshGFace::operator() (GFace *gf) { - gf->model()->setCurrentMeshEntity(gf); - if (debugSurface >= 0 && gf->tag() != debugSurface){ + if(debugSurface >= 0 && gf->tag() != debugSurface){ gf->meshStatistics.status = GFace::DONE; return; } @@ -1403,7 +1240,8 @@ void meshGFace::operator() (GFace *gf) const char *algo = "Unknown"; if(AlgoDelaunay2D(gf)) - algo = (CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL) ? "Frontal" : "Delaunay"; + algo = (CTX::instance()->mesh.algo2d == ALGO_2D_FRONTAL) ? + "Frontal" : "Delaunay"; else if(CTX::instance()->mesh.algo2d == ALGO_2D_MESHADAPT_OLD) algo = "MeshAdapt (old)"; else @@ -1417,16 +1255,18 @@ void meshGFace::operator() (GFace *gf) Msg::Debug("Computing edge loops"); Msg::Debug("Generating the mesh"); - if(noseam(gf) || gf->getNativeType() == GEntity::GmshModel || gf->edgeLoops.empty()){ - //gmsh2DMeshGeneratorPeriodic(gf, debugSurface >= 0 || debugSurface == -100); - gmsh2DMeshGenerator(gf, 0, repairSelfIntersecting1dMesh, debugSurface >= 0 || debugSurface == -100); + if(noseam(gf) || gf->getNativeType() == GEntity::GmshModel || + gf->edgeLoops.empty()){ + gmsh2DMeshGenerator(gf, 0, repairSelfIntersecting1dMesh, + debugSurface >= 0 || debugSurface == -100); } else{ - if(!gmsh2DMeshGeneratorPeriodic(gf, debugSurface >= 0 || debugSurface == -100)) + if(!gmsh2DMeshGeneratorPeriodic + (gf, debugSurface >= 0 || debugSurface == -100)) Msg::Error("Impossible to mesh face %d", gf->tag()); } - // gmshQMorph(gf); + // gmshQMorph(gf); Msg::Debug("Type %d %d triangles generated, %d internal vertices", gf->geomType(), gf->triangles.size(), gf->mesh_vertices.size()); @@ -1493,9 +1333,11 @@ void orientMeshGFace::operator()(GFace *gf) GEdge *ge = *edges.begin(); GVertex *beg = ge->getBeginVertex(); GVertex *end = ge->getEndVertex(); - if(!beg || beg->mesh_vertices.empty() || !end || end->mesh_vertices.empty()) return; + if(!beg || beg->mesh_vertices.empty() || !end || end->mesh_vertices.empty()) + return; MVertex *v1 = beg->mesh_vertices[0]; - MVertex *v2 = ge->mesh_vertices.empty() ? end->mesh_vertices[0] : ge->mesh_vertices[0]; + MVertex *v2 = ge->mesh_vertices.empty() ? end->mesh_vertices[0] : + ge->mesh_vertices[0]; int sign = *ori.begin(); MEdge ref(sign > 0 ? v1 : v2, sign > 0 ? v2 : v1); if(shouldRevert(ref, gf->triangles) || shouldRevert(ref, gf->quadrangles)){ diff --git a/Mesh/meshGFace.h b/Mesh/meshGFace.h index bff73b2626..9ad9da65a0 100644 --- a/Mesh/meshGFace.h +++ b/Mesh/meshGFace.h @@ -38,12 +38,6 @@ class orientMeshGFace { }; void fourthPoint(double *p1, double *p2, double *p3, double *p4); - -// Compute edge loops of the face, all_mvertices are the vertices of -// the -void computeEdgeLoops(const GFace *gf, - std::vector<MVertex*> &all_mvertices, - std::vector<int> &indices); void findTransfiniteCorners(GFace *gf, std::vector<MVertex*> &corners); int MeshTransfiniteSurface(GFace *gf); int MeshExtrudedSurface(GFace *gf, std::set<std::pair<MVertex*, MVertex*> > diff --git a/Mesh/meshGFaceTransfinite.cpp b/Mesh/meshGFaceTransfinite.cpp index fb1125f127..e2e9579625 100644 --- a/Mesh/meshGFaceTransfinite.cpp +++ b/Mesh/meshGFaceTransfinite.cpp @@ -80,6 +80,58 @@ void findTransfiniteCorners(GFace *gf, std::vector<MVertex*> &corners) } } +static void computeEdgeLoops(const GFace *gf, std::vector<MVertex*> &all_mvertices, + std::vector<int> &indices) +{ + std::list<GEdge*> edges = gf->edges(); + std::list<int> ori = gf->orientations(); + std::list<GEdge*>::iterator it = edges.begin(); + std::list<int>::iterator ito = ori.begin(); + + indices.push_back(0); + GVertex *start = ((*ito) == 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + GVertex *v_end = ((*ito) != 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + all_mvertices.push_back(start->mesh_vertices[0]); + if(*ito == 1) + for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++) + all_mvertices.push_back((*it)->mesh_vertices[i]); + else + for(int i = (*it)->mesh_vertices.size() - 1; i >= 0; i--) + all_mvertices.push_back((*it)->mesh_vertices[i]); + + GVertex *v_start = start; + while(1){ + ++it; + ++ito; + if(v_end == start){ + indices.push_back(all_mvertices.size()); + if(it == edges.end ()) break; + start = ((*ito) == 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + v_end = ((*ito) != 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + v_start = start; + } + else{ + if(it == edges.end ()){ + Msg::Error("Something wrong in edge loop computation"); + return; + } + v_start = ((*ito) == 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + if(v_start != v_end){ + Msg::Error("Something wrong in edge loop computation"); + return; + } + v_end = ((*ito) != 1) ? (*it)->getBeginVertex() : (*it)->getEndVertex(); + } + all_mvertices.push_back(v_start->mesh_vertices[0]); + if(*ito == 1) + for(unsigned int i = 0; i < (*it)->mesh_vertices.size(); i++) + all_mvertices.push_back((*it)->mesh_vertices[i]); + else + for(int i = (*it)->mesh_vertices.size()-1; i >= 0; i--) + all_mvertices.push_back((*it)->mesh_vertices[i]); + } +} + int MeshTransfiniteSurface(GFace *gf) { if(gf->meshAttributes.Method != MESH_TRANSFINITE) return 0; -- GitLab