// sets the entity m from which the mesh will be copied void GEntity::setMeshMaster(int m_signed) { if(m_signed == tag()){ _meshMaster = m_signed; return; } GEntity *gMaster = 0; int m = abs(m_signed); switch(dim()){ case 0 : gMaster = model()->getVertexByTag(m); break; case 1 : gMaster = model()->getEdgeByTag(m); break; case 2 : gMaster = model()->getFaceByTag(m); break; case 3 : gMaster = model()->getRegionByTag(m); break; } if (!gMaster){ Msg::Error("Model entity %d of dimension %d cannot be the mesh master of entity %d", m, dim(), tag()); return; } int masterOfMaster = gMaster->meshMaster(); if (masterOfMaster == gMaster->tag()){ _meshMaster = m_signed; } else { setMeshMaster ( masterOfMaster * ((m_signed > 0) ? 1 : -1)); } }
int main(int argc, char **argv) { GmshInitialize(argc, argv); GmshSetOption("Mesh", "Algorithm", 5.); GmshSetOption("General", "Terminal", 1.); GModel *m = new GModel(); m->readMSH("bunny.msh"); m->fillVertexArrays(); std::vector<GEntity*> entities; m->getEntities(entities); for(unsigned int i = 0; i < entities.size(); i++){ GEntity *ge = entities[i]; printf("coucou entite %d (dimension %d)\n", ge->tag(), ge->dim()); if(ge->va_triangles) printf(" j'ai un va de triangles: %d vertex\n", ge->va_triangles->getNumVertices()); if(ge->va_lines) printf(" j'ai un va de lignes: %d vertex\n", ge->va_lines->getNumVertices()); } delete m; GmshFinalize(); }
// gets the entity from which the mesh will be copied int GEntity::meshMaster() const { if (_meshMaster == tag()) return tag(); GEntity *gMaster = 0; switch(dim()){ case 0 : gMaster = model()->getVertexByTag(abs(_meshMaster)); break; case 1 : gMaster = model()->getEdgeByTag(abs(_meshMaster)); break; case 2 : gMaster = model()->getFaceByTag(abs(_meshMaster)); break; case 3 : gMaster = model()->getRegionByTag(abs(_meshMaster)); break; } if (!gMaster){ Msg::Error("Could not find mesh master entity %d",_meshMaster); return tag(); } int masterOfMaster = gMaster->meshMaster(); if (masterOfMaster == gMaster->tag()){ return _meshMaster ; } else { return gMaster->meshMaster() * ((_meshMaster > 0) ? 1 : -1); } }
void updateBoVec<2, MEdge>( const int normalSource, const MVertex *const vertex, const int zoneIndex, const int vertIndex, const CCon::FaceVector<MZoneBoundary<2>::GlobalVertexData<MEdge>::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: /*--------------------------------------------------------------------* * In this case, there are possibly two GEdges from this zone * connected to the vertex. If the angle between the two edges is * significant, the BC patch will be split and this vertex will be * written in both patches with different normals. If the angle is * small, or only one GEdge belongs to this zone, then the vertex will * only be written to one patch. *--------------------------------------------------------------------*/ { // Find edge entities that are connected to elements in the zone std::vector<std::pair<GEdge *, int> > useGEdge; const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(zoneIndex == faces[iFace].zoneIndex) { MEdge mEdge = faces[iFace].parentElement->getEdge(faces[iFace].parentFace); // Get the other vertex on the mesh edge. MVertex *vertex2 = mEdge.getMinVertex(); if(vertex2 == vertex) vertex2 = mEdge.getMaxVertex(); // Check if the entity associated with vertex2 is a line and // is also connected to vertex. If so, add it to the container of // edge entities that will be used to determine the normal GEntity *const ent2 = vertex2->onWhat(); if(ent2->dim() == 1) { useGEdge.push_back( std::pair<GEdge *, int>(static_cast<GEdge *>(ent2), iFace)); } } } //--'useGEdge' now contains the edge entities that will be used to // determine //--the normals switch(useGEdge.size()) { case 0: // goto getNormalFromElements; // We probably don't want BC data if none of the faces attatched to // this vertex and in this zone are on the boundary. break; case 1: { const GEdge *const gEdge = static_cast<const GEdge *>(useGEdge[0].first); SVector3 boNormal; if(edge_normal(vertex, zoneIndex, gEdge, faces, boNormal)) goto getNormalFromElements; zoneBoVec.push_back(VertexBoundary(zoneIndex, gEdge->tag(), boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gEdge->tag()); } break; case 2: { // Get the first normal const GEdge *const gEdge1 = static_cast<const GEdge *>(useGEdge[0].first); SVector3 boNormal1; if(edge_normal(vertex, zoneIndex, gEdge1, faces, boNormal1, useGEdge[0].second)) goto getNormalFromElements; // Get the second normal const GEdge *const gEdge2 = static_cast<const GEdge *>(useGEdge[1].first); SVector3 boNormal2; if(edge_normal(vertex, zoneIndex, gEdge2, faces, boNormal2, useGEdge[1].second)) goto getNormalFromElements; if(dot(boNormal1, boNormal2) < 0.98) { //--Write 2 separate patches zoneBoVec.push_back( VertexBoundary(zoneIndex, gEdge1->tag(), boNormal1, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gEdge1->tag()); zoneBoVec.push_back( VertexBoundary(zoneIndex, gEdge2->tag(), boNormal2, const_cast<MVertex *>(vertex), vertIndex)); patch.add(gEdge2->tag()); } else { //--Write one patch boNormal1 += boNormal2; boNormal1 *= 0.5; zoneBoVec.push_back( VertexBoundary(zoneIndex, gEdge1->tag(), boNormal1, const_cast<MVertex *>(vertex), vertIndex)); patch.addPair(gEdge1->tag(), gEdge2->tag()); } } break; default: Msg::Error("Internal error based on 2-D boundary assumptions (file " "\'MZoneBoundary.cpp'). Boundary vertices may be " "incorrect"); break; } } break; case 1: /*--------------------------------------------------------------------* * The vertex exists on an edge and belongs to only 1 BC patch. *--------------------------------------------------------------------*/ { SVector3 boNormal; if(edge_normal(vertex, zoneIndex, static_cast<const GEdge *>(ent), faces, boNormal)) goto getNormalFromElements; zoneBoVec.push_back(VertexBoundary(zoneIndex, ent->tag(), boNormal, const_cast<MVertex *>(vertex), vertIndex)); patch.add(ent->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; } // The mesh plane normal is computed from all elements attached to the // vertex SVector3 meshPlaneNormal(0.); // This normal is perpendicular to the // plane of the mesh const int nFace = faces.size(); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { // Make sure all the planes go in the same direction //**Required? SVector3 mpnt = faces[iFace].parentElement->getFace(0).normal(); if(dot(mpnt, meshPlaneNormal) < 0.) mpnt.negate(); meshPlaneNormal += mpnt; } } // Sum the normals from each element. The tangent is computed from all // faces in the zone attached to the vertex and is weighted by the length of // the edge. Each tangent has to be converted independently into an // inwards-pointing normal. SVector3 boNormal(0.); for(int iFace = 0; iFace != nFace; ++iFace) { if(faces[iFace].zoneIndex == zoneIndex) { const SVector3 tangent = faces[iFace] .parentElement->getEdge(faces[iFace].parentFace) .tangent(); // Normal to the boundary (unknown direction) SVector3 bnt = crossprod(tangent, meshPlaneNormal); // 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); } }
// Main function for fast curving void HighOrderMeshFastCurving(GModel *gm, FastCurvingParameters &p) { double t1 = Cpu(); Msg::StatusBar(true, "Optimizing high order mesh..."); std::vector<GEntity*> allEntities; gm->getEntities(allEntities); // Compute vert. -> elt. connectivity Msg::Info("Computing connectivity..."); std::map<MVertex*, std::vector<MElement *> > vertex2elements; for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) calcVertex2Elements(p.dim, allEntities[iEnt], vertex2elements); // Get BL field (if any) BoundaryLayerField *blf = getBLField(gm); // Build multimap of each geometric entity to its boundaries std::multimap<GEntity*,GEntity*> entities; if (blf) { // BF field? for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) { GEntity* &entity = allEntities[iEnt]; if (entity->dim() == p.dim && (!p.onlyVisible || entity->getVisibility())) // Consider only "domain" entities if (p.dim == 2) { // "Domain" face? std::list<GEdge*> edges = entity->edges(); for (std::list<GEdge*>::iterator itEd = edges.begin(); itEd != edges.end(); itEd++) // Loop over model boundary edges if (blf->isEdgeBL((*itEd)->tag())) // Already skip model edge if no BL there entities.insert(std::pair<GEntity*,GEntity*>(entity, *itEd)); } else if (p.dim == 3) { // "Domain" region? std::list<GFace*> faces = entity->faces(); for (std::list<GFace*>::iterator itF = faces.begin(); itF != faces.end(); itF++) // Loop over model boundary faces if (blf->isFaceBL((*itF)->tag())) // Already skip model face if no BL there entities.insert(std::pair<GEntity*,GEntity*>(entity, *itF)); } } } else { // No BL field for (int iEnt = 0; iEnt < allEntities.size(); ++iEnt) { GEntity* &entity = allEntities[iEnt]; if (entity->dim() == p.dim-1 && (!p.onlyVisible || entity->getVisibility())) // Consider boundary entities entities.insert(std::pair<GEntity*,GEntity*>(0, entity)); } } // Build normals if necessary std::map<GEntity*, std::map<MVertex*, SVector3> > normVertEnt; // Normal to each vertex for each geom. entity if (!blf) { Msg::Warning("Boundary layer data not found, trying to detect columns"); buildNormals(vertex2elements, entities, p, normVertEnt); } // Loop over geometric entities for (std::multimap<GEntity*,GEntity*>::iterator itBE = entities.begin(); itBE != entities.end(); itBE++) { GEntity *domEnt = itBE->first, *bndEnt = itBE->second; BoundaryLayerColumns *blc = 0; if (blf) { Msg::Info("Curving elements for entity %d bounding entity %d...", bndEnt->tag(), domEnt->tag()); if (p.dim == 2) blc = domEnt->cast2Face()->getColumns(); else if (p.dim == 3) blc = domEnt->cast2Region()->getColumns(); else Msg::Error("Fast curving implemented only in dim. 2 and 3"); } else Msg::Info("Curving elements for boundary entity %d...", bndEnt->tag()); std::map<MVertex*, SVector3> &normVert = normVertEnt[bndEnt]; curveMeshFromBnd(vertex2elements, normVert, blc, bndEnt, p); } double t2 = Cpu(); Msg::StatusBar(true, "Done curving high order mesh (%g s)", t2-t1); }