PyObject* FemMeshPy::addEdge(PyObject *args) { int n1,n2; if (!PyArg_ParseTuple(args, "ii",&n1,&n2)) return 0; try { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); if (!node1 || !node2) throw std::runtime_error("Failed to get node of the given indices"); SMDS_MeshEdge* edge = meshDS->AddEdge(node1, node2); if (!edge) throw std::runtime_error("Failed to add edge"); return Py::new_reference_to(Py::Int(edge->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::BaseExceptionFreeCADError, e.what()); return 0; } }
PyObject* FemMeshPy::addFace(PyObject *args) { int n1,n2,n3; if (!PyArg_ParseTuple(args, "iii",&n1,&n2,&n3)) return 0; try { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); const SMDS_MeshNode* node3 = meshDS->FindNode(n3); if (!node1 || !node2 || !node3) throw std::runtime_error("Failed to get node of the given indices"); SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3); if (!face) throw std::runtime_error("Failed to add face"); return Py::new_reference_to(Py::Int(face->GetID())); } catch (const std::exception& e) { PyErr_SetString(PyExc_Exception, e.what()); return 0; } }
TSideVector StdMeshers_FaceSide::GetFaceWires(const TopoDS_Face& theFace, SMESH_Mesh & theMesh, const bool theIgnoreMediumNodes, TError & theError) { TopoDS_Vertex V1; list< TopoDS_Edge > edges; list< int > nbEdgesInWires; int nbWires = SMESH_Block::GetOrderedEdges (theFace, V1, edges, nbEdgesInWires); // split list of all edges into separate wires TSideVector wires( nbWires ); list< int >::iterator nbE = nbEdgesInWires.begin(); list< TopoDS_Edge >::iterator from, to; from = to = edges.begin(); for ( int iW = 0; iW < nbWires; ++iW ) { std::advance( to, *nbE++ ); list< TopoDS_Edge > wireEdges( from, to ); // assure that there is a node on the first vertex // as StdMeshers_FaceSide::GetUVPtStruct() requires while ( !SMESH_Algo::VertexNode( TopExp::FirstVertex( wireEdges.front(), true), theMesh.GetMeshDS())) { wireEdges.splice(wireEdges.end(), wireEdges, wireEdges.begin(), ++wireEdges.begin()); if ( from->IsSame( wireEdges.front() )) { theError = TError ( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"No nodes on vertices")); return TSideVector(0); } } // find out side orientation, which is important if there are several wires (PAL19080) bool isForward = true; if ( nbWires > 1 ) { TopExp_Explorer e( theFace, TopAbs_EDGE ); while ( ! e.Current().IsSame( wireEdges.back() )) e.Next(); isForward = ( e.Current().Orientation() == wireEdges.back().Orientation() ); } StdMeshers_FaceSide* wire = new StdMeshers_FaceSide( theFace, wireEdges, &theMesh, isForward, theIgnoreMediumNodes); wires[ iW ] = StdMeshers_FaceSidePtr( wire ); from = to; } return wires; }
bool EvaluatePentahedralMesh(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, MapShapeNbElems& aResMap) { StdMeshers_Penta_3D anAlgo; bool bOK = anAlgo.Evaluate(aMesh, aShape, aResMap); //err = anAlgo.GetComputeError(); //if ( !bOK && anAlgo.ErrorStatus() == 5 ) if( !bOK ) { static StdMeshers_Prism_3D * aPrism3D = 0; if ( !aPrism3D ) { SMESH_Gen* gen = aMesh.GetGen(); aPrism3D = new StdMeshers_Prism_3D( gen->GetANewId(), 0, gen ); } SMESH_Hypothesis::Hypothesis_Status aStatus; if ( aPrism3D->CheckHypothesis( aMesh, aShape, aStatus ) ) { return aPrism3D->Evaluate(aMesh, aShape, aResMap); } } return bOK; }
bool NETGENPlugin_NETGEN_3D::Evaluate(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, MapShapeNbElems& aResMap) { int nbtri = 0, nbqua = 0; double fullArea = 0.0; for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) { TopoDS_Face F = TopoDS::Face( exp.Current() ); SMESH_subMesh *sm = aMesh.GetSubMesh(F); MapShapeNbElemsItr anIt = aResMap.find(sm); if( anIt==aResMap.end() ) { SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); return false; } std::vector<int> aVec = (*anIt).second; nbtri += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]); nbqua += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]); GProp_GProps G; BRepGProp::SurfaceProperties(F,G); double anArea = G.Mass(); fullArea += anArea; } // collect info from edges int nb0d_e = 0, nb1d_e = 0; bool IsQuadratic = false; bool IsFirst = true; TopTools_MapOfShape tmpMap; for (TopExp_Explorer exp(aShape, TopAbs_EDGE); exp.More(); exp.Next()) { TopoDS_Edge E = TopoDS::Edge(exp.Current()); if( tmpMap.Contains(E) ) continue; tmpMap.Add(E); SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); if( anIt==aResMap.end() ) { SMESH_ComputeErrorPtr& smError = aSubMesh->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED, "Submesh can not be evaluated",this)); return false; } std::vector<int> aVec = (*anIt).second; nb0d_e += aVec[SMDSEntity_Node]; nb1d_e += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]); if(IsFirst) { IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]); IsFirst = false; } } tmpMap.Clear(); double ELen_face = sqrt(2.* ( fullArea/(nbtri+nbqua*2) ) / sqrt(3.0) ); double ELen_vol = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. ); double ELen = Min(ELen_vol,ELen_face*2); GProp_GProps G; BRepGProp::VolumeProperties(aShape,G); double aVolume = G.Mass(); double tetrVol = 0.1179*ELen*ELen*ELen; double CoeffQuality = 0.9; int nbVols = (int)aVolume/tetrVol/CoeffQuality; int nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2; int nb1d_in = (int) ( nbVols*6 - nb1d_e - nb1d_f ) / 5; std::vector<int> aVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i]=0; if( IsQuadratic ) { aVec[SMDSEntity_Node] = nb1d_in/6 + 1 + nb1d_in; aVec[SMDSEntity_Quad_Tetra] = nbVols - nbqua*2; aVec[SMDSEntity_Quad_Pyramid] = nbqua; } else { aVec[SMDSEntity_Node] = nb1d_in/6 + 1; aVec[SMDSEntity_Tetra] = nbVols - nbqua*2; aVec[SMDSEntity_Pyramid] = nbqua; } SMESH_subMesh *sm = aMesh.GetSubMesh(aShape); aResMap.insert(std::make_pair(sm,aVec)); return true; }
bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh& aMesh, SMESH_MesherHelper& helper, vector< const SMDS_MeshNode* >& nodeVec, Ng_Mesh * Netgen_mesh) { netgen::multithread.terminate = 0; netgen::Mesh* ngMesh = (netgen::Mesh*)Netgen_mesh; int Netgen_NbOfNodes = Ng_GetNP(Netgen_mesh); #if NETGEN_VERSION < 5 char *optstr = 0; #endif int startWith = netgen::MESHCONST_MESHVOLUME; int endWith = netgen::MESHCONST_OPTVOLUME; int err = 1; NETGENPlugin_Mesher aMesher( &aMesh, helper.GetSubShape(), /*isVolume=*/true ); netgen::OCCGeometry occgeo; if ( _hypParameters ) { aMesher.SetParameters( _hypParameters ); if ( !_hypParameters->GetOptimize() ) endWith = netgen::MESHCONST_MESHVOLUME; } else if ( _hypMaxElementVolume ) { netgen::mparam.maxh = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. ); // limitVolumeSize( ngMesh, netgen::mparam.maxh ); // result is unpredictable } else if ( aMesh.HasShapeToMesh() ) { aMesher.PrepareOCCgeometry( occgeo, helper.GetSubShape(), aMesh ); netgen::mparam.maxh = occgeo.GetBoundingBox().Diam()/2; } else { netgen::Point3d pmin, pmax; ngMesh->GetBox (pmin, pmax); netgen::mparam.maxh = Dist(pmin, pmax)/2; } if ( !_hypParameters && aMesh.HasShapeToMesh() ) { netgen::mparam.minh = aMesher.GetDefaultMinSize( helper.GetSubShape(), netgen::mparam.maxh ); } try { OCC_CATCH_SIGNALS; #if NETGEN_VERSION > 4 ngMesh->CalcLocalH(netgen::mparam.grading); err = netgen::OCCGenerateMesh(occgeo, ngMesh, netgen::mparam, startWith, endWith); #else ngMesh->CalcLocalH(); err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr); #endif if(netgen::multithread.terminate) return false; if ( err ) error(SMESH_Comment("Error in netgen::OCCGenerateMesh() at ") << netgen::multithread.task); } catch (Standard_Failure& ex) { SMESH_Comment str("Exception in netgen::OCCGenerateMesh()"); str << " at " << netgen::multithread.task << ": " << ex.DynamicType()->Name(); if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) str << ": " << ex.GetMessageString(); error(str); } catch (netgen::NgException exc) { SMESH_Comment str("NgException"); if ( strlen( netgen::multithread.task ) > 0 ) str << " at " << netgen::multithread.task; str << ": " << exc.What(); error(str); } catch (...) { SMESH_Comment str("Exception in netgen::OCCGenerateMesh()"); if ( strlen( netgen::multithread.task ) > 0 ) str << " at " << netgen::multithread.task; error(str); } int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh); int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh); MESSAGE("End of Volume Mesh Generation. err=" << err << ", nb new nodes: " << Netgen_NbOfNodesNew - Netgen_NbOfNodes << ", nb tetra: " << Netgen_NbOfTetra); // ------------------------------------------------------------------- // Feed back the SMESHDS with the generated Nodes and Volume Elements // ------------------------------------------------------------------- if ( err ) { SMESH_ComputeErrorPtr ce = NETGENPlugin_Mesher::ReadErrors(nodeVec); if ( ce && !ce->myBadElements.empty() ) error( ce ); } bool isOK = ( /*status == NG_OK &&*/ Netgen_NbOfTetra > 0 );// get whatever built if ( isOK ) { double Netgen_point[3]; int Netgen_tetrahedron[4]; // create and insert new nodes into nodeVec nodeVec.resize( Netgen_NbOfNodesNew + 1, 0 ); int nodeIndex = Netgen_NbOfNodes + 1; for ( ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex ) { Ng_GetPoint( Netgen_mesh, nodeIndex, Netgen_point ); nodeVec.at(nodeIndex) = helper.AddNode(Netgen_point[0], Netgen_point[1], Netgen_point[2]); } // create tetrahedrons for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex ) { Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron); try { helper.AddVolume (nodeVec.at( Netgen_tetrahedron[0] ), nodeVec.at( Netgen_tetrahedron[1] ), nodeVec.at( Netgen_tetrahedron[2] ), nodeVec.at( Netgen_tetrahedron[3] )); } catch (...) { } } } return !err; }
bool NETGENPlugin_NETGEN_2D_ONLY::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) { MESSAGE("NETGENPlugin_NETGEN_2D_ONLY::Compute()"); SMESHDS_Mesh* meshDS = aMesh.GetMeshDS(); int faceID = meshDS->ShapeToIndex( aShape ); SMESH_MesherHelper helper(aMesh); _quadraticMesh = helper.IsQuadraticSubMesh(aShape); helper.SetElementsOnShape( true ); const bool ignoreMediumNodes = _quadraticMesh; // ------------------------ // get all edges of a face // ------------------------ const TopoDS_Face F = TopoDS::Face( aShape.Oriented( TopAbs_FORWARD )); TError problem; TSideVector wires = StdMeshers_FaceSide::GetFaceWires( F, aMesh, ignoreMediumNodes, problem ); if ( problem && !problem->IsOK() ) return error( problem ); int nbWires = wires.size(); if ( nbWires == 0 ) return error( "Problem in StdMeshers_FaceSide::GetFaceWires()"); if ( wires[0]->NbSegments() < 3 ) // ex: a circle with 2 segments return error(COMPERR_BAD_INPUT_MESH, SMESH_Comment("Too few segments: ")<<wires[0]->NbSegments()); // ------------------------- // Make input netgen mesh // ------------------------- Ng_Init(); netgen::Mesh * ngMesh = new netgen::Mesh (); netgen::OCCGeometry occgeo; NETGENPlugin_Mesher::PrepareOCCgeometry( occgeo, F, aMesh ); occgeo.fmap.Clear(); // face can be reversed, which is wrong in this case (issue 19978) occgeo.fmap.Add( F ); vector< const SMDS_MeshNode* > nodeVec; problem = AddSegmentsToMesh( *ngMesh, occgeo, wires, helper, nodeVec ); if ( problem && !problem->IsOK() ) { delete ngMesh; Ng_Exit(); return error( problem ); } // -------------------- // compute edge length // -------------------- double edgeLength = 0; if (_hypLengthFromEdges || (!_hypLengthFromEdges && !_hypMaxElementArea)) { int nbSegments = 0; for ( int iW = 0; iW < nbWires; ++iW ) { edgeLength += wires[ iW ]->Length(); nbSegments += wires[ iW ]->NbSegments(); } if ( nbSegments ) edgeLength /= nbSegments; } if ( _hypMaxElementArea ) { double maxArea = _hypMaxElementArea->GetMaxArea(); edgeLength = sqrt(2. * maxArea/sqrt(3.0)); } if ( edgeLength < DBL_MIN ) edgeLength = occgeo.GetBoundingBox().Diam(); //cout << " edgeLength = " << edgeLength << endl; netgen::mparam.maxh = edgeLength; netgen::mparam.quad = _hypQuadranglePreference ? 1 : 0; //ngMesh->SetGlobalH ( edgeLength ); // ------------------------- // Generate surface mesh // ------------------------- char *optstr = 0; int startWith = MESHCONST_MESHSURFACE; int endWith = MESHCONST_OPTSURFACE; int err = 1; try { #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 OCC_CATCH_SIGNALS; #endif #ifdef NETGEN_V5 err = netgen::OCCGenerateMesh(occgeo, ngMesh,netgen::mparam, startWith, endWith); #else err = netgen::OCCGenerateMesh(occgeo, ngMesh, startWith, endWith, optstr); #endif } catch (Standard_Failure& ex) { string comment = ex.DynamicType()->Name(); if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) { comment += ": "; comment += ex.GetMessageString(); } error(COMPERR_OCC_EXCEPTION, comment); } catch (NgException exc) { error( SMESH_Comment("NgException: ") << exc.What() ); } catch (...) { error(COMPERR_EXCEPTION,"Exception in netgen::OCCGenerateMesh()"); } // ---------------------------------------------------- // Fill the SMESHDS with the generated nodes and faces // ---------------------------------------------------- int nbNodes = ngMesh->GetNP(); int nbFaces = ngMesh->GetNSE(); int nbInputNodes = nodeVec.size(); nodeVec.resize( nbNodes, 0 ); // add nodes for ( int i = nbInputNodes + 1; i <= nbNodes; ++i ) { const MeshPoint& ngPoint = ngMesh->Point(i); SMDS_MeshNode * node = meshDS->AddNode(ngPoint(0), ngPoint(1), ngPoint(2)); nodeVec[ i-1 ] = node; } // create faces bool reverse = ( aShape.Orientation() == TopAbs_REVERSED ); for ( int i = 1; i <= nbFaces ; ++i ) { const Element2d& elem = ngMesh->SurfaceElement(i); vector<const SMDS_MeshNode*> nodes( elem.GetNP() ); for (int j=1; j <= elem.GetNP(); ++j) { int pind = elem.PNum(j); const SMDS_MeshNode* node = nodeVec.at(pind-1); if ( reverse ) nodes[ nodes.size()-j ] = node; else nodes[ j-1 ] = node; if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE ) { const PointGeomInfo& pgi = elem.GeomInfoPi(j); meshDS->SetNodeOnFace((SMDS_MeshNode*)node, faceID, pgi.u, pgi.v); } } SMDS_MeshFace* face = 0; if ( elem.GetType() == TRIG ) face = helper.AddFace(nodes[0],nodes[1],nodes[2]); else face = helper.AddFace(nodes[0],nodes[1],nodes[2],nodes[3]); } Ng_DeleteMesh((nglib::Ng_Mesh*)ngMesh); Ng_Exit(); NETGENPlugin_Mesher::RemoveTmpFiles(); return !err; }
PyObject* FemMeshPy::addFace(PyObject *args) { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); int n1,n2,n3; if (PyArg_ParseTuple(args, "iii",&n1,&n2,&n3)) { // old form, deprecated try { const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); const SMDS_MeshNode* node3 = meshDS->FindNode(n3); if (!node1 || !node2 || !node3) throw std::runtime_error("Failed to get node of the given indices"); SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3); if (!face) throw std::runtime_error("Failed to add face"); return Py::new_reference_to(Py::Long(face->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::BaseExceptionFreeCADError, e.what()); return 0; } } PyErr_Clear(); PyObject *obj; int ElementId=-1; if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) { Py::List list(obj); std::vector<const SMDS_MeshNode*> Nodes; for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { #if PY_MAJOR_VERSION >= 3 Py::Long NoNr(*it); #else Py::Int NoNr(*it); #endif const SMDS_MeshNode* node = meshDS->FindNode(NoNr); if (!node) throw std::runtime_error("Failed to get node of the given indices"); Nodes.push_back(node); } SMDS_MeshFace* face=0; if(ElementId != -1) { switch(Nodes.size()){ case 3: face = meshDS->AddFaceWithID(Nodes[0],Nodes[1],Nodes[2],ElementId); if (!face) throw std::runtime_error("Failed to add triangular face with given ElementId"); break; case 4: face = meshDS->AddFaceWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],ElementId); if (!face) throw std::runtime_error("Failed to add face with given ElementId"); break; case 6: face = meshDS->AddFaceWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],ElementId); if (!face) throw std::runtime_error("Failed to add face with given ElementId"); break; case 8: face = meshDS->AddFaceWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],ElementId); if (!face) throw std::runtime_error("Failed to add face with given ElementId"); break; default: throw std::runtime_error("Unknown node count, [3|4|6|8] are allowed"); //unknown face type } }else{ switch(Nodes.size()){ case 3: face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2]); if (!face) throw std::runtime_error("Failed to add triangular face"); break; case 4: face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2],Nodes[3]); if (!face) throw std::runtime_error("Failed to add face"); break; case 6: face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5]); if (!face) throw std::runtime_error("Failed to add face"); break; case 8: face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7]); if (!face) throw std::runtime_error("Failed to add face"); break; default: throw std::runtime_error("Unknown node count, [4|5|6|8] are allowed"); //unknown face type } } return Py::new_reference_to(Py::Long(face->GetID())); } PyErr_SetString(PyExc_TypeError, "addFace accepts:\n" "-- int,int,int\n" "-- [3|4|6|8 int],[int]\n"); return 0; }
bool SMESH_Gen::IsGlobalHypothesis(const SMESH_Hypothesis* theHyp, SMESH_Mesh& aMesh) { SMESH_HypoFilter filter( SMESH_HypoFilter::Is( theHyp )); return aMesh.GetHypothesis( aMesh.GetMeshDS()->ShapeToMesh(), filter, false ); }
bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) { TopExp_Explorer exp; SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); myHelper = new SMESH_MesherHelper( aMesh ); myHelper->IsQuadraticSubMesh( aShape ); // to delete helper at exit from Compute() std::auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper ); // get 2 shells TopoDS_Solid solid = TopoDS::Solid( aShape ); TopoDS_Shell outerShell = BRepClass3d::OuterShell( solid ); TopoDS_Shape innerShell; int nbShells = 0; for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells ) if ( !outerShell.IsSame( It.Value() )) innerShell = It.Value(); if ( nbShells != 2 ) return error(COMPERR_BAD_SHAPE, SMESH_Comment("Must be 2 shells but not ")<<nbShells); // ---------------------------------- // Associate subshapes of the shells // ---------------------------------- TAssocTool::TShapeShapeMap shape2ShapeMap; if ( !TAssocTool::FindSubShapeAssociation( outerShell, &aMesh, innerShell, &aMesh, shape2ShapeMap) ) return error(COMPERR_BAD_SHAPE,"Topology of inner and outer shells seems different" ); // ------------------ // Make mesh // ------------------ TNode2ColumnMap node2columnMap; myLayerPositions.clear(); for ( exp.Init( outerShell, TopAbs_FACE ); exp.More(); exp.Next() ) { // Corresponding subshapes TopoDS_Face outFace = TopoDS::Face( exp.Current() ); TopoDS_Face inFace; if ( !shape2ShapeMap.IsBound( outFace )) { return error(SMESH_Comment("Corresponding inner face not found for face #" ) << meshDS->ShapeToIndex( outFace )); } else { inFace = TopoDS::Face( shape2ShapeMap( outFace )); } // Find matching nodes of in and out faces TNodeNodeMap nodeIn2OutMap; if ( ! TAssocTool::FindMatchingNodesOnFaces( inFace, &aMesh, outFace, &aMesh, shape2ShapeMap, nodeIn2OutMap )) return error(COMPERR_BAD_INPUT_MESH,SMESH_Comment("Mesh on faces #") << meshDS->ShapeToIndex( outFace ) << " and " << meshDS->ShapeToIndex( inFace ) << " seems different" ); // Create volumes SMDS_ElemIteratorPtr faceIt = meshDS->MeshElements( inFace )->GetElements(); while ( faceIt->more() ) // loop on faces on inFace { const SMDS_MeshElement* face = faceIt->next(); if ( !face || face->GetType() != SMDSAbs_Face ) continue; int nbNodes = face->NbNodes(); if ( face->IsQuadratic() ) nbNodes /= 2; // find node columns for each node vector< const TNodeColumn* > columns( nbNodes ); for ( int i = 0; i < nbNodes; ++i ) { const SMDS_MeshNode* nIn = face->GetNode( i ); TNode2ColumnMap::iterator n_col = node2columnMap.find( nIn ); if ( n_col != node2columnMap.end() ) { columns[ i ] = & n_col->second; } else { TNodeNodeMap::iterator nInOut = nodeIn2OutMap.find( nIn ); if ( nInOut == nodeIn2OutMap.end() ) RETURN_BAD_RESULT("No matching node for "<< nIn->GetID() << " in face "<< face->GetID()); columns[ i ] = makeNodeColumn( node2columnMap, nIn, nInOut->second ); } } StdMeshers_Prism_3D::AddPrisms( columns, myHelper ); } } // loop on faces of out shell return true; }
bool StdMeshers_Projection_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) { if ( !_sourceHypo ) return false; SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); SMESH_Mesh * tgtMesh = & aMesh; if ( !srcMesh ) srcMesh = tgtMesh; SMESHDS_Mesh * srcMeshDS = srcMesh->GetMeshDS(); SMESHDS_Mesh * tgtMeshDS = tgtMesh->GetMeshDS(); // get shell from shape3D TopoDS_Shell srcShell, tgtShell; TopExp_Explorer exp( _sourceHypo->GetSource3DShape(), TopAbs_SHELL ); int nbShell; for ( nbShell = 0; exp.More(); exp.Next(), ++nbShell ) srcShell = TopoDS::Shell( exp.Current() ); if ( nbShell != 1 ) return error(COMPERR_BAD_SHAPE, SMESH_Comment("Source shape must have 1 shell but not ") << nbShell); exp.Init( aShape, TopAbs_SHELL ); for ( nbShell = 0; exp.More(); exp.Next(), ++nbShell ) tgtShell = TopoDS::Shell( exp.Current() ); if ( nbShell != 1 ) return error(COMPERR_BAD_SHAPE, SMESH_Comment("Target shape must have 1 shell but not ") << nbShell); // Check that shapes are blocks if ( TAssocTool::Count( tgtShell, TopAbs_FACE , 1 ) != 6 || TAssocTool::Count( tgtShell, TopAbs_EDGE , 1 ) != 12 || TAssocTool::Count( tgtShell, TopAbs_WIRE , 1 ) != 6 ) return error(COMPERR_BAD_SHAPE, "Target shape is not a block"); if ( TAssocTool::Count( srcShell, TopAbs_FACE , 1 ) != 6 || TAssocTool::Count( srcShell, TopAbs_EDGE , 1 ) != 12 || TAssocTool::Count( srcShell, TopAbs_WIRE , 1 ) != 6 ) return error(COMPERR_BAD_SHAPE, "Source shape is not a block"); // Assure that mesh on a source shape is computed SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( _sourceHypo->GetSource3DShape() ); //SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( aShape ); if ( tgtMesh == srcMesh && !aShape.IsSame( _sourceHypo->GetSource3DShape() )) { if ( !TAssocTool::MakeComputed( srcSubMesh )) return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed"); } else { if ( !srcSubMesh->IsMeshComputed() ) return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed"); } // Find 2 pairs of corresponding vertices TopoDS_Vertex tgtV000, tgtV100, srcV000, srcV100; TAssocTool::TShapeShapeMap shape2ShapeMap; if ( _sourceHypo->HasVertexAssociation() ) { tgtV000 = _sourceHypo->GetTargetVertex(1); tgtV100 = _sourceHypo->GetTargetVertex(2); srcV000 = _sourceHypo->GetSourceVertex(1); srcV100 = _sourceHypo->GetSourceVertex(2); } else { if ( !TAssocTool::FindSubShapeAssociation( tgtShell, tgtMesh, srcShell, srcMesh, shape2ShapeMap) ) return error(COMPERR_BAD_SHAPE,"Topology of source and target shapes seems different" ); exp.Init( tgtShell, TopAbs_EDGE ); TopExp::Vertices( TopoDS::Edge( exp.Current() ), tgtV000, tgtV100 ); if ( !shape2ShapeMap.IsBound( tgtV000 ) || !shape2ShapeMap.IsBound( tgtV100 )) return error("Association of subshapes failed" ); srcV000 = TopoDS::Vertex( shape2ShapeMap( tgtV000 )); srcV100 = TopoDS::Vertex( shape2ShapeMap( tgtV100 )); if ( !TAssocTool::IsSubShape( srcV000, srcShell ) || !TAssocTool::IsSubShape( srcV100, srcShell )) return error("Incorrect association of subshapes" ); } // Load 2 SMESH_Block's with src and tgt shells SMESH_Block srcBlock, tgtBlock; TopTools_IndexedMapOfOrientedShape scrShapes, tgtShapes; if ( !tgtBlock.LoadBlockShapes( tgtShell, tgtV000, tgtV100, tgtShapes )) return error(COMPERR_BAD_SHAPE, "Can't detect block subshapes. Not a block?"); if ( !srcBlock.LoadBlockShapes( srcShell, srcV000, srcV100, scrShapes )) return error(COMPERR_BAD_SHAPE, "Can't detect block subshapes. Not a block?"); // Find matching nodes of src and tgt shells TNodeNodeMap src2tgtNodeMap; for ( int fId = SMESH_Block::ID_FirstF; fId < SMESH_Block::ID_Shell; ++fId ) { // Corresponding subshapes TopoDS_Face srcFace = TopoDS::Face( scrShapes( fId )); TopoDS_Face tgtFace = TopoDS::Face( tgtShapes( fId )); if ( _sourceHypo->HasVertexAssociation() ) { // associate face subshapes shape2ShapeMap.Clear(); vector< int > edgeIdVec; SMESH_Block::GetFaceEdgesIDs( fId, edgeIdVec ); for ( int i = 0; i < edgeIdVec.size(); ++i ) { int eID = edgeIdVec[ i ]; shape2ShapeMap.Bind( tgtShapes( eID ), scrShapes( eID )); if ( i < 2 ) { vector< int > vertexIdVec; SMESH_Block::GetEdgeVertexIDs( eID, vertexIdVec ); shape2ShapeMap.Bind( tgtShapes( vertexIdVec[0] ), scrShapes( vertexIdVec[0] )); shape2ShapeMap.Bind( tgtShapes( vertexIdVec[1] ), scrShapes( vertexIdVec[1] )); } } } // Find matching nodes of tgt and src faces TNodeNodeMap faceMatchingNodes; if ( ! TAssocTool::FindMatchingNodesOnFaces( srcFace, srcMesh, tgtFace, tgtMesh, shape2ShapeMap, faceMatchingNodes )) return error(COMPERR_BAD_INPUT_MESH,SMESH_Comment("Mesh on faces #") << srcMeshDS->ShapeToIndex( srcFace ) << " and " << tgtMeshDS->ShapeToIndex( tgtFace ) << " seems different" ); // put found matching nodes of 2 faces to the global map src2tgtNodeMap.insert( faceMatchingNodes.begin(), faceMatchingNodes.end() ); } // ------------------ // Make mesh // ------------------ SMDS_VolumeTool volTool; SMESH_MesherHelper helper( *tgtMesh ); helper.IsQuadraticSubMesh( aShape ); SMESHDS_SubMesh* srcSMDS = srcSubMesh->GetSubMeshDS(); SMDS_ElemIteratorPtr volIt = srcSMDS->GetElements(); while ( volIt->more() ) // loop on source volumes { const SMDS_MeshElement* srcVol = volIt->next(); if ( !srcVol || srcVol->GetType() != SMDSAbs_Volume ) continue; int nbNodes = srcVol->NbNodes(); SMDS_VolumeTool::VolumeType volType = volTool.GetType( nbNodes ); if ( srcVol->IsQuadratic() ) nbNodes = volTool.NbCornerNodes( volType ); // Find or create a new tgt node for each node of a src volume vector< const SMDS_MeshNode* > nodes( nbNodes ); for ( int i = 0; i < nbNodes; ++i ) { const SMDS_MeshNode* srcNode = srcVol->GetNode( i ); const SMDS_MeshNode* tgtNode = 0; TNodeNodeMap::iterator sN_tN = src2tgtNodeMap.find( srcNode ); if ( sN_tN != src2tgtNodeMap.end() ) // found { tgtNode = sN_tN->second; } else // Create a new tgt node { // compute normalized parameters of source node in srcBlock gp_Pnt srcCoord = gpXYZ( srcNode ); gp_XYZ srcParam; if ( !srcBlock.ComputeParameters( srcCoord, srcParam )) return error(SMESH_Comment("Can't compute normalized parameters ") << "for source node " << srcNode->GetID()); // compute coordinates of target node by srcParam gp_XYZ tgtXYZ; if ( !tgtBlock.ShellPoint( srcParam, tgtXYZ )) return error("Can't compute coordinates by normalized parameters"); // add node SMDS_MeshNode* newNode = tgtMeshDS->AddNode( tgtXYZ.X(), tgtXYZ.Y(), tgtXYZ.Z() ); tgtMeshDS->SetNodeInVolume( newNode, helper.GetSubShapeID() ); tgtNode = newNode; src2tgtNodeMap.insert( make_pair( srcNode, tgtNode )); } nodes[ i ] = tgtNode; } // Create a new volume SMDS_MeshVolume * tgtVol = 0; int id = 0, force3d = false; switch ( volType ) { case SMDS_VolumeTool::TETRA : case SMDS_VolumeTool::QUAD_TETRA: tgtVol = helper.AddVolume( nodes[0], nodes[1], nodes[2], nodes[3], id, force3d); break; case SMDS_VolumeTool::PYRAM : case SMDS_VolumeTool::QUAD_PYRAM: tgtVol = helper.AddVolume( nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], id, force3d); break; case SMDS_VolumeTool::PENTA : case SMDS_VolumeTool::QUAD_PENTA: tgtVol = helper.AddVolume( nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], id, force3d); break; case SMDS_VolumeTool::HEXA : case SMDS_VolumeTool::QUAD_HEXA : tgtVol = helper.AddVolume( nodes[0], nodes[1], nodes[2], nodes[3], nodes[4], nodes[5], nodes[6], nodes[7], id, force3d); break; default: // polyhedron const SMDS_PolyhedralVolumeOfNodes * poly = dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*>( srcVol ); if ( !poly ) RETURN_BAD_RESULT("Unexpected volume type"); tgtVol = tgtMeshDS->AddPolyhedralVolume( nodes, poly->GetQuanities() ); } if ( tgtVol ) { tgtMeshDS->SetMeshElementOnShape( tgtVol, helper.GetSubShapeID() ); } } // loop on volumes of src shell return true; }
bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, MapShapeNbElems& aResMap) { if( aShape.ShapeType() != TopAbs_FACE ) { return false; } SMESH_subMesh * smf = aMesh.GetSubMesh(aShape); MapShapeNbElemsItr anIt = aResMap.find(smf); if( anIt != aResMap.end() ) { return false; } myLayerPositions.clear(); gp_Pnt P0(0,0,0); gp_Pnt P1(100,0,0); computeLayerPositions(P0,P1); TopoDS_Edge E1,E2,E3; Handle(Geom_Curve) C1,C2,C3; double f1,l1,f2,l2,f3,l3; int nbe = 0; TopExp_Explorer exp; for ( exp.Init( aShape, TopAbs_EDGE ); exp.More(); exp.Next() ) { nbe++; TopoDS_Edge E = TopoDS::Edge( exp.Current() ); if(nbe==1) { E1 = E; C1 = BRep_Tool::Curve(E,f1,l1); } else if(nbe==2) { E2 = E; C2 = BRep_Tool::Curve(E,f2,l2); } else if(nbe==3) { E3 = E; C3 = BRep_Tool::Curve(E,f3,l3); } } TopoDS_Edge CircEdge, LinEdge1, LinEdge2; int nb0d=0, nb2d_tria=0, nb2d_quad=0; bool isQuadratic = false; if(nbe==1) { // C1 must be a circle Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(C1); if( !aCirc.IsNull() ) { bool ok = _gen->Evaluate( aMesh, CircEdge, aResMap ); if(ok) { SMESH_subMesh * sm = aMesh.GetSubMesh(CircEdge); MapShapeNbElemsItr anIt = aResMap.find(sm); vector<int> aVec = (*anIt).second; isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge]; if(isQuadratic) { // main nodes nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size(); // radial medium nodes nb0d += (aVec[SMDSEntity_Node]+1) * (myLayerPositions.size()+1); // other medium nodes nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size(); } else { nb0d = (aVec[SMDSEntity_Node]+1) * myLayerPositions.size(); } nb2d_tria = aVec[SMDSEntity_Node] + 1; nb2d_quad = nb0d; } } } else if(nbe==2) { // one curve must be a half of circle and other curve must be // a segment of line Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C1); while( !tc.IsNull() ) { C1 = tc->BasisCurve(); tc = Handle(Geom_TrimmedCurve)::DownCast(C1); } tc = Handle(Geom_TrimmedCurve)::DownCast(C2); while( !tc.IsNull() ) { C2 = tc->BasisCurve(); tc = Handle(Geom_TrimmedCurve)::DownCast(C2); } Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(C1); Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(C2); CircEdge = E1; LinEdge1 = E2; double fp = f1; double lp = l1; if( aCirc.IsNull() ) { aCirc = Handle(Geom_Circle)::DownCast(C2); CircEdge = E2; LinEdge1 = E1; fp = f2; lp = l2; aLine = Handle(Geom_Line)::DownCast(C3); } bool ok = !aCirc.IsNull() && !aLine.IsNull(); if( fabs(fabs(lp-fp)-M_PI) > Precision::Confusion() ) { // not half of circle ok = false; } SMESH_subMesh* sm1 = aMesh.GetSubMesh(LinEdge1); MapShapeNbElemsItr anIt = aResMap.find(sm1); if( anIt!=aResMap.end() ) { ok = false; } if(ok) { ok = _gen->Evaluate( aMesh, CircEdge, aResMap ); } if(ok) { SMESH_subMesh * sm = aMesh.GetSubMesh(CircEdge); MapShapeNbElemsItr anIt = aResMap.find(sm); vector<int> aVec = (*anIt).second; isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge]; if(isQuadratic) { // main nodes nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size(); // radial medium nodes nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1); // other medium nodes nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size(); } else { nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size(); } nb2d_tria = aVec[SMDSEntity_Node] + 1; nb2d_quad = nb2d_tria * myLayerPositions.size(); // add evaluation for edges vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; if(isQuadratic) { aResVec[SMDSEntity_Node] = 4*myLayerPositions.size() + 3; aResVec[SMDSEntity_Quad_Edge] = 2*myLayerPositions.size() + 2; } else { aResVec[SMDSEntity_Node] = 2*myLayerPositions.size() + 1; aResVec[SMDSEntity_Edge] = 2*myLayerPositions.size() + 2; } sm = aMesh.GetSubMesh(LinEdge1); aResMap.insert(make_pair(sm,aResVec)); } } else { // nbe==3 // one curve must be a part of circle and other curves must be // segments of line Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(C1); while( !tc.IsNull() ) { C1 = tc->BasisCurve(); tc = Handle(Geom_TrimmedCurve)::DownCast(C1); } tc = Handle(Geom_TrimmedCurve)::DownCast(C2); while( !tc.IsNull() ) { C2 = tc->BasisCurve(); tc = Handle(Geom_TrimmedCurve)::DownCast(C2); } tc = Handle(Geom_TrimmedCurve)::DownCast(C3); while( !tc.IsNull() ) { C3 = tc->BasisCurve(); tc = Handle(Geom_TrimmedCurve)::DownCast(C3); } Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(C1); Handle(Geom_Line) aLine1 = Handle(Geom_Line)::DownCast(C2); Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast(C3); CircEdge = E1; LinEdge1 = E2; LinEdge2 = E3; double fp = f1; double lp = l1; if( aCirc.IsNull() ) { aCirc = Handle(Geom_Circle)::DownCast(C2); CircEdge = E2; LinEdge1 = E3; LinEdge2 = E1; fp = f2; lp = l2; aLine1 = Handle(Geom_Line)::DownCast(C3); aLine2 = Handle(Geom_Line)::DownCast(C1); if( aCirc.IsNull() ) { aCirc = Handle(Geom_Circle)::DownCast(C3); CircEdge = E3; LinEdge1 = E1; LinEdge2 = E2; fp = f3; lp = l3; aLine1 = Handle(Geom_Line)::DownCast(C1); aLine2 = Handle(Geom_Line)::DownCast(C2); } } bool ok = !aCirc.IsNull() && !aLine1.IsNull() && !aLine1.IsNull(); SMESH_subMesh* sm = aMesh.GetSubMesh(LinEdge1); MapShapeNbElemsItr anIt = aResMap.find(sm); if( anIt!=aResMap.end() ) { ok = false; } sm = aMesh.GetSubMesh(LinEdge2); anIt = aResMap.find(sm); if( anIt!=aResMap.end() ) { ok = false; } if(ok) { ok = _gen->Evaluate( aMesh, CircEdge, aResMap ); } if(ok) { SMESH_subMesh * sm = aMesh.GetSubMesh(CircEdge); MapShapeNbElemsItr anIt = aResMap.find(sm); vector<int> aVec = (*anIt).second; isQuadratic = aVec[SMDSEntity_Quad_Edge]>aVec[SMDSEntity_Edge]; if(isQuadratic) { // main nodes nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size(); // radial medium nodes nb0d += aVec[SMDSEntity_Node] * (myLayerPositions.size()+1); // other medium nodes nb0d += (aVec[SMDSEntity_Node]+1) * myLayerPositions.size(); } else { nb0d = aVec[SMDSEntity_Node] * myLayerPositions.size(); } nb2d_tria = aVec[SMDSEntity_Node] + 1; nb2d_quad = nb2d_tria * myLayerPositions.size(); // add evaluation for edges vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; if(isQuadratic) { aResVec[SMDSEntity_Node] = 2*myLayerPositions.size() + 1; aResVec[SMDSEntity_Quad_Edge] = myLayerPositions.size() + 1; } else { aResVec[SMDSEntity_Node] = myLayerPositions.size(); aResVec[SMDSEntity_Edge] = myLayerPositions.size() + 1; } sm = aMesh.GetSubMesh(LinEdge1); aResMap.insert(make_pair(sm,aResVec)); sm = aMesh.GetSubMesh(LinEdge2); aResMap.insert(make_pair(sm,aResVec)); } } vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); //cout<<"nb0d = "<<nb0d<<" nb2d_tria = "<<nb2d_tria<<" nb2d_quad = "<<nb2d_quad<<endl; if(nb0d>0) { aResVec[0] = nb0d; if(isQuadratic) { aResVec[SMDSEntity_Quad_Triangle] = nb2d_tria; aResVec[SMDSEntity_Quad_Quadrangle] = nb2d_quad; } else { aResVec[SMDSEntity_Triangle] = nb2d_tria; aResVec[SMDSEntity_Quadrangle] = nb2d_quad; } aResMap.insert(make_pair(sm,aResVec)); return true; } // invalid case aResMap.insert(make_pair(sm,aResVec)); SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED, "Submesh can not be evaluated",this)); return false; }
bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) { TopExp_Explorer exp; SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); myHelper = new SMESH_MesherHelper( aMesh ); myHelper->IsQuadraticSubMesh( aShape ); // to delete helper at exit from Compute() auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper ); myLayerPositions.clear(); TopoDS_Edge CircEdge, LinEdge1, LinEdge2; int nbe = analyseFace( aShape, CircEdge, LinEdge1, LinEdge2 ); if( nbe>3 || nbe < 1 || CircEdge.IsNull() ) return error(COMPERR_BAD_SHAPE); gp_Pnt P0,P1; // points for rotation TColgp_SequenceOfPnt Points; // angles for rotation TColStd_SequenceOfReal Angles; // Nodes1 and Nodes2 - nodes along radiuses // CNodes - nodes on circle edge vector< const SMDS_MeshNode* > Nodes1, Nodes2, CNodes; SMDS_MeshNode * NC; // parameters edge nodes on face TColgp_SequenceOfPnt2d Pnts2d1; gp_Pnt2d PC; int faceID = meshDS->ShapeToIndex(aShape); TopoDS_Face F = TopoDS::Face(aShape); Handle(Geom_Surface) S = BRep_Tool::Surface(F); if(nbe==1) { Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge )); bool ok = _gen->Compute( aMesh, CircEdge ); if( !ok ) return false; map< double, const SMDS_MeshNode* > theNodes; ok = GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes); if( !ok ) return false; CNodes.clear(); map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin(); const SMDS_MeshNode* NF = (*itn).second; CNodes.push_back( (*itn).second ); double fang = (*itn).first; if ( itn != theNodes.end() ) { itn++; for(; itn != theNodes.end(); itn++ ) { CNodes.push_back( (*itn).second ); double ang = (*itn).first - fang; if( ang>M_PI ) ang = ang - 2*M_PI; if( ang<-M_PI ) ang = ang + 2*M_PI; Angles.Append( ang ); } } P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() ); P0 = aCirc->Location(); myLayerPositions.clear(); computeLayerPositions(P0,P1); exp.Init( CircEdge, TopAbs_VERTEX ); TopoDS_Vertex V1 = TopoDS::Vertex( exp.Current() ); gp_Pnt2d p2dV = BRep_Tool::Parameters( V1, TopoDS::Face(aShape) ); NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z()); GeomAPI_ProjectPointOnSurf PPS(P0,S); double U0,V0; PPS.Parameters(1,U0,V0); meshDS->SetNodeOnFace(NC, faceID, U0, V0); PC = gp_Pnt2d(U0,V0); gp_Vec aVec(P0,P1); gp_Vec2d aVec2d(PC,p2dV); Nodes1.resize( myLayerPositions.size()+1 ); Nodes2.resize( myLayerPositions.size()+1 ); int i = 0; for(; i<myLayerPositions.size(); i++) { gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i], P0.Y() + aVec.Y()*myLayerPositions[i], P0.Z() + aVec.Z()*myLayerPositions[i] ); Points.Append(P); SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z()); Nodes1[i] = node; Nodes2[i] = node; double U = PC.X() + aVec2d.X()*myLayerPositions[i]; double V = PC.Y() + aVec2d.Y()*myLayerPositions[i]; meshDS->SetNodeOnFace( node, faceID, U, V ); Pnts2d1.Append(gp_Pnt2d(U,V)); } Nodes1[Nodes1.size()-1] = NF; Nodes2[Nodes1.size()-1] = NF; } else if(nbe==2 && LinEdge1.Orientation() != TopAbs_INTERNAL ) { // one curve must be a half of circle and other curve must be // a segment of line double fp, lp; Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge, &fp, &lp )); if( fabs(fabs(lp-fp)-M_PI) > Precision::Confusion() ) { // not half of circle return error(COMPERR_BAD_SHAPE); } Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 )); if( aLine.IsNull() ) { // other curve not line return error(COMPERR_BAD_SHAPE); } bool linEdgeComputed = false; if( SMESH_subMesh* sm1 = aMesh.GetSubMesh(LinEdge1) ) { if( !sm1->IsEmpty() ) { if( isEdgeCompitaballyMeshed( LinEdge1, aMesh.GetSubMesh(F) )) linEdgeComputed = true; else return error("Invalid set of hypotheses"); } } bool ok = _gen->Compute( aMesh, CircEdge ); if( !ok ) return false; map< double, const SMDS_MeshNode* > theNodes; GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes); CNodes.clear(); map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin(); double fang = (*itn).first; itn++; for(; itn != theNodes.end(); itn++ ) { CNodes.push_back( (*itn).second ); double ang = (*itn).first - fang; if( ang>M_PI ) ang = ang - 2*M_PI; if( ang<-M_PI ) ang = ang + 2*M_PI; Angles.Append( ang ); } const SMDS_MeshNode* NF = theNodes.begin()->second; const SMDS_MeshNode* NL = theNodes.rbegin()->second; CNodes.push_back( NF ); P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() ); gp_Pnt P2( NL->X(), NL->Y(), NL->Z() ); P0 = aCirc->Location(); myLayerPositions.clear(); computeLayerPositions(P0,P1); if ( linEdgeComputed ) { if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge1,true,theNodes)) return error("Invalid mesh on a straight edge"); vector< const SMDS_MeshNode* > *pNodes1 = &Nodes1, *pNodes2 = &Nodes2; bool nodesFromP0ToP1 = ( theNodes.rbegin()->second == NF ); if ( !nodesFromP0ToP1 ) std::swap( pNodes1, pNodes2 ); map< double, const SMDS_MeshNode* >::reverse_iterator ritn = theNodes.rbegin(); itn = theNodes.begin(); for ( int i = Nodes1.size()-1; i > -1; ++itn, ++ritn, --i ) { (*pNodes1)[i] = ritn->second; (*pNodes2)[i] = itn->second; Points.Append( gpXYZ( Nodes1[i])); Pnts2d1.Append( myHelper->GetNodeUV( F, Nodes1[i])); } NC = const_cast<SMDS_MeshNode*>( itn->second ); Points.Remove( Nodes1.size() ); } else { gp_Vec aVec(P0,P1); int edgeID = meshDS->ShapeToIndex(LinEdge1); // check orientation Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp); gp_Pnt Ptmp; Crv->D0(fp,Ptmp); bool ori = true; if( P1.Distance(Ptmp) > Precision::Confusion() ) ori = false; // get UV points for edge gp_Pnt2d PF,PL; BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL ); PC = gp_Pnt2d( (PF.X()+PL.X())/2, (PF.Y()+PL.Y())/2 ); gp_Vec2d V2d; if(ori) V2d = gp_Vec2d(PC,PF); else V2d = gp_Vec2d(PC,PL); // add nodes on edge double cp = (fp+lp)/2; double dp2 = (lp-fp)/2; NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z()); meshDS->SetNodeOnEdge(NC, edgeID, cp); Nodes1.resize( myLayerPositions.size()+1 ); Nodes2.resize( myLayerPositions.size()+1 ); int i = 0; for(; i<myLayerPositions.size(); i++) { gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i], P0.Y() + aVec.Y()*myLayerPositions[i], P0.Z() + aVec.Z()*myLayerPositions[i] ); Points.Append(P); SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z()); Nodes1[i] = node; double param; if(ori) param = fp + dp2*(1-myLayerPositions[i]); else param = cp + dp2*myLayerPositions[i]; meshDS->SetNodeOnEdge(node, edgeID, param); P = gp_Pnt( P0.X() - aVec.X()*myLayerPositions[i], P0.Y() - aVec.Y()*myLayerPositions[i], P0.Z() - aVec.Z()*myLayerPositions[i] ); node = meshDS->AddNode(P.X(), P.Y(), P.Z()); Nodes2[i] = node; if(!ori) param = fp + dp2*(1-myLayerPositions[i]); else param = cp + dp2*myLayerPositions[i]; meshDS->SetNodeOnEdge(node, edgeID, param); // parameters on face gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i], PC.Y() + V2d.Y()*myLayerPositions[i] ); Pnts2d1.Append(P2d); } Nodes1[ myLayerPositions.size() ] = NF; Nodes2[ myLayerPositions.size() ] = NL; // create 1D elements on edge vector< const SMDS_MeshNode* > tmpNodes; tmpNodes.resize(2*Nodes1.size()+1); for(i=0; i<Nodes2.size(); i++) tmpNodes[Nodes2.size()-i-1] = Nodes2[i]; tmpNodes[Nodes2.size()] = NC; for(i=0; i<Nodes1.size(); i++) tmpNodes[Nodes2.size()+1+i] = Nodes1[i]; for(i=1; i<tmpNodes.size(); i++) { SMDS_MeshEdge* ME = myHelper->AddEdge( tmpNodes[i-1], tmpNodes[i] ); if(ME) meshDS->SetMeshElementOnShape(ME, edgeID); } markLinEdgeAsComputedByMe( LinEdge1, aMesh.GetSubMesh( F )); } } else // nbe==3 or ( nbe==2 && linEdge is INTERNAL ) { if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL ) LinEdge2 = LinEdge1; // one curve must be a part of circle and other curves must be // segments of line double fp, lp; Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast( getCurve( CircEdge )); Handle(Geom_Line) aLine1 = Handle(Geom_Line)::DownCast( getCurve( LinEdge1 )); Handle(Geom_Line) aLine2 = Handle(Geom_Line)::DownCast( getCurve( LinEdge2 )); if( aLine1.IsNull() || aLine2.IsNull() ) { // other curve not line return error(COMPERR_BAD_SHAPE); } bool linEdge1Computed = false; if ( SMESH_subMesh* sm1 = aMesh.GetSubMesh(LinEdge1)) if( !sm1->IsEmpty() ) { if( isEdgeCompitaballyMeshed( LinEdge1, aMesh.GetSubMesh(F) )) linEdge1Computed = true; else return error("Invalid set of hypotheses"); } bool linEdge2Computed = false; if ( SMESH_subMesh* sm2 = aMesh.GetSubMesh(LinEdge2)) if( !sm2->IsEmpty() ) { if( isEdgeCompitaballyMeshed( LinEdge2, aMesh.GetSubMesh(F) )) linEdge2Computed = true; else return error("Invalid set of hypotheses"); } bool ok = _gen->Compute( aMesh, CircEdge ); if( !ok ) return false; map< double, const SMDS_MeshNode* > theNodes; GetSortedNodesOnEdge(aMesh.GetMeshDS(),CircEdge,true,theNodes); const SMDS_MeshNode* NF = theNodes.begin()->second; const SMDS_MeshNode* NL = theNodes.rbegin()->second; CNodes.clear(); CNodes.push_back( NF ); map< double, const SMDS_MeshNode* >::iterator itn = theNodes.begin(); double fang = (*itn).first; itn++; for(; itn != theNodes.end(); itn++ ) { CNodes.push_back( (*itn).second ); double ang = (*itn).first - fang; if( ang>M_PI ) ang = ang - 2*M_PI; if( ang<-M_PI ) ang = ang + 2*M_PI; Angles.Append( ang ); } P1 = gp_Pnt( NF->X(), NF->Y(), NF->Z() ); gp_Pnt P2( NL->X(), NL->Y(), NL->Z() ); P0 = aCirc->Location(); myLayerPositions.clear(); computeLayerPositions(P0,P1); Nodes1.resize( myLayerPositions.size()+1 ); Nodes2.resize( myLayerPositions.size()+1 ); exp.Init( LinEdge1, TopAbs_VERTEX ); TopoDS_Vertex V1 = TopoDS::Vertex( exp.Current() ); exp.Next(); TopoDS_Vertex V2 = TopoDS::Vertex( exp.Current() ); gp_Pnt PE1 = BRep_Tool::Pnt(V1); gp_Pnt PE2 = BRep_Tool::Pnt(V2); if( ( P1.Distance(PE1) > Precision::Confusion() ) && ( P1.Distance(PE2) > Precision::Confusion() ) ) { std::swap( LinEdge1, LinEdge2 ); std::swap( linEdge1Computed, linEdge2Computed ); } TopoDS_Vertex VC = V2; if( ( P1.Distance(PE1) > Precision::Confusion() ) && ( P2.Distance(PE1) > Precision::Confusion() ) ) VC = V1; int vertID = meshDS->ShapeToIndex(VC); // LinEdge1 if ( linEdge1Computed ) { if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge1,true,theNodes)) return error("Invalid mesh on a straight edge"); bool nodesFromP0ToP1 = ( theNodes.rbegin()->second == NF ); NC = const_cast<SMDS_MeshNode*> ( nodesFromP0ToP1 ? theNodes.begin()->second : theNodes.rbegin()->second ); int i = 0, ir = Nodes1.size()-1; int * pi = nodesFromP0ToP1 ? &i : &ir; itn = theNodes.begin(); if ( nodesFromP0ToP1 ) ++itn; for ( ; i < Nodes1.size(); ++i, --ir, ++itn ) { Nodes1[*pi] = itn->second; } for ( i = 0; i < Nodes1.size()-1; ++i ) { Points.Append( gpXYZ( Nodes1[i])); Pnts2d1.Append( myHelper->GetNodeUV( F, Nodes1[i])); } } else { int edgeID = meshDS->ShapeToIndex(LinEdge1); gp_Vec aVec(P0,P1); // check orientation Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge1,fp,lp); gp_Pnt Ptmp = Crv->Value(fp); bool ori = false; if( P1.Distance(Ptmp) > Precision::Confusion() ) ori = true; // get UV points for edge gp_Pnt2d PF,PL; BRep_Tool::UVPoints( LinEdge1, TopoDS::Face(aShape), PF, PL ); gp_Vec2d V2d; if(ori) { V2d = gp_Vec2d(PF,PL); PC = PF; } else { V2d = gp_Vec2d(PL,PF); PC = PL; } NC = const_cast<SMDS_MeshNode*>( VertexNode( VC, meshDS )); if ( !NC ) { NC = meshDS->AddNode(P0.X(), P0.Y(), P0.Z()); meshDS->SetNodeOnVertex(NC, vertID); } double dp = lp-fp; int i = 0; for(; i<myLayerPositions.size(); i++) { gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i], P0.Y() + aVec.Y()*myLayerPositions[i], P0.Z() + aVec.Z()*myLayerPositions[i] ); Points.Append(P); SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z()); Nodes1[i] = node; double param; if(!ori) param = fp + dp*(1-myLayerPositions[i]); else param = fp + dp*myLayerPositions[i]; meshDS->SetNodeOnEdge(node, edgeID, param); // parameters on face gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i], PC.Y() + V2d.Y()*myLayerPositions[i] ); Pnts2d1.Append(P2d); } Nodes1[ myLayerPositions.size() ] = NF; // create 1D elements on edge SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes1[0] ); if(ME) meshDS->SetMeshElementOnShape(ME, edgeID); for(i=1; i<Nodes1.size(); i++) { ME = myHelper->AddEdge( Nodes1[i-1], Nodes1[i] ); if(ME) meshDS->SetMeshElementOnShape(ME, edgeID); } if (nbe==2 && LinEdge1.Orientation() == TopAbs_INTERNAL ) Nodes2 = Nodes1; } markLinEdgeAsComputedByMe( LinEdge1, aMesh.GetSubMesh( F )); // LinEdge2 if ( linEdge2Computed ) { if (!GetSortedNodesOnEdge(aMesh.GetMeshDS(),LinEdge2,true,theNodes)) return error("Invalid mesh on a straight edge"); bool nodesFromP0ToP2 = ( theNodes.rbegin()->second == NL ); int i = 0, ir = Nodes1.size()-1; int * pi = nodesFromP0ToP2 ? &i : &ir; itn = theNodes.begin(); if ( nodesFromP0ToP2 ) ++itn; for ( ; i < Nodes2.size(); ++i, --ir, ++itn ) Nodes2[*pi] = itn->second; } else { int edgeID = meshDS->ShapeToIndex(LinEdge2); gp_Vec aVec = gp_Vec(P0,P2); // check orientation Handle(Geom_Curve) Crv = BRep_Tool::Curve(LinEdge2,fp,lp); gp_Pnt Ptmp = Crv->Value(fp); bool ori = false; if( P2.Distance(Ptmp) > Precision::Confusion() ) ori = true; // get UV points for edge gp_Pnt2d PF,PL; BRep_Tool::UVPoints( LinEdge2, TopoDS::Face(aShape), PF, PL ); gp_Vec2d V2d; if(ori) { V2d = gp_Vec2d(PF,PL); PC = PF; } else { V2d = gp_Vec2d(PL,PF); PC = PL; } double dp = lp-fp; for(int i=0; i<myLayerPositions.size(); i++) { gp_Pnt P( P0.X() + aVec.X()*myLayerPositions[i], P0.Y() + aVec.Y()*myLayerPositions[i], P0.Z() + aVec.Z()*myLayerPositions[i] ); SMDS_MeshNode * node = meshDS->AddNode(P.X(), P.Y(), P.Z()); Nodes2[i] = node; double param; if(!ori) param = fp + dp*(1-myLayerPositions[i]); else param = fp + dp*myLayerPositions[i]; meshDS->SetNodeOnEdge(node, edgeID, param); // parameters on face gp_Pnt2d P2d( PC.X() + V2d.X()*myLayerPositions[i], PC.Y() + V2d.Y()*myLayerPositions[i] ); } Nodes2[ myLayerPositions.size() ] = NL; // create 1D elements on edge SMDS_MeshEdge* ME = myHelper->AddEdge( NC, Nodes2[0] ); if(ME) meshDS->SetMeshElementOnShape(ME, edgeID); for(int i=1; i<Nodes2.size(); i++) { ME = myHelper->AddEdge( Nodes2[i-1], Nodes2[i] ); if(ME) meshDS->SetMeshElementOnShape(ME, edgeID); } } markLinEdgeAsComputedByMe( LinEdge2, aMesh.GetSubMesh( F )); } // orientation bool IsForward = ( CircEdge.Orientation()==TopAbs_FORWARD ); // create nodes and mesh elements on face // find axis of rotation gp_Pnt P2 = gp_Pnt( CNodes[1]->X(), CNodes[1]->Y(), CNodes[1]->Z() ); gp_Vec Vec1(P0,P1); gp_Vec Vec2(P0,P2); gp_Vec Axis = Vec1.Crossed(Vec2); // create elements int i = 1; //cout<<"Angles.Length() = "<<Angles.Length()<<" Points.Length() = "<<Points.Length()<<endl; //cout<<"Nodes1.size() = "<<Nodes1.size()<<" Pnts2d1.Length() = "<<Pnts2d1.Length()<<endl; for(; i<Angles.Length(); i++) { vector< const SMDS_MeshNode* > tmpNodes; tmpNodes.reserve(Nodes1.size()); gp_Trsf aTrsf; gp_Ax1 theAxis(P0,gp_Dir(Axis)); aTrsf.SetRotation( theAxis, Angles.Value(i) ); gp_Trsf2d aTrsf2d; aTrsf2d.SetRotation( PC, Angles.Value(i) ); // create nodes int j = 1; for(; j<=Points.Length(); j++) { double cx,cy,cz; Points.Value(j).Coord( cx, cy, cz ); aTrsf.Transforms( cx, cy, cz ); SMDS_MeshNode* node = myHelper->AddNode( cx, cy, cz ); // find parameters on face Pnts2d1.Value(j).Coord( cx, cy ); aTrsf2d.Transforms( cx, cy ); // set node on face meshDS->SetNodeOnFace( node, faceID, cx, cy ); tmpNodes[j-1] = node; } // create faces tmpNodes[Points.Length()] = CNodes[i]; // quad for(j=0; j<Nodes1.size()-1; j++) { SMDS_MeshFace* MF; if(IsForward) MF = myHelper->AddFace( tmpNodes[j], Nodes1[j], Nodes1[j+1], tmpNodes[j+1] ); else MF = myHelper->AddFace( tmpNodes[j], tmpNodes[j+1], Nodes1[j+1], Nodes1[j] ); if(MF) meshDS->SetMeshElementOnShape(MF, faceID); } // tria SMDS_MeshFace* MF; if(IsForward) MF = myHelper->AddFace( NC, Nodes1[0], tmpNodes[0] ); else MF = myHelper->AddFace( NC, tmpNodes[0], Nodes1[0] ); if(MF) meshDS->SetMeshElementOnShape(MF, faceID); for(j=0; j<Nodes1.size(); j++) { Nodes1[j] = tmpNodes[j]; } } // create last faces // quad for(i=0; i<Nodes1.size()-1; i++) { SMDS_MeshFace* MF; if(IsForward) MF = myHelper->AddFace( Nodes2[i], Nodes1[i], Nodes1[i+1], Nodes2[i+1] ); else MF = myHelper->AddFace( Nodes2[i], Nodes2[i+1], Nodes1[i+1], Nodes1[i] ); if(MF) meshDS->SetMeshElementOnShape(MF, faceID); } // tria SMDS_MeshFace* MF; if(IsForward) MF = myHelper->AddFace( NC, Nodes1[0], Nodes2[0] ); else MF = myHelper->AddFace( NC, Nodes2[0], Nodes1[0] ); if(MF) meshDS->SetMeshElementOnShape(MF, faceID); return true; }
Mesh::MeshObject* Mesher::createMesh() const { // OCC standard mesher if (method == Standard) { Handle_StlMesh_Mesh aMesh = new StlMesh_Mesh(); if (!shape.IsNull()) { BRepTools::Clean(shape); #if OCC_VERSION_HEX >= 0x060801 BRepMesh_IncrementalMesh bMesh(shape, deflection, Standard_False, angularDeflection); StlTransfer::RetrieveMesh(shape,aMesh); #else StlTransfer::BuildIncrementalMesh(shape, deflection, #if OCC_VERSION_HEX >= 0x060503 Standard_True, #endif aMesh); #endif } std::map<uint32_t, std::vector<std::size_t> > colorMap; for (std::size_t i=0; i<colors.size(); i++) { colorMap[colors[i]].push_back(i); } bool createSegm = (static_cast<int>(colors.size()) == aMesh->NbDomains()); MeshCore::MeshFacetArray faces; faces.reserve(aMesh->NbTriangles()); std::set<Vertex> vertices; Standard_Real x1, y1, z1; Standard_Real x2, y2, z2; Standard_Real x3, y3, z3; std::vector< std::vector<unsigned long> > meshSegments; std::size_t numMeshFaces = 0; StlMesh_MeshExplorer xp(aMesh); for (Standard_Integer nbd=1;nbd<=aMesh->NbDomains();nbd++) { std::size_t numDomainFaces = 0; for (xp.InitTriangle(nbd); xp.MoreTriangle(); xp.NextTriangle()) { xp.TriangleVertices(x1,y1,z1,x2,y2,z2,x3,y3,z3); std::set<Vertex>::iterator it; MeshCore::MeshFacet face; // 1st vertex Vertex v1(x1,y1,z1); it = vertices.find(v1); if (it == vertices.end()) { v1.i = vertices.size(); face._aulPoints[0] = v1.i; vertices.insert(v1); } else { face._aulPoints[0] = it->i; } // 2nd vertex Vertex v2(x2,y2,z2); it = vertices.find(v2); if (it == vertices.end()) { v2.i = vertices.size(); face._aulPoints[1] = v2.i; vertices.insert(v2); } else { face._aulPoints[1] = it->i; } // 3rd vertex Vertex v3(x3,y3,z3); it = vertices.find(v3); if (it == vertices.end()) { v3.i = vertices.size(); face._aulPoints[2] = v3.i; vertices.insert(v3); } else { face._aulPoints[2] = it->i; } // make sure that we don't insert invalid facets if (face._aulPoints[0] != face._aulPoints[1] && face._aulPoints[1] != face._aulPoints[2] && face._aulPoints[2] != face._aulPoints[0]) { faces.push_back(face); numDomainFaces++; } } // add a segment for the face if (createSegm || this->segments) { std::vector<unsigned long> segment(numDomainFaces); std::generate(segment.begin(), segment.end(), Base::iotaGen<unsigned long>(numMeshFaces)); numMeshFaces += numDomainFaces; meshSegments.push_back(segment); } } MeshCore::MeshPointArray verts; verts.resize(vertices.size()); for (auto it : vertices) verts[it.i] = it.toPoint(); MeshCore::MeshKernel kernel; kernel.Adopt(verts, faces, true); Mesh::MeshObject* meshdata = new Mesh::MeshObject(); meshdata->swap(kernel); if (createSegm) { int index = 0; for (auto it : colorMap) { Mesh::Segment segm(meshdata, false); for (auto jt : it.second) { segm.addIndices(meshSegments[jt]); } segm.save(true); std::stringstream str; str << "patch" << index++; segm.setName(str.str()); meshdata->addSegment(segm); } } else { for (auto it : meshSegments) { meshdata->addSegment(it); } } return meshdata; } #ifndef HAVE_SMESH throw Base::Exception("SMESH is not available on this platform"); #else std::list<SMESH_Hypothesis*> hypoth; SMESH_Gen* meshgen = SMESH_Gen::get(); SMESH_Mesh* mesh = meshgen->CreateMesh(0, true); int hyp=0; switch (method) { #if defined (HAVE_NETGEN) case Netgen: { NETGENPlugin_Hypothesis_2D* hyp2d = new NETGENPlugin_Hypothesis_2D(hyp++,0,meshgen); if (fineness >=0 && fineness < 5) { hyp2d->SetFineness(NETGENPlugin_Hypothesis_2D::Fineness(fineness)); } // user defined values else { if (growthRate > 0) hyp2d->SetGrowthRate(growthRate); if (nbSegPerEdge > 0) hyp2d->SetNbSegPerEdge(nbSegPerEdge); if (nbSegPerRadius > 0) hyp2d->SetNbSegPerRadius(nbSegPerRadius); } hyp2d->SetQuadAllowed(allowquad); hyp2d->SetOptimize(optimize); hyp2d->SetSecondOrder(secondOrder); // apply bisecting to create four triangles out of one hypoth.push_back(hyp2d); NETGENPlugin_NETGEN_2D* alg2d = new NETGENPlugin_NETGEN_2D(hyp++,0,meshgen); hypoth.push_back(alg2d); } break; #endif #if defined (HAVE_MEFISTO) case Mefisto: { if (maxLength > 0) { StdMeshers_MaxLength* hyp1d = new StdMeshers_MaxLength(hyp++, 0, meshgen); hyp1d->SetLength(maxLength); hypoth.push_back(hyp1d); } else if (localLength > 0) { StdMeshers_LocalLength* hyp1d = new StdMeshers_LocalLength(hyp++,0,meshgen); hyp1d->SetLength(localLength); hypoth.push_back(hyp1d); } else if (maxArea > 0) { StdMeshers_MaxElementArea* hyp2d = new StdMeshers_MaxElementArea(hyp++,0,meshgen); hyp2d->SetMaxArea(maxArea); hypoth.push_back(hyp2d); } else if (deflection > 0) { StdMeshers_Deflection1D* hyp1d = new StdMeshers_Deflection1D(hyp++,0,meshgen); hyp1d->SetDeflection(deflection); hypoth.push_back(hyp1d); } else if (minLen > 0 && maxLen > 0) { StdMeshers_Arithmetic1D* hyp1d = new StdMeshers_Arithmetic1D(hyp++,0,meshgen); hyp1d->SetLength(minLen, false); hyp1d->SetLength(maxLen, true); hypoth.push_back(hyp1d); } else { StdMeshers_AutomaticLength* hyp1d = new StdMeshers_AutomaticLength(hyp++,0,meshgen); hypoth.push_back(hyp1d); } { StdMeshers_NumberOfSegments* hyp1d = new StdMeshers_NumberOfSegments(hyp++,0,meshgen); hyp1d->SetNumberOfSegments(1); hypoth.push_back(hyp1d); } if (regular) { StdMeshers_Regular_1D* hyp1d = new StdMeshers_Regular_1D(hyp++,0,meshgen); hypoth.push_back(hyp1d); } StdMeshers_TrianglePreference* hyp2d_1 = new StdMeshers_TrianglePreference(hyp++,0,meshgen); hypoth.push_back(hyp2d_1); StdMeshers_MEFISTO_2D* alg2d = new StdMeshers_MEFISTO_2D(hyp++,0,meshgen); hypoth.push_back(alg2d); } break; #endif default: break; } // Set new cout MeshingOutput stdcout; std::streambuf* oldcout = std::cout.rdbuf(&stdcout); // Apply the hypothesis and create the mesh mesh->ShapeToMesh(shape); for (int i=0; i<hyp;i++) mesh->AddHypothesis(shape, i); meshgen->Compute(*mesh, mesh->GetShapeToMesh()); // Restore old cout std::cout.rdbuf(oldcout); // build up the mesh structure SMDS_FaceIteratorPtr aFaceIter = mesh->GetMeshDS()->facesIterator(); SMDS_NodeIteratorPtr aNodeIter = mesh->GetMeshDS()->nodesIterator(); MeshCore::MeshPointArray verts; MeshCore::MeshFacetArray faces; verts.reserve(mesh->NbNodes()); faces.reserve(mesh->NbFaces()); int index=0; std::map<const SMDS_MeshNode*, int> mapNodeIndex; for (;aNodeIter->more();) { const SMDS_MeshNode* aNode = aNodeIter->next(); MeshCore::MeshPoint p; p.Set((float)aNode->X(), (float)aNode->Y(), (float)aNode->Z()); verts.push_back(p); mapNodeIndex[aNode] = index++; } for (;aFaceIter->more();) { const SMDS_MeshFace* aFace = aFaceIter->next(); if (aFace->NbNodes() == 3) { MeshCore::MeshFacet f; for (int i=0; i<3;i++) { const SMDS_MeshNode* node = aFace->GetNode(i); f._aulPoints[i] = mapNodeIndex[node]; } faces.push_back(f); } else if (aFace->NbNodes() == 4) { MeshCore::MeshFacet f1, f2; const SMDS_MeshNode* node0 = aFace->GetNode(0); const SMDS_MeshNode* node1 = aFace->GetNode(1); const SMDS_MeshNode* node2 = aFace->GetNode(2); const SMDS_MeshNode* node3 = aFace->GetNode(3); f1._aulPoints[0] = mapNodeIndex[node0]; f1._aulPoints[1] = mapNodeIndex[node1]; f1._aulPoints[2] = mapNodeIndex[node2]; f2._aulPoints[0] = mapNodeIndex[node0]; f2._aulPoints[1] = mapNodeIndex[node2]; f2._aulPoints[2] = mapNodeIndex[node3]; faces.push_back(f1); faces.push_back(f2); } else if (aFace->NbNodes() == 6) { MeshCore::MeshFacet f1, f2, f3, f4; const SMDS_MeshNode* node0 = aFace->GetNode(0); const SMDS_MeshNode* node1 = aFace->GetNode(1); const SMDS_MeshNode* node2 = aFace->GetNode(2); const SMDS_MeshNode* node3 = aFace->GetNode(3); const SMDS_MeshNode* node4 = aFace->GetNode(4); const SMDS_MeshNode* node5 = aFace->GetNode(5); f1._aulPoints[0] = mapNodeIndex[node0]; f1._aulPoints[1] = mapNodeIndex[node3]; f1._aulPoints[2] = mapNodeIndex[node5]; f2._aulPoints[0] = mapNodeIndex[node1]; f2._aulPoints[1] = mapNodeIndex[node4]; f2._aulPoints[2] = mapNodeIndex[node3]; f3._aulPoints[0] = mapNodeIndex[node2]; f3._aulPoints[1] = mapNodeIndex[node5]; f3._aulPoints[2] = mapNodeIndex[node4]; f4._aulPoints[0] = mapNodeIndex[node3]; f4._aulPoints[1] = mapNodeIndex[node4]; f4._aulPoints[2] = mapNodeIndex[node5]; faces.push_back(f1); faces.push_back(f2); faces.push_back(f3); faces.push_back(f4); } else if (aFace->NbNodes() == 8) { MeshCore::MeshFacet f1, f2, f3, f4, f5, f6; const SMDS_MeshNode* node0 = aFace->GetNode(0); const SMDS_MeshNode* node1 = aFace->GetNode(1); const SMDS_MeshNode* node2 = aFace->GetNode(2); const SMDS_MeshNode* node3 = aFace->GetNode(3); const SMDS_MeshNode* node4 = aFace->GetNode(4); const SMDS_MeshNode* node5 = aFace->GetNode(5); const SMDS_MeshNode* node6 = aFace->GetNode(6); const SMDS_MeshNode* node7 = aFace->GetNode(7); f1._aulPoints[0] = mapNodeIndex[node0]; f1._aulPoints[1] = mapNodeIndex[node4]; f1._aulPoints[2] = mapNodeIndex[node7]; f2._aulPoints[0] = mapNodeIndex[node1]; f2._aulPoints[1] = mapNodeIndex[node5]; f2._aulPoints[2] = mapNodeIndex[node4]; f3._aulPoints[0] = mapNodeIndex[node2]; f3._aulPoints[1] = mapNodeIndex[node6]; f3._aulPoints[2] = mapNodeIndex[node5]; f4._aulPoints[0] = mapNodeIndex[node3]; f4._aulPoints[1] = mapNodeIndex[node7]; f4._aulPoints[2] = mapNodeIndex[node6]; // Two solutions are possible: // <4,6,7>, <4,5,6> or <4,5,7>, <5,6,7> Base::Vector3d v4(node4->X(),node4->Y(),node4->Z()); Base::Vector3d v5(node5->X(),node5->Y(),node5->Z()); Base::Vector3d v6(node6->X(),node6->Y(),node6->Z()); Base::Vector3d v7(node7->X(),node7->Y(),node7->Z()); double dist46 = Base::DistanceP2(v4,v6); double dist57 = Base::DistanceP2(v5,v7); if (dist46 > dist57) { f5._aulPoints[0] = mapNodeIndex[node4]; f5._aulPoints[1] = mapNodeIndex[node6]; f5._aulPoints[2] = mapNodeIndex[node7]; f6._aulPoints[0] = mapNodeIndex[node4]; f6._aulPoints[1] = mapNodeIndex[node5]; f6._aulPoints[2] = mapNodeIndex[node6]; } else { f5._aulPoints[0] = mapNodeIndex[node4]; f5._aulPoints[1] = mapNodeIndex[node5]; f5._aulPoints[2] = mapNodeIndex[node7]; f6._aulPoints[0] = mapNodeIndex[node5]; f6._aulPoints[1] = mapNodeIndex[node6]; f6._aulPoints[2] = mapNodeIndex[node7]; } faces.push_back(f1); faces.push_back(f2); faces.push_back(f3); faces.push_back(f4); faces.push_back(f5); faces.push_back(f6); } else { Base::Console().Warning("Face with %d nodes ignored\n", aFace->NbNodes()); } } // clean up TopoDS_Shape aNull; mesh->ShapeToMesh(aNull); mesh->Clear(); delete mesh; for (std::list<SMESH_Hypothesis*>::iterator it = hypoth.begin(); it != hypoth.end(); ++it) delete *it; MeshCore::MeshKernel kernel; kernel.Adopt(verts, faces, true); Mesh::MeshObject* meshdata = new Mesh::MeshObject(); meshdata->swap(kernel); return meshdata; #endif // HAVE_SMESH }
bool NETGENPlugin_NETGEN_2D_ONLY::Evaluate(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, MapShapeNbElems& aResMap) { TopoDS_Face F = TopoDS::Face(aShape); if(F.IsNull()) return false; // collect info from edges int nb0d = 0, nb1d = 0; bool IsQuadratic = false; bool IsFirst = true; double fullLen = 0.0; TopTools_MapOfShape tmpMap; for (TopExp_Explorer exp(F, TopAbs_EDGE); exp.More(); exp.Next()) { TopoDS_Edge E = TopoDS::Edge(exp.Current()); if( tmpMap.Contains(E) ) continue; tmpMap.Add(E); SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); if( anIt==aResMap.end() ) { SMESH_subMesh *sm = aMesh.GetSubMesh(F); SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); return false; } std::vector<int> aVec = (*anIt).second; nb0d += aVec[SMDSEntity_Node]; nb1d += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]); double aLen = SMESH_Algo::EdgeLength(E); fullLen += aLen; if(IsFirst) { IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]); IsFirst = false; } } tmpMap.Clear(); // compute edge length double ELen = 0; if (_hypLengthFromEdges || (!_hypLengthFromEdges && !_hypMaxElementArea)) { if ( nb1d > 0 ) ELen = fullLen / nb1d; } if ( _hypMaxElementArea ) { double maxArea = _hypMaxElementArea->GetMaxArea(); ELen = sqrt(2. * maxArea/sqrt(3.0)); } GProp_GProps G; BRepGProp::SurfaceProperties(F,G); double anArea = G.Mass(); const int hugeNb = numeric_limits<int>::max()/10; if ( anArea / hugeNb > ELen*ELen ) { SMESH_subMesh *sm = aMesh.GetSubMesh(F); SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated.\nToo small element length",this)); return false; } int nbFaces = (int) ( anArea / ( ELen*ELen*sqrt(3.) / 4 ) ); int nbNodes = (int) ( ( nbFaces*3 - (nb1d-1)*2 ) / 6 + 1 ); std::vector<int> aVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i]=0; if( IsQuadratic ) { aVec[SMDSEntity_Node] = nbNodes; aVec[SMDSEntity_Quad_Triangle] = nbFaces; } else { aVec[SMDSEntity_Node] = nbNodes; aVec[SMDSEntity_Triangle] = nbFaces; } SMESH_subMesh *sm = aMesh.GetSubMesh(F); aResMap.insert(std::make_pair(sm,aVec)); return true; }
static bool checkConformIgnoredAlgos(SMESH_Mesh& aMesh, SMESH_subMesh* aSubMesh, const SMESH_Algo* aGlobIgnoAlgo, const SMESH_Algo* aLocIgnoAlgo, bool & checkConform, set<SMESH_subMesh*>& aCheckedMap, list< SMESH_Gen::TAlgoStateError > & theErrors) { ASSERT( aSubMesh ); if ( aSubMesh->GetSubShape().ShapeType() == TopAbs_VERTEX) return true; bool ret = true; const list<const SMESHDS_Hypothesis*>& listHyp = aMesh.GetMeshDS()->GetHypothesis( aSubMesh->GetSubShape() ); list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin(); for ( ; it != listHyp.end(); it++) { const SMESHDS_Hypothesis * aHyp = *it; if (aHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO) continue; const SMESH_Algo* algo = dynamic_cast<const SMESH_Algo*> (aHyp); ASSERT ( algo ); if ( aLocIgnoAlgo ) // algo is hidden by a local algo of upper dim { theErrors.push_back( SMESH_Gen::TAlgoStateError() ); theErrors.back().Set( SMESH_Hypothesis::HYP_HIDDEN_ALGO, algo, false ); INFOS( "Local <" << algo->GetName() << "> is hidden by local <" << aLocIgnoAlgo->GetName() << ">"); } else { bool isGlobal = (aMesh.IsMainShape( aSubMesh->GetSubShape() )); int dim = algo->GetDim(); int aMaxGlobIgnoDim = ( aGlobIgnoAlgo ? aGlobIgnoAlgo->GetDim() : -1 ); bool isNeededDim = ( aGlobIgnoAlgo ? aGlobIgnoAlgo->NeedLowerHyps( dim ) : false ); if (( dim < aMaxGlobIgnoDim && !isNeededDim ) && ( isGlobal || !aGlobIgnoAlgo->SupportSubmeshes() )) { // algo is hidden by a global algo theErrors.push_back( SMESH_Gen::TAlgoStateError() ); theErrors.back().Set( SMESH_Hypothesis::HYP_HIDDEN_ALGO, algo, true ); INFOS( ( isGlobal ? "Global" : "Local" ) << " <" << algo->GetName() << "> is hidden by global <" << aGlobIgnoAlgo->GetName() << ">"); } else if ( !algo->NeedDiscreteBoundary() && !isGlobal) { // local algo is not hidden and hides algos on sub-shapes if (checkConform && !aSubMesh->IsConform( algo )) { ret = false; checkConform = false; // no more check conformity INFOS( "ERROR: Local <" << algo->GetName() << "> would produce not conform mesh: " "<Not Conform Mesh Allowed> hypotesis is missing"); theErrors.push_back( SMESH_Gen::TAlgoStateError() ); theErrors.back().Set( SMESH_Hypothesis::HYP_NOTCONFORM, algo, false ); } // sub-algos will be hidden by a local <algo> if <algo> does not support sub-meshes if ( algo->SupportSubmeshes() ) algo = 0; SMESH_subMeshIteratorPtr revItSub = aSubMesh->getDependsOnIterator( /*includeSelf=*/false, /*complexShapeFirst=*/true); bool checkConform2 = false; while ( revItSub->more() ) { SMESH_subMesh* sm = revItSub->next(); checkConformIgnoredAlgos (aMesh, sm, aGlobIgnoAlgo, algo, checkConform2, aCheckedMap, theErrors); aCheckedMap.insert( sm ); } } } } return ret; }
bool SMESH_Gen::GetAlgoState(SMESH_Mesh& theMesh, const TopoDS_Shape& theShape, list< TAlgoStateError > & theErrors) { //MESSAGE("SMESH_Gen::CheckAlgoState"); bool ret = true; bool hasAlgo = false; SMESH_subMesh* sm = theMesh.GetSubMesh(theShape); const SMESHDS_Mesh* meshDS = theMesh.GetMeshDS(); TopoDS_Shape mainShape = meshDS->ShapeToMesh(); // ----------------- // get global algos // ----------------- const SMESH_Algo* aGlobAlgoArr[] = {0,0,0,0}; const list<const SMESHDS_Hypothesis*>& listHyp = meshDS->GetHypothesis( mainShape ); list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin(); for ( ; it != listHyp.end(); it++) { const SMESHDS_Hypothesis * aHyp = *it; if (aHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO) continue; const SMESH_Algo* algo = dynamic_cast<const SMESH_Algo*> (aHyp); ASSERT ( algo ); int dim = algo->GetDim(); aGlobAlgoArr[ dim ] = algo; hasAlgo = true; } // -------------------------------------------------------- // info on algos that will be ignored because of ones that // don't NeedDiscreteBoundary() attached to super-shapes, // check that a conform mesh will be produced // -------------------------------------------------------- // find a global algo possibly hiding sub-algos int dim; const SMESH_Algo* aGlobIgnoAlgo = 0; for (dim = 3; dim > 0; dim--) { if (aGlobAlgoArr[ dim ] && !aGlobAlgoArr[ dim ]->NeedDiscreteBoundary() /*&& !aGlobAlgoArr[ dim ]->SupportSubmeshes()*/ ) { aGlobIgnoAlgo = aGlobAlgoArr[ dim ]; break; } } set<SMESH_subMesh*> aCheckedSubs; bool checkConform = ( !theMesh.IsNotConformAllowed() ); // loop on theShape and its sub-shapes SMESH_subMeshIteratorPtr revItSub = sm->getDependsOnIterator( /*includeSelf=*/true, /*complexShapeFirst=*/true); while ( revItSub->more() ) { SMESH_subMesh* smToCheck = revItSub->next(); if ( smToCheck->GetSubShape().ShapeType() == TopAbs_VERTEX) break; if ( aCheckedSubs.insert( smToCheck ).second ) // not yet checked if (!checkConformIgnoredAlgos (theMesh, smToCheck, aGlobIgnoAlgo, 0, checkConform, aCheckedSubs, theErrors)) ret = false; if ( smToCheck->GetAlgoState() != SMESH_subMesh::NO_ALGO ) hasAlgo = true; } // ---------------------------------------------------------------- // info on missing hypothesis and find out if all needed algos are // well defined // ---------------------------------------------------------------- //MESSAGE( "---info on missing hypothesis and find out if all needed algos are"); // find max dim of global algo int aTopAlgoDim = 0; for (dim = 3; dim > 0; dim--) { if (aGlobAlgoArr[ dim ]) { aTopAlgoDim = dim; break; } } bool checkNoAlgo = theMesh.HasShapeToMesh() ? bool( aTopAlgoDim ) : false; bool globalChecked[] = { false, false, false, false }; // loop on theShape and its sub-shapes aCheckedSubs.clear(); revItSub = sm->getDependsOnIterator( /*includeSelf=*/true, /*complexShapeFirst=*/true); while ( revItSub->more() ) { SMESH_subMesh* smToCheck = revItSub->next(); if ( smToCheck->GetSubShape().ShapeType() == TopAbs_VERTEX) break; if (!checkMissing (this, theMesh, smToCheck, aTopAlgoDim, globalChecked, checkNoAlgo, aCheckedSubs, theErrors)) { ret = false; if (smToCheck->GetAlgoState() == SMESH_subMesh::NO_ALGO ) checkNoAlgo = false; } } if ( !hasAlgo ) { ret = false; theErrors.push_back( TAlgoStateError() ); theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, theMesh.HasShapeToMesh() ? 1 : 3, true ); } return ret; }
bool StdMeshers_CompositeSegment_1D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape) { TopoDS_Edge edge = TopoDS::Edge( aShape ); SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); // Get edges to be discretized as a whole TopoDS_Face nullFace; auto_ptr< StdMeshers_FaceSide > side( GetFaceSide(aMesh, edge, nullFace, true )); //side->dump("IN COMPOSITE SEG"); if ( side->NbEdges() < 2 ) return StdMeshers_Regular_1D::Compute( aMesh, aShape ); // update segment lenght computed by StdMeshers_AutomaticLength const list <const SMESHDS_Hypothesis * > & hyps = GetUsedHypothesis(aMesh, aShape); if ( !hyps.empty() ) { StdMeshers_AutomaticLength * autoLenHyp = const_cast<StdMeshers_AutomaticLength *> (dynamic_cast <const StdMeshers_AutomaticLength * >(hyps.front())); if ( autoLenHyp ) _value[ BEG_LENGTH_IND ]= autoLenHyp->GetLength( &aMesh, side->Length() ); } // Compute node parameters auto_ptr< BRepAdaptor_CompCurve > C3d ( side->GetCurve3d() ); double f = C3d->FirstParameter(), l = C3d->LastParameter(); list< double > params; if ( !computeInternalParameters ( aMesh, *C3d, side->Length(), f, l, params, false )) return false; // Redistribute parameters near ends TopoDS_Vertex VFirst = side->FirstVertex(); TopoDS_Vertex VLast = side->LastVertex(); redistributeNearVertices( aMesh, *C3d, side->Length(), params, VFirst, VLast ); params.push_front(f); params.push_back(l); int nbNodes = params.size(); // Create mesh const SMDS_MeshNode * nFirst = SMESH_Algo::VertexNode( VFirst, meshDS ); const SMDS_MeshNode * nLast = SMESH_Algo::VertexNode( VLast, meshDS ); if (!nFirst) return error(COMPERR_BAD_INPUT_MESH, TComm("No node on vertex ") <<meshDS->ShapeToIndex(VFirst)); if (!nLast) return error(COMPERR_BAD_INPUT_MESH, TComm("No node on vertex ") <<meshDS->ShapeToIndex(VLast)); vector<const SMDS_MeshNode*> nodes( nbNodes, (const SMDS_MeshNode*)0 ); nodes.front() = nFirst; nodes.back() = nLast; // create internal nodes list< double >::iterator parIt = params.begin(); double prevPar = *parIt; Standard_Real u; for ( int iN = 0; parIt != params.end(); ++iN, ++parIt) { if ( !nodes[ iN ] ) { gp_Pnt p = C3d->Value( *parIt ); SMDS_MeshNode* n = meshDS->AddNode( p.X(), p.Y(), p.Z()); C3d->Edge( *parIt, edge, u ); meshDS->SetNodeOnEdge( n, edge, u ); // cout << "new NODE: par="<<*parIt<<" ePar="<<u<<" e="<<edge.TShape().operator->() // << " " << n << endl; nodes[ iN ] = n; } // create edges if ( iN ) { double mPar = ( prevPar + *parIt )/2; if ( _quadraticMesh ) { // create medium node double segLen = GCPnts_AbscissaPoint::Length(*C3d, prevPar, *parIt); GCPnts_AbscissaPoint ruler( *C3d, segLen/2., prevPar ); if ( ruler.IsDone() ) mPar = ruler.Parameter(); gp_Pnt p = C3d->Value( mPar ); SMDS_MeshNode* n = meshDS->AddNode( p.X(), p.Y(), p.Z()); //cout << "new NODE "<< n << endl; meshDS->SetNodeOnEdge( n, edge, u ); SMDS_MeshEdge * seg = meshDS->AddEdge(nodes[ iN-1 ], nodes[ iN ], n); meshDS->SetMeshElementOnShape(seg, edge); } else { C3d->Edge( mPar, edge, u ); SMDS_MeshEdge * seg = meshDS->AddEdge(nodes[ iN-1 ], nodes[ iN ]); meshDS->SetMeshElementOnShape(seg, edge); } } prevPar = *parIt; } // remove nodes on internal vertices for ( int iE = 1; iE < side->NbEdges(); ++iE ) { TopoDS_Vertex V = side->FirstVertex( iE ); while ( const SMDS_MeshNode * n = SMESH_Algo::VertexNode( V, meshDS )) meshDS->RemoveNode( n ); } // Update submeshes state for all edges and internal vertices, // make them look computed even if none edge or node is set on them careOfSubMeshes( *side, _EventListener ); return true; }
PyObject* FemMeshPy::addEdge(PyObject *args) { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); int n1,n2; if (PyArg_ParseTuple(args, "ii",&n1,&n2)) { try { const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); if (!node1 || !node2) throw std::runtime_error("Failed to get node of the given indices"); SMDS_MeshEdge* edge = meshDS->AddEdge(node1, node2); if (!edge) throw std::runtime_error("Failed to add edge"); return Py::new_reference_to(Py::Long(edge->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::BaseExceptionFreeCADError, e.what()); return 0; } } PyErr_Clear(); PyObject *obj; int ElementId=-1; if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) { Py::List list(obj); std::vector<const SMDS_MeshNode*> Nodes; for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { #if PY_MAJOR_VERSION >= 3 Py::Long NoNr(*it); #else Py::Int NoNr(*it); #endif const SMDS_MeshNode* node = meshDS->FindNode(NoNr); if (!node) throw std::runtime_error("Failed to get node of the given indices"); Nodes.push_back(node); } SMDS_MeshEdge* edge=0; if(ElementId != -1) { switch(Nodes.size()){ case 2: edge = meshDS->AddEdgeWithID(Nodes[0],Nodes[1],ElementId); if (!edge) throw std::runtime_error("Failed to add edge with given ElementId"); break; case 3: edge = meshDS->AddEdgeWithID(Nodes[0],Nodes[1],Nodes[2],ElementId); if (!edge) throw std::runtime_error("Failed to add edge with given ElementId"); break; default: throw std::runtime_error("Unknown node count, [2|3] are allowed"); //unknown edge type } } else { switch(Nodes.size()){ case 2: edge = meshDS->AddEdge(Nodes[0],Nodes[1]); if (!edge) throw std::runtime_error("Failed to add edge"); break; case 3: edge = meshDS->AddEdge(Nodes[0],Nodes[1],Nodes[2]); if (!edge) throw std::runtime_error("Failed to add edge"); break; default: throw std::runtime_error("Unknown node count, [2|3] are allowed"); //unknown edge type } } #if PY_MAJOR_VERSION >= 3 return Py::new_reference_to(Py::Long(edge->GetID())); #else return Py::new_reference_to(Py::Int(edge->GetID())); #endif } PyErr_SetString(PyExc_TypeError, "addEdge accepts:\n" "-- int,int\n" "-- [2|3],[int]\n"); return 0; }
PyObject* FemMeshPy::addFace(PyObject *args) { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); int n1,n2,n3; if (PyArg_ParseTuple(args, "iii",&n1,&n2,&n3)) { // old form, debrekadet try { const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); const SMDS_MeshNode* node3 = meshDS->FindNode(n3); if (!node1 || !node2 || !node3) throw std::runtime_error("Failed to get node of the given indices"); SMDS_MeshFace* face = meshDS->AddFace(node1, node2, node3); if (!face) throw std::runtime_error("Failed to add face"); return Py::new_reference_to(Py::Int(face->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::BaseExceptionFreeCADError, e.what()); return 0; } } PyErr_Clear(); PyObject *obj; int ElementId=-1; if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) { Py::List list(obj); std::vector<const SMDS_MeshNode*> Nodes; for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { Py::Int NoNr(*it); const SMDS_MeshNode* node = meshDS->FindNode(NoNr); if (!node) throw std::runtime_error("Failed to get node of the given indices"); Nodes.push_back(node); } SMDS_MeshFace* face=0; switch(Nodes.size()){ case 3: face = meshDS->AddFace(Nodes[0],Nodes[1],Nodes[2]); if (!face) throw std::runtime_error("Failed to add triangular face"); break; default: throw std::runtime_error("Unknown node count, [3|4|6|8] are allowed"); //unknown face type } return Py::new_reference_to(Py::Int(face->GetID())); } PyErr_SetString(PyExc_TypeError, "Line constructor accepts:\n" "-- empty parameter list\n" "-- Line\n" "-- Point, Point"); return 0; }
PyObject* FemMeshPy::addVolume(PyObject *args) { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); int n1,n2,n3,n4; if (PyArg_ParseTuple(args, "iiii",&n1,&n2,&n3,&n4)) { try { const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); const SMDS_MeshNode* node3 = meshDS->FindNode(n3); const SMDS_MeshNode* node4 = meshDS->FindNode(n4); if (!node1 || !node2 || !node3 || !node4) throw std::runtime_error("Failed to get node of the given indices"); SMDS_MeshVolume* vol = meshDS->AddVolume(node1, node2, node3, node4); if (!vol) throw std::runtime_error("Failed to add volume"); return Py::new_reference_to(Py::Long(vol->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::BaseExceptionFreeCADError, e.what()); return 0; } } PyErr_Clear(); PyObject *obj; int ElementId=-1; if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) { Py::List list(obj); std::vector<const SMDS_MeshNode*> Nodes; for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { #if PY_MAJOR_VERSION >= 3 Py::Long NoNr(*it); #else Py::Int NoNr(*it); #endif const SMDS_MeshNode* node = meshDS->FindNode(NoNr); if (!node) throw std::runtime_error("Failed to get node of the given indices"); Nodes.push_back(node); } SMDS_MeshVolume* vol=0; if(ElementId != -1) { switch(Nodes.size()){ case 4: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],ElementId); if (!vol) throw std::runtime_error("Failed to add Tet4 volume with given ElementId"); break; case 5: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],ElementId); if (!vol) throw std::runtime_error("Failed to add Pyra5 volume with given ElementId"); break; case 6: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],ElementId); if (!vol) throw std::runtime_error("Failed to add Penta6 volume with given ElementId"); break; case 8: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],ElementId); if (!vol) throw std::runtime_error("Failed to add Hexa8 volume with given ElementId"); break; case 10: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],ElementId); if (!vol) throw std::runtime_error("Failed to add Tet10 volume with given ElementId"); break; case 13: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12],ElementId); if (!vol) throw std::runtime_error("Failed to add Pyra13 volume with given ElementId"); break; case 15: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12],Nodes[13],Nodes[14],ElementId); if (!vol) throw std::runtime_error("Failed to add Penta15 volume with given ElementId"); break; case 20: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12],Nodes[13],Nodes[14],Nodes[15],Nodes[16],Nodes[17],Nodes[18],Nodes[19],ElementId); if (!vol) throw std::runtime_error("Failed to add Hexa20 volume with given ElementId"); break; default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|15|20] are allowed"); //unknown volume type } }else{ switch(Nodes.size()){ case 4: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3]); if (!vol) throw std::runtime_error("Failed to add Tet4 volume"); break; case 5: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4]); if (!vol) throw std::runtime_error("Failed to add Pyra5 volume"); break; case 6: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5]); if (!vol) throw std::runtime_error("Failed to add Penta6 volume"); break; case 8: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7]); if (!vol) throw std::runtime_error("Failed to add Hexa8 volume"); break; case 10: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9]); if (!vol) throw std::runtime_error("Failed to add Tet10 volume"); break; case 13: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12]); if (!vol) throw std::runtime_error("Failed to add Pyra13 volume"); break; case 15: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12],Nodes[13],Nodes[14]); if (!vol) throw std::runtime_error("Failed to add Penta15 volume"); break; case 20: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],Nodes[10],Nodes[11],Nodes[12],Nodes[13],Nodes[14],Nodes[15],Nodes[16],Nodes[17],Nodes[18],Nodes[19]); if (!vol) throw std::runtime_error("Failed to add Hexa20 volume"); break; default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|15|20] are allowed"); //unknown volume type } } return Py::new_reference_to(Py::Long(vol->GetID())); } PyErr_SetString(PyExc_TypeError, "addVolume accepts:\n" "-- int,int,int,int\n" "-- [4|5|6|8|10|13|15|20 int],[int]\n"); return 0; }
PyObject* FemMeshPy::addVolume(PyObject *args) { SMESH_Mesh* mesh = getFemMeshPtr()->getSMesh(); SMESHDS_Mesh* meshDS = mesh->GetMeshDS(); int n1,n2,n3,n4; if (PyArg_ParseTuple(args, "iiii",&n1,&n2,&n3,&n4)) { try { const SMDS_MeshNode* node1 = meshDS->FindNode(n1); const SMDS_MeshNode* node2 = meshDS->FindNode(n2); const SMDS_MeshNode* node3 = meshDS->FindNode(n3); const SMDS_MeshNode* node4 = meshDS->FindNode(n4); if (!node1 || !node2 || !node3 || !node4) throw std::runtime_error("Failed to get node of the given indices"); SMDS_MeshVolume* vol = meshDS->AddVolume(node1, node2, node3, node4); if (!vol) throw std::runtime_error("Failed to add volume"); return Py::new_reference_to(Py::Int(vol->GetID())); } catch (const std::exception& e) { PyErr_SetString(Base::BaseExceptionFreeCADError, e.what()); return 0; } } PyErr_Clear(); PyObject *obj; int ElementId=-1; if (PyArg_ParseTuple(args, "O!|i", &PyList_Type, &obj, &ElementId)) { Py::List list(obj); std::vector<const SMDS_MeshNode*> Nodes; for (Py::List::iterator it = list.begin(); it != list.end(); ++it) { Py::Int NoNr(*it); const SMDS_MeshNode* node = meshDS->FindNode(NoNr); if (!node) throw std::runtime_error("Failed to get node of the given indices"); Nodes.push_back(node); } SMDS_MeshVolume* vol=0; if(ElementId != -1) { switch(Nodes.size()){ case 4: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],ElementId); if (!vol) throw std::runtime_error("Failed to add Tet4 volume"); break; case 8: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],ElementId); if (!vol) throw std::runtime_error("Failed to add Tet10 volume"); break; case 10: vol = meshDS->AddVolumeWithID(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9],ElementId); if (!vol) throw std::runtime_error("Failed to add Tet10 volume"); break; default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|18] are allowed"); //unknown face type } }else{ switch(Nodes.size()){ case 4: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3]); if (!vol) throw std::runtime_error("Failed to add Tet4 volume"); break; case 8: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7]); if (!vol) throw std::runtime_error("Failed to add Tet10 volume"); break; case 10: vol = meshDS->AddVolume(Nodes[0],Nodes[1],Nodes[2],Nodes[3],Nodes[4],Nodes[5],Nodes[6],Nodes[7],Nodes[8],Nodes[9]); if (!vol) throw std::runtime_error("Failed to add Tet10 volume"); break; default: throw std::runtime_error("Unknown node count, [4|5|6|8|10|13|18] are allowed"); //unknown face type } } return Py::new_reference_to(Py::Int(vol->GetID())); } PyErr_SetString(PyExc_TypeError, "Line constructor accepts:\n" "-- empty parameter list\n" "-- Line\n" "-- Point, Point"); return 0; }
bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) { netgen::multithread.terminate = 0; netgen::multithread.task = "Volume meshing"; _progressByTic = -1.; SMESHDS_Mesh* meshDS = aMesh.GetMeshDS(); SMESH_MesherHelper helper(aMesh); bool _quadraticMesh = helper.IsQuadraticSubMesh(aShape); helper.SetElementsOnShape( true ); int Netgen_NbOfNodes = 0; double Netgen_point[3]; int Netgen_triangle[3]; NETGENPlugin_NetgenLibWrapper ngLib; Ng_Mesh * Netgen_mesh = ngLib._ngMesh; // vector of nodes in which node index == netgen ID vector< const SMDS_MeshNode* > nodeVec; { const int invalid_ID = -1; SMESH::Controls::Area areaControl; SMESH::Controls::TSequenceOfXYZ nodesCoords; // maps nodes to ng ID typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap; typedef TNodeToIDMap::value_type TN2ID; TNodeToIDMap nodeToNetgenID; // find internal shapes NETGENPlugin_Internals internals( aMesh, aShape, /*is3D=*/true ); // --------------------------------- // Feed the Netgen with surface mesh // --------------------------------- TopAbs_ShapeEnum mainType = aMesh.GetShapeToMesh().ShapeType(); bool checkReverse = ( mainType == TopAbs_COMPOUND || mainType == TopAbs_COMPSOLID ); SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( aMesh )); if ( _viscousLayersHyp ) { netgen::multithread.percent = 3; proxyMesh = _viscousLayersHyp->Compute( aMesh, aShape ); if ( !proxyMesh ) return false; } if ( aMesh.NbQuadrangles() > 0 ) { netgen::multithread.percent = 6; StdMeshers_QuadToTriaAdaptor* Adaptor = new StdMeshers_QuadToTriaAdaptor; Adaptor->Compute(aMesh,aShape,proxyMesh.get()); proxyMesh.reset( Adaptor ); } for ( TopExp_Explorer exFa( aShape, TopAbs_FACE ); exFa.More(); exFa.Next()) { const TopoDS_Shape& aShapeFace = exFa.Current(); int faceID = meshDS->ShapeToIndex( aShapeFace ); bool isInternalFace = internals.isInternalShape( faceID ); bool isRev = false; if ( checkReverse && !isInternalFace && helper.NbAncestors(aShapeFace, aMesh, aShape.ShapeType()) > 1 ) // IsReversedSubMesh() can work wrong on strongly curved faces, // so we use it as less as possible isRev = helper.IsReversedSubMesh( TopoDS::Face( aShapeFace )); const SMESHDS_SubMesh * aSubMeshDSFace = proxyMesh->GetSubMesh( aShapeFace ); if ( !aSubMeshDSFace ) continue; SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements(); while ( iteratorElem->more() ) // loop on elements on a geom face { // check mesh face const SMDS_MeshElement* elem = iteratorElem->next(); if ( !elem ) return error( COMPERR_BAD_INPUT_MESH, "Null element encounters"); if ( elem->NbCornerNodes() != 3 ) return error( COMPERR_BAD_INPUT_MESH, "Not triangle element encounters"); // Add nodes of triangles and triangles them-selves to netgen mesh // add three nodes of triangle bool hasDegen = false; for ( int iN = 0; iN < 3; ++iN ) { const SMDS_MeshNode* node = elem->GetNode( iN ); const int shapeID = node->getshapeId(); if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_EDGE && helper.IsDegenShape( shapeID )) { // ignore all nodes on degeneraged edge and use node on its vertex instead TopoDS_Shape vertex = TopoDS_Iterator( meshDS->IndexToShape( shapeID )).Value(); node = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), meshDS ); hasDegen = true; } int& ngID = nodeToNetgenID.insert(TN2ID( node, invalid_ID )).first->second; if ( ngID == invalid_ID ) { ngID = ++Netgen_NbOfNodes; Netgen_point [ 0 ] = node->X(); Netgen_point [ 1 ] = node->Y(); Netgen_point [ 2 ] = node->Z(); Ng_AddPoint(Netgen_mesh, Netgen_point); } Netgen_triangle[ isRev ? 2-iN : iN ] = ngID; } // add triangle if ( hasDegen && (Netgen_triangle[0] == Netgen_triangle[1] || Netgen_triangle[0] == Netgen_triangle[2] || Netgen_triangle[2] == Netgen_triangle[1] )) continue; Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle); if ( isInternalFace && !proxyMesh->IsTemporary( elem )) { swap( Netgen_triangle[1], Netgen_triangle[2] ); Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle); } } // loop on elements on a face } // loop on faces of a SOLID or SHELL // insert old nodes into nodeVec nodeVec.resize( nodeToNetgenID.size() + 1, 0 ); TNodeToIDMap::iterator n_id = nodeToNetgenID.begin(); for ( ; n_id != nodeToNetgenID.end(); ++n_id ) nodeVec[ n_id->second ] = n_id->first; nodeToNetgenID.clear(); if ( internals.hasInternalVertexInSolid() ) { netgen::OCCGeometry occgeo; NETGENPlugin_Mesher::AddIntVerticesInSolids( occgeo, (netgen::Mesh&) *Netgen_mesh, nodeVec, internals); } } // ------------------------- // Generate the volume mesh // ------------------------- return ( ngLib._isComputeOk = compute( aMesh, helper, nodeVec, Netgen_mesh)); }
bool StdMeshers_RadialPrism_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) { TopExp_Explorer exp; SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); myHelper = new SMESH_MesherHelper( aMesh ); myHelper->IsQuadraticSubMesh( aShape ); // to delete helper at exit from Compute() std::auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper ); // get 2 shells TopoDS_Solid solid = TopoDS::Solid( aShape ); TopoDS_Shell outerShell = BRepClass3d::OuterShell( solid ); TopoDS_Shape innerShell; int nbShells = 0; for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells ) if ( !outerShell.IsSame( It.Value() )) innerShell = It.Value(); if ( nbShells != 2 ) return error(COMPERR_BAD_SHAPE, SMESH_Comment("Must be 2 shells but not ")<<nbShells); // ---------------------------------- // Associate sub-shapes of the shells // ---------------------------------- ProjectionUtils::TShapeShapeMap shape2ShapeMaps[2]; bool mapOk1 = ProjectionUtils::FindSubShapeAssociation( innerShell, &aMesh, outerShell, &aMesh, shape2ShapeMaps[0]); bool mapOk2 = ProjectionUtils::FindSubShapeAssociation( innerShell.Reversed(), &aMesh, outerShell, &aMesh, shape2ShapeMaps[1]); if ( !mapOk1 && !mapOk2 ) return error(COMPERR_BAD_SHAPE,"Topology of inner and outer shells seems different" ); int iMap; if ( shape2ShapeMaps[0].Extent() == shape2ShapeMaps[1].Extent() ) { // choose an assiciation by shortest distance between VERTEXes double dist1 = 0, dist2 = 0; TopTools_DataMapIteratorOfDataMapOfShapeShape ssIt( shape2ShapeMaps[0]._map1to2 ); for (; ssIt.More(); ssIt.Next() ) { if ( ssIt.Key().ShapeType() != TopAbs_VERTEX ) continue; gp_Pnt pIn = BRep_Tool::Pnt( TopoDS::Vertex( ssIt.Key() )); gp_Pnt pOut1 = BRep_Tool::Pnt( TopoDS::Vertex( ssIt.Value() )); gp_Pnt pOut2 = BRep_Tool::Pnt( TopoDS::Vertex( shape2ShapeMaps[1]( ssIt.Key() ))); dist1 += pIn.SquareDistance( pOut1 ); dist2 += pIn.SquareDistance( pOut2 ); } iMap = ( dist1 < dist2 ) ? 0 : 1; } else { iMap = ( shape2ShapeMaps[0].Extent() > shape2ShapeMaps[1].Extent() ) ? 0 : 1; } ProjectionUtils::TShapeShapeMap& shape2ShapeMap = shape2ShapeMaps[iMap]; // ------------------ // Make mesh // ------------------ TNode2ColumnMap node2columnMap; myLayerPositions.clear(); for ( exp.Init( outerShell, TopAbs_FACE ); exp.More(); exp.Next() ) { // Corresponding sub-shapes TopoDS_Face outFace = TopoDS::Face( exp.Current() ); TopoDS_Face inFace; if ( !shape2ShapeMap.IsBound( outFace, /*isOut=*/true )) { return error(SMESH_Comment("Corresponding inner face not found for face #" ) << meshDS->ShapeToIndex( outFace )); } else { inFace = TopoDS::Face( shape2ShapeMap( outFace, /*isOut=*/true )); } // Find matching nodes of in and out faces ProjectionUtils::TNodeNodeMap nodeIn2OutMap; if ( ! ProjectionUtils::FindMatchingNodesOnFaces( inFace, &aMesh, outFace, &aMesh, shape2ShapeMap, nodeIn2OutMap )) return error(COMPERR_BAD_INPUT_MESH,SMESH_Comment("Mesh on faces #") << meshDS->ShapeToIndex( outFace ) << " and " << meshDS->ShapeToIndex( inFace ) << " seems different" ); // Create volumes SMDS_ElemIteratorPtr faceIt = meshDS->MeshElements( inFace )->GetElements(); while ( faceIt->more() ) // loop on faces on inFace { const SMDS_MeshElement* face = faceIt->next(); if ( !face || face->GetType() != SMDSAbs_Face ) continue; int nbNodes = face->NbNodes(); if ( face->IsQuadratic() ) nbNodes /= 2; // find node columns for each node vector< const TNodeColumn* > columns( nbNodes ); for ( int i = 0; i < nbNodes; ++i ) { const SMDS_MeshNode* nIn = face->GetNode( i ); TNode2ColumnMap::iterator n_col = node2columnMap.find( nIn ); if ( n_col != node2columnMap.end() ) { columns[ i ] = & n_col->second; } else { TNodeNodeMap::iterator nInOut = nodeIn2OutMap.find( nIn ); if ( nInOut == nodeIn2OutMap.end() ) RETURN_BAD_RESULT("No matching node for "<< nIn->GetID() << " in face "<< face->GetID()); columns[ i ] = makeNodeColumn( node2columnMap, nIn, nInOut->second ); } } StdMeshers_Prism_3D::AddPrisms( columns, myHelper ); } } // loop on faces of out shell return true; }
bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh& aMesh, SMESH_MesherHelper* aHelper) { const int invalid_ID = -1; netgen::multithread.terminate = 0; _progressByTic = -1.; SMESH_MesherHelper::MType MeshType = aHelper->IsQuadraticMesh(); if ( MeshType == SMESH_MesherHelper::COMP ) return error( COMPERR_BAD_INPUT_MESH, SMESH_Comment("Mesh with linear and quadratic elements given")); aHelper->SetIsQuadratic( MeshType == SMESH_MesherHelper::QUADRATIC ); // --------------------------------- // Feed the Netgen with surface mesh // --------------------------------- int Netgen_NbOfNodes = 0; int Netgen_param2ndOrder = 0; double Netgen_paramFine = 1.; double Netgen_paramSize = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. ); double Netgen_point[3]; int Netgen_triangle[3]; int Netgen_tetrahedron[4]; NETGENPlugin_NetgenLibWrapper ngLib; Ng_Mesh * Netgen_mesh = ngLib._ngMesh; SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( aMesh )); if ( aMesh.NbQuadrangles() > 0 ) { StdMeshers_QuadToTriaAdaptor* Adaptor = new StdMeshers_QuadToTriaAdaptor; Adaptor->Compute(aMesh); proxyMesh.reset( Adaptor ); } // maps nodes to ng ID typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap; typedef TNodeToIDMap::value_type TN2ID; TNodeToIDMap nodeToNetgenID; SMDS_ElemIteratorPtr fIt = proxyMesh->GetFaces(); while( fIt->more()) { // check element const SMDS_MeshElement* elem = fIt->next(); if ( !elem ) return error( COMPERR_BAD_INPUT_MESH, "Null element encounters"); if ( elem->NbCornerNodes() != 3 ) return error( COMPERR_BAD_INPUT_MESH, "Not triangle element encounters"); // add three nodes of triangle for ( int iN = 0; iN < 3; ++iN ) { const SMDS_MeshNode* node = elem->GetNode( iN ); int& ngID = nodeToNetgenID.insert(TN2ID( node, invalid_ID )).first->second; if ( ngID == invalid_ID ) { ngID = ++Netgen_NbOfNodes; Netgen_point [ 0 ] = node->X(); Netgen_point [ 1 ] = node->Y(); Netgen_point [ 2 ] = node->Z(); Ng_AddPoint(Netgen_mesh, Netgen_point); } Netgen_triangle[ iN ] = ngID; } Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle); } proxyMesh.reset(); // delete tmp faces // vector of nodes in which node index == netgen ID vector< const SMDS_MeshNode* > nodeVec ( nodeToNetgenID.size() + 1 ); // insert old nodes into nodeVec TNodeToIDMap::iterator n_id = nodeToNetgenID.begin(); for ( ; n_id != nodeToNetgenID.end(); ++n_id ) nodeVec.at( n_id->second ) = n_id->first; nodeToNetgenID.clear(); // ------------------------- // Generate the volume mesh // ------------------------- return ( ngLib._isComputeOk = compute( aMesh, *aHelper, nodeVec, Netgen_mesh)); }
bool StdMeshers_RadialPrism_3D::Evaluate(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, MapShapeNbElems& aResMap) { // get 2 shells TopoDS_Solid solid = TopoDS::Solid( aShape ); TopoDS_Shell outerShell = BRepClass3d::OuterShell( solid ); TopoDS_Shape innerShell; int nbShells = 0; for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells ) if ( !outerShell.IsSame( It.Value() )) innerShell = It.Value(); if ( nbShells != 2 ) { std::vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); aResMap.insert(std::make_pair(sm,aResVec)); SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); return false; } // Associate sub-shapes of the shells ProjectionUtils::TShapeShapeMap shape2ShapeMap; if ( !ProjectionUtils::FindSubShapeAssociation( outerShell, &aMesh, innerShell, &aMesh, shape2ShapeMap) ) { std::vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); aResMap.insert(std::make_pair(sm,aResVec)); SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); return false; } // get info for outer shell int nb0d_Out=0, nb2d_3_Out=0, nb2d_4_Out=0; //TopTools_SequenceOfShape FacesOut; for (TopExp_Explorer exp(outerShell, TopAbs_FACE); exp.More(); exp.Next()) { //FacesOut.Append(exp.Current()); SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); std::vector<int> aVec = (*anIt).second; nb0d_Out += aVec[SMDSEntity_Node]; nb2d_3_Out += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]); nb2d_4_Out += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]); } int nb1d_Out = 0; TopTools_MapOfShape tmpMap; for (TopExp_Explorer exp(outerShell, TopAbs_EDGE); exp.More(); exp.Next()) { if( tmpMap.Contains( exp.Current() ) ) continue; tmpMap.Add( exp.Current() ); SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); std::vector<int> aVec = (*anIt).second; nb0d_Out += aVec[SMDSEntity_Node]; nb1d_Out += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]); } tmpMap.Clear(); for (TopExp_Explorer exp(outerShell, TopAbs_VERTEX); exp.More(); exp.Next()) { if( tmpMap.Contains( exp.Current() ) ) continue; tmpMap.Add( exp.Current() ); nb0d_Out++; } // get info for inner shell int nb0d_In=0, nb2d_3_In=0, nb2d_4_In=0; //TopTools_SequenceOfShape FacesIn; for (TopExp_Explorer exp(innerShell, TopAbs_FACE); exp.More(); exp.Next()) { //FacesIn.Append(exp.Current()); SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); std::vector<int> aVec = (*anIt).second; nb0d_In += aVec[SMDSEntity_Node]; nb2d_3_In += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]); nb2d_4_In += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]); } int nb1d_In = 0; tmpMap.Clear(); bool IsQuadratic = false; bool IsFirst = true; for (TopExp_Explorer exp(innerShell, TopAbs_EDGE); exp.More(); exp.Next()) { if( tmpMap.Contains( exp.Current() ) ) continue; tmpMap.Add( exp.Current() ); SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); std::vector<int> aVec = (*anIt).second; nb0d_In += aVec[SMDSEntity_Node]; nb1d_In += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]); if(IsFirst) { IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]); IsFirst = false; } } tmpMap.Clear(); for (TopExp_Explorer exp(innerShell, TopAbs_VERTEX); exp.More(); exp.Next()) { if( tmpMap.Contains( exp.Current() ) ) continue; tmpMap.Add( exp.Current() ); nb0d_In++; } bool IsOK = (nb0d_Out==nb0d_In) && (nb1d_Out==nb1d_In) && (nb2d_3_Out==nb2d_3_In) && (nb2d_4_Out==nb2d_4_In); if(!IsOK) { std::vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); aResMap.insert(std::make_pair(sm,aResVec)); SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); return false; } int nbLayers = 0; if( myNbLayerHypo ) { nbLayers = myNbLayerHypo->GetNumberOfLayers(); } if ( myDistributionHypo ) { if ( !myDistributionHypo->GetLayerDistribution() ) { std::vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); aResMap.insert(std::make_pair(sm,aResVec)); SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); return false; } TopExp_Explorer exp(outerShell, TopAbs_VERTEX); TopoDS_Vertex Vout = TopoDS::Vertex(exp.Current()); TopoDS_Vertex Vin = TopoDS::Vertex( shape2ShapeMap(Vout) ); if ( myLayerPositions.empty() ) { gp_Pnt pIn = BRep_Tool::Pnt(Vin); gp_Pnt pOut = BRep_Tool::Pnt(Vout); computeLayerPositions( pIn, pOut ); } nbLayers = myLayerPositions.size() + 1; } std::vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; if(IsQuadratic) { aResVec[SMDSEntity_Quad_Penta] = nb2d_3_Out * nbLayers; aResVec[SMDSEntity_Quad_Hexa] = nb2d_4_Out * nbLayers; int nb1d = ( nb2d_3_Out*3 + nb2d_4_Out*4 ) / 2; aResVec[SMDSEntity_Node] = nb0d_Out * ( 2*nbLayers - 1 ) - nb1d * nbLayers; } else { aResVec[SMDSEntity_Node] = nb0d_Out * ( nbLayers - 1 ); aResVec[SMDSEntity_Penta] = nb2d_3_Out * nbLayers; aResVec[SMDSEntity_Hexa] = nb2d_4_Out * nbLayers; } SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); aResMap.insert(std::make_pair(sm,aResVec)); return true; }
bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) { MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume); SMESHDS_Mesh* meshDS = aMesh.GetMeshDS(); const int invalid_ID = -1; SMESH::Controls::Area areaControl; SMESH::Controls::TSequenceOfXYZ nodesCoords; // ------------------------------------------------------------------- // get triangles on aShell and make a map of nodes to Netgen node IDs // ------------------------------------------------------------------- SMESH_MesherHelper helper(aMesh); SMESH_MesherHelper* myTool = &helper; bool _quadraticMesh = myTool->IsQuadraticSubMesh(aShape); typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap; TNodeToIDMap nodeToNetgenID; list< const SMDS_MeshElement* > triangles; list< bool > isReversed; // orientation of triangles TopAbs_ShapeEnum mainType = aMesh.GetShapeToMesh().ShapeType(); bool checkReverse = ( mainType == TopAbs_COMPOUND || mainType == TopAbs_COMPSOLID ); // for the degeneraged edge: ignore all but one node on it; // map storing ids of degen edges and vertices and their netgen id: map< int, int* > degenShapeIdToPtrNgId; map< int, int* >::iterator shId_ngId; list< int > degenNgIds; StdMeshers_QuadToTriaAdaptor Adaptor; Adaptor.Compute(aMesh,aShape); for (TopExp_Explorer exp(aShape,TopAbs_FACE); exp.More(); exp.Next()) { const TopoDS_Shape& aShapeFace = exp.Current(); const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( aShapeFace ); if ( aSubMeshDSFace ) { bool isRev = false; if ( checkReverse && helper.NbAncestors(aShapeFace, aMesh, aShape.ShapeType()) > 1 ) // IsReversedSubMesh() can work wrong on strongly curved faces, // so we use it as less as possible isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS ); SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements(); while ( iteratorElem->more() ) // loop on elements on a face { // check element const SMDS_MeshElement* elem = iteratorElem->next(); if ( !elem ) return error( COMPERR_BAD_INPUT_MESH, "Null element encounters"); bool isTraingle = ( elem->NbNodes()==3 || (_quadraticMesh && elem->NbNodes()==6 )); if ( !isTraingle ) { //return error( COMPERR_BAD_INPUT_MESH, // SMESH_Comment("Not triangle element ")<<elem->GetID()); // using adaptor const list<const SMDS_FaceOfNodes*>* faces = Adaptor.GetTriangles(elem); if(faces==0) { return error( COMPERR_BAD_INPUT_MESH, SMESH_Comment("Not triangles in adaptor for element ")<<elem->GetID()); } list<const SMDS_FaceOfNodes*>::const_iterator itf = faces->begin(); for(; itf!=faces->end(); itf++ ) { triangles.push_back( (*itf) ); isReversed.push_back( isRev ); // put triange's nodes to nodeToNetgenID map SMDS_ElemIteratorPtr triangleNodesIt = (*itf)->nodesIterator(); while ( triangleNodesIt->more() ) { const SMDS_MeshNode * node = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next()); if(myTool->IsMedium(node)) continue; nodeToNetgenID.insert( make_pair( node, invalid_ID )); } } } else { // keep a triangle triangles.push_back( elem ); isReversed.push_back( isRev ); // put elem nodes to nodeToNetgenID map SMDS_ElemIteratorPtr triangleNodesIt = elem->nodesIterator(); while ( triangleNodesIt->more() ) { const SMDS_MeshNode * node = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next()); if(myTool->IsMedium(node)) continue; nodeToNetgenID.insert( make_pair( node, invalid_ID )); } } #ifdef _DEBUG_ // check if a trainge is degenerated areaControl.GetPoints( elem, nodesCoords ); double area = areaControl.GetValue( nodesCoords ); if ( area <= DBL_MIN ) { MESSAGE( "Warning: Degenerated " << elem ); } #endif } // look for degeneraged edges and vetices for (TopExp_Explorer expE(aShapeFace,TopAbs_EDGE); expE.More(); expE.Next()) { TopoDS_Edge aShapeEdge = TopoDS::Edge( expE.Current() ); if ( BRep_Tool::Degenerated( aShapeEdge )) { degenNgIds.push_back( invalid_ID ); int* ptrIdOnEdge = & degenNgIds.back(); // remember edge id int edgeID = meshDS->ShapeToIndex( aShapeEdge ); degenShapeIdToPtrNgId.insert( make_pair( edgeID, ptrIdOnEdge )); // remember vertex id int vertexID = meshDS->ShapeToIndex( TopExp::FirstVertex( aShapeEdge )); degenShapeIdToPtrNgId.insert( make_pair( vertexID, ptrIdOnEdge )); } } } } // --------------------------------- // Feed the Netgen with surface mesh // --------------------------------- int Netgen_NbOfNodes = 0; int Netgen_param2ndOrder = 0; double Netgen_paramFine = 1.; double Netgen_paramSize = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. ); double Netgen_point[3]; int Netgen_triangle[3]; int Netgen_tetrahedron[4]; Ng_Init(); Ng_Mesh * Netgen_mesh = Ng_NewMesh(); // set nodes and remember thier netgen IDs bool isDegen = false, hasDegen = !degenShapeIdToPtrNgId.empty(); TNodeToIDMap::iterator n_id = nodeToNetgenID.begin(); for ( ; n_id != nodeToNetgenID.end(); ++n_id ) { const SMDS_MeshNode* node = n_id->first; // ignore nodes on degenerated edge if ( hasDegen ) { int shapeId = node->GetPosition()->GetShapeId(); shId_ngId = degenShapeIdToPtrNgId.find( shapeId ); isDegen = ( shId_ngId != degenShapeIdToPtrNgId.end() ); if ( isDegen && *(shId_ngId->second) != invalid_ID ) { n_id->second = *(shId_ngId->second); continue; } } Netgen_point [ 0 ] = node->X(); Netgen_point [ 1 ] = node->Y(); Netgen_point [ 2 ] = node->Z(); Ng_AddPoint(Netgen_mesh, Netgen_point); n_id->second = ++Netgen_NbOfNodes; // set netgen ID if ( isDegen ) // all nodes on a degen edge get one netgen ID *(shId_ngId->second) = n_id->second; } // set triangles list< const SMDS_MeshElement* >::iterator tria = triangles.begin(); list< bool >::iterator reverse = isReversed.begin(); for ( ; tria != triangles.end(); ++tria, ++reverse ) { int i = 0; SMDS_ElemIteratorPtr triangleNodesIt = (*tria)->nodesIterator(); while ( triangleNodesIt->more() ) { const SMDS_MeshNode * node = static_cast<const SMDS_MeshNode *>(triangleNodesIt->next()); if(myTool->IsMedium(node)) continue; Netgen_triangle[ *reverse ? 2 - i : i ] = nodeToNetgenID[ node ]; ++i; } if ( !hasDegen || // ignore degenerated triangles, they have 2 or 3 same ids (Netgen_triangle[0] != Netgen_triangle[1] && Netgen_triangle[0] != Netgen_triangle[2] && Netgen_triangle[2] != Netgen_triangle[1] )) { Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle); } } // ------------------------- // Generate the volume mesh // ------------------------- Ng_Meshing_Parameters Netgen_param; Netgen_param.secondorder = Netgen_param2ndOrder; Netgen_param.fineness = Netgen_paramFine; Netgen_param.maxh = Netgen_paramSize; Ng_Result status; try { #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 OCC_CATCH_SIGNALS; #endif status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param); } catch (Standard_Failure& exc) { error(COMPERR_OCC_EXCEPTION, exc.GetMessageString()); status = NG_VOLUME_FAILURE; } catch (...) { error("Exception in Ng_GenerateVolumeMesh()"); status = NG_VOLUME_FAILURE; } if ( GetComputeError()->IsOK() ) { switch ( status ) { case NG_SURFACE_INPUT_ERROR: error( status, "NG_SURFACE_INPUT_ERROR"); case NG_VOLUME_FAILURE: error( status, "NG_VOLUME_FAILURE"); case NG_STL_INPUT_ERROR: error( status, "NG_STL_INPUT_ERROR"); case NG_SURFACE_FAILURE: error( status, "NG_SURFACE_FAILURE"); case NG_FILE_NOT_FOUND: error( status, "NG_FILE_NOT_FOUND"); }; } int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh); int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh); MESSAGE("End of Volume Mesh Generation. status=" << status << ", nb new nodes: " << Netgen_NbOfNodesNew - Netgen_NbOfNodes << ", nb tetra: " << Netgen_NbOfTetra); // ------------------------------------------------------------------- // Feed back the SMESHDS with the generated Nodes and Volume Elements // ------------------------------------------------------------------- bool isOK = ( /*status == NG_OK &&*/ Netgen_NbOfTetra > 0 );// get whatever built if ( isOK ) { // vector of nodes in which node index == netgen ID vector< const SMDS_MeshNode* > nodeVec ( Netgen_NbOfNodesNew + 1 ); // insert old nodes into nodeVec for ( n_id = nodeToNetgenID.begin(); n_id != nodeToNetgenID.end(); ++n_id ) { nodeVec.at( n_id->second ) = n_id->first; } // create and insert new nodes into nodeVec int nodeIndex = Netgen_NbOfNodes + 1; int shapeID = meshDS->ShapeToIndex( aShape ); for ( ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex ) { Ng_GetPoint( Netgen_mesh, nodeIndex, Netgen_point ); SMDS_MeshNode * node = meshDS->AddNode(Netgen_point[0], Netgen_point[1], Netgen_point[2]); meshDS->SetNodeInVolume(node, shapeID); nodeVec.at(nodeIndex) = node; } // create tetrahedrons for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex ) { Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron); SMDS_MeshVolume * elt = myTool->AddVolume (nodeVec.at( Netgen_tetrahedron[0] ), nodeVec.at( Netgen_tetrahedron[1] ), nodeVec.at( Netgen_tetrahedron[2] ), nodeVec.at( Netgen_tetrahedron[3] )); meshDS->SetMeshElementOnShape(elt, shapeID ); } } Ng_DeleteMesh(Netgen_mesh); Ng_Exit(); NETGENPlugin_Mesher::RemoveTmpFiles(); return (status == NG_OK); }
bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, const bool aShapeOnly /*=false*/, const bool anUpward /*=false*/, const ::MeshDimension aDim /*=::MeshDim_3D*/, TSetOfInt* aShapesId /*=0*/) { MESSAGE("SMESH_Gen::Compute"); MEMOSTAT; bool ret = true; SMESH_subMesh *sm = aMesh.GetSubMesh(aShape); const bool includeSelf = true; const bool complexShapeFirst = true; const int globalAlgoDim = 100; SMESH_subMeshIteratorPtr smIt; // Fix of Issue 22150. Due to !BLSURF->OnlyUnaryInput(), BLSURF computes edges // that must be computed by Projection 1D-2D when Projection asks to compute // one face only. SMESH_subMesh::compute_event computeEvent = aShapeOnly ? SMESH_subMesh::COMPUTE_SUBMESH : SMESH_subMesh::COMPUTE; if ( anUpward ) // is called from the below code in this method { // =============================================== // Mesh all the sub-shapes starting from vertices // =============================================== smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst); while ( smIt->more() ) { SMESH_subMesh* smToCompute = smIt->next(); // do not mesh vertices of a pseudo shape const TopoDS_Shape& shape = smToCompute->GetSubShape(); const TopAbs_ShapeEnum shapeType = shape.ShapeType(); if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX ) continue; // check for preview dimension limitations if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim ) { // clear compute state not to show previous compute errors // if preview invoked less dimension less than previous smToCompute->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); continue; } if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) { if (_compute_canceled) return false; setCurrentSubMesh( smToCompute ); smToCompute->ComputeStateEngine( computeEvent ); setCurrentSubMesh( NULL ); } // we check all the sub-meshes here and detect if any of them failed to compute if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE && ( shapeType != TopAbs_EDGE || !SMESH_Algo::isDegenerated( TopoDS::Edge( shape )))) ret = false; else if ( aShapesId ) aShapesId->insert( smToCompute->GetId() ); } //aMesh.GetMeshDS()->Modified(); return ret; } else { // ================================================================ // Apply algos that do NOT require discreteized boundaries // ("all-dimensional") and do NOT support sub-meshes, starting from // the most complex shapes and collect sub-meshes with algos that // DO support sub-meshes // ================================================================ list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes[4]; // for each dim // map to sort sm with same dim algos according to dim of // the shape the algo assigned to (issue 0021217). // Other issues influenced the algo applying order: // 21406, 21556, 21893, 20206 multimap< int, SMESH_subMesh* > shDim2sm; multimap< int, SMESH_subMesh* >::reverse_iterator shDim2smIt; TopoDS_Shape algoShape; int prevShapeDim = -1, aShapeDim; smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst); while ( smIt->more() ) { SMESH_subMesh* smToCompute = smIt->next(); if ( smToCompute->GetComputeState() != SMESH_subMesh::READY_TO_COMPUTE ) continue; const TopoDS_Shape& aSubShape = smToCompute->GetSubShape(); aShapeDim = GetShapeDim( aSubShape ); if ( aShapeDim < 1 ) break; // check for preview dimension limitations if ( aShapesId && aShapeDim > (int)aDim ) continue; SMESH_Algo* algo = GetAlgo( smToCompute, &algoShape ); if ( algo && !algo->NeedDiscreteBoundary() ) { if ( algo->SupportSubmeshes() ) { // reload sub-meshes from shDim2sm into smWithAlgoSupportingSubmeshes // so that more local algos to go first if ( prevShapeDim != aShapeDim ) { prevShapeDim = aShapeDim; for ( shDim2smIt = shDim2sm.rbegin(); shDim2smIt != shDim2sm.rend(); ++shDim2smIt ) if ( shDim2smIt->first == globalAlgoDim ) smWithAlgoSupportingSubmeshes[ aShapeDim ].push_back( shDim2smIt->second ); else smWithAlgoSupportingSubmeshes[ aShapeDim ].push_front( shDim2smIt->second ); shDim2sm.clear(); } // add smToCompute to shDim2sm map if ( algoShape.IsSame( aMesh.GetShapeToMesh() )) { aShapeDim = globalAlgoDim; // to compute last } else { aShapeDim = GetShapeDim( algoShape ); if ( algoShape.ShapeType() == TopAbs_COMPOUND ) { TopoDS_Iterator it( algoShape ); aShapeDim += GetShapeDim( it.Value() ); } } shDim2sm.insert( make_pair( aShapeDim, smToCompute )); } else // Compute w/o support of sub-meshes { if (_compute_canceled) return false; setCurrentSubMesh( smToCompute ); smToCompute->ComputeStateEngine( computeEvent ); setCurrentSubMesh( NULL ); if ( aShapesId ) aShapesId->insert( smToCompute->GetId() ); } } } // reload sub-meshes from shDim2sm into smWithAlgoSupportingSubmeshes for ( shDim2smIt = shDim2sm.rbegin(); shDim2smIt != shDim2sm.rend(); ++shDim2smIt ) if ( shDim2smIt->first == globalAlgoDim ) smWithAlgoSupportingSubmeshes[3].push_back( shDim2smIt->second ); else smWithAlgoSupportingSubmeshes[0].push_front( shDim2smIt->second ); // ====================================================== // Apply all-dimensional algorithms supporing sub-meshes // ====================================================== std::vector< SMESH_subMesh* > smVec; for ( aShapeDim = 0; aShapeDim < 4; ++aShapeDim ) { // ------------------------------------------------ // sort list of sub-meshes according to mesh order // ------------------------------------------------ smVec.assign( smWithAlgoSupportingSubmeshes[ aShapeDim ].begin(), smWithAlgoSupportingSubmeshes[ aShapeDim ].end() ); aMesh.SortByMeshOrder( smVec ); // ------------------------------------------------------------ // compute sub-meshes with local uni-dimensional algos under // sub-meshes with all-dimensional algos // ------------------------------------------------------------ // start from lower shapes for ( size_t i = 0; i < smVec.size(); ++i ) { sm = smVec[i]; // get a shape the algo is assigned to if ( !GetAlgo( sm, & algoShape )) continue; // strange... // look for more local algos smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst); while ( smIt->more() ) { SMESH_subMesh* smToCompute = smIt->next(); const TopoDS_Shape& aSubShape = smToCompute->GetSubShape(); const int aShapeDim = GetShapeDim( aSubShape ); //if ( aSubShape.ShapeType() == TopAbs_VERTEX ) continue; if ( aShapeDim < 1 ) continue; // check for preview dimension limitations if ( aShapesId && GetShapeDim( aSubShape.ShapeType() ) > (int)aDim ) continue; SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() ); filter .And( SMESH_HypoFilter::IsApplicableTo( aSubShape )) .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh )); if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true)) { if ( ! subAlgo->NeedDiscreteBoundary() ) continue; SMESH_Hypothesis::Hypothesis_Status status; if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status )) // mesh a lower smToCompute starting from vertices Compute( aMesh, aSubShape, aShapeOnly, /*anUpward=*/true, aDim, aShapesId ); } } } // -------------------------------- // apply the all-dimensional algos // -------------------------------- for ( size_t i = 0; i < smVec.size(); ++i ) { sm = smVec[i]; if ( sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) { const TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType(); // check for preview dimension limitations if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim ) continue; if (_compute_canceled) return false; setCurrentSubMesh( sm ); sm->ComputeStateEngine( computeEvent ); setCurrentSubMesh( NULL ); if ( aShapesId ) aShapesId->insert( sm->GetId() ); } } } // loop on shape dimensions // ----------------------------------------------- // mesh the rest sub-shapes starting from vertices // ----------------------------------------------- ret = Compute( aMesh, aShape, aShapeOnly, /*anUpward=*/true, aDim, aShapesId ); } MESSAGE( "VSR - SMESH_Gen::Compute() finished, OK = " << ret); MEMOSTAT; SMESHDS_Mesh *myMesh = aMesh.GetMeshDS(); MESSAGE("*** compactMesh after compute"); myMesh->compactMesh(); // fix quadratic mesh by bending iternal links near concave boundary if ( aShape.IsSame( aMesh.GetShapeToMesh() ) && !aShapesId && // not preview ret ) // everything is OK { SMESH_MesherHelper aHelper( aMesh ); if ( aHelper.IsQuadraticMesh() != SMESH_MesherHelper::LINEAR ) { aHelper.FixQuadraticElements( sm->GetComputeError() ); } } return ret; }
void NETGENPlugin_Mesher::PrepareOCCgeometry(netgen::OCCGeometry& occgeo, const TopoDS_Shape& shape, SMESH_Mesh& mesh, list< SMESH_subMesh* > * meshedSM) { BRepTools::Clean (shape); try { #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 OCC_CATCH_SIGNALS; #endif BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh (shape, 0.01, true); } catch (Standard_Failure) { } Bnd_Box bb; BRepBndLib::Add (shape, bb); double x1,y1,z1,x2,y2,z2; bb.Get (x1,y1,z1,x2,y2,z2); MESSAGE("shape bounding box:\n" << "(" << x1 << " " << y1 << " " << z1 << ") " << "(" << x2 << " " << y2 << " " << z2 << ")"); netgen::Point<3> p1 = netgen::Point<3> (x1,y1,z1); netgen::Point<3> p2 = netgen::Point<3> (x2,y2,z2); occgeo.boundingbox = netgen::Box<3> (p1,p2); occgeo.shape = shape; occgeo.changed = 1; //occgeo.BuildFMap(); // fill maps of shapes of occgeo with not yet meshed subshapes // get root submeshes list< SMESH_subMesh* > rootSM; if ( SMESH_subMesh* sm = mesh.GetSubMeshContaining( shape )) { rootSM.push_back( sm ); } else { for ( TopoDS_Iterator it( shape ); it.More(); it.Next() ) rootSM.push_back( mesh.GetSubMesh( it.Value() )); } // add subshapes of empty submeshes list< SMESH_subMesh* >::iterator rootIt = rootSM.begin(), rootEnd = rootSM.end(); for ( ; rootIt != rootEnd; ++rootIt ) { SMESH_subMesh * root = *rootIt; SMESH_subMeshIteratorPtr smIt = root->getDependsOnIterator(/*includeSelf=*/true, /*complexShapeFirst=*/true); // to find a right orientation of subshapes (PAL20462) TopTools_IndexedMapOfShape subShapes; TopExp::MapShapes(root->GetSubShape(), subShapes); while ( smIt->more() ) { SMESH_subMesh* sm = smIt->next(); if ( !meshedSM || sm->IsEmpty() ) { TopoDS_Shape shape = sm->GetSubShape(); if ( shape.ShapeType() != TopAbs_VERTEX ) shape = subShapes( subShapes.FindIndex( shape ));// - shape->index->oriented shape switch ( shape.ShapeType() ) { case TopAbs_FACE : occgeo.fmap.Add( shape ); break; case TopAbs_EDGE : occgeo.emap.Add( shape ); break; case TopAbs_VERTEX: occgeo.vmap.Add( shape ); break; case TopAbs_SOLID :occgeo.somap.Add( shape ); break; default:; } } // collect submeshes of meshed shapes else if (meshedSM) { meshedSM->push_back( sm ); } } } occgeo.facemeshstatus.SetSize (occgeo.fmap.Extent()); occgeo.facemeshstatus = 0; }
bool SMESH_Gen::Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, MapShapeNbElems& aResMap, const bool anUpward, TSetOfInt* aShapesId) { MESSAGE("SMESH_Gen::Evaluate"); bool ret = true; SMESH_subMesh *sm = aMesh.GetSubMesh(aShape); const bool includeSelf = true; const bool complexShapeFirst = true; SMESH_subMeshIteratorPtr smIt; if ( anUpward ) { // is called from below code here // ----------------------------------------------- // mesh all the sub-shapes starting from vertices // ----------------------------------------------- smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst); while ( smIt->more() ) { SMESH_subMesh* smToCompute = smIt->next(); // do not mesh vertices of a pseudo shape const TopAbs_ShapeEnum shapeType = smToCompute->GetSubShape().ShapeType(); //if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX ) // continue; if ( !aMesh.HasShapeToMesh() ) { if( shapeType == TopAbs_VERTEX || shapeType == TopAbs_WIRE || shapeType == TopAbs_SHELL ) continue; } smToCompute->Evaluate(aResMap); if( aShapesId ) aShapesId->insert( smToCompute->GetId() ); } return ret; } else { // ----------------------------------------------------------------- // apply algos that DO NOT require Discreteized boundaries and DO NOT // support sub-meshes, starting from the most complex shapes // and collect sub-meshes with algos that DO support sub-meshes // ----------------------------------------------------------------- list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes; smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst); while ( smIt->more() ) { SMESH_subMesh* smToCompute = smIt->next(); const TopoDS_Shape& aSubShape = smToCompute->GetSubShape(); const int aShapeDim = GetShapeDim( aSubShape ); if ( aShapeDim < 1 ) break; SMESH_Algo* algo = GetAlgo( smToCompute ); if ( algo && !algo->NeedDiscreteBoundary() ) { if ( algo->SupportSubmeshes() ) { smWithAlgoSupportingSubmeshes.push_front( smToCompute ); } else { smToCompute->Evaluate(aResMap); if ( aShapesId ) aShapesId->insert( smToCompute->GetId() ); } } } // ------------------------------------------------------------ // sort list of meshes according to mesh order // ------------------------------------------------------------ std::vector< SMESH_subMesh* > smVec( smWithAlgoSupportingSubmeshes.begin(), smWithAlgoSupportingSubmeshes.end() ); aMesh.SortByMeshOrder( smVec ); // ------------------------------------------------------------ // compute sub-meshes under shapes with algos that DO NOT require // Discreteized boundaries and DO support sub-meshes // ------------------------------------------------------------ // start from lower shapes for ( size_t i = 0; i < smVec.size(); ++i ) { sm = smVec[i]; // get a shape the algo is assigned to TopoDS_Shape algoShape; if ( !GetAlgo( sm, & algoShape )) continue; // strange... // look for more local algos smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst); while ( smIt->more() ) { SMESH_subMesh* smToCompute = smIt->next(); const TopoDS_Shape& aSubShape = smToCompute->GetSubShape(); const int aShapeDim = GetShapeDim( aSubShape ); if ( aShapeDim < 1 ) continue; SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() ); filter .And( SMESH_HypoFilter::IsApplicableTo( aSubShape )) .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh )); if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true )) { if ( ! subAlgo->NeedDiscreteBoundary() ) continue; SMESH_Hypothesis::Hypothesis_Status status; if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status )) // mesh a lower smToCompute starting from vertices Evaluate( aMesh, aSubShape, aResMap, /*anUpward=*/true, aShapesId ); } } } // ---------------------------------------------------------- // apply the algos that do not require Discreteized boundaries // ---------------------------------------------------------- for ( size_t i = 0; i < smVec.size(); ++i ) { sm = smVec[i]; sm->Evaluate(aResMap); if ( aShapesId ) aShapesId->insert( sm->GetId() ); } // ----------------------------------------------- // mesh the rest sub-shapes starting from vertices // ----------------------------------------------- ret = Evaluate( aMesh, aShape, aResMap, /*anUpward=*/true, aShapesId ); } MESSAGE( "VSR - SMESH_Gen::Evaluate() finished, OK = " << ret); return ret; }