//======================================================================= //function : addEdgeRelation //purpose : local function to remember relation between initial and modified edge //======================================================================= static void addEdgeRelation(TopTools_DataMapOfShapeShape& theMap, const TopoDS_Edge& theInitE, const TopoDS_Edge& theResE) { if ( theMap.IsBound( theInitE ) ) theMap.ChangeFind( theInitE ) = theResE; else theMap.Bind( theInitE, theResE ); }
//======================================================================= // function: FuseVertices // purpose: //======================================================================= void NMTTools_PaveFiller::FuseVertices (const TopoDS_Shape& aCompound, TopTools_DataMapOfShapeShape& aDMVV)const { Standard_Integer i, aNbVV, n1, n2, nX; NMTTools_PaveFiller tPF; // tPF.SetCompositeShape(aCompound); // tPF.Init(); // tPF.PerformVV(); //tPF.PerformNewVertices(); //qq // NMTDS_ShapesDataStructure& tDS=*(tPF.DS()); NMTDS_InterfPool& tInterfPool=*(tPF.IP()); BOPTools_CArray1OfVVInterference& aVVt=tInterfPool.VVInterferences(); // aNbVV=aVVt.Extent(); for (i=1; i<=aNbVV; ++i) { const BOPTools_VVInterference& aVV=aVVt(i); aVV.Indices(n1, n2); nX=aVV.NewShape(); if (nX) { const TopoDS_Shape& aV1=tDS.Shape(n1); const TopoDS_Shape& aV2=tDS.Shape(n2); const TopoDS_Shape& aVx=tDS.Shape(nX); aDMVV.Bind(aV1, aVx); aDMVV.Bind(aV2, aVx); } } }
//======================================================================= // 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 }
bool FaceUniter::process() { if (workShell.IsNull()) return false; modifiedShapes.clear(); deletedShapes.clear(); typeObjects.push_back(&getPlaneObject()); typeObjects.push_back(&getCylinderObject()); //add more face types. ModelRefine::FaceTypeSplitter splitter; splitter.addShell(workShell); std::vector<FaceTypedBase *>::iterator typeIt; for(typeIt = typeObjects.begin(); typeIt != typeObjects.end(); ++typeIt) splitter.registerType((*typeIt)->getType()); splitter.split(); ModelRefine::FaceVectorType facesToRemove; ModelRefine::FaceVectorType facesToSew; ModelRefine::FaceAdjacencySplitter adjacencySplitter(workShell); for(typeIt = typeObjects.begin(); typeIt != typeObjects.end(); ++typeIt) { ModelRefine::FaceVectorType typedFaces = splitter.getTypedFaceVector((*typeIt)->getType()); ModelRefine::FaceEqualitySplitter equalitySplitter; equalitySplitter.split(typedFaces, *typeIt); for (std::size_t indexEquality(0); indexEquality < equalitySplitter.getGroupCount(); ++indexEquality) { adjacencySplitter.split(equalitySplitter.getGroup(indexEquality)); // std::cout << " adjacency group count: " << adjacencySplitter.getGroupCount() << std::endl; for (std::size_t adjacentIndex(0); adjacentIndex < adjacencySplitter.getGroupCount(); ++adjacentIndex) { // std::cout << " face count is: " << adjacencySplitter.getGroup(adjacentIndex).size() << std::endl; TopoDS_Face newFace = (*typeIt)->buildFace(adjacencySplitter.getGroup(adjacentIndex)); if (!newFace.IsNull()) { facesToSew.push_back(newFace); if (facesToRemove.capacity() <= facesToRemove.size() + adjacencySplitter.getGroup(adjacentIndex).size()) facesToRemove.reserve(facesToRemove.size() + adjacencySplitter.getGroup(adjacentIndex).size()); FaceVectorType temp = adjacencySplitter.getGroup(adjacentIndex); facesToRemove.insert(facesToRemove.end(), temp.begin(), temp.end()); // the first shape will be marked as modified, i.e. replaced by newFace, all others are marked as deleted if (!temp.empty()) { modifiedShapes.push_back(std::make_pair(temp.front(), newFace)); deletedShapes.insert(deletedShapes.end(), temp.begin()+1, temp.end()); } } } } } if (facesToSew.size() > 0) { modifiedSignal = true; workShell = ModelRefine::removeFaces(workShell, facesToRemove); TopExp_Explorer xp; bool emptyShell = true; for (xp.Init(workShell, TopAbs_FACE); xp.More(); xp.Next()) { emptyShell = false; break; } if (!emptyShell || facesToSew.size() > 1) { BRepBuilderAPI_Sewing sew; sew.Add(workShell); FaceVectorType::iterator sewIt; for(sewIt = facesToSew.begin(); sewIt != facesToSew.end(); ++sewIt) sew.Add(*sewIt); sew.Perform(); workShell = TopoDS::Shell(sew.SewedShape()); // update the list of modifications for (std::vector<ShapePairType>::iterator it = modifiedShapes.begin(); it != modifiedShapes.end(); ++it) { if (sew.IsModified(it->second)) { it->second = sew.Modified(it->second); break; } } } else { // workShell has no more faces and we add exactly one face BRep_Builder builder; builder.MakeShell(workShell); FaceVectorType::iterator sewIt; for(sewIt = facesToSew.begin(); sewIt != facesToSew.end(); ++sewIt) builder.Add(workShell, *sewIt); } BRepLib_FuseEdges edgeFuse(workShell, Standard_True); TopTools_DataMapOfShapeShape affectedFaces; edgeFuse.Faces(affectedFaces); TopTools_DataMapIteratorOfDataMapOfShapeShape mapIt; for (mapIt.Initialize(affectedFaces); mapIt.More(); mapIt.Next()) { ShapeFix_Face faceFixer(TopoDS::Face(mapIt.Value())); faceFixer.Perform(); } workShell = TopoDS::Shell(edgeFuse.Shape()); // update the list of modifications TopTools_DataMapOfShapeShape faceMap; edgeFuse.Faces(faceMap); for (std::vector<ShapePairType>::iterator it = modifiedShapes.begin(); it != modifiedShapes.end(); ++it) { if (faceMap.IsBound(it->second)) { const TopoDS_Shape& value = faceMap.Find(it->second); if (!value.IsSame(it->second)) it->second = value; } } } return true; }
//======================================================================= //function : Execute //purpose : //======================================================================= Standard_Integer GEOMImpl_Fillet1dDriver::Execute(TFunction_Logbook& log) const { if (Label().IsNull()) return 0; Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label()); GEOMImpl_IFillet1d aCI (aFunction); Handle(GEOM_Function) aRefShape = aCI.GetShape(); TopoDS_Shape aShape = aRefShape->GetValue(); if (aShape.IsNull()) return 0; if (aShape.ShapeType() != TopAbs_WIRE) Standard_ConstructionError::Raise("Wrong arguments: polyline as wire must be given"); TopoDS_Wire aWire = TopoDS::Wire(aShape); double rad = aCI.GetR(); if ( rad < Precision::Confusion()) return 0; // collect vertices for make fillet TopTools_ListOfShape aVertexList; TopTools_MapOfShape mapShape; int aLen = aCI.GetLength(); if ( aLen > 0 ) { for (int ind = 1; ind <= aLen; ind++) { TopoDS_Shape aShapeVertex; if (GEOMImpl_ILocalOperations::GetSubShape (aWire, aCI.GetVertex(ind), aShapeVertex)) if (mapShape.Add(aShapeVertex)) aVertexList.Append( aShapeVertex ); } } else { // get all vertices from wire TopExp_Explorer anExp( aWire, TopAbs_VERTEX ); for ( ; anExp.More(); anExp.Next() ) { if (mapShape.Add(anExp.Current())) aVertexList.Append( anExp.Current() ); } } if (aVertexList.IsEmpty()) Standard_ConstructionError::Raise("Invalid input no vertices to make fillet"); //INFO: this algorithm implemented in assumption that user can select both // vertices of some edges to make fillet. In this case we should remember // already modified initial edges to take care in next fillet step TopTools_DataMapOfShapeShape anEdgeToEdgeMap; //iterates on vertices, and make fillet on each couple of edges //collect result fillet edges in list TopTools_ListOfShape aListOfNewEdge; // remember relation between initial and modified map TopTools_IndexedDataMapOfShapeListOfShape aMapVToEdges; TopExp::MapShapesAndAncestors( aWire, TopAbs_VERTEX, TopAbs_EDGE, aMapVToEdges ); TopTools_ListIteratorOfListOfShape anIt( aVertexList ); for ( ; anIt.More(); anIt.Next() ) { TopoDS_Vertex aV = TopoDS::Vertex( anIt.Value() ); if ( aV.IsNull() || !aMapVToEdges.Contains( aV ) ) continue; const TopTools_ListOfShape& aVertexEdges = aMapVToEdges.FindFromKey( aV ); if ( aVertexEdges.Extent() != 2 ) continue; // no input data to make fillet TopoDS_Edge anEdge1 = TopoDS::Edge( aVertexEdges.First() ); TopoDS_Edge anEdge2 = TopoDS::Edge( aVertexEdges.Last() ); // check if initial edges already modified in previous fillet operation if ( anEdgeToEdgeMap.IsBound( anEdge1 ) ) anEdge1 = TopoDS::Edge(anEdgeToEdgeMap.Find( anEdge1 )); if ( anEdgeToEdgeMap.IsBound( anEdge2 ) ) anEdge2 = TopoDS::Edge(anEdgeToEdgeMap.Find( anEdge2 )); if ( anEdge1.IsNull() || anEdge2.IsNull() || anEdge1.IsSame( anEdge2 ) ) continue; //no input data to make fillet // create plane on 2 edges gp_Pln aPlane; if ( !takePlane(anEdge1, anEdge2, aV, aPlane) ) continue; // seems edges does not belong to same plane or parallel (fillet can not be build) GEOMImpl_Fillet1d aFilletAlgo(anEdge1, anEdge2, aPlane); if ( !aFilletAlgo.Perform(rad) ) continue; // can not create fillet with given radius // take fillet result in given vertex TopoDS_Edge aModifE1, aModifE2; TopoDS_Edge aNewE = aFilletAlgo.Result(BRep_Tool::Pnt(aV), aModifE1, aModifE2); if (aNewE.IsNull()) continue; // no result found // add new created edges and take modified edges aListOfNewEdge.Append( aNewE ); // check if face edges modified, // if yes, than map to original edges (from vertex-edges list), because edges can be modified before if (aModifE1.IsNull() || !anEdge1.IsSame( aModifE1 )) addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.First()), aModifE1 ); if (aModifE2.IsNull() || !anEdge2.IsSame( aModifE2 )) addEdgeRelation( anEdgeToEdgeMap, TopoDS::Edge(aVertexEdges.Last()), aModifE2 ); } if ( anEdgeToEdgeMap.IsEmpty() && aListOfNewEdge.IsEmpty() ) { StdFail_NotDone::Raise("1D Fillet can't be computed on the given shape with the given radius"); return 0; } // create new wire instead of original for ( TopExp_Explorer anExp( aWire, TopAbs_EDGE ); anExp.More(); anExp.Next() ) { TopoDS_Shape anEdge = anExp.Current(); if ( !anEdgeToEdgeMap.IsBound( anEdge ) ) aListOfNewEdge.Append( anEdge ); else if (!anEdgeToEdgeMap.Find( anEdge ).IsNull()) aListOfNewEdge.Append( anEdgeToEdgeMap.Find( anEdge ) ); } GEOMImpl_IShapesOperations::SortShapes( aListOfNewEdge ); BRepBuilderAPI_MakeWire aWireTool; aWireTool.Add( aListOfNewEdge ); aWireTool.Build(); if (!aWireTool.IsDone()) return 0; aWire = aWireTool.Wire(); aFunction->SetValue(aWire); log.SetTouched(Label()); return 1; }
//======================================================================= //function : PerformAreas //purpose : //======================================================================= void GEOMAlgo_BuilderFace::PerformAreas() { myErrorStatus=0; // Standard_Boolean bIsGrowth, bIsHole; Standard_Real aTol; TopTools_ListOfShape aNewFaces, aHoleWires; TopoDS_Shape anInfinitePointShape; TopTools_DataMapOfShapeShape aInOutMap; TopTools_DataMapOfShapeListOfShape aMSH; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH; TopTools_ListIteratorOfListOfShape aIt1, aIt2; TopTools_IndexedMapOfShape aMHE; BRep_Builder aBB; Handle(Geom_Surface) aS; TopLoc_Location aLoc; // aTol=BRep_Tool::Tolerance(myFace); aS=BRep_Tool::Surface(myFace, aLoc); // myAreas.Clear(); // // Draft faces [aNewFaces] aIt1.Initialize(myLoops); for ( ; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aWire=aIt1.Value(); // bIsGrowth=IsGrowthWire(aWire, aMHE); if (bIsGrowth) { // make a growth face from a wire TopoDS_Face aFace; aBB.MakeFace(aFace, aS, aLoc, aTol); aBB.Add (aFace, aWire); // aNewFaces.Append (aFace); } else{ // check if a wire is a hole //XX //bIsHole=IsHole(aWire, myFace, myContext); bIsHole=GEOMAlgo_BuilderTools::IsHole(aWire, myFace); //XX if (bIsHole) { aHoleWires.Append(aWire); TopExp::MapShapes(aWire, TopAbs_EDGE, aMHE); } else { // make a growth face from a wire TopoDS_Face aFace; aBB.MakeFace(aFace, aS, aLoc, aTol); aBB.Add (aFace, aWire); // aNewFaces.Append (aFace); } } } // // 2. Find outer growth shell that is most close to each hole shell aIt2.Initialize(aHoleWires); for (; aIt2.More(); aIt2.Next()) { const TopoDS_Shape& aHole = aIt2.Value(); // aIt1.Initialize(aNewFaces); for ( ; aIt1.More(); aIt1.Next()) { const TopoDS_Shape& aF=aIt1.Value(); // if (!IsInside(aHole, aF, myContext)){ continue; } // if ( aInOutMap.IsBound (aHole)){ const TopoDS_Shape& aF2=aInOutMap(aHole); if (IsInside(aF, aF2, myContext)) { aInOutMap.UnBind(aHole); aInOutMap.Bind (aHole, aF); } } else{ aInOutMap.Bind (aHole, aF); } } // // Add aHole to a map Face/ListOfHoles [aMSH] if (aInOutMap.IsBound(aHole)){ const TopoDS_Shape& aF=aInOutMap(aHole); if (aMSH.IsBound(aF)) { TopTools_ListOfShape& aLH=aMSH.ChangeFind(aF); aLH.Append(aHole); } else { TopTools_ListOfShape aLH; aLH.Append(aHole); aMSH.Bind(aF, aLH); } } }// for (; aIt2.More(); aIt2.Next()) // // 3. Add aHoles to Faces aItMSH.Initialize(aMSH); for (; aItMSH.More(); aItMSH.Next()) { TopoDS_Face aF=TopoDS::Face(aItMSH.Key()); // const TopTools_ListOfShape& aLH=aItMSH.Value(); aIt2.Initialize(aLH); for (; aIt2.More(); aIt2.Next()) { const TopoDS_Shape& aHole = aIt2.Value(); aBB.Add (aF, aHole); } // // update classifier aTol=BRep_Tool::Tolerance(aF); IntTools_FClass2d& aClsf=myContext->FClass2d(aF); aClsf.Init(aF, aTol); } // // These aNewFaces are draft faces that // do not contain any internal shapes // myAreas.Append(aNewFaces); }