// build the BDS from a list of GFace // This is a TRUE copy BDS_Mesh *gmsh2BDS(std::list<GFace*> &l) { BDS_Mesh *m = new BDS_Mesh; for (std::list<GFace*>::iterator it = l.begin(); it != l.end(); ++it){ GFace *gf = *it; m->add_geom(gf->tag(), 2); BDS_GeomEntity *g2 = m->get_geom(gf->tag(), 2); for (unsigned int i = 0; i < gf->triangles.size(); i++){ MTriangle *e = gf->triangles[i]; BDS_Point *p[3]; for (int j = 0; j < 3; j++){ p[j] = m->find_point(e->getVertex(j)->getNum()); if (!p[j]) { p[j] = m->add_point(e->getVertex(j)->getNum(), e->getVertex(j)->x(), e->getVertex(j)->y(), e->getVertex(j)->z()); SPoint2 param; reparamMeshVertexOnFace(e->getVertex(j), gf, param); p[j]->u = param[0]; p[j]->v = param[1]; m->add_geom(e->getVertex(j)->onWhat()->tag(), e->getVertex(j)->onWhat()->dim()); BDS_GeomEntity *g = m->get_geom(e->getVertex(j)->onWhat()->tag(), e->getVertex(j)->onWhat()->dim()); p[j]->g = g; } } BDS_Face *f = m->add_triangle(p[0]->iD, p[1]->iD, p[2]->iD); f->g = g2; } } return m; }
void backgroundMesh2D::create_mesh_copy() { // TODO: useful to extend it to other elements ??? //std::set<SPoint2> myBCNodes; GFace *face = dynamic_cast<GFace*>(gf); if(!face) { Msg::Error("Entity is not a face in background mesh"); return; } for (unsigned int i = 0; i < face->triangles.size(); i++) { MTriangle *e = face->triangles[i]; MVertex *news[3]; for (int j=0; j<3; j++) { MVertex *v = e->getVertex(j); std::map<MVertex*,MVertex*>::iterator it = _3Dto2D.find(v); MVertex *newv =0; if (it == _3Dto2D.end()) { SPoint2 p; reparamMeshVertexOnFace(v, face, p); newv = new MVertex (p.x(), p.y(), 0.0);// creates new vertex with xyz= u,v,0. vertices.push_back(newv); _3Dto2D[v] = newv; _2Dto3D[newv] = v; //if(v->onWhat()->dim()<2) myBCNodes.insert(p); } else newv = it->second; news[j] = newv; } elements.push_back(new MTriangle(news[0],news[1],news[2])); } }
void frameFieldBackgroundMesh2D::eval_crossfield(MVertex *vert, STensor3 &cf) { SPoint2 parampoint; GFace *face = dynamic_cast<GFace*>(gf); if(!face) { Msg::Error("Entity is not a face in background mesh"); return; } reparamMeshVertexOnFace(vert, face, parampoint); return eval_crossfield(parampoint[0], parampoint[1], cf); }
void backgroundMesh2D::updateSizes() { DoubleStorageType::iterator itv = sizeField.begin(); for ( ; itv != sizeField.end(); ++itv) { SPoint2 p; MVertex *v = _2Dto3D[itv->first]; double lc; if (v->onWhat()->dim() == 0) { lc = sizeFactor * BGM_MeshSize(v->onWhat(), 0,0,v->x(),v->y(),v->z()); } else if (v->onWhat()->dim() == 1) { double u; v->getParameter(0, u); lc = sizeFactor * BGM_MeshSize(v->onWhat(), u, 0, v->x(), v->y(), v->z()); } else { GFace *face = dynamic_cast<GFace*>(gf); if(!face) { Msg::Error("Entity is not a face in background mesh"); return; } reparamMeshVertexOnFace(v, face, p); lc = sizeFactor * BGM_MeshSize(face, p.x(), p.y(), v->x(), v->y(), v->z()); } // printf("2D -- %g %g 3D -- %g %g\n",p.x(),p.y(),v->x(),v->y()); itv->second = min(lc,itv->second); itv->second = max(itv->second, sizeFactor * CTX::instance()->mesh.lcMin); itv->second = min(itv->second, sizeFactor * CTX::instance()->mesh.lcMax); } // do not allow large variations in the size field // (Int. J. Numer. Meth. Engng. 43, 1143-1165 (1998) MESH GRADATION // CONTROL, BOROUCHAKI, HECHT, FREY) std::set<MEdge,Less_Edge> edges; for (unsigned int i = 0; i < getNumMeshElements(); i++) { for (int j = 0; j < getElement(i)->getNumEdges(); j++) { edges.insert(getElement(i)->getEdge(j)); } } const double _beta = 1.3; for (int i=0; i<0; i++) { std::set<MEdge,Less_Edge>::iterator it = edges.begin(); for ( ; it != edges.end(); ++it) { MVertex *v0 = it->getVertex(0); MVertex *v1 = it->getVertex(1); MVertex *V0 = _2Dto3D[v0]; MVertex *V1 = _2Dto3D[v1]; DoubleStorageType::iterator s0 = sizeField.find(V0); DoubleStorageType::iterator s1 = sizeField.find(V1); if (s0->second < s1->second)s1->second = min(s1->second,_beta*s0->second); else s0->second = min(s0->second,_beta*s1->second); } } }
static double _relocateVertex(GFace *gf, MVertex *ver, const std::vector<MElement *> <, double tol) { if(ver->onWhat()->dim() != 2) return 2.0; SPoint2 p1(0, 0); SPoint2 p2; if(ver->getParameter(0, p2[0])) { ver->getParameter(1, p2[1]); } else { return _relocateVertex2(gf, ver, lt, tol); } std::size_t counter = 0; for(std::size_t i = 0; i < lt.size(); i++) { for(std::size_t j = 0; j < lt[i]->getNumVertices(); j++) { MVertex *v = lt[i]->getVertex(j); SPoint2 pp; reparamMeshVertexOnFace(v, gf, pp); counter++; if(v->onWhat()->dim() == 1) { GEdge *ge = dynamic_cast<GEdge *>(v->onWhat()); // do not take any chance if(ge->isSeam(gf)) return 2.0; } p1 += pp; } } p1 *= 1. / (double)counter; double worst; double xi = Maximize_Quality_Golden_Section(ver, gf, p1, p2, lt, tol, worst); // if (xi != 0) printf("xi = %g\n",xi); SPoint2 p = p1 * (1 - xi) + p2 * xi; GPoint pp = gf->point(p); if(!pp.succeeded()) return 2.0; ver->x() = pp.x(); ver->y() = pp.y(); ver->z() = pp.z(); ver->setParameter(0, pp.u()); ver->setParameter(1, pp.v()); return worst; }
void highOrderTools::computeMetricInfo(GFace *gf, MElement *e, fullMatrix<double> &J, fullMatrix<double> &JT, fullVector<double> &D) { int nbNodes = e->getNumVertices(); // printf("ELEMENT --\n"); for (int j = 0; j < nbNodes; j++){ SPoint2 param; reparamMeshVertexOnFace(e->getVertex(j), gf, param); // printf("%g %g vs %g %g %g\n",param.x(),param.y(), // e->getVertex(j)->x(),e->getVertex(j)->y(),e->getVertex(j)->z()); Pair<SVector3,SVector3> der = gf->firstDer(param); int XJ = j; int YJ = j + nbNodes; int ZJ = j + 2 * nbNodes; int UJ = j; int VJ = j + nbNodes; J(XJ,UJ) = der.first().x(); J(YJ,UJ) = der.first().y(); J(ZJ,UJ) = der.first().z(); J(XJ,VJ) = der.second().x(); J(YJ,VJ) = der.second().y(); J(ZJ,VJ) = der.second().z(); JT(UJ,XJ) = der.first().x(); JT(UJ,YJ) = der.first().y(); JT(UJ,ZJ) = der.first().z(); JT(VJ,XJ) = der.second().x(); JT(VJ,YJ) = der.second().y(); JT(VJ,ZJ) = der.second().z(); SVector3 ss = getSSL(e->getVertex(j)); GPoint gp = gf->point(param); D(XJ) = (gp.x() - ss.x()); D(YJ) = (gp.y() - ss.y()); D(ZJ) = (gp.z() - ss.z()); } }
double taylorDistanceFace(MElement *el, GFace *gf) { const int nV = el->getNumVertices(); const GradientBasis *gb = BasisFactory::getGradientBasis(FuncSpaceData(el)); // Coordinates of vertices fullMatrix<double> nodesXYZ(nV, 3); el->getNodesCoord(nodesXYZ); // Normal to CAD at vertices std::vector<SVector3> normCAD(nV); for (int i=0; i<nV; i++) { SPoint2 pCAD; reparamMeshVertexOnFace(el->getVertex(i), gf, pCAD); normCAD[i] = gf->normal(pCAD); normCAD[i].normalize(); } // Compute distance return sqrt(taylorDistanceSq2D(gb, nodesXYZ, normCAD)); }
void highOrderTools::applySmoothingTo(std::vector<MElement*> &all, GFace *gf) { #ifdef HAVE_TAUCS linearSystemCSRTaucs<double> *lsys = new linearSystemCSRTaucs<double>; #else linearSystemPETSc<double> *lsys = new linearSystemPETSc<double>; #endif // compute the straight sided positions of high order nodes that are // on the edges of the face in the UV plane dofManager<double> myAssembler(lsys); elasticityTerm El(0, 1.0, CTX::instance()->mesh.hoPoissonRatio, _tag); std::vector<MElement*> layer, v; double minD; getDistordedElements(all, CTX::instance()->mesh.hoThresholdMin, v, minD); int numBad = v.size(); const int nbLayers = CTX::instance()->mesh.hoNLayers; for (int i = 0; i < nbLayers; i++){ addOneLayer(all, v, layer); v.insert(v.end(), layer.begin(), layer.end()); } if (!v.size()) return; Msg::Info("Smoothing high order mesh : model face %d (%d elements considered in " "the elastic analogy, worst mapping %12.5E, %3d bad elements)", gf->tag(), v.size(),minD,numBad); addOneLayer(all, v, layer); std::set<MVertex*>::iterator it; std::set<MVertex*> verticesToMove; // on the last layer, fix displacement to 0 for (unsigned int i = 0; i < layer.size(); i++){ for (int j = 0; j < layer[i]->getNumVertices(); j++){ MVertex *vert = layer[i]->getVertex(j); myAssembler.fixVertex(vert, 0, _tag, 0); myAssembler.fixVertex(vert, 1, _tag, 0); } } // fix all vertices that cannot move for (unsigned int i = 0; i < v.size(); i++){ moveToStraightSidedLocation(v[i]); for (int j = 0; j < v[i]->getNumVertices(); j++){ MVertex *vert = v[i]->getVertex(j); if (vert->onWhat()->dim() < 2){ double du = 0, dv = 0; myAssembler.fixVertex(vert, 0, _tag, du); myAssembler.fixVertex(vert, 1, _tag, dv); } } } // number the other DOFs for (unsigned int i = 0; i < v.size(); i++){ for (int j = 0; j < v[i]->getNumVertices(); j++){ MVertex *vert = v[i]->getVertex(j); myAssembler.numberVertex(vert, 0, _tag); myAssembler.numberVertex(vert, 1, _tag); verticesToMove.insert(vert); } } double dx0 = smooth_metric_(v, gf, myAssembler, verticesToMove, El); double dx = dx0; Msg::Debug(" dx0 = %12.5E", dx0); int iter = 0; while(0){ double dx2 = smooth_metric_(v, gf, myAssembler, verticesToMove, El); Msg::Debug(" dx2 = %12.5E", dx2); if (fabs(dx2 - dx) < 1.e-4 * dx0)break; if (iter++ > 2)break; dx = dx2; } for (it = verticesToMove.begin(); it != verticesToMove.end(); ++it){ SPoint2 param; if ((*it)->onWhat()->dim() == 2){ reparamMeshVertexOnFace(*it, gf, param); GPoint gp = gf->point(param); (*it)->x() = gp.x(); (*it)->y() = gp.y(); (*it)->z() = gp.z(); _targetLocation[*it] = SVector3(gp.x(), gp.y(), gp.z()); } else{ SVector3 p = getTL(*it); (*it)->x() = p.x(); (*it)->y() = p.y(); (*it)->z() = p.z(); } } delete lsys; }
void backgroundMesh2D::propagateValues(DoubleStorageType &dirichlet, simpleFunction<double> &eval_diffusivity, bool in_parametric_plane) { #if defined(HAVE_SOLVER) linearSystem<double> *_lsys = 0; #if defined(HAVE_PETSC) && !defined(HAVE_TAUCS) _lsys = new linearSystemPETSc<double>; #elif defined(HAVE_GMM) && !defined(HAVE_TAUCS) linearSystemGmm<double> *_lsysb = new linearSystemGmm<double>; _lsysb->setGmres(1); _lsys = _lsysb; #elif defined(HAVE_TAUCS) _lsys = new linearSystemCSRTaucs<double>; #else _lsys = new linearSystemFull<double>; #endif dofManager<double> myAssembler(_lsys); // fix boundary conditions DoubleStorageType::iterator itv = dirichlet.begin(); for ( ; itv != dirichlet.end(); ++itv) { myAssembler.fixVertex(itv->first, 0, 1, itv->second); } // Number vertices std::set<MVertex*> vs; GFace *face = dynamic_cast<GFace*>(gf); if(!face) { Msg::Error("Entity is not a face in background mesh"); delete _lsys; return; } for (unsigned int k = 0; k < face->triangles.size(); k++) for (int j=0; j<3; j++)vs.insert(face->triangles[k]->getVertex(j)); for (unsigned int k = 0; k < face->quadrangles.size(); k++) for (int j=0; j<4; j++)vs.insert(face->quadrangles[k]->getVertex(j)); std::map<MVertex*,SPoint3> theMap; if ( in_parametric_plane) { for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it) { SPoint2 p; reparamMeshVertexOnFace ( *it, face, p); theMap[*it] = SPoint3((*it)->x(),(*it)->y(),(*it)->z()); (*it)->setXYZ(p.x(),p.y(),0.0); } } for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it) myAssembler.numberVertex(*it, 0, 1); // Assemble laplaceTerm l(0, 1, &eval_diffusivity); for (unsigned int k = 0; k < face->triangles.size(); k++) { MTriangle *t = face->triangles[k]; SElement se(t); l.addToMatrix(myAssembler, &se); } // Solve if (myAssembler.sizeOfR()) { _lsys->systemSolve(); } // save solution for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it) { myAssembler.getDofValue(*it, 0, 1, dirichlet[*it]); } if ( in_parametric_plane) { for (std::set<MVertex*>::iterator it = vs.begin(); it != vs.end(); ++it) { SPoint3 p = theMap[(*it)]; (*it)->setXYZ(p.x(),p.y(),p.z()); } } delete _lsys; #endif }
void updateBoVec<3, MFace>( const int normalSource, const MVertex *const vertex, const int zoneIndex, const int vertIndex, const CCon::FaceVector<MZoneBoundary<3>::GlobalVertexData<MFace>::FaceDataB> &faces, ZoneBoVec &zoneBoVec, BCPatchIndex &patch, bool &warnNormFromElem) { GEntity *ent; if(normalSource == NormalSourceElement) goto getNormalFromElements; ent = vertex->onWhat(); if(ent == 0) { goto getNormalFromElements; // No entity: try to find a normal from the faces } else { switch(ent->dim()) { case 0: case 1: /*--------------------------------------------------------------------* * In this case, there are possibly multiple GFaces from this zone * connected to the vertex. One patch for each GFace will be written. *--------------------------------------------------------------------*/ { //--Get a list of face entities connected to 'ent' std::list<GFace *> gFaceList; switch(ent->dim()) { case 0: { std::vector<GEdge *> gEdgeList = ent->edges(); std::list<GFace *> gFaceList; for(std::vector<GEdge *>::const_iterator gEIt = gEdgeList.begin(); gEIt != gEdgeList.end(); ++gEIt) { std::vector<GFace *> alist = (*gEIt)->faces(); gFaceList.insert(gFaceList.end(), alist.begin(), alist.end()); } // Remove duplicates gFaceList.sort(); gFaceList.unique(); } break; case 1: { std::vector<GFace *> fac = ent->faces(); gFaceList.insert(gFaceList.end(), fac.begin(), fac.end()); } break; } //--Get a list of face entities connected to the 'vertex' that are also // in the //--zone std::list<const GFace *> useGFace; std::vector<GEdge *> gEdgeList; const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(zoneIndex == faces[iFace].zoneIndex) { bool matchedFace = false; MFace mFace = faces[iFace].parentElement->getFace(faces[iFace].parentFace); const int nVOnF = mFace.getNumVertices(); int vertexOnF = 0; // The index of 'vertex' in the face for(int iVOnF = 0; iVOnF != nVOnF; ++iVOnF) { const MVertex *const vertex2 = mFace.getVertex(iVOnF); if(vertex == vertex2) vertexOnF = iVOnF; else { const GEntity *const ent2 = vertex2->onWhat(); if(ent2->dim() == 2) { matchedFace = true; useGFace.push_back(static_cast<const GFace *>(ent2)); break; } } } // Triangle MElements are a total P.I.T.A.: // - If the original 'ent' is a vertex, one MVertex can be on the // GVertex, and the other two on GEdges, and then the MElement is // still on the GFace. // - If the original 'ent' is an edge, one MVertex can be on the // original GEdge, another on a GVertex, and the final on another // GEdge, and then the MElement is still on the GFace. There is // also the unlikely case where the two other MVertex are both on // edges ... and the MElement is still on the GFace. if(!matchedFace && (3 == nVOnF)) { const MVertex *vertex2 = 0; const MVertex *vertex3 = 0; switch(vertexOnF) { case 0: vertex2 = mFace.getVertex(1); vertex3 = mFace.getVertex(2); break; case 1: vertex2 = mFace.getVertex(0); vertex3 = mFace.getVertex(2); break; case 2: vertex2 = mFace.getVertex(0); vertex3 = mFace.getVertex(1); break; } if(vertex2 && vertex3) { const GEntity *const ent2 = vertex2->onWhat(); const GEntity *const ent3 = vertex3->onWhat(); if(ent2 && ent3) { if(ent2->dim() == 1 && ent3->dim() == 1) { // Which GFace is bounded by edges ent2 and ent3? for(std::list<GFace *>::const_iterator gFIt = gFaceList.begin(); gFIt != gFaceList.end(); ++gFIt) { gEdgeList = (*gFIt)->edges(); if((std::find(gEdgeList.begin(), gEdgeList.end(), ent2) != gEdgeList.end()) && (std::find(gEdgeList.begin(), gEdgeList.end(), ent3) != gEdgeList.end())) { // Edges ent2 and ent3 bound this face useGFace.push_back(*gFIt); break; } } } else if(ent->dim() == 1 && (ent2->dim() + ent3->dim() == 1)) { const GEntity *entCmp; if(ent2->dim() == 1) entCmp = ent2; else entCmp = ent3; // Which GFace is bounded by entCmp for(std::list<GFace *>::const_iterator gFIt = gFaceList.begin(); gFIt != gFaceList.end(); ++gFIt) { gEdgeList = (*gFIt)->edges(); if(std::find(gEdgeList.begin(), gEdgeList.end(), entCmp) != gEdgeList.end()) { // Edge entCmp and the original edge bound this face useGFace.push_back(*gFIt); break; } } } } } } // Stupid triangles } // End if face in zone } // End loop over faces // Duplicates are a possibility, remove useGFace.sort(); useGFace.unique(); //--'useGFace' now contains the face entities that connect to vertex. A // BC //--patch will be written for each of them. for(std::list<const GFace *>::const_iterator gFIt = useGFace.begin(); gFIt != useGFace.end(); ++gFIt) { SPoint2 par; if(!reparamMeshVertexOnFace(const_cast<MVertex *>(vertex), *gFIt, par)) goto getNormalFromElements; // :P After all that! SVector3 boNormal = (*gFIt)->normal(par); SPoint3 interior(0., 0., 0.); int cFace = 0; const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { ++cFace; interior += faces[iFace].parentElement->barycenter(); } } interior /= cFace; if(dot(boNormal, SVector3(vertex->point(), interior)) < 0.) boNormal.negate(); zoneBoVec.push_back( VertexBoundary(zoneIndex, (*gFIt)->tag(), boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add((*gFIt)->tag()); } } break; case 2: /*--------------------------------------------------------------------* * The vertex exists on a face and belongs to only 1 BC patch. *--------------------------------------------------------------------*/ { const GFace *const gFace = static_cast<const GFace *>(ent); SPoint2 par; if(!reparamMeshVertexOnFace(const_cast<MVertex *>(vertex), gFace, par)) goto getNormalFromElements; SVector3 boNormal = static_cast<const GFace *>(ent)->normal(par); SPoint3 interior(0., 0., 0.); int cFace = 0; const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { ++cFace; interior += faces[iFace].parentElement->barycenter(); } } interior /= cFace; if(dot(boNormal, SVector3(vertex->point(), interior)) < 0.) boNormal.negate(); zoneBoVec.push_back(VertexBoundary(zoneIndex, gFace->tag(), boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gFace->tag()); } break; default: goto getNormalFromElements; } } return; getNormalFromElements:; /*--------------------------------------------------------------------* * Geometry information cannot be used - generate normals from the * elements *--------------------------------------------------------------------*/ { if(warnNormFromElem && normalSource == 1) { Msg::Warning("Some or all boundary normals were determined from mesh " "elements instead of from the geometry"); warnNormFromElem = false; } // Sum the normals from each element connected to the vertex and in the // zone. Each normal has to be converted independently into an inwards- // pointing normal. //**Weight each normal by the area of the boundary element? SVector3 boNormal(0.); const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { // Normal to the boundary (unknown direction) SVector3 bnt = faces[iFace].parentElement->getFace(faces[iFace].parentFace).normal(); // Inwards normal const SVector3 inwards(vertex->point(), faces[iFace].parentElement->barycenter()); if(dot(bnt, inwards) < 0.) bnt.negate(); boNormal += bnt; } } boNormal.normalize(); zoneBoVec.push_back(VertexBoundary( zoneIndex, 0, boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(0); } }
int GModel::writeCELUM(const std::string &name, bool saveAll, double scalingFactor) { std::string namef = name + "_f"; FILE *fpf = Fopen(namef.c_str(), "w"); if(!fpf) { Msg::Error("Unable to open file '%s'", namef.c_str()); return 0; } std::string names = name + "_s"; FILE *fps = Fopen(names.c_str(), "w"); if(!fps) { Msg::Error("Unable to open file '%s'", names.c_str()); fclose(fpf); return 0; } if(noPhysicalGroups()) saveAll = true; // count faces and vertices; the CELUM format duplicates vertices on the // boundary of CAD patches int numf = 0, nums = 0; for(fiter it = firstFace(); it != lastFace(); it++) { GFace *f = *it; if(!saveAll && f->physicals.empty()) continue; numf += f->triangles.size(); std::set<MVertex *> vset; for(std::size_t i = 0; i < f->triangles.size(); i++) { for(int j = 0; j < 3; j++) vset.insert(f->triangles[i]->getVertex(j)); } nums += vset.size(); } Msg::Info("Writing %d triangles and %d vertices", numf, nums); int idf = 1, ids = 1; /* * a file with faces - number of faces - empty line ... for each face - number of the face (starts at 1 : used for read errors) - char string (name of geom part, material,... ) - list of 3 vertex nums - empty line ... * a file with vertices - number of vertices - conversion factor - empty line ... for each vertex - number of the vertex (starts at 1 : used for read errors) - cartesian coordinates of the vertex - componants of the exterior oriented normal - value of 1st principal curvature - value of second princpal curvature - components of 1st principal direction - components of 2nd principal direction - empty line ... */ fprintf(fpf, "%d\n\n", numf); fprintf(fps, "%d %g\n\n", nums, 1.0); for(fiter it = firstFace(); it != lastFace(); it++) { GFace *f = *it; if(!saveAll && f->physicals.empty()) continue; std::vector<MVertex *> vvec; std::map<MVertex *, CelumInfo> vmap; for(std::size_t i = 0; i < f->triangles.size(); i++) { fprintf(fpf, "%d \"face %d\"", idf++, f->tag()); for(int j = 0; j < 3; j++) { MVertex *v = f->triangles[i]->getVertex(j); if(!vmap.count(v)) { v->setIndex(ids++); SPoint2 param; bool ok = reparamMeshVertexOnFace(v, f, param); if(!ok) Msg::Warning("Could not reparamtrize vertex %d on face %d", v->getNum(), f->tag()); CelumInfo info; info.normal = f->normal(param); f->curvatures(param, info.dirMax, info.dirMin, info.curvMax, info.curvMin); vmap[v] = info; vvec.push_back(v); } fprintf(fpf, " %ld", v->getIndex()); } fprintf(fpf, "\n\n"); } for(std::size_t i = 0; i < vvec.size(); i++) { MVertex *v = vvec[i]; std::map<MVertex *, CelumInfo>::iterator it = vmap.find(v); fprintf(fps, "%ld %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n\n", it->first->getIndex(), it->first->x(), it->first->y(), it->first->z(), it->second.normal.x(), it->second.normal.y(), it->second.normal.z(), it->second.curvMin, it->second.curvMax, it->second.dirMin.x(), it->second.dirMin.y(), it->second.dirMin.z(), it->second.dirMax.x(), it->second.dirMax.y(), it->second.dirMax.z()); } } fclose(fpf); fclose(fps); return 1; }
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; }
bool computeFourNeighbors(frameFieldBackgroundMesh2D *bgm, MVertex *v_center, // the vertex for which we want to // generate 4 neighbors (real // vertex (xyz), not parametric!) SPoint2 &midpoint, bool goNonLinear, // do we compute the position in // the real surface which is // nonlinear SPoint2 newP[4][NUMDIR], // look into other directions SMetric3 &metricField) // the mesh metric { // we assume that v is on surface gf, and backgroundMesh2D has been created // based on gf // get BGM and GFace GFace *gf = dynamic_cast<GFace *>(bgm->getBackgroundGEntity()); // get the parametric coordinates of the point on the surface reparamMeshVertexOnFace(v_center, gf, midpoint); // get RK info on midpoint (infos in two directions...) RK_form infos; bgm->compute_RK_infos(midpoint[0], midpoint[1], v_center->x(), v_center->y(), v_center->z(), infos); metricField = infos.metricField; // shoot in four directions SPoint2 param_vec; double h; for(int i = 0; i < 4; i++) { // in four directions switch(i) { case 0: param_vec = infos.paramt1; h = infos.paramh.first; break; case 1: param_vec = infos.paramt2; h = infos.paramh.second; break; case 2: param_vec = infos.paramt1 * -1.; h = infos.paramh.first; break; case 3: param_vec = infos.paramt2 * -1.; h = infos.paramh.second; break; } shoot(midpoint, param_vec, h, newP[i][0]); // std::cout << "(" << midpoint[0] << "," <<midpoint[1] << ") -> (" << // newP[i][0][0] << "," << newP[i][0][1] << ") " << std::endl; } // the following comes from surfaceFiller.cpp... const double EPS = 1.e-7; for(int j = 0; j < 2; j++) { for(int i = 0; i < 4; i++) { newP[i][0][j] += (EPS * (double)rand() / RAND_MAX); } } // We could stop here. Yet, if the metric varies a lot, we can solve a // nonlinear problem in order to find a better approximation in the real // surface if(1 && goNonLinear) { double L = infos.localsize; double newPoint[4][2]; for(int j = 0; j < 2; j++) { for(int i = 0; i < 4; i++) { newPoint[i][j] = newP[i][0][j]; } } double ERR[4]; for(int i = 0; i < 4; i++) { // // if (newPoint[i][0] < rangeU.low())newPoint[i][0] = rangeU.low(); // if (newPoint[i][0] > rangeU.high())newPoint[i][0] = rangeU.high(); // if (newPoint[i][1] < rangeV.low())newPoint[i][1] = rangeV.low(); // if (newPoint[i][1] > rangeV.high())newPoint[i][1] = rangeV.high(); GPoint pp = gf->point(newP[i][0]); double D = sqrt((pp.x() - v_center->x()) * (pp.x() - v_center->x()) + (pp.y() - v_center->y()) * (pp.y() - v_center->y()) + (pp.z() - v_center->z()) * (pp.z() - v_center->z())); ERR[i] = 100 * fabs(D - L) / (D + L); // printf("L = %12.5E D = %12.5E ERR = // %12.5E\n",L,D,100*fabs(D-L)/(D+L)); } surfaceFunctorGFace ss(gf); SVector3 dirs[4] = {infos.t1 * (-1.0), infos.t2 * (-1.0), infos.t1 * (1.0), infos.t2 * (1.0)}; for(int i = 0; i < 4; i++) { if(ERR[i] > 12) { double uvt[3] = {newPoint[i][0], newPoint[i][1], 0.0}; // printf("Intersecting with circle N = %g %g %g dir = %g %g %g R // = %g p = %g %g // %g\n",n.x(),n.y(),n.z(),dirs[i].x(),dirs[i].y(),dirs[i].z(),L, // v_center->x(),v_center->y(),v_center->z()); curveFunctorCircle cf( dirs[i], infos.normal, SVector3(v_center->x(), v_center->y(), v_center->z()), L); if(intersectCurveSurface(cf, ss, uvt, infos.paramh.first * 1.e-3)) { GPoint pp = gf->point(SPoint2(uvt[0], uvt[1])); double D = sqrt((pp.x() - v_center->x()) * (pp.x() - v_center->x()) + (pp.y() - v_center->y()) * (pp.y() - v_center->y()) + (pp.z() - v_center->z()) * (pp.z() - v_center->z())); double DP = sqrt((newPoint[i][0] - uvt[0]) * (newPoint[i][0] - uvt[0]) + (newPoint[i][1] - uvt[1]) * (newPoint[i][1] - uvt[1])); double newErr = 100 * fabs(D - L) / (D + L); // if (v_center->onWhat() != gf && gf->tag() == 3){ // crossField2d::normalizeAngle (uvt[2]); // printf("INTERSECT angle = %g DP %g\n",uvt[2],DP); // } if(newErr < 1 && DP < .1) { // printf("%12.5E vs %12.5E : %12.5E %12.5E vs %12.5E %12.5E // \n",ERR[i],newErr,newPoint[i][0],newPoint[i][1],uvt[0],uvt[1]); newPoint[i][0] = uvt[0]; newPoint[i][1] = uvt[1]; } // printf("OK\n"); } else { Msg::Debug("Cannot put a new point on Surface %d", gf->tag()); // printf("NOT OK\n"); } } } // return the four new vertices for(int i = 0; i < 4; i++) { newP[i][0] = SPoint2(newPoint[i][0], newPoint[i][1]); } } return true; }
void Filler2D::pointInsertion2D(GFace *gf, std::vector<MVertex *> &packed, std::vector<SMetric3> &metrics) { // NB/ do not use the mesh in GFace, use the one in backgroundMesh2D! // if(debug) std::cout << " ------------------ OLD -------------------" << // std::endl; stringstream ssa; //// ssa << "oldbgm_angles_" << gf->tag() << ".pos"; //// backgroundMesh::current()->print(ssa.str(),gf,1); // ssa << "oldbgm_sizes_" << gf->tag() << ".pos"; // backgroundMesh::current()->print(ssa.str(),gf,0); // // // // // if(debug) std::cout << " ------------------ NEW -------------------" << // std::endl; backgroundMesh2D *bgm2 = // dynamic_cast<backgroundMesh2D*>(BGMManager::get(gf)); stringstream ss2; // ss2 << "basebg_sizefield_" << gf->tag() << ".pos"; // bgm2->exportSizeField(ss2.str()); // // // // return; // BGMManager::set_use_cross_field(true); const bool goNonLinear = true; const bool debug = false; const bool export_stuff = true; if(debug) std::cout << "ENTERING POINTINSERTION2D" << std::endl; double a; // acquire background mesh if(debug) std::cout << "pointInsertion2D: recover BGM" << std::endl; a = Cpu(); frameFieldBackgroundMesh2D *bgm = dynamic_cast<frameFieldBackgroundMesh2D *>(BGMManager::get(gf)); time_bgm_and_smoothing += (Cpu() - a); if(!bgm) { Msg::Error("BGM dynamic cast failed in filler2D::pointInsertion2D"); return; } // export BGM size field if(export_stuff) { std::cout << "pointInsertion2D: export size field " << std::endl; std::stringstream ss; ss << "bg2D_sizefield_" << gf->tag() << ".pos"; bgm->exportSizeField(ss.str()); std::cout << "pointInsertion2D : export crossfield " << std::endl; std::stringstream sscf; sscf << "bg2D_crossfield_" << gf->tag() << ".pos"; bgm->exportCrossField(sscf.str()); std::cout << "pointInsertion2D : export smoothness " << std::endl; std::stringstream sss; sss << "bg2D_smoothness_" << gf->tag() << ".pos"; bgm->exportSmoothness(sss.str()); } // point insertion algorithm: a = Cpu(); // for debug check... int priority_counter = 0; std::map<MVertex *, int> vert_priority; // get all the boundary vertices if(debug) std::cout << "pointInsertion2D : get bnd vertices " << std::endl; std::set<MVertex *> bnd_vertices = bgm->get_vertices_of_maximum_dim(1); // put boundary vertices in a fifo queue std::set<smoothness_point_pair, compareSurfacePointWithExclusionRegionPtr_Smoothness> fifo; std::vector<surfacePointWithExclusionRegion *> vertices; // initiate the rtree if(debug) std::cout << "pointInsertion2D : initiate RTree " << std::endl; RTree<surfacePointWithExclusionRegion *, double, 2, double> rtree; SMetric3 metricField(1.0); SPoint2 newp[4][NUMDIR]; std::set<MVertex *>::iterator it = bnd_vertices.begin(); for(; it != bnd_vertices.end(); ++it) { SPoint2 midpoint; computeFourNeighbors(bgm, *it, midpoint, goNonLinear, newp, metricField); surfacePointWithExclusionRegion *sp = new surfacePointWithExclusionRegion(*it, newp, midpoint, metricField); smoothness_point_pair mp; mp.ptr = sp; mp.rank = (1. - bgm->get_smoothness(midpoint[0], midpoint[1])); fifo.insert(mp); vertices.push_back(sp); double _min[2], _max[2]; sp->minmax(_min, _max); rtree.Insert(_min, _max, sp); } // ---------- main loop ----------------- while(!fifo.empty()) { if(debug) std::cout << " -------- fifo.size() = " << fifo.size() << std::endl; int count_nbaddedpt = 0; surfacePointWithExclusionRegion *parent = (*fifo.begin()).ptr; fifo.erase(fifo.begin()); for(int dir = 0; dir < NUMDIR; dir++) { for(int i = 0; i < 4; i++) { if(!inExclusionZone(parent->_p[i][dir], rtree, vertices)) { GPoint gp = gf->point(parent->_p[i][dir]); MFaceVertex *v = new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, gp.u(), gp.v()); SPoint2 midpoint; computeFourNeighbors(bgm, v, midpoint, goNonLinear, newp, metricField); surfacePointWithExclusionRegion *sp = new surfacePointWithExclusionRegion(v, newp, midpoint, metricField, parent); smoothness_point_pair mp; mp.ptr = sp; mp.rank = (1. - bgm->get_smoothness(gp.u(), gp.v())); if(debug) vert_priority[v] = priority_counter++; fifo.insert(mp); vertices.push_back(sp); double _min[2], _max[2]; sp->minmax(_min, _max); rtree.Insert(_min, _max, sp); if(debug) { std::cout << " adding node (" << sp->_v->x() << "," << sp->_v->y() << "," << sp->_v->z() << ")" << std::endl; std::cout << " ----------------------------- sub --- fifo.size() = " << fifo.size() << std::endl; } count_nbaddedpt++; } } } if(debug) std::cout << "////////// nbre of added point: " << count_nbaddedpt << std::endl; } time_insertion += (Cpu() - a); if(debug) { std::stringstream ss; ss << "priority_" << gf->tag() << ".pos"; print_nodal_info(ss.str().c_str(), vert_priority); ss.clear(); } // add the vertices as additional vertices in the // surface mesh char ccc[256]; sprintf(ccc, "points%d.pos", gf->tag()); FILE *f = Fopen(ccc, "w"); if(f) { fprintf(f, "View \"\"{\n"); for(unsigned int i = 0; i < vertices.size(); i++) { vertices[i]->print(f, i); if(vertices[i]->_v->onWhat() == gf) { packed.push_back(vertices[i]->_v); metrics.push_back(vertices[i]->_meshMetric); SPoint2 midpoint; reparamMeshVertexOnFace(vertices[i]->_v, gf, midpoint); } delete vertices[i]; } fprintf(f, "};"); fclose(f); } }
double highOrderTools::smooth_metric_(std::vector<MElement*> & v, GFace *gf, dofManager<double> &myAssembler, std::set<MVertex*> &verticesToMove, elasticityTerm &El) { std::set<MVertex*>::iterator it; double dx = 0.0; if (myAssembler.sizeOfR()){ // while convergence for (unsigned int i = 0; i < v.size(); i++){ MElement *e = v[i]; int nbNodes = e->getNumVertices(); const int n2 = 2 * nbNodes; const int n3 = 3 * nbNodes; fullMatrix<double> K33(n3, n3); fullMatrix<double> K22(n2, n2); fullMatrix<double> J32(n3, n2); fullMatrix<double> J23(n2, n3); fullVector<double> D3(n3); fullVector<double> R2(n2); fullMatrix<double> J23K33(n2, n3); K33.setAll(0.0); SElement se(e); El.elementMatrix(&se, K33); computeMetricInfo(gf, e, J32, J23, D3); J23K33.gemm(J23, K33, 1, 0); K22.gemm(J23K33, J32, 1, 0); J23K33.mult(D3, R2); for (int j = 0; j < n2; j++){ Dof RDOF = El.getLocalDofR(&se, j); myAssembler.assemble(RDOF, -R2(j)); for (int k = 0; k < n2; k++){ Dof CDOF = El.getLocalDofC(&se, k); myAssembler.assemble(RDOF, CDOF, K22(j, k)); } } } myAssembler.systemSolve(); // for all element, compute detJ at integration points --> material law end // while convergence for (it = verticesToMove.begin(); it != verticesToMove.end(); ++it){ if ((*it)->onWhat()->dim() == 2){ SPoint2 param; reparamMeshVertexOnFace((*it), gf, param); SPoint2 dparam; myAssembler.getDofValue((*it), 0, _tag, dparam[0]); myAssembler.getDofValue((*it), 1, _tag, dparam[1]); SPoint2 newp = param+dparam; dx += newp.x() * newp.x() + newp.y() * newp.y(); (*it)->setParameter(0, newp.x()); (*it)->setParameter(1, newp.y()); } } myAssembler.systemClear(); } return dx; }
bool gmshFace::buildSTLTriangulation(bool force) { return false; if(va_geom_triangles){ if(force) delete va_geom_triangles; else return true; } stl_vertices.clear(); stl_triangles.clear(); #if defined(HAVE_MESH) if (!triangles.size()){ contextMeshOptions _temp = CTX::instance()->mesh; FieldManager *fields = model()->getFields(); int BGM = fields->getBackgroundField(); fields->setBackgroundField(0); CTX::instance()->mesh.lcFromPoints = 0; CTX::instance()->mesh.lcFromCurvature = 1; CTX::instance()->mesh.lcExtendFromBoundary = 0; CTX::instance()->mesh.scalingFactor = 1; CTX::instance()->mesh.lcFactor = 1; CTX::instance()->mesh.order = 1; CTX::instance()->mesh.lcIntegrationPrecision = 1.e-3; // CTX::instance()->mesh.Algorithm = 5; model()->mesh(2); CTX::instance()->mesh = _temp; fields->setBackgroundField(fields->get(BGM)); } #endif std::map<MVertex*,int> _v; int COUNT =0; for (unsigned int j = 0; j < triangles.size(); j++){ for (int i = 0; i < 3; i++){ std::map<MVertex*,int>::iterator it = _v.find(triangles[j]->getVertex(j)); if (it != _v.end()){ stl_triangles.push_back(COUNT); _v[triangles[j]->getVertex(j)] = COUNT++; } else stl_triangles.push_back(it->second); } } std::map<MVertex*,int>::iterator itv = _v.begin(); for ( ; itv != _v.end() ; ++itv){ MVertex *v = itv->first; SPoint2 param; reparamMeshVertexOnFace(v, this, param); stl_vertices.push_back(param); } va_geom_triangles = new VertexArray(3, stl_triangles.size() / 3); unsigned int c = CTX::instance()->color.geom.surface; unsigned int col[4] = {c, c, c, c}; for (unsigned int i = 0; i < stl_triangles.size(); i += 3){ SPoint2 &p1(stl_vertices[stl_triangles[i]]); SPoint2 &p2(stl_vertices[stl_triangles[i + 1]]); SPoint2 &p3(stl_vertices[stl_triangles[i + 2]]); GPoint gp1 = GFace::point(p1); GPoint gp2 = GFace::point(p2); GPoint gp3 = GFace::point(p3); double x[3] = {gp1.x(), gp2.x(), gp3.x()}; double y[3] = {gp1.y(), gp2.y(), gp3.y()}; double z[3] = {gp1.z(), gp2.z(), gp3.z()}; SVector3 n[3] = {normal(p1), normal(p2), normal(p3)}; va_geom_triangles->add(x, y, z, n, col); } va_geom_triangles->finalize(); return true; }
static void Subdivide(GFace *gf, bool splitIntoQuads, bool splitIntoHexas, faceContainer &faceVertices) { if(!splitIntoQuads && !splitIntoHexas){ std::vector<MTriangle*> triangles2; for(unsigned int i = 0; i < gf->triangles.size(); i++){ MTriangle *t = gf->triangles[i]; if(t->getNumVertices() == 6){ triangles2.push_back (new MTriangle(t->getVertex(0), t->getVertex(3), t->getVertex(5))); triangles2.push_back (new MTriangle(t->getVertex(3), t->getVertex(4), t->getVertex(5))); triangles2.push_back (new MTriangle(t->getVertex(3), t->getVertex(1), t->getVertex(4))); triangles2.push_back (new MTriangle(t->getVertex(5), t->getVertex(4), t->getVertex(2))); } delete t; } gf->triangles = triangles2; } std::vector<MQuadrangle*> quadrangles2; for(unsigned int i = 0; i < gf->quadrangles.size(); i++){ MQuadrangle *q = gf->quadrangles[i]; if(q->getNumVertices() == 9){ quadrangles2.push_back (new MQuadrangle(q->getVertex(0), q->getVertex(4), q->getVertex(8), q->getVertex(7))); quadrangles2.push_back (new MQuadrangle(q->getVertex(4), q->getVertex(1), q->getVertex(5), q->getVertex(8))); quadrangles2.push_back (new MQuadrangle(q->getVertex(8), q->getVertex(5), q->getVertex(2), q->getVertex(6))); quadrangles2.push_back (new MQuadrangle(q->getVertex(7), q->getVertex(8), q->getVertex(6), q->getVertex(3))); } delete q; } if(splitIntoQuads || splitIntoHexas){ for(unsigned int i = 0; i < gf->triangles.size(); i++){ MTriangle *t = gf->triangles[i]; if(t->getNumVertices() == 6){ SPoint2 pt; SPoint3 ptx; t->pnt(0.5, 0.5, 0, ptx); bool reparamOK = true; for(int k = 0; k < 6; k++){ SPoint2 temp; reparamOK &= reparamMeshVertexOnFace(t->getVertex(k), gf, temp); pt[0] += temp[0] / 6.; pt[1] += temp[1] / 6.; } MVertex *newv; if (reparamOK){ GPoint gp = gf->point(pt); newv = new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, pt[0], pt[1]); } else { newv = new MVertex(ptx.x(), ptx.y(), ptx.z(), gf); } gf->mesh_vertices.push_back(newv); if(splitIntoHexas) faceVertices[t->getFace(0)].push_back(newv); quadrangles2.push_back (new MQuadrangle(t->getVertex(0), t->getVertex(3), newv, t->getVertex(5))); quadrangles2.push_back (new MQuadrangle(t->getVertex(3), t->getVertex(1), t->getVertex(4), newv)); quadrangles2.push_back (new MQuadrangle(t->getVertex(5), newv,t->getVertex(4), t->getVertex(2))); delete t; } } gf->triangles.clear(); } gf->quadrangles = quadrangles2; for(unsigned int i = 0; i < gf->mesh_vertices.size(); i++) gf->mesh_vertices[i]->setPolynomialOrder(1); gf->deleteVertexArrays(); }