//============================================================================= 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: MakeAloneVertices // purpose: //======================================================================= void NMTTools_PaveFiller::MakeAloneVertices() { Standard_Integer i, aNbFFs, nF1, nF2, j, aNbPnts, nFx, aNbV; Standard_Real aTolF1, aTolF2, aTolSum, aTolV; TColStd_ListIteratorOfListOfInteger aIt; TColStd_ListOfInteger aLI; TopoDS_Vertex aV; TopoDS_Compound aCompound; BRep_Builder aBB; TopTools_DataMapOfShapeListOfInteger aDMVFF, aDMVFF1; TopTools_DataMapIteratorOfDataMapOfShapeListOfInteger aItDMVFF; TopTools_DataMapOfShapeShape aDMVV; TopTools_DataMapOfIntegerShape aDMIV; TopTools_DataMapOfShapeInteger aDMVI; TopTools_DataMapIteratorOfDataMapOfShapeInteger aItDMVI; TopTools_DataMapIteratorOfDataMapOfIntegerShape aItDMIV; // aBB.MakeCompound(aCompound); // myAloneVertices.Clear(); // BOPTools_CArray1OfSSInterference& aFFs=myIP->SSInterferences(); // // 1. Collect alone vertices from FFs aNbV=0; aNbFFs=aFFs.Extent(); for (i=1; i<=aNbFFs; ++i) { BOPTools_SSInterference& aFFi=aFFs(i); aFFi.Indices(nF1, nF2); // const TopoDS_Face aF1=TopoDS::Face(myDS->Shape(nF1));//mpv const TopoDS_Face aF2=TopoDS::Face(myDS->Shape(nF2));//mpv // aTolF1=BRep_Tool::Tolerance(aF1); aTolF2=BRep_Tool::Tolerance(aF2); aTolSum=aTolF1+aTolF2; // aLI.Clear(); aLI.Append(nF1); aLI.Append(nF2); // const IntTools_SequenceOfPntOn2Faces& aSeqAlonePnts=aFFi.AlonePnts(); aNbPnts=aSeqAlonePnts.Length(); for (j=1; j<=aNbPnts; ++j) { const gp_Pnt& aP=aSeqAlonePnts(j).P1().Pnt(); BOPTools_Tools::MakeNewVertex(aP, aTolSum, aV); aDMVFF.Bind(aV, aLI); aBB.Add(aCompound, aV); ++aNbV; } } if (!aNbV) { return; } // // 2. Try to fuse alone vertices themselves; FuseVertices(aCompound, aDMVV); // // if some are fused, replace them by new ones aItDMVFF.Initialize(aDMVFF); for (; aItDMVFF.More(); aItDMVFF.Next()) { const TopoDS_Shape& aVx=aItDMVFF.Key(); const TColStd_ListOfInteger& aLIx=aItDMVFF.Value(); // if (!aDMVV.IsBound(aVx)) { aDMVFF1.Bind(aVx, aLIx); } else { const TopoDS_Shape& aVy=aDMVV.Find(aVx); if (aDMVFF1.IsBound(aVy)) { TColStd_ListOfInteger& aLIy=aDMVFF1.ChangeFind(aVy); aIt.Initialize(aLIx); for(; aIt.More(); aIt.Next()) { nFx=aIt.Value(); aLIy.Append(nFx); } } else { aDMVFF1.Bind(aVy, aLIx); } } } aDMVFF.Clear(); // // refine lists of faces in aDMVFF1; aItDMVFF.Initialize(aDMVFF1); for (; aItDMVFF.More(); aItDMVFF.Next()) { TColStd_MapOfInteger aMIy; TColStd_ListOfInteger aLIy; // const TopoDS_Shape& aVx=aItDMVFF.Key(); TColStd_ListOfInteger& aLIx=aDMVFF1.ChangeFind(aVx); aIt.Initialize(aLIx); for(; aIt.More(); aIt.Next()) { nFx=aIt.Value(); if (aMIy.Add(nFx)) { aLIy.Append(nFx); } } aLIx.Clear(); aLIx.Append(aLIy); } //================================== // // 3. Collect vertices from DS Standard_Integer aNbS, nV, nVSD, aNbVDS, i1, i2, aNbVSD; // aNbS=myDS->NumberOfShapesOfTheObject(); // old shapes for (i=1; i<=aNbS; ++i) { const TopoDS_Shape& aS=myDS->Shape(i); if (aS.ShapeType() != TopAbs_VERTEX){ continue; } // nVSD=FindSDVertex(i); nV=(nVSD) ? nVSD : i; const TopoDS_Shape& aVx=myDS->Shape(nV); if (!aDMVI.IsBound(aVx)) { aDMVI.Bind(aVx, nV); } } // new shapes i1=myDS->NumberOfSourceShapes()+1; i2=myDS->NumberOfInsertedShapes(); for (i=i1; i<=i2; ++i) { const TopoDS_Shape aS=myDS->Shape(i);//mpv if (aS.ShapeType() != TopAbs_VERTEX){ continue; } if (!aDMVI.IsBound(aS)) { aDMVI.Bind(aS, i); } } // // 4. Initialize BoundSortBox on aDMVI // Handle(Bnd_HArray1OfBox) aHAB; Bnd_BoundSortBox aBSB; // aNbVDS=aDMVI.Extent(); aHAB=new Bnd_HArray1OfBox(1, aNbVDS); // aItDMVI.Initialize(aDMVI); for (i=1; aItDMVI.More(); aItDMVI.Next(), ++i) { Bnd_Box aBox; // nV=aItDMVI.Value(); aV=TopoDS::Vertex(aItDMVI.Key()); aTolV=BRep_Tool::Tolerance(aV); aBox.SetGap(aTolV); BRepBndLib::Add(aV, aBox); aHAB->SetValue(i, aBox); // aDMIV.Bind(i, aV); } aBSB.Initialize(aHAB); // // 5. Compare aItDMVFF.Initialize(aDMVFF1); for (; aItDMVFF.More(); aItDMVFF.Next()) { Bnd_Box aBoxV; // const TColStd_ListOfInteger& aLIFF=aItDMVFF.Value(); aV=TopoDS::Vertex(aItDMVFF.Key()); // aTolV=BRep_Tool::Tolerance(aV); aBoxV.SetGap(aTolV); BRepBndLib::Add(aV, aBoxV); // const TColStd_ListOfInteger& aLIVSD=aBSB.Compare(aBoxV); aNbVSD=aLIVSD.Extent(); if (aNbVSD==0) { // add new vertex in DS and update map myAloneVertices BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq; // myDS->InsertShapeAndAncestorsSuccessors(aV, anASSeq); nV=myDS->NumberOfInsertedShapes(); // aIt.Initialize(aLIFF); for (; aIt.More(); aIt.Next()) { nFx=aIt.Value(); if (myAloneVertices.Contains(nFx)) { TColStd_IndexedMapOfInteger& aMVx=myAloneVertices.ChangeFromKey(nFx); aMVx.Add(nV); } else { TColStd_IndexedMapOfInteger aMVx; aMVx.Add(nV); myAloneVertices.Add(nFx, aMVx); } } } } // qqf { Standard_Integer aNbF, aNbAV, nF, k; NMTTools_IndexedDataMapOfIndexedMapOfInteger aMAVF; // aNbF=myAloneVertices.Extent(); if (aNbF<2) { return; } // // 1. fill map Alone Vertex/Face -> aMAVF for (i=1; i<=aNbF; ++i) { nF=myAloneVertices.FindKey(i); const TColStd_IndexedMapOfInteger& aMAV=myAloneVertices(i); aNbAV=aMAV.Extent(); for(j=1; j<=aNbAV; ++j) { nV=aMAV(j); if (aMAVF.Contains(nV)) { TColStd_IndexedMapOfInteger& aMF=aMAVF.ChangeFromKey(nV); aMF.Add(nF); } else{ TColStd_IndexedMapOfInteger aMF; aMF.Add(nF); aMAVF.Add(nV, aMF); } } } // // 2 Obtain pairs of faces aNbAV=aMAVF.Extent(); for (i=1; i<=aNbAV; ++i) { const TColStd_IndexedMapOfInteger& aMF=aMAVF(i); aNbF=aMF.Extent(); for(j=1; j<aNbF; ++j) { nF1=aMF(j); for(k=j+1; k<=aNbF; ++k) { nF2=aMF(k); myIP->Add(nF1, nF2, Standard_True, NMTDS_TI_FF); } } } } // qqt }
//======================================================================= // 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); } } // }