//============================================================================= bool NETGENPlugin_Mesher::Evaluate(MapShapeNbElems& aResMap) { #ifdef WNT netgen::MeshingParameters& mparams = netgen::GlobalMeshingParameters(); #else netgen::MeshingParameters& mparams = netgen::mparam; #endif // ------------------------- // Prepare OCC geometry // ------------------------- netgen::OCCGeometry occgeo; list< SMESH_subMesh* > meshedSM; PrepareOCCgeometry( occgeo, _shape, *_mesh, &meshedSM ); bool tooManyElems = false; const int hugeNb = std::numeric_limits<int>::max() / 100; // ---------------- // evaluate 1D // ---------------- // pass 1D simple parameters to NETGEN int nbs = 0; if ( _simpleHyp ) { if ( int nbSeg = _simpleHyp->GetNumberOfSegments() ) { nbs = nbSeg; // nb of segments mparams.segmentsperedge = nbSeg + 0.1; mparams.maxh = occgeo.boundingbox.Diam(); mparams.grading = 0.01; } else { // segment length mparams.segmentsperedge = 1; mparams.maxh = _simpleHyp->GetLocalLength(); } } TopTools_DataMapOfShapeInteger EdgesMap; double fullLen = 0.0; double fullNbSeg = 0; for (TopExp_Explorer exp(_shape, TopAbs_EDGE); exp.More(); exp.Next()) { TopoDS_Edge E = TopoDS::Edge( exp.Current() ); if( EdgesMap.IsBound(E) ) continue; SMESH_subMesh *sm = _mesh->GetSubMesh(E); std::vector<int> aVec(SMDSEntity_Last, 0); double aLen = SMESH_Algo::EdgeLength(E); fullLen += aLen; int nb1d = nbs; tooManyElems = ( aLen/hugeNb > mparams.maxh ); if(nb1d==0 && !tooManyElems) { nb1d = (int)( aLen/mparams.maxh + 1 ); } if ( tooManyElems ) // avoid FPE { aVec[SMDSEntity_Node] = hugeNb; aVec[ mparams.secondorder > 0 ? SMDSEntity_Quad_Edge : SMDSEntity_Edge] = hugeNb; } else { fullNbSeg += nb1d; if( mparams.secondorder > 0 ) { aVec[SMDSEntity_Node] = 2*nb1d - 1; aVec[SMDSEntity_Quad_Edge] = nb1d; } else { aVec[SMDSEntity_Node] = nb1d - 1; aVec[SMDSEntity_Edge] = nb1d; } } aResMap.insert(std::make_pair(sm,aVec)); EdgesMap.Bind(E,nb1d); } // ---------------- // evaluate 2D // ---------------- if ( _simpleHyp ) { if ( double area = _simpleHyp->GetMaxElementArea() ) { // face area mparams.maxh = sqrt(2. * area/sqrt(3.0)); mparams.grading = 0.4; // moderate size growth } else { // length from edges mparams.maxh = fullLen/fullNbSeg; mparams.grading = 0.2; // slow size growth } mparams.maxh = min( mparams.maxh, occgeo.boundingbox.Diam()/2 ); } for (TopExp_Explorer exp(_shape, TopAbs_FACE); exp.More(); exp.Next()) { TopoDS_Face F = TopoDS::Face( exp.Current() ); SMESH_subMesh *sm = _mesh->GetSubMesh(F); GProp_GProps G; BRepGProp::SurfaceProperties(F,G); double anArea = G.Mass(); tooManyElems = tooManyElems || ( anArea/hugeNb > mparams.maxh*mparams.maxh ); int nb1d = 0; if ( !tooManyElems ) for (TopExp_Explorer exp1(F,TopAbs_EDGE); exp1.More(); exp1.Next()) nb1d += EdgesMap.Find(exp1.Current()); int nbFaces = tooManyElems ? hugeNb : int( 4*anArea / mparams.maxh*mparams.maxh*sqrt(3.)); int nbNodes = tooManyElems ? hugeNb : (( nbFaces*3 - (nb1d-1)*2 ) / 6 + 1 ); std::vector<int> aVec(SMDSEntity_Last, 0); if( mparams.secondorder > 0 ) { int nb1d_in = (nbFaces*3 - nb1d) / 2; aVec[SMDSEntity_Node] = nbNodes + nb1d_in; aVec[SMDSEntity_Quad_Triangle] = nbFaces; } else { aVec[SMDSEntity_Node] = nbNodes; aVec[SMDSEntity_Triangle] = nbFaces; } aResMap.insert(std::make_pair(sm,aVec)); } // ---------------- // evaluate 3D // ---------------- if(_isVolume) { // pass 3D simple parameters to NETGEN const NETGENPlugin_SimpleHypothesis_3D* simple3d = dynamic_cast< const NETGENPlugin_SimpleHypothesis_3D* > ( _simpleHyp ); if ( simple3d ) { if ( double vol = simple3d->GetMaxElementVolume() ) { // max volume mparams.maxh = pow( 72, 1/6. ) * pow( vol, 1/3. ); mparams.maxh = min( mparams.maxh, occgeo.boundingbox.Diam()/2 ); } else { // using previous length from faces } mparams.grading = 0.4; } GProp_GProps G; BRepGProp::VolumeProperties(_shape,G); double aVolume = G.Mass(); double tetrVol = 0.1179*mparams.maxh*mparams.maxh*mparams.maxh; tooManyElems = tooManyElems || ( aVolume/hugeNb > tetrVol ); int nbVols = tooManyElems ? hugeNb : int(aVolume/tetrVol); int nb1d_in = int(( nbVols*6 - fullNbSeg ) / 6 ); std::vector<int> aVec(SMDSEntity_Last, 0 ); if ( tooManyElems ) // avoid FPE { aVec[SMDSEntity_Node] = hugeNb; aVec[ mparams.secondorder > 0 ? SMDSEntity_Quad_Tetra : SMDSEntity_Tetra] = hugeNb; } else { if( mparams.secondorder > 0 ) { aVec[SMDSEntity_Node] = nb1d_in/3 + 1 + nb1d_in; aVec[SMDSEntity_Quad_Tetra] = nbVols; } else { aVec[SMDSEntity_Node] = nb1d_in/3 + 1; aVec[SMDSEntity_Tetra] = nbVols; } } SMESH_subMesh *sm = _mesh->GetSubMesh(_shape); aResMap.insert(std::make_pair(sm,aVec)); } return true; }
//======================================================================= // function: FillSameDomainFaces // purpose: //======================================================================= void GEOMAlgo_Builder::FillSameDomainFaces() { Standard_Boolean bIsSDF, bHasImage1, bHasImage2, bForward; Standard_Integer i, j, aNbFF, nF1, nF2, aNbPBInOn, aNbC, aNbSE; Standard_Integer aNbF1, aNbF2, i2s, aNbSD; TopTools_MapOfShape aMFence; TopTools_ListOfShape aLX1, aLX2; TopTools_ListIteratorOfListOfShape aItF1, aItF2; NMTTools_ListOfCoupleOfShape aLCS; // const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS(); NMTTools_PaveFiller* pPF=myPaveFiller; NMTDS_InterfPool* pIP=pPF->IP(); BOPTools_CArray1OfSSInterference& aFFs=pIP->SSInterferences(); const Handle(IntTools_Context)& aCtx= pPF->Context(); // // //mySameDomainShapes.Clear(); // // 1. For each FF find among images of faces // all pairs of same domain faces (SDF) [=> aLCS] aNbFF=aFFs.Extent(); for (i=1; i<=aNbFF; ++i) { BOPTools_SSInterference& aFF=aFFs(i); aFF.Indices(nF1, nF2); // const TopoDS_Face& aF1=TopoDS::Face(aDS.Shape(nF1)); const TopoDS_Face& aF2=TopoDS::Face(aDS.Shape(nF2)); // // if there are no in/on 2D split parts the faces nF1, nF2 // can not be SDF const BOPTools_ListOfPaveBlock& aLPBInOn=aFF.PaveBlocks(); aNbPBInOn=aLPBInOn.Extent(); // //=== const TColStd_ListOfInteger& aLSE=aFF.SharedEdges(); aNbSE=aLSE.Extent(); if (!aNbPBInOn && !aNbSE) { continue; } //=== // // if there is at least one section edge between faces nF1, nF2 // they can not be SDF BOPTools_SequenceOfCurves& aSC=aFF.Curves(); aNbC=aSC.Length(); if (aNbC) { continue; } // // the faces are suspected to be SDF. // Try to find SDF among images of nF1, nF2 aMFence.Clear(); // //-------------------------------------------------------- bHasImage1=mySplitFaces.HasImage(aF1); bHasImage2=mySplitFaces.HasImage(aF2); // aLX1.Clear(); if (!bHasImage1) { aLX1.Append(aF1); } // aLX2.Clear(); if (!bHasImage2) { aLX2.Append(aF2); } // const TopTools_ListOfShape& aLF1r=(bHasImage1)? mySplitFaces.Image(aF1) : aLX1; const TopTools_ListOfShape& aLF2r=(bHasImage2)? mySplitFaces.Image(aF2) : aLX2; // TopTools_DataMapOfIntegerShape aMIS; TColStd_ListIteratorOfListOfInteger aItLI; NMTDS_BoxBndTreeSelector aSelector; NMTDS_BoxBndTree aBBTree; NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree); // aNbF1=aLF1r.Extent(); aNbF2=aLF2r.Extent(); bForward=(aNbF1<aNbF2); // const TopTools_ListOfShape& aLF1=bForward ? aLF1r : aLF2r; const TopTools_ListOfShape& aLF2=bForward ? aLF2r : aLF1r; // // 1. aTreeFiller aItF2.Initialize(aLF2); for (i2s=1; aItF2.More(); aItF2.Next(), ++i2s) { Bnd_Box aBoxF2s; // const TopoDS_Face& aF2s=*((TopoDS_Face*)(&aItF2.Value())); // BRepBndLib::Add(aF2s, aBoxF2s); // aMIS.Bind(i2s, aF2s); // aTreeFiller.Add(i2s, aBoxF2s); }//for (i2s=1; aItF2.More(); aItF2.Next(), ++i2s) { // aTreeFiller.Fill(); // // 2. aItF1.Initialize(aLF1); for (j=1; aItF1.More(); aItF1.Next(), ++j) { Bnd_Box aBoxF1x; // const TopoDS_Face& aF1x=*((TopoDS_Face*)(&aItF1.Value())); // BRepBndLib::Add(aF1x, aBoxF1x); // aSelector.Clear(); aSelector.SetBox(aBoxF1x); aNbSD=aBBTree.Select(aSelector); if (!aNbSD) { continue; } // const TColStd_ListOfInteger& aLI=aSelector.Indices(); aItLI.Initialize(aLI); for (; aItLI.More(); aItLI.Next()) { i2s=aItLI.Value(); const TopoDS_Face& aF2y=*((TopoDS_Face*)(&aMIS.Find(i2s))); // bIsSDF=NMTTools_Tools::AreFacesSameDomain(aF1x, aF2y, aCtx); if (bIsSDF) { if (aMFence.Contains(aF1x) || aMFence.Contains(aF2y)) { continue; } aMFence.Add(aF1x); aMFence.Add(aF2y); // NMTTools_CoupleOfShape aCS; // aCS.SetShape1(aF1x); aCS.SetShape2(aF2y); aLCS.Append(aCS); // if (bForward) { if (aF1x==aF1) { if (!mySplitFaces.HasImage(aF1)) { mySplitFaces.Bind(aF1, aF1); } } if (aF2y==aF2) { if (!mySplitFaces.HasImage(aF2)) { mySplitFaces.Bind(aF2, aF2); } } } else { if (aF1x==aF2) { if (!mySplitFaces.HasImage(aF2)) { mySplitFaces.Bind(aF2, aF2); } } if (aF2y==aF1) { if (!mySplitFaces.HasImage(aF1)) { mySplitFaces.Bind(aF1, aF1); } } } // break; }//if (bIsSDF) { }//for (; aItLI.More(); aItLI.Next()) { }//for (; aItF1.More(); aItF1.Next()) { }//for (i=1; i<=aNbFF; ++i) //------------------------------------------------------------- aNbC=aLCS.Extent(); if (!aNbC) { return; } // // 2. Find Chains NMTTools_IndexedDataMapOfShapeIndexedMapOfShape aMC; // NMTTools_Tools::FindChains(aLCS, aMC); // Standard_Boolean bIsImage; Standard_Integer aIx, aIxMin, aNbMSDF, k, aNbMFj; TopoDS_Shape aFOld, aFSDmin; TopTools_IndexedMapOfShape aMFj; TopTools_DataMapOfShapeInteger aDMSI; // aItF1.Initialize(myShapes); for (j=1; aItF1.More(); aItF1.Next(), ++j) { const TopoDS_Shape& aSj=aItF1.Value(); aMFj.Clear(); TopExp::MapShapes(aSj, TopAbs_FACE, aMFj); aNbMFj=aMFj.Extent(); for (k=1; k<=aNbMFj; ++k) { const TopoDS_Shape& aFk=aMFj(k); if (!aDMSI.IsBound(aFk)) { aDMSI.Bind(aFk, j); } } } // // 3. Fill the map of SDF mySameDomainFaces aNbC=aMC.Extent(); for (i=1; i<=aNbC; ++i) { // const TopoDS_Shape& aF=aMC.FindKey(i); const TopTools_IndexedMapOfShape& aMSDF=aMC(i); // aNbMSDF=aMSDF.Extent(); for (j=1; j<=aNbMSDF; ++j) { const TopoDS_Shape& aFSD=aMSDF(j); bIsImage=mySplitFaces.IsImage(aFSD); aFOld=aFSD; if (bIsImage) { aFOld=mySplitFaces.ImageFrom(aFSD); } // aIx=aDMSI.Find(aFOld); if (j==1) { aIxMin=aIx; aFSDmin=aFSD; continue; } else { if (aIx<aIxMin) { aIxMin=aIx; aFSDmin=aFSD; } } } // for (j=1; j<=aNbMSDF; ++j) { const TopoDS_Shape& aFSD=aMSDF(j); mySameDomainShapes.Add(aFSD, aFSDmin); } } // }