void drawContext::drawMesh() { if(!CTX::instance()->mesh.draw) return; // make sure to flag any model-dependent post-processing view as // changed if the underlying mesh has, before resetting the changed // flag if(CTX::instance()->mesh.changed){ for(unsigned int i = 0; i < GModel::list.size(); i++) for(unsigned int j = 0; j < PView::list.size(); j++) if(PView::list[j]->getData()->hasModel(GModel::list[i])) PView::list[j]->setChanged(true); } glPointSize((float)CTX::instance()->mesh.pointSize); gl2psPointSize((float)(CTX::instance()->mesh.pointSize * CTX::instance()->print.epsPointSizeFactor)); glLineWidth((float)CTX::instance()->mesh.lineWidth); gl2psLineWidth((float)(CTX::instance()->mesh.lineWidth * CTX::instance()->print.epsLineWidthFactor)); if(CTX::instance()->mesh.lightTwoSide) glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); else glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); if(!CTX::instance()->clipWholeElements){ for(int i = 0; i < 6; i++) if(CTX::instance()->mesh.clip & (1 << i)) glEnable((GLenum)(GL_CLIP_PLANE0 + i)); else glDisable((GLenum)(GL_CLIP_PLANE0 + i)); } for(unsigned int i = 0; i < GModel::list.size(); i++){ GModel *m = GModel::list[i]; m->fillVertexArrays(); if(m->getVisibility() && isVisible(m)){ int status = m->getMeshStatus(); if(status >= 0) std::for_each(m->firstVertex(), m->lastVertex(), drawMeshGVertex(this)); if(status >= 1) std::for_each(m->firstEdge(), m->lastEdge(), drawMeshGEdge(this)); if(status >= 2){ beginFakeTransparency(); std::for_each(m->firstFace(), m->lastFace(), drawMeshGFace(this)); endFakeTransparency(); } if(status >= 3) std::for_each(m->firstRegion(), m->lastRegion(), drawMeshGRegion(this)); } } CTX::instance()->mesh.changed = 0; for(int i = 0; i < 6; i++) glDisable((GLenum)(GL_CLIP_PLANE0 + i)); }
void collapseSmallEdges(GModel &gm) { return; // gm.renumberMeshVertices(true); std::list<GFace*> faces; for (GModel::fiter fit = gm.firstFace(); fit != gm.lastFace(); fit++){ faces.push_back(*fit); } BDS_Mesh *pm = gmsh2BDS(faces); outputScalarField(pm->triangles, "all.pos", 0); for (GModel::eiter eit = gm.firstEdge(); eit != gm.lastEdge(); eit++){ } delete pm; }
PView *GMSH_CVTRemeshPlugin::execute(PView *v) { //TODO normalization GModel* m = GModel::current() ; std::vector<double> vertices ; std::vector<unsigned int> faces ; unsigned int offset = 0 ; for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it) { (*it)->buildSTLTriangulation() ; for(unsigned int i = 0; i < (*it)->stl_vertices.size(); ++i) { GPoint p = (*it)->point((*it)->stl_vertices[i]) ; vertices.push_back(p.x()) ; vertices.push_back(p.y()) ; vertices.push_back(p.z()) ; } for(unsigned int i = 0; i < (*it)->stl_triangles.size(); ++i) { faces.push_back((*it)->stl_triangles[i]+offset) ; } offset += (*it)->stl_vertices.size() ; } Revoropt::MeshBuilder<3> mesh ; mesh.swap_vertices(vertices) ; mesh.swap_faces(faces) ; double mesh_center[3] ; double mesh_scale ; Revoropt::normalize_mesh(&mesh, mesh_center, &mesh_scale) ; double nradius = (double)CVTRemeshOptions_Number[5].def ; //normals std::vector<double> normals(3*mesh.vertices_size()) ; Revoropt::full_robust_vertex_normals(&mesh,nradius,normals.data()) ; //lifted vertices std::vector<double> lifted_vertices(6*mesh.vertices_size(), 0) ; for(unsigned int vertex = 0; vertex < mesh.vertices_size(); ++vertex) { std::copy( mesh.vertex(vertex), mesh.vertex(vertex)+3, lifted_vertices.data()+6*vertex ) ; std::copy( normals.data()+3*vertex, normals.data()+3*vertex+3, lifted_vertices.data()+6*vertex+3 ) ; } //setup lifted mesh Revoropt::ROMeshWrapper<3,6> lifted_mesh( lifted_vertices.data(), lifted_vertices.size()/6, &mesh ) ; //triangle weight factor double twfactor = (double)CVTRemeshOptions_Number[3].def ; //face ratios std::vector<double> triangle_weights(lifted_mesh.faces_size()) ; if(twfactor > 0) { for(unsigned int f = 0; f < lifted_mesh.faces_size(); ++f) { //vertices of the initial triangle const unsigned int* fverts = mesh.face(f) ; //positions const double* x[3] ; for(int i=0; i<3; ++i) { x[i] = lifted_mesh.vertex(fverts[i]) ; } //ratio double ratio = 1 ; //vectors typedef Eigen::Matrix<double,3,1> Vector3 ; Eigen::Map<const Vector3> v0(x[0]) ; Eigen::Map<const Vector3> v1(x[1]) ; Eigen::Map<const Vector3> v2(x[2]) ; //triangle frame Vector3 U = (v1-v0) ; const double U_len = U.norm() ; if(U_len > 0) { U /= U_len ; Vector3 H = (v2-v0) ; H = H - H.dot(U)*U ; const double H_len = H.norm() ; if(H_len > 0) { //we know that the triangle is not flat H /= H_len ; //gradient of the barycentric weights in the triangle Eigen::Matrix<double,3,2> bar_grads ; bar_grads(2,0) = 0 ; bar_grads(2,1) = 1/H_len ; //gradient norms of every normal component for(int i = 0; i < 2; ++i) { //reference frame for the vertex Eigen::Map<const Vector3> vi0(x[(i+1)%3]) ; Eigen::Map<const Vector3> vi1(x[(i+2)%3]) ; Eigen::Map<const Vector3> vi2(x[ i ]) ; Vector3 Ui = (vi1-vi0) ; Ui /= Ui.norm() ; Vector3 Hi = (vi2-vi0) ; Hi = Hi - Hi.dot(Ui)*Ui ; const double Hi_invlen = 1/Hi.norm() ; Hi *= Hi_invlen ; bar_grads(i,0) = Hi.dot(U)*Hi_invlen ; bar_grads(i,1) = Hi.dot(H)*Hi_invlen ; } //gradient of each component of the normal Eigen::Map<const Vector3> n0(x[0]+3) ; Eigen::Map<const Vector3> n1(x[1]+3) ; Eigen::Map<const Vector3> n2(x[2]+3) ; Eigen::Matrix<double,3,2> n_grads = Eigen::Matrix<double,3,2>::Zero() ; n_grads = n0*bar_grads.row(0) ; n_grads += n1*bar_grads.row(1) ; n_grads += n2*bar_grads.row(2) ; //maximal gradient norm double g_max = n_grads.row(0).dot(n_grads.row(0)) ; double g_other = n_grads.row(1).dot(n_grads.row(1)) ; g_max = g_max > g_other ? g_max : g_other ; g_other = n_grads.row(2).dot(n_grads.row(2)) ; g_max = g_max > g_other ? g_max : g_other ; if(g_max == g_max) { //prevent nan ratio += g_max ; } } } triangle_weights[f] = pow(ratio,twfactor) ; } } //normal factor double nfactor = (double)CVTRemeshOptions_Number[2].def ; ; //weight the normal component by the provided factor for(unsigned int i = 0; i<lifted_mesh.vertices_size(); ++i) { double* v = lifted_vertices.data() + 6*i ; v[3]*= nfactor ; v[4]*= nfactor ; v[5]*= nfactor ; } //number of sites unsigned int nsites = (unsigned int)CVTRemeshOptions_Number[0].def ; //lifted sites std::vector<double> lifted_sites(6*nsites) ; if(twfactor > 0) { Revoropt::generate_random_sites< Revoropt::ROMesh<3,6> >( &lifted_mesh, nsites, lifted_sites.data(), triangle_weights.data() ) ; } else { Revoropt::generate_random_sites< Revoropt::ROMesh<3,6> >( &lifted_mesh, nsites, lifted_sites.data() ) ; } //setup the cvt minimizer Revoropt::CVT::DirectMinimizer< Revoropt::ROMesh<3,6> > cvt ; cvt.set_sites(lifted_sites.data(), nsites) ; cvt.set_mesh(&lifted_mesh) ; if(twfactor > 0) { cvt.set_triangle_weights(triangle_weights.data()) ; } //setup the callback SolverCallback callback ; //number of iterations unsigned int niter = (unsigned int)CVTRemeshOptions_Number[1].def ; ; unsigned int aniso_niter = std::min<unsigned int>(10,niter) ; //solver status int status = 0 ; //isotropic iterations if(niter > 10) { aniso_niter = std::max(aniso_niter,niter*10/100) ; cvt.set_anisotropy(1) ; status = cvt.minimize<Revoropt::Solver::AlgLBFGS>(niter-aniso_niter, &callback) ; } //anisotropic iterations if(niter > 0) { //tangent space anisotropy double tanisotropy = (double)CVTRemeshOptions_Number[4].def ; ; //anisotropic iterations cvt.set_anisotropy(tanisotropy) ; status = cvt.minimize<Revoropt::Solver::AlgLBFGS>(aniso_niter, &callback) ; } //rdt std::vector<unsigned int> rdt_triangles ; Revoropt::RDTBuilder< Revoropt::ROMesh<3,6> > build_rdt(rdt_triangles) ; Revoropt::RVD< Revoropt::ROMesh<3,6> > rvd ; rvd.set_sites(lifted_sites.data(), nsites) ; rvd.set_mesh(&lifted_mesh) ; rvd.compute(build_rdt) ; GFace* res_face = new discreteFace(m, m->getMaxElementaryNumber(2)+1) ; m->add(res_face) ; //scale back and transfer to gmsh std::vector<MVertex*> m_verts(nsites) ; for(unsigned int i = 0; i < nsites; ++i) { m_verts[i] = new MVertex( lifted_sites[6*i ]*mesh_scale + mesh_center[0], lifted_sites[6*i+1]*mesh_scale + mesh_center[1], lifted_sites[6*i+2]*mesh_scale + mesh_center[2] ) ; res_face->addMeshVertex(m_verts[i]) ; } for(unsigned int i = 0; i < rdt_triangles.size()/3; ++i) { res_face->addTriangle( new MTriangle( m_verts[rdt_triangles[3*i ]], m_verts[rdt_triangles[3*i+1]], m_verts[rdt_triangles[3*i+2]] ) ) ; } res_face->setAllElementsVisible(true) ; return v ; }
bool OptHOM::addBndObjGrad(double factor, double &Obj, alglib::real_1d_array &gradObj) { // set the mesh to its present position std::vector<SPoint3> xyz,uvw; mesh.getGEntityPositions(xyz,uvw); mesh.updateGEntityPositions(); //could be better (e.g. store the model in the Mesh:: datastrucure) GModel *gm = GModel::current(); // for all model edges, compute the error between the geometry and the mesh maxDistCAD = 0.0; double distCAD = 0.0; for (GModel::eiter it = gm->firstEdge(); it != gm->lastEdge(); ++it){ // do not do straight lines if ((*it)->geomType() == GEntity::Line)continue; // look at all mesh lines std::vector<bool> doWeCompute((*it)->lines.size()); for (unsigned int i=0;i<(*it)->lines.size(); i++){ doWeCompute[i] = false; for (unsigned int j=0;j<(*it)->lines[i]->getNumVertices(); j++){ int index = mesh.getFreeVertexStartIndex((*it)->lines[i]->getVertex(j)); if (index >=0){ doWeCompute[i] = true; continue; } } } std::vector<double> dist((*it)->lines.size()); for (unsigned int i=0;i<(*it)->lines.size(); i++){ if (doWeCompute[i]){ // compute the distance from the geometry to the mesh dist[i] = MLineGEdgeDistance ( (*it)->lines[i] , *it ); maxDistCAD = std::max(maxDistCAD,dist[i]); distCAD += dist [i] * factor; } } // be clever to compute the derivative : iterate on all // Distance = \sum_{lines} Distance (line, GEdge) // For a high order vertex, we compute the derivative only by // recomputing the distance to one only line const double eps = 1.e-6; for (unsigned int i=0;i<(*it)->lines.size(); i++){ if (doWeCompute[i]){ for (int j=2 ; j<(*it)->lines[i]->getNumVertices() ; j++){ MVertex *v = (*it)->lines[i]->getVertex(j); int index = mesh.getFreeVertexStartIndex(v); // printf("%d %d (%d %d)\n",v->getNum(),index,v->onWhat()->tag(),v->onWhat()->dim()); if (index >= 0){ double t; v->getParameter(0,t); SPoint3 pp (v->x(),v->y(),v->z()); GPoint gp = (*it)->point(t+eps); v->setParameter(0,t+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); double dist2 = MLineGEdgeDistance ( (*it)->lines[i] , *it ); double deriv = (dist2 - dist[i])/eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,t); // printf("%g %g %g\n",dist[i],dist2, MLineGEdgeDistance ( (*it)->lines[i] , *it )); // get the index of the vertex gradObj[index] += deriv * factor; } } } // printf("done\n"); // For a low order vertex classified on the GEdge, we recompute // two distances for the two MLines connected to the vertex for (unsigned int i=0;i<(*it)->lines.size()-1; i++){ MVertex *v = (*it)->lines[i]->getVertex(1); int index = mesh.getFreeVertexStartIndex(v); if (index >= 0){ double t; v->getParameter(0,t); SPoint3 pp (v->x(),v->y(),v->z()); GPoint gp = (*it)->point(t+eps); v->setParameter(0,t+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); MLine *l1 = (*it)->lines[i]; MLine *l2 = (*it)->lines[i+1]; // printf("%d %d -- %d %d\n",l1->getVertex(0)->getNum(),l1->getVertex(1)->getNum(),l2->getVertex(0)->getNum(),l2->getVertex(1)->getNum()); double deriv = (MLineGEdgeDistance ( l1 , *it ) - dist[i]) /eps + (MLineGEdgeDistance ( l2 , *it ) - dist[i+1])/eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,t); gradObj[index] += deriv * factor; } } } } // printf("computing distance : 1D part %12.5E\n",distCAD); // now the 3D part ! std::vector<std::vector<SVector3> > gsfT; computeGradSFAtNodes ( (*gm->firstFace())->triangles[0],gsfT); std::map<MVertex*,SVector3> normalsToCAD; for(GModel::fiter it = gm->firstFace(); it != gm->lastFace(); ++it){ // do not do plane surfaces if ((*it)->geomType() == GEntity::Plane)continue; std::map<MTriangle*,double> dist; std::vector<bool> doWeCompute((*it)->triangles.size()); for (unsigned int i=0;i<(*it)->triangles.size(); i++){ doWeCompute[i] = false; for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){ int index = mesh.getFreeVertexStartIndex((*it)->triangles[i]->getVertex(j)); if (index >=0){ doWeCompute[i] = true; } } if (doWeCompute[i]){ for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){ MVertex *v = (*it)->triangles[i]->getVertex(j); if (normalsToCAD.find(v) == normalsToCAD.end()){ SPoint2 p_cad; reparamMeshVertexOnFace(v, *it, p_cad); SVector3 tg_cad = (*it)->normal(p_cad); tg_cad.normalize(); normalsToCAD[v] = tg_cad; } } } } for (unsigned int i=0;i<(*it)->triangles.size(); i++){ // compute the distance from the geometry to the mesh if(doWeCompute[i]){ const double d = MFaceGFaceDistanceOld((*it)->triangles[i], *it, &gsfT, &normalsToCAD); dist[(*it)->triangles[i]] = d; maxDistCAD = std::max(maxDistCAD,d); distCAD += d * factor; } } // be clever again to compute the derivatives const double eps = 1.e-6; for (unsigned int i=0;i<(*it)->triangles.size(); i++){ if(doWeCompute[i]){ for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){ // for (; itm !=v2t.end(); ++itm){ MVertex *v = (*it)->triangles[i]->getVertex(j); if(v->onWhat()->dim() == 1){ int index = mesh.getFreeVertexStartIndex(v); if (index >= 0){ MTriangle *t = (*it)->triangles[i]; GEdge *ge = v->onWhat()->cast2Edge(); double t_; v->getParameter(0,t_); SPoint3 pp (v->x(),v->y(),v->z()); GPoint gp = ge->point(t_+eps); v->setParameter(0,t_+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); const double distT = dist[t]; double deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,t_); gradObj[index] += deriv * factor; } } if(v->onWhat() == *it){ int index = mesh.getFreeVertexStartIndex(v); if (index >= 0){ MTriangle *t = (*it)->triangles[i]; double uu,vv; v->getParameter(0,uu); v->getParameter(1,vv); SPoint3 pp (v->x(),v->y(),v->z()); const double distT = dist[t]; GPoint gp = (*it)->point(uu+eps,vv); v->setParameter(0,uu+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); double deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,uu); gradObj[index] += deriv * factor; gp = (*it)->point(uu,vv+eps); v->setParameter(1,vv+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(1,vv); gradObj[index+1] += deriv * factor; } } } } } } mesh.updateGEntityPositions(xyz,uvw); Obj +=distCAD; // printf("computing distance : 2D part %12.5E\n",distCAD); // printf("%22.15E\n",distCAD); return true; }
int main(int argc,char *argv[]) { if(argc < 6){ printf("Usage: %s file lx ly lz rmax [levels=1] [refcs=1]\n", argv[0]); printf("where\n"); printf(" 'file' contains a CAD model\n"); printf(" 'lx', 'ly' and 'lz' are the sizes of the elements along the" " x-, y- and z-axis at the coarsest level\n"); printf(" 'rmax' is the radius of the largest sphere that can be inscribed" " in the structure\n"); printf(" 'levels' sets the number of levels in the grid\n"); printf(" 'refcs' selects if curved surfaces should be refined\n"); return -1; } GmshInitialize(); GmshSetOption("General", "Terminal", 1.); GmshMergeFile(argv[1]); double lx = atof(argv[2]), ly = atof(argv[3]), lz = atof(argv[4]); double rmax = atof(argv[5]); int levels = (argc > 6) ? atof(argv[6]) : 1; int refineCurvedSurfaces = (argc > 7) ? atof(argv[7]) : 1; // minimum distance between points in the cloud at the coarsest // level double sampling = std::min(rmax, std::min(lx, std::min(ly, lz))); // radius of the "tube" created around parts to refine at the // coarsest level double rtube = std::max(lx, std::max(ly, lz)) * 2.; GModel *gm = GModel::current(); std::vector<SPoint3> points; Msg::Info("Filling coarse point cloud on surfaces"); for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++) (*fit)->fillPointCloud(sampling, &points); Msg::Info(" %d points in the surface cloud", (int)points.size()); std::vector<SPoint3> refinePoints; if(levels > 1){ double s = sampling / pow(2., levels - 1); Msg::Info("Filling refined point cloud on curves and curved surfaces"); for (GModel::eiter eit = gm->firstEdge(); eit != gm->lastEdge(); eit++) fillPointCloud(*eit, s, refinePoints); // FIXME: refine this by computing e.g. "mean" curvature if(refineCurvedSurfaces){ for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++) if((*fit)->geomType() != GEntity::Plane) (*fit)->fillPointCloud(2 * s, &refinePoints); } Msg::Info(" %d points in the refined cloud", (int)refinePoints.size()); } SBoundingBox3d bb; for(unsigned int i = 0; i < points.size(); i++) bb += points[i]; for(unsigned int i = 0; i < refinePoints.size(); i++) bb += refinePoints[i]; bb.scale(1.21, 1.21, 1.21); SVector3 range = bb.max() - bb.min(); int NX = range.x() / lx; int NY = range.y() / ly; int NZ = range.z() / lz; if(NX < 2) NX = 2; if(NY < 2) NY = 2; if(NZ < 2) NZ = 2; Msg::Info(" bounding box min: %g %g %g -- max: %g %g %g", bb.min().x(), bb.min().y(), bb.min().z(), bb.max().x(), bb.max().y(), bb.max().z()); Msg::Info(" Nx=%d Ny=%d Nz=%d", NX, NY, NZ); cartesianBox<double> box(bb.min().x(), bb.min().y(), bb.min().z(), SVector3(range.x(), 0, 0), SVector3(0, range.y(), 0), SVector3(0, 0, range.z()), NX, NY, NZ, levels); Msg::Info("Inserting active cells in the cartesian grid"); Msg::Info(" level %d", box.getLevel()); for (unsigned int i = 0; i < points.size(); i++) insertActiveCells(points[i].x(), points[i].y(), points[i].z(), rmax, box); cartesianBox<double> *parent = &box, *child; while((child = parent->getChildBox())){ Msg::Info(" level %d", child->getLevel()); for(unsigned int i = 0; i < refinePoints.size(); i++) insertActiveCells(refinePoints[i].x(), refinePoints[i].y(), refinePoints[i].z(), rtube / pow(2., (levels - child->getLevel())), *child); parent = child; } // remove child cells that do not entirely fill parent cell or for // which there is no parent neighbor; then remove parent cells that // have children Msg::Info("Removing cells to match X-FEM mesh topology constraints"); removeBadChildCells(&box); removeParentCellsWithChildren(&box); // we generate duplicate nodes at this point so we can easily access // cell values at each level; we will clean up by renumbering after // filtering Msg::Info("Initializing nodal values in the cartesian grid"); box.createNodalValues(); Msg::Info("Computing levelset on the cartesian grid"); computeLevelset(gm, box); Msg::Info("Removing cells outside the structure"); removeOutsideCells(&box); Msg::Info("Renumbering mesh vertices across levels"); box.renumberNodes(); bool decomposeInSimplex = false; box.writeMSH("yeah.msh", decomposeInSimplex); Msg::Info("Done!"); GmshFinalize(); }
PView *GMSH_BubblesPlugin::execute(PView *v) { double shrink = (double)BubblesOptions_Number[0].def; std::string fileName = BubblesOptions_String[0].def; FILE *fp = Fopen(fileName.c_str(), "w"); if(!fp){ Msg::Error("Could not open output file '%s'", fileName.c_str()); return v; } GModel *m = GModel::current(); int p = m->getMaxElementaryNumber(0) + 1; int l = m->getMaxElementaryNumber(1) + 1; int s = m->getMaxElementaryNumber(2) + 1; int ll = s, ps = 1; SBoundingBox3d bbox = m->bounds(); double lc = norm(SVector3(bbox.max(), bbox.min())) / 100; fprintf(fp, "lc = %g;\n", lc); for(GModel::viter vit = m->firstVertex(); vit != m->lastVertex(); vit++) (*vit)->writeGEO(fp, "lc"); for(GModel::eiter eit = m->firstEdge(); eit != m->lastEdge(); eit++) (*eit)->writeGEO(fp); for(GModel::fiter fit = m->firstFace(); fit != m->lastFace(); fit++){ (*fit)->writeGEO(fp); fprintf(fp, "Delete { Surface {%d}; }\n", (*fit)->tag()); int sbeg = s; int llbeg = ll; // compute vertex-to-triangle_barycenter map std::map<MVertex*, std::vector<SPoint3> > v2t; for(unsigned int i = 0; i < (*fit)->triangles.size(); i++) for(int j = 0; j < 3; j++) v2t[(*fit)->triangles[i]->getVertex(j)].push_back((*fit)->triangles[i]->barycenter()); // add boundary vertices in map to get cells "closer" to the boundary for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin(); it != v2t.end(); it++){ MVertex *v = it->first; if(v->onWhat() && v->onWhat()->dim() < 2) it->second.push_back(SPoint3(it->first->x(), it->first->y(), it->first->z())); } for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin(); it != v2t.end(); it++){ if(it->second.size() > 2){ // get barycenter of cell boundary points and order them SPoint3 bc; for(unsigned int i = 0; i < it->second.size(); i++) bc += it->second[i]; bc *= 1. / (double)it->second.size(); compareAngle comp(bc); std::sort(it->second.begin(), it->second.end(), comp); // shrink cells if(shrink){ for(unsigned int i = 0; i < it->second.size(); i++){ double dir[3] = {it->second[i].x() - bc.x(), it->second[i].y() - bc.y(), it->second[i].z() - bc.z()}; it->second[i][0] -= shrink * dir[0]; it->second[i][1] -= shrink * dir[1]; it->second[i][2] -= shrink * dir[2]; } } // create b-spline bounded surface for each cell int nump = it->second.size(); for(int i = 0; i < nump; i++){ SPoint3 &b(it->second[i]); fprintf(fp, "Point(%d) = {%.16g, %.16g, %.16g, lc};\n", p++, b.x(), b.y(), b.z()); } fprintf(fp, "BSpline(%d) = {", l++); for(int i = nump - 1; i >= 0; i--) fprintf(fp, "%d,", p - i - 1); fprintf(fp, "%d};\n", p - nump); fprintf(fp, "Line Loop(%d) = {%d};\n", ll++, l - 1); fprintf(fp, "Plane Surface(%d) = {%d};\n", s++, ll - 1); } } fprintf(fp, "Physical Surface(%d) = {%d:%d};\n", ps++, sbeg, s - 1); fprintf(fp, "Plane Surface(%d) = {%d, %d:%d};\n", s++, (*fit)->tag(), llbeg, ll - 1); fprintf(fp, "Physical Surface(%d) = {%d};\n", ps++, s - 1); } fclose(fp); return v; }