StdMeshers_FaceSide * StdMeshers_CompositeSegment_1D::GetFaceSide(SMESH_Mesh& aMesh, const TopoDS_Edge& anEdge, const TopoDS_Face& aFace, const bool ignoreMeshed) { list< TopoDS_Edge > edges; edges.push_back( anEdge ); list <const SMESHDS_Hypothesis *> hypList; SMESH_Algo* theAlgo = aMesh.GetGen()->GetAlgo( aMesh, anEdge ); if ( theAlgo ) hypList = theAlgo->GetUsedHypothesis(aMesh, anEdge, false); for ( int forward = 0; forward < 2; ++forward ) { TopoDS_Edge eNext = nextC1Edge( anEdge, aMesh, forward ); while ( !eNext.IsNull() ) { if ( ignoreMeshed ) { // eNext must not have computed mesh if ( SMESHDS_SubMesh* sm = aMesh.GetMeshDS()->MeshElements(eNext) ) if ( sm->NbNodes() || sm->NbElements() ) break; } // eNext must have same hypotheses SMESH_Algo* algo = aMesh.GetGen()->GetAlgo( aMesh, eNext ); if ( !algo || string(theAlgo->GetName()) != algo->GetName() || hypList != algo->GetUsedHypothesis(aMesh, eNext, false)) break; if ( forward ) edges.push_back( eNext ); else edges.push_front( eNext ); eNext = nextC1Edge( eNext, aMesh, forward ); } } return new StdMeshers_FaceSide( aFace, edges, &aMesh, true, false ); }
static bool checkMissing(SMESH_Gen* aGen, SMESH_Mesh& aMesh, SMESH_subMesh* aSubMesh, const int aTopAlgoDim, bool* globalChecked, const bool checkNoAlgo, set<SMESH_subMesh*>& aCheckedMap, list< SMESH_Gen::TAlgoStateError > & theErrors) { switch ( aSubMesh->GetSubShape().ShapeType() ) { case TopAbs_EDGE: case TopAbs_FACE: case TopAbs_SOLID: break; // check this sub-mesh, it can be meshed default: return true; // not meshable sub-mesh } if ( aCheckedMap.count( aSubMesh )) return true; //MESSAGE("=====checkMissing"); int ret = true; SMESH_Algo* algo = 0; switch (aSubMesh->GetAlgoState()) { case SMESH_subMesh::NO_ALGO: { if (checkNoAlgo) { // should there be any algo? int shapeDim = SMESH_Gen::GetShapeDim( aSubMesh->GetSubShape() ); if (aTopAlgoDim > shapeDim) { MESSAGE( "ERROR: " << shapeDim << "D algorithm is missing" ); ret = false; theErrors.push_back( SMESH_Gen::TAlgoStateError() ); theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, shapeDim, true ); } } return ret; } case SMESH_subMesh::MISSING_HYP: { // notify if an algo missing hyp is attached to aSubMesh algo = aSubMesh->GetAlgo(); ASSERT( algo ); bool IsGlobalHypothesis = aGen->IsGlobalHypothesis( algo, aMesh ); if (!IsGlobalHypothesis || !globalChecked[ algo->GetDim() ]) { TAlgoStateErrorName errName = SMESH_Hypothesis::HYP_MISSING; SMESH_Hypothesis::Hypothesis_Status status; algo->CheckHypothesis( aMesh, aSubMesh->GetSubShape(), status ); if ( status == SMESH_Hypothesis::HYP_BAD_PARAMETER ) { MESSAGE( "ERROR: hypothesis of " << (IsGlobalHypothesis ? "Global " : "Local ") << "<" << algo->GetName() << "> has a bad parameter value"); errName = status; } else if ( status == SMESH_Hypothesis::HYP_BAD_GEOMETRY ) { MESSAGE( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ") << "<" << algo->GetName() << "> assigned to mismatching geometry"); errName = status; } else { MESSAGE( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ") << "<" << algo->GetName() << "> misses some hypothesis"); } if (IsGlobalHypothesis) globalChecked[ algo->GetDim() ] = true; theErrors.push_back( SMESH_Gen::TAlgoStateError() ); theErrors.back().Set( errName, algo, IsGlobalHypothesis ); } ret = false; break; } case SMESH_subMesh::HYP_OK: algo = aSubMesh->GetAlgo(); ret = true; if (!algo->NeedDiscreteBoundary()) { SMESH_subMeshIteratorPtr itsub = aSubMesh->getDependsOnIterator( /*includeSelf=*/false, /*complexShapeFirst=*/false); while ( itsub->more() ) aCheckedMap.insert( itsub->next() ); } break; default: ASSERT(0); } // do not check under algo that hides sub-algos or // re-start checking NO_ALGO state ASSERT (algo); bool isTopLocalAlgo = ( aTopAlgoDim <= algo->GetDim() && !aGen->IsGlobalHypothesis( algo, aMesh )); if (!algo->NeedDiscreteBoundary() || isTopLocalAlgo) { bool checkNoAlgo2 = ( algo->NeedDiscreteBoundary() ); SMESH_subMeshIteratorPtr itsub = aSubMesh->getDependsOnIterator( /*includeSelf=*/false, /*complexShapeFirst=*/true); while ( itsub->more() ) { // sub-meshes should not be checked further more SMESH_subMesh* sm = itsub->next(); if (isTopLocalAlgo) { //check algo on sub-meshes int aTopAlgoDim2 = algo->GetDim(); if (!checkMissing (aGen, aMesh, sm, aTopAlgoDim2, globalChecked, checkNoAlgo2, aCheckedMap, theErrors)) { ret = false; if (sm->GetAlgoState() == SMESH_subMesh::NO_ALGO ) checkNoAlgo2 = false; } } aCheckedMap.insert( sm ); } } return ret; }
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; }
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; }
bool StdMeshers_Hexa_3D::Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, MapShapeNbElems& aResMap) { vector < SMESH_subMesh * >meshFaces; TopTools_SequenceOfShape aFaces; for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) { aFaces.Append(exp.Current()); SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current()); ASSERT(aSubMesh); meshFaces.push_back(aSubMesh); } if (meshFaces.size() != 6) { //return error(COMPERR_BAD_SHAPE, TComm(meshFaces.size())<<" instead of 6 faces in a block"); static StdMeshers_CompositeHexa_3D compositeHexa(-10, 0, aMesh.GetGen()); return compositeHexa.Evaluate(aMesh, aShape, aResMap); } int i = 0; for(; i<6; i++) { //TopoDS_Shape aFace = meshFaces[i]->GetSubShape(); TopoDS_Shape aFace = aFaces.Value(i+1); SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace); if( !algo ) { 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; } string algoName = algo->GetName(); bool isAllQuad = false; if (algoName == "Quadrangle_2D") { MapShapeNbElemsItr anIt = aResMap.find(meshFaces[i]); if( anIt == aResMap.end() ) continue; std::vector<int> aVec = (*anIt).second; int nbtri = Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]); if( nbtri == 0 ) isAllQuad = true; } if ( ! isAllQuad ) { return EvaluatePentahedralMesh(aMesh, aShape, aResMap); } } // find number of 1d elems for 1 face int nb1d = 0; TopTools_MapOfShape Edges1; bool IsQuadratic = false; bool IsFirst = true; for (TopExp_Explorer exp(aFaces.Value(1), TopAbs_EDGE); exp.More(); exp.Next()) { Edges1.Add(exp.Current()); SMESH_subMesh *sm = aMesh.GetSubMesh(exp.Current()); if( sm ) { MapShapeNbElemsItr anIt = aResMap.find(sm); if( anIt == aResMap.end() ) continue; std::vector<int> aVec = (*anIt).second; nb1d += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]); if(IsFirst) { IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]); IsFirst = false; } } } // find face opposite to 1 face int OppNum = 0; for(i=2; i<=6; i++) { bool IsOpposite = true; for(TopExp_Explorer exp(aFaces.Value(i), TopAbs_EDGE); exp.More(); exp.Next()) { if( Edges1.Contains(exp.Current()) ) { IsOpposite = false; break; } } if(IsOpposite) { OppNum = i; break; } } // find number of 2d elems on side faces int nb2d = 0; for(i=2; i<=6; i++) { if( i == OppNum ) continue; MapShapeNbElemsItr anIt = aResMap.find( meshFaces[i-1] ); if( anIt == aResMap.end() ) continue; std::vector<int> aVec = (*anIt).second; nb2d += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]); } MapShapeNbElemsItr anIt = aResMap.find( meshFaces[0] ); std::vector<int> aVec = (*anIt).second; int nb2d_face0 = Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]); int nb0d_face0 = aVec[SMDSEntity_Node]; std::vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; if(IsQuadratic) { aResVec[SMDSEntity_Quad_Hexa] = nb2d_face0 * ( nb2d/nb1d ); int nb1d_face0_int = ( nb2d_face0*4 - nb1d ) / 2; aResVec[SMDSEntity_Node] = nb0d_face0 * ( 2*nb2d/nb1d - 1 ) - nb1d_face0_int * nb2d/nb1d; } else { aResVec[SMDSEntity_Node] = nb0d_face0 * ( nb2d/nb1d - 1 ); aResVec[SMDSEntity_Hexa] = nb2d_face0 * ( nb2d/nb1d ); } SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); aResMap.insert(std::make_pair(sm,aResVec)); return true; }
bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape)// throw(SALOME_Exception) { // PAL14921. Enable catching std::bad_alloc and Standard_OutOfMemory outside //Unexpect aCatch(SalomeException); MESSAGE("StdMeshers_Hexa_3D::Compute"); SMESHDS_Mesh * meshDS = aMesh.GetMeshDS(); // 0. - shape and face mesh verification // 0.1 - shape must be a solid (or a shell) with 6 faces vector < SMESH_subMesh * >meshFaces; for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) { SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current()); ASSERT(aSubMesh); meshFaces.push_back(aSubMesh); } if (meshFaces.size() != 6) { //return error(COMPERR_BAD_SHAPE, TComm(meshFaces.size())<<" instead of 6 faces in a block"); static StdMeshers_CompositeHexa_3D compositeHexa(-10, 0, aMesh.GetGen()); if ( !compositeHexa.Compute( aMesh, aShape )) return error( compositeHexa.GetComputeError() ); return true; } // 0.2 - is each face meshed with Quadrangle_2D? (so, with a wire of 4 edges) // tool for working with quadratic elements SMESH_MesherHelper aTool (aMesh); _quadraticMesh = aTool.IsQuadraticSubMesh(aShape); // cube structure typedef struct cubeStruct { TopoDS_Vertex V000; TopoDS_Vertex V001; TopoDS_Vertex V010; TopoDS_Vertex V011; TopoDS_Vertex V100; TopoDS_Vertex V101; TopoDS_Vertex V110; TopoDS_Vertex V111; faceQuadStruct* quad_X0; faceQuadStruct* quad_X1; faceQuadStruct* quad_Y0; faceQuadStruct* quad_Y1; faceQuadStruct* quad_Z0; faceQuadStruct* quad_Z1; Point3DStruct* np; // normalised 3D coordinates } CubeStruct; CubeStruct aCube; // bounding faces FaceQuadStruct* aQuads[6]; for (int i = 0; i < 6; i++) aQuads[i] = 0; for (int i = 0; i < 6; i++) { TopoDS_Shape aFace = meshFaces[i]->GetSubShape(); SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace); string algoName = algo->GetName(); bool isAllQuad = false; if (algoName == "Quadrangle_2D") { SMESHDS_SubMesh * sm = meshDS->MeshElements( aFace ); if ( sm ) { isAllQuad = true; SMDS_ElemIteratorPtr eIt = sm->GetElements(); while ( isAllQuad && eIt->more() ) { const SMDS_MeshElement* elem = eIt->next(); isAllQuad = ( elem->NbNodes()==4 ||(_quadraticMesh && elem->NbNodes()==8) ); } } } if ( ! isAllQuad ) { SMESH_ComputeErrorPtr err = ComputePentahedralMesh(aMesh, aShape); return ClearAndReturn( aQuads, error(err)); } StdMeshers_Quadrangle_2D *quadAlgo = dynamic_cast < StdMeshers_Quadrangle_2D * >(algo); ASSERT(quadAlgo); try { aQuads[i] = quadAlgo->CheckAnd2Dcompute(aMesh, aFace, _quadraticMesh); if(!aQuads[i]) { return error( quadAlgo->GetComputeError()); } } catch(SALOME_Exception & S_ex) { return ClearAndReturn( aQuads, error(COMPERR_SLM_EXCEPTION,TComm(S_ex.what()) << " Raised by StdMeshers_Quadrangle_2D " " on face #" << meshDS->ShapeToIndex( aFace ))); } // 0.2.1 - number of points on the opposite edges must be the same if (aQuads[i]->side[0]->NbPoints() != aQuads[i]->side[2]->NbPoints() || aQuads[i]->side[1]->NbPoints() != aQuads[i]->side[3]->NbPoints() /*aQuads[i]->side[0]->NbEdges() != 1 || aQuads[i]->side[1]->NbEdges() != 1 || aQuads[i]->side[2]->NbEdges() != 1 || aQuads[i]->side[3]->NbEdges() != 1*/) { MESSAGE("different number of points on the opposite edges of face " << i); // Try to go into penta algorithm 'cause it has been improved. SMESH_ComputeErrorPtr err = ComputePentahedralMesh(aMesh, aShape); return ClearAndReturn( aQuads, error(err)); } } // 1. - identify faces and vertices of the "cube" // 1.1 - ancestor maps vertex->edges in the cube // TopTools_IndexedDataMapOfShapeListOfShape MS; // TopExp::MapShapesAndAncestors(aShape, TopAbs_VERTEX, TopAbs_EDGE, MS); // 1.2 - first face is choosen as face Y=0 of the unit cube const TopoDS_Shape & aFace = meshFaces[0]->GetSubShape(); //const TopoDS_Face & F = TopoDS::Face(aFace); // 1.3 - identify the 4 vertices of the face Y=0: V000, V100, V101, V001 aCube.V000 = aQuads[0]->side[0]->FirstVertex(); // will be (0,0,0) on the unit cube aCube.V100 = aQuads[0]->side[0]->LastVertex(); // will be (1,0,0) on the unit cube aCube.V001 = aQuads[0]->side[2]->FirstVertex(); // will be (0,0,1) on the unit cube aCube.V101 = aQuads[0]->side[2]->LastVertex(); // will be (1,0,1) on the unit cube TopTools_IndexedMapOfShape MV0; TopExp::MapShapes(aFace, TopAbs_VERTEX, MV0); aCube.V010 = OppositeVertex( aCube.V000, MV0, aQuads); aCube.V110 = OppositeVertex( aCube.V100, MV0, aQuads); aCube.V011 = OppositeVertex( aCube.V001, MV0, aQuads); aCube.V111 = OppositeVertex( aCube.V101, MV0, aQuads); // 1.6 - find remaining faces given 4 vertices int _indY0 = 0; int _indY1 = GetFaceIndex(aMesh, aShape, meshFaces, aCube.V010, aCube.V011, aCube.V110, aCube.V111); int _indZ0 = GetFaceIndex(aMesh, aShape, meshFaces, aCube.V000, aCube.V010, aCube.V100, aCube.V110); int _indZ1 = GetFaceIndex(aMesh, aShape, meshFaces, aCube.V001, aCube.V011, aCube.V101, aCube.V111); int _indX0 = GetFaceIndex(aMesh, aShape, meshFaces, aCube.V000, aCube.V001, aCube.V010, aCube.V011); int _indX1 = GetFaceIndex(aMesh, aShape, meshFaces, aCube.V100, aCube.V101, aCube.V110, aCube.V111); // IPAL21120: SIGSEGV on Meshing attached Compound with Automatic Hexadralization if ( _indY1 < 1 || _indZ0 < 1 || _indZ1 < 1 || _indX0 < 1 || _indX1 < 1 ) return error(COMPERR_BAD_SHAPE); aCube.quad_Y0 = aQuads[_indY0]; aCube.quad_Y1 = aQuads[_indY1]; aCube.quad_Z0 = aQuads[_indZ0]; aCube.quad_Z1 = aQuads[_indZ1]; aCube.quad_X0 = aQuads[_indX0]; aCube.quad_X1 = aQuads[_indX1]; // 1.7 - get convertion coefs from face 2D normalized to 3D normalized Conv2DStruct cx0; // for face X=0 Conv2DStruct cx1; // for face X=1 Conv2DStruct cy0; Conv2DStruct cy1; Conv2DStruct cz0; Conv2DStruct cz1; GetConv2DCoefs(*aCube.quad_X0, meshFaces[_indX0]->GetSubShape(), aCube.V000, aCube.V010, aCube.V011, aCube.V001, cx0); GetConv2DCoefs(*aCube.quad_X1, meshFaces[_indX1]->GetSubShape(), aCube.V100, aCube.V110, aCube.V111, aCube.V101, cx1); GetConv2DCoefs(*aCube.quad_Y0, meshFaces[_indY0]->GetSubShape(), aCube.V000, aCube.V100, aCube.V101, aCube.V001, cy0); GetConv2DCoefs(*aCube.quad_Y1, meshFaces[_indY1]->GetSubShape(), aCube.V010, aCube.V110, aCube.V111, aCube.V011, cy1); GetConv2DCoefs(*aCube.quad_Z0, meshFaces[_indZ0]->GetSubShape(), aCube.V000, aCube.V100, aCube.V110, aCube.V010, cz0); GetConv2DCoefs(*aCube.quad_Z1, meshFaces[_indZ1]->GetSubShape(), aCube.V001, aCube.V101, aCube.V111, aCube.V011, cz1); // 1.8 - create a 3D structure for normalized values int nbx = aCube.quad_Z0->side[0]->NbPoints(); if (cz0.a1 == 0.) nbx = aCube.quad_Z0->side[1]->NbPoints(); int nby = aCube.quad_X0->side[0]->NbPoints(); if (cx0.a1 == 0.) nby = aCube.quad_X0->side[1]->NbPoints(); int nbz = aCube.quad_Y0->side[0]->NbPoints(); if (cy0.a1 != 0.) nbz = aCube.quad_Y0->side[1]->NbPoints(); int i1, j1, nbxyz = nbx * nby * nbz; Point3DStruct *np = new Point3DStruct[nbxyz]; // 1.9 - store node indexes of faces { const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX0]->GetSubShape()); faceQuadStruct *quad = aCube.quad_X0; int i = 0; // j = x/face , k = y/face int nbdown = quad->side[0]->NbPoints(); int nbright = quad->side[1]->NbPoints(); SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); while(itf->more()) { const SMDS_MeshNode * node = itf->next(); if(aTool.IsMedium(node)) continue; if ( !findIJ( node, quad, i1, j1 )) return ClearAndReturn( aQuads, false ); int ij1 = j1 * nbdown + i1; quad->uv_grid[ij1].node = node; } for (int i1 = 0; i1 < nbdown; i1++) for (int j1 = 0; j1 < nbright; j1++) { int ij1 = j1 * nbdown + i1; int j = cx0.ia * i1 + cx0.ib * j1 + cx0.ic; // j = x/face int k = cx0.ja * i1 + cx0.jb * j1 + cx0.jc; // k = y/face int ijk = k * nbx * nby + j * nbx + i; //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk); np[ijk].node = quad->uv_grid[ij1].node; //SCRUTE(np[ijk].nodeId); } } { const TopoDS_Face & F = TopoDS::Face(meshFaces[_indX1]->GetSubShape()); SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); faceQuadStruct *quad = aCube.quad_X1; int i = nbx - 1; // j = x/face , k = y/face int nbdown = quad->side[0]->NbPoints(); int nbright = quad->side[1]->NbPoints(); while(itf->more()) { const SMDS_MeshNode * node = itf->next(); if(aTool.IsMedium(node)) continue; if ( !findIJ( node, quad, i1, j1 )) return ClearAndReturn( aQuads, false ); int ij1 = j1 * nbdown + i1; quad->uv_grid[ij1].node = node; } for (int i1 = 0; i1 < nbdown; i1++) for (int j1 = 0; j1 < nbright; j1++) { int ij1 = j1 * nbdown + i1; int j = cx1.ia * i1 + cx1.ib * j1 + cx1.ic; // j = x/face int k = cx1.ja * i1 + cx1.jb * j1 + cx1.jc; // k = y/face int ijk = k * nbx * nby + j * nbx + i; //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk); np[ijk].node = quad->uv_grid[ij1].node; //SCRUTE(np[ijk].nodeId); } } { const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY0]->GetSubShape()); SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); faceQuadStruct *quad = aCube.quad_Y0; int j = 0; // i = x/face , k = y/face int nbdown = quad->side[0]->NbPoints(); int nbright = quad->side[1]->NbPoints(); while(itf->more()) { const SMDS_MeshNode * node = itf->next(); if(aTool.IsMedium(node)) continue; if ( !findIJ( node, quad, i1, j1 )) return ClearAndReturn( aQuads, false ); int ij1 = j1 * nbdown + i1; quad->uv_grid[ij1].node = node; } for (int i1 = 0; i1 < nbdown; i1++) for (int j1 = 0; j1 < nbright; j1++) { int ij1 = j1 * nbdown + i1; int i = cy0.ia * i1 + cy0.ib * j1 + cy0.ic; // i = x/face int k = cy0.ja * i1 + cy0.jb * j1 + cy0.jc; // k = y/face int ijk = k * nbx * nby + j * nbx + i; //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk); np[ijk].node = quad->uv_grid[ij1].node; //SCRUTE(np[ijk].nodeId); } } { const TopoDS_Face & F = TopoDS::Face(meshFaces[_indY1]->GetSubShape()); SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); faceQuadStruct *quad = aCube.quad_Y1; int j = nby - 1; // i = x/face , k = y/face int nbdown = quad->side[0]->NbPoints(); int nbright = quad->side[1]->NbPoints(); while(itf->more()) { const SMDS_MeshNode * node = itf->next(); if(aTool.IsMedium(node)) continue; if ( !findIJ( node, quad, i1, j1 )) return ClearAndReturn( aQuads, false ); int ij1 = j1 * nbdown + i1; quad->uv_grid[ij1].node = node; } for (int i1 = 0; i1 < nbdown; i1++) for (int j1 = 0; j1 < nbright; j1++) { int ij1 = j1 * nbdown + i1; int i = cy1.ia * i1 + cy1.ib * j1 + cy1.ic; // i = x/face int k = cy1.ja * i1 + cy1.jb * j1 + cy1.jc; // k = y/face int ijk = k * nbx * nby + j * nbx + i; //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk); np[ijk].node = quad->uv_grid[ij1].node; //SCRUTE(np[ijk].nodeId); } } { const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ0]->GetSubShape()); SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); faceQuadStruct *quad = aCube.quad_Z0; int k = 0; // i = x/face , j = y/face int nbdown = quad->side[0]->NbPoints(); int nbright = quad->side[1]->NbPoints(); while(itf->more()) { const SMDS_MeshNode * node = itf->next(); if(aTool.IsMedium(node)) continue; if ( !findIJ( node, quad, i1, j1 )) return ClearAndReturn( aQuads, false ); int ij1 = j1 * nbdown + i1; quad->uv_grid[ij1].node = node; } for (int i1 = 0; i1 < nbdown; i1++) for (int j1 = 0; j1 < nbright; j1++) { int ij1 = j1 * nbdown + i1; int i = cz0.ia * i1 + cz0.ib * j1 + cz0.ic; // i = x/face int j = cz0.ja * i1 + cz0.jb * j1 + cz0.jc; // j = y/face int ijk = k * nbx * nby + j * nbx + i; //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk); np[ijk].node = quad->uv_grid[ij1].node; //SCRUTE(np[ijk].nodeId); } } { const TopoDS_Face & F = TopoDS::Face(meshFaces[_indZ1]->GetSubShape()); SMDS_NodeIteratorPtr itf= aMesh.GetSubMesh(F)->GetSubMeshDS()->GetNodes(); faceQuadStruct *quad = aCube.quad_Z1; int k = nbz - 1; // i = x/face , j = y/face int nbdown = quad->side[0]->NbPoints(); int nbright = quad->side[1]->NbPoints(); while(itf->more()) { const SMDS_MeshNode * node = itf->next(); if(aTool.IsMedium(node)) continue; if ( !findIJ( node, quad, i1, j1 )) return ClearAndReturn( aQuads, false ); int ij1 = j1 * nbdown + i1; quad->uv_grid[ij1].node = node; } for (int i1 = 0; i1 < nbdown; i1++) for (int j1 = 0; j1 < nbright; j1++) { int ij1 = j1 * nbdown + i1; int i = cz1.ia * i1 + cz1.ib * j1 + cz1.ic; // i = x/face int j = cz1.ja * i1 + cz1.jb * j1 + cz1.jc; // j = y/face int ijk = k * nbx * nby + j * nbx + i; //MESSAGE(" "<<ij1<<" "<<i<<" "<<j<<" "<<ijk); np[ijk].node = quad->uv_grid[ij1].node; //SCRUTE(np[ijk].nodeId); } } // 2.0 - for each node of the cube: // - get the 8 points 3D = 8 vertices of the cube // - get the 12 points 3D on the 12 edges of the cube // - get the 6 points 3D on the 6 faces with their ID // - compute the point 3D // - store the point 3D in SMESHDS, store its ID in 3D structure int shapeID = meshDS->ShapeToIndex( aShape ); Pt3 p000, p001, p010, p011, p100, p101, p110, p111; Pt3 px00, px01, px10, px11; Pt3 p0y0, p0y1, p1y0, p1y1; Pt3 p00z, p01z, p10z, p11z; Pt3 pxy0, pxy1, px0z, px1z, p0yz, p1yz; GetPoint(p000, 0, 0, 0, nbx, nby, nbz, np, meshDS); GetPoint(p001, 0, 0, nbz - 1, nbx, nby, nbz, np, meshDS); GetPoint(p010, 0, nby - 1, 0, nbx, nby, nbz, np, meshDS); GetPoint(p011, 0, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS); GetPoint(p100, nbx - 1, 0, 0, nbx, nby, nbz, np, meshDS); GetPoint(p101, nbx - 1, 0, nbz - 1, nbx, nby, nbz, np, meshDS); GetPoint(p110, nbx - 1, nby - 1, 0, nbx, nby, nbz, np, meshDS); GetPoint(p111, nbx - 1, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS); for (int i = 1; i < nbx - 1; i++) { for (int j = 1; j < nby - 1; j++) { for (int k = 1; k < nbz - 1; k++) { // *** seulement maillage regulier // 12 points on edges GetPoint(px00, i, 0, 0, nbx, nby, nbz, np, meshDS); GetPoint(px01, i, 0, nbz - 1, nbx, nby, nbz, np, meshDS); GetPoint(px10, i, nby - 1, 0, nbx, nby, nbz, np, meshDS); GetPoint(px11, i, nby - 1, nbz - 1, nbx, nby, nbz, np, meshDS); GetPoint(p0y0, 0, j, 0, nbx, nby, nbz, np, meshDS); GetPoint(p0y1, 0, j, nbz - 1, nbx, nby, nbz, np, meshDS); GetPoint(p1y0, nbx - 1, j, 0, nbx, nby, nbz, np, meshDS); GetPoint(p1y1, nbx - 1, j, nbz - 1, nbx, nby, nbz, np, meshDS); GetPoint(p00z, 0, 0, k, nbx, nby, nbz, np, meshDS); GetPoint(p01z, 0, nby - 1, k, nbx, nby, nbz, np, meshDS); GetPoint(p10z, nbx - 1, 0, k, nbx, nby, nbz, np, meshDS); GetPoint(p11z, nbx - 1, nby - 1, k, nbx, nby, nbz, np, meshDS); // 12 points on faces GetPoint(pxy0, i, j, 0, nbx, nby, nbz, np, meshDS); GetPoint(pxy1, i, j, nbz - 1, nbx, nby, nbz, np, meshDS); GetPoint(px0z, i, 0, k, nbx, nby, nbz, np, meshDS); GetPoint(px1z, i, nby - 1, k, nbx, nby, nbz, np, meshDS); GetPoint(p0yz, 0, j, k, nbx, nby, nbz, np, meshDS); GetPoint(p1yz, nbx - 1, j, k, nbx, nby, nbz, np, meshDS); int ijk = k * nbx * nby + j * nbx + i; double x = double (i) / double (nbx - 1); // *** seulement double y = double (j) / double (nby - 1); // *** maillage double z = double (k) / double (nbz - 1); // *** regulier Pt3 X; for (int i = 0; i < 3; i++) { X[i] = (1 - x) * p0yz[i] + x * p1yz[i] + (1 - y) * px0z[i] + y * px1z[i] + (1 - z) * pxy0[i] + z * pxy1[i] - (1 - x) * ((1 - y) * p00z[i] + y * p01z[i]) - x * ((1 - y) * p10z[i] + y * p11z[i]) - (1 - y) * ((1 - z) * px00[i] + z * px01[i]) - y * ((1 - z) * px10[i] + z * px11[i]) - (1 - z) * ((1 - x) * p0y0[i] + x * p1y0[i]) - z * ((1 - x) * p0y1[i] + x * p1y1[i]) + (1 - x) * ((1 - y) * ((1 - z) * p000[i] + z * p001[i]) + y * ((1 - z) * p010[i] + z * p011[i])) + x * ((1 - y) * ((1 - z) * p100[i] + z * p101[i]) + y * ((1 - z) * p110[i] + z * p111[i])); } SMDS_MeshNode * node = meshDS->AddNode(X[0], X[1], X[2]); np[ijk].node = node; meshDS->SetNodeInVolume(node, shapeID); } } } // find orientation of furute volumes according to MED convention vector< bool > forward( nbx * nby ); SMDS_VolumeTool vTool; for (int i = 0; i < nbx - 1; i++) { for (int j = 0; j < nby - 1; j++) { int n1 = j * nbx + i; int n2 = j * nbx + i + 1; int n3 = (j + 1) * nbx + i + 1; int n4 = (j + 1) * nbx + i; int n5 = nbx * nby + j * nbx + i; int n6 = nbx * nby + j * nbx + i + 1; int n7 = nbx * nby + (j + 1) * nbx + i + 1; int n8 = nbx * nby + (j + 1) * nbx + i; SMDS_VolumeOfNodes tmpVol (np[n1].node,np[n2].node,np[n3].node,np[n4].node, np[n5].node,np[n6].node,np[n7].node,np[n8].node); vTool.Set( &tmpVol ); forward[ n1 ] = vTool.IsForward(); } } //2.1 - for each node of the cube (less 3 *1 Faces): // - store hexahedron in SMESHDS MESSAGE("Storing hexahedron into the DS"); for (int i = 0; i < nbx - 1; i++) { for (int j = 0; j < nby - 1; j++) { bool isForw = forward.at( j * nbx + i ); for (int k = 0; k < nbz - 1; k++) { int n1 = k * nbx * nby + j * nbx + i; int n2 = k * nbx * nby + j * nbx + i + 1; int n3 = k * nbx * nby + (j + 1) * nbx + i + 1; int n4 = k * nbx * nby + (j + 1) * nbx + i; int n5 = (k + 1) * nbx * nby + j * nbx + i; int n6 = (k + 1) * nbx * nby + j * nbx + i + 1; int n7 = (k + 1) * nbx * nby + (j + 1) * nbx + i + 1; int n8 = (k + 1) * nbx * nby + (j + 1) * nbx + i; SMDS_MeshVolume * elt; if ( isForw ) { elt = aTool.AddVolume(np[n1].node, np[n2].node, np[n3].node, np[n4].node, np[n5].node, np[n6].node, np[n7].node, np[n8].node); } else { elt = aTool.AddVolume(np[n1].node, np[n4].node, np[n3].node, np[n2].node, np[n5].node, np[n8].node, np[n7].node, np[n6].node); } meshDS->SetMeshElementOnShape(elt, shapeID); } } } if ( np ) delete [] np; return ClearAndReturn( aQuads, true ); }