1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2014 OPEN CASCADE SAS
3 // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4 // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5 // EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 // This file is part of Open CASCADE Technology software library.
9 // This library is free software; you can redistribute it and/or modify it under
10 // the terms of the GNU Lesser General Public License version 2.1 as published
11 // by the Free Software Foundation, with special exception defined in the file
12 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13 // distribution for complete text of the license and disclaimer of any warranty.
15 // Alternatively, this file may be used under the terms of Open CASCADE
16 // commercial license or contractual agreement.
19 #include <BOPAlgo_Builder.hxx>
20 #include <BOPAlgo_BuilderFace.hxx>
21 #include <BOPAlgo_PaveFiller.hxx>
22 #include <BOPAlgo_Tools.hxx>
23 #include <BOPDS_DS.hxx>
24 #include <BOPDS_FaceInfo.hxx>
25 #include <BOPDS_Interf.hxx>
26 #include <BOPDS_MapOfPaveBlock.hxx>
27 #include <BOPDS_PaveBlock.hxx>
28 #include <BOPDS_ShapeInfo.hxx>
29 #include <BOPDS_VectorOfCurve.hxx>
30 #include <BOPDS_VectorOfInterfFF.hxx>
31 #include <BOPDS_VectorOfPoint.hxx>
32 #include <BOPTools_AlgoTools.hxx>
33 #include <BOPTools_AlgoTools2D.hxx>
34 #include <BOPTools_AlgoTools3D.hxx>
35 #include <BOPTools_CoupleOfShape.hxx>
36 #include <BOPTools_ListOfCoupleOfShape.hxx>
37 #include <BOPTools_MapOfSet.hxx>
38 #include <BOPTools_Parallel.hxx>
39 #include <BRep_Builder.hxx>
40 #include <BRepLib.hxx>
41 #include <BRep_Tool.hxx>
42 #include <GeomAdaptor_Surface.hxx>
43 #include <GeomLib.hxx>
44 #include <NCollection_IncAllocator.hxx>
45 #include <NCollection_Vector.hxx>
46 #include <Precision.hxx>
47 #include <IntTools_Context.hxx>
48 #include <TColStd_ListOfInteger.hxx>
49 #include <TColStd_MapOfInteger.hxx>
50 #include <TopExp_Explorer.hxx>
52 #include <TopoDS_Compound.hxx>
53 #include <TopoDS_Edge.hxx>
54 #include <TopoDS_Face.hxx>
55 #include <TopoDS_Shape.hxx>
56 #include <TopoDS_Vertex.hxx>
57 #include <TopTools_ListOfShape.hxx>
62 TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
63 const TopTools_DataMapOfShapeListOfShape& theImages,
64 Handle(IntTools_Context)& theCtx);
66 //=======================================================================
67 //class : BOPAlgo_PairOfShapeBoolean
69 //=======================================================================
70 class BOPAlgo_PairOfShapeBoolean : public BOPAlgo_Algo {
75 BOPAlgo_PairOfShapeBoolean() :
77 myFlag(Standard_False) {
80 virtual ~BOPAlgo_PairOfShapeBoolean() {
83 TopoDS_Shape& Shape1() {
87 TopoDS_Shape& Shape2() {
91 Standard_Boolean& Flag() {
95 void SetContext(const Handle(IntTools_Context)& aContext) {
99 const Handle(IntTools_Context)& Context()const {
103 virtual void Perform() {
104 BOPAlgo_Algo::UserBreak();
106 const TopoDS_Face& aFj=*((TopoDS_Face*)&myShape1);
107 const TopoDS_Face& aFk=*((TopoDS_Face*)&myShape2);
108 myFlag=BOPTools_AlgoTools::AreFacesSameDomain(aFj, aFk, myContext, myFuzzyValue);
112 Standard_Boolean myFlag;
113 TopoDS_Shape myShape1;
114 TopoDS_Shape myShape2;
115 Handle(IntTools_Context) myContext;
118 typedef NCollection_Vector<BOPAlgo_PairOfShapeBoolean> \
119 BOPAlgo_VectorOfPairOfShapeBoolean;
121 typedef BOPTools_ContextFunctor
122 <BOPAlgo_PairOfShapeBoolean,
123 BOPAlgo_VectorOfPairOfShapeBoolean,
124 Handle(IntTools_Context),
125 IntTools_Context> BOPAlgo_BuilderSDFaceFunctor;
127 typedef BOPTools_ContextCnt
128 <BOPAlgo_BuilderSDFaceFunctor,
129 BOPAlgo_VectorOfPairOfShapeBoolean,
130 Handle(IntTools_Context)> BOPAlgo_BuilderSDFaceCnt;
132 //=======================================================================
135 typedef NCollection_Vector<BOPAlgo_BuilderFace> BOPAlgo_VectorOfBuilderFace;
137 typedef BOPTools_Functor
138 <BOPAlgo_BuilderFace,
139 BOPAlgo_VectorOfBuilderFace> BOPAlgo_BuilderFaceFunctor;
142 <BOPAlgo_BuilderFaceFunctor,
143 BOPAlgo_VectorOfBuilderFace> BOPAlgo_BuilderFaceCnt;
145 //=======================================================================
146 //class : BOPAlgo_VFI
148 //=======================================================================
149 class BOPAlgo_VFI : public BOPAlgo_Algo {
152 DEFINE_STANDARD_ALLOC
156 myIsInternal(Standard_False) {
159 virtual ~BOPAlgo_VFI(){
162 void SetVertex(const TopoDS_Vertex& aV) {
166 TopoDS_Vertex& Vertex() {
170 void SetFace(const TopoDS_Face& aF) {
174 TopoDS_Face& Face() {
178 Standard_Boolean IsInternal()const {
182 void SetContext(const Handle(IntTools_Context)& aContext) {
186 const Handle(IntTools_Context)& Context()const {
190 virtual void Perform() {
191 Standard_Real aT1, aT2, dummy;
193 BOPAlgo_Algo::UserBreak();
194 Standard_Integer iFlag =
195 myContext->ComputeVF(myV, myF, aT1, aT2, dummy, myFuzzyValue);
196 myIsInternal = (iFlag == 0);
200 Standard_Boolean myIsInternal;
203 Handle(IntTools_Context) myContext;
206 typedef NCollection_Vector<BOPAlgo_VFI> BOPAlgo_VectorOfVFI;
208 typedef BOPTools_ContextFunctor
211 Handle(IntTools_Context),
212 IntTools_Context> BOPAlgo_VFIFunctor;
214 typedef BOPTools_ContextCnt
217 Handle(IntTools_Context)> BOPAlgo_VFICnt;
219 //=======================================================================
220 //function : FillImagesFaces
222 //=======================================================================
223 void BOPAlgo_Builder::FillImagesFaces()
226 FillSameDomainFaces();
227 FillInternalVertices();
229 //=======================================================================
230 //function : BuildSplitFaces
232 //=======================================================================
233 void BOPAlgo_Builder::BuildSplitFaces()
235 Standard_Boolean bHasFaceInfo, bIsClosed, bIsDegenerated, bToReverse;
236 Standard_Integer i, j, k, aNbS, aNbPBIn, aNbPBOn, aNbPBSc, aNbAV, nSp;
237 TopoDS_Face aFF, aFSD;
238 TopoDS_Edge aSp, aEE;
239 TopAbs_Orientation anOriF, anOriE;
240 TopExp_Explorer aExp;
241 TopTools_ListIteratorOfListOfShape aIt;
242 TColStd_ListOfInteger aLIAV;
243 TopTools_MapOfShape aMFence;
244 Handle(NCollection_BaseAllocator) aAllocator;
245 BOPAlgo_VectorOfBuilderFace aVBF;
247 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~scope f
249 NCollection_BaseAllocator::CommonBaseAllocator();
251 TopTools_ListOfShape aLE(aAllocator);
252 TopTools_MapOfShape aMDE(100, aAllocator);
254 // Build temporary map of faces images to avoid rebuilding
255 // of the faces without any IN or section edges
256 NCollection_IndexedDataMap<Standard_Integer, TopTools_ListOfShape> aFacesIm;
258 aNbS=myDS->NbSourceShapes();
260 for (i=0; i<aNbS; ++i) {
261 const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
262 if (aSI.ShapeType()!=TopAbs_FACE) {
266 const TopoDS_Face& aF=(*(TopoDS_Face*)(&aSI.Shape()));
267 Standard_Boolean isUClosed = Standard_False,
268 isVClosed = Standard_False,
269 isChecked = Standard_False;
271 bHasFaceInfo=myDS->HasFaceInfo(i);
276 const BOPDS_FaceInfo& aFI=myDS->FaceInfo(i);
278 const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
279 const BOPDS_IndexedMapOfPaveBlock& aMPBOn=aFI.PaveBlocksOn();
280 const BOPDS_IndexedMapOfPaveBlock& aMPBSc=aFI.PaveBlocksSc();
282 myDS->AloneVertices(i, aLIAV);
284 aNbPBIn=aMPBIn.Extent();
285 aNbPBOn=aMPBOn.Extent();
286 aNbPBSc=aMPBSc.Extent();
287 aNbAV=aLIAV.Extent();
288 if (!aNbPBIn && !aNbPBOn && !aNbPBSc && !aNbAV) { // not compete
292 if (!aNbPBIn && !aNbPBSc)
296 // Check if any wires of the face have been modified.
297 // If not, there is no need to create the new face.
298 TopoDS_Iterator aItW(aF);
299 for (; aItW.More(); aItW.Next())
301 if (myImages.IsBound(aItW.Value()))
308 // No internal parts for the face, so just build the draft face
309 // and keep it to pass directly into result.
310 // If the original face has any internal edges or multi-connected vertices,
311 // the draft face will be null, as such sub-shapes may split the face on parts
312 // (as in the case "bugs modalg_5 bug25245_1").
313 // The BuilderFace algorithm will be called in this case.
314 TopoDS_Face aFD = BuildDraftFace(aF, myImages, myContext);
317 aFacesIm(aFacesIm.Add(i, TopTools_ListOfShape())).Append(aFD);
324 anOriF=aF.Orientation();
326 aFF.Orientation(TopAbs_FORWARD);
328 // 1. Fill the edges set for the face aFF -> LE
331 // 1.1 Bounding edges
332 aExp.Init(aFF, TopAbs_EDGE);
333 for (; aExp.More(); aExp.Next()) {
334 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
335 anOriE=aE.Orientation();
337 if (!myImages.IsBound(aE)) {
338 if (anOriE==TopAbs_INTERNAL) {
340 aEE.Orientation(TopAbs_FORWARD);
342 aEE.Orientation(TopAbs_REVERSED);
354 const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aF);
355 GeomLib::IsClosed(aSurf, BRep_Tool::Tolerance(aE),
356 isUClosed, isVClosed);
358 isChecked = Standard_True;
361 bIsClosed = Standard_False;
363 if((isUClosed || isVClosed) && BRep_Tool::IsClosed(aE, aF))
366 Standard_Boolean isUIso = Standard_False, isVIso = Standard_False;
367 BOPTools_AlgoTools2D::IsEdgeIsoline(aE, aF, isUIso, isVIso);
369 bIsClosed = ((isUClosed && isUIso) || (isVClosed && isVIso));
372 bIsDegenerated=BRep_Tool::Degenerated(aE);
374 const TopTools_ListOfShape& aLIE=myImages.Find(aE);
375 aIt.Initialize(aLIE);
376 for (; aIt.More(); aIt.Next()) {
377 aSp=(*(TopoDS_Edge*)(&aIt.Value()));
378 if (bIsDegenerated) {
379 aSp.Orientation(anOriE);
384 if (anOriE==TopAbs_INTERNAL) {
385 aSp.Orientation(TopAbs_FORWARD);
387 aSp.Orientation(TopAbs_REVERSED);
393 if (aMFence.Add(aSp)) {
394 if (!BRep_Tool::IsClosed(aSp, aF)){
395 BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, aF);
398 aSp.Orientation(TopAbs_FORWARD);
400 aSp.Orientation(TopAbs_REVERSED);
402 }// if (aMFence.Add(aSp))
406 aSp.Orientation(anOriE);
407 bToReverse=BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, myContext);
412 }// for (; aIt.More(); aIt.Next()) {
413 }// for (; aExp.More(); aExp.Next()) {
417 for (j=1; j<=aNbPBIn; ++j) {
418 const Handle(BOPDS_PaveBlock)& aPB=aMPBIn(j);
420 aSp=(*(TopoDS_Edge*)(&myDS->Shape(nSp)));
422 aSp.Orientation(TopAbs_FORWARD);
424 aSp.Orientation(TopAbs_REVERSED);
430 for (j=1; j<=aNbPBSc; ++j) {
431 const Handle(BOPDS_PaveBlock)& aPB=aMPBSc(j);
433 aSp=(*(TopoDS_Edge*)(&myDS->Shape(nSp)));
435 aSp.Orientation(TopAbs_FORWARD);
437 aSp.Orientation(TopAbs_REVERSED);
441 if (!myPaveFiller->NonDestructive()) {
442 // speed up for planar faces
443 BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFF);
445 // 3 Build split faces
446 BOPAlgo_BuilderFace& aBF=aVBF.Appended();
449 aBF.SetRunParallel(myRunParallel);
450 aBF.SetProgressIndicator(myProgressIndicator);
452 }// for (i=0; i<aNbS; ++i) {
454 //===================================================
455 BOPAlgo_BuilderFaceCnt::Perform(myRunParallel, aVBF);
456 //===================================================
458 Standard_Integer aNbBF = aVBF.Length();
459 for (k = 0; k < aNbBF; ++k)
461 BOPAlgo_BuilderFace& aBF = aVBF(k);
462 aFacesIm.Add(myDS->Index(aBF.Face()), aBF.Areas());
465 aNbBF = aFacesIm.Extent();
466 for (k = 1; k <= aNbBF; ++k)
468 const TopoDS_Face& aF = TopoDS::Face(myDS->Shape(aFacesIm.FindKey(k)));
469 anOriF = aF.Orientation();
470 const TopTools_ListOfShape& aLFR = aFacesIm(k);
472 TopTools_ListOfShape* pLFIm = myImages.Bound(aF, TopTools_ListOfShape());
473 aIt.Initialize(aLFR);
474 for (; aIt.More(); aIt.Next()) {
475 TopoDS_Shape& aFR=aIt.ChangeValue();
476 if (anOriF==TopAbs_REVERSED)
477 aFR.Orientation(TopAbs_REVERSED);
482 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~scope t
485 //=======================================================================
486 //function : AddEdgeSet
488 //=======================================================================
490 NCollection_IndexedDataMap<BOPTools_Set,
491 TopTools_ListOfShape,
492 BOPTools_SetMapHasher> BOPAlgo_IndexedDataMapOfSetListOfShape;
494 static void AddEdgeSet(const TopoDS_Shape& theS,
495 BOPAlgo_IndexedDataMapOfSetListOfShape& theMap,
496 const Handle(NCollection_BaseAllocator)& theAllocator)
500 aSE.Add(theS, TopAbs_EDGE);
501 // Add set to the map, keeping connection to the shape
502 TopTools_ListOfShape* pLF = theMap.ChangeSeek(aSE);
504 pLF = &theMap(theMap.Add(aSE, TopTools_ListOfShape(theAllocator)));
508 //=======================================================================
509 //function : FillSameDomainFaces
511 //=======================================================================
512 void BOPAlgo_Builder::FillSameDomainFaces()
514 // It is necessary to analyze all Face/Face intersections
515 // and find all faces with equal sets of edges
516 const BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
517 Standard_Integer aNbFFs = aFFs.Length();
521 Handle(NCollection_BaseAllocator) aAllocator = new NCollection_IncAllocator;
523 // Vector to store the indices of faces for future sorting
524 // for making the SD face for the group from the face with
525 // smallest index in Data structure
526 NCollection_Vector<Standard_Integer> aFIVec(256, aAllocator);
527 // Fence map to avoid repeated checks of the same face.
528 TColStd_MapOfInteger aMFence(1, aAllocator);
530 // Fill the vector with indices of faces
531 for (Standard_Integer i = 0; i < aNbFFs; ++i)
533 const BOPDS_InterfFF& aFF = aFFs(i);
535 Standard_Integer nF[2];
536 aFF.Indices(nF[0], nF[1]);
537 // store indices to the vector
538 for (Standard_Integer j = 0; j < 2; ++j)
540 if (!myDS->HasFaceInfo(nF[j]))
543 if (!aMFence.Add(nF[j]))
546 aFIVec.Appended() = nF[j];
551 std::sort(aFIVec.begin(), aFIVec.end());
553 // Data map of set of edges with all faces having this set
554 NCollection_IndexedDataMap<BOPTools_Set,
555 TopTools_ListOfShape,
556 BOPTools_SetMapHasher> anESetFaces(1, aAllocator);
557 // Map of planar bounded faces. If such faces have the same Edge set
558 // they are considered Same domain, without additional check.
559 TopTools_MapOfShape aMFPlanar(1, aAllocator);
561 Standard_Integer aNbF = aFIVec.Length();
562 for (Standard_Integer i = 0; i < aNbF; ++i)
564 const Standard_Integer nF = aFIVec(i);
565 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nF);
566 const TopoDS_Shape& aF = aSI.Shape();
568 Standard_Boolean bCheckPlanar = Standard_False;
570 // At this stage, context should contain adaptor for all intersected faces,
571 // so getting a type of the underlying surface should be done at no cost.
572 if (myContext->SurfaceAdaptor(TopoDS::Face(aF)).GetType() == GeomAbs_Plane)
574 // Check bounding box of the face - it should not be open in any side
575 const Bnd_Box& aBox = aSI.Box();
576 bCheckPlanar = !(aBox.IsOpenXmin() || aBox.IsOpenXmax() ||
577 aBox.IsOpenYmin() || aBox.IsOpenYmax() ||
578 aBox.IsOpenZmin() || aBox.IsOpenZmax());
582 const TopTools_ListOfShape* pLFSp = myImages.Seek(aF);
585 TopTools_ListIteratorOfListOfShape aItLF(*pLFSp);
586 for (; aItLF.More(); aItLF.Next())
588 AddEdgeSet(aItLF.Value(), anESetFaces, aAllocator);
590 aMFPlanar.Add(aItLF.Value());
595 AddEdgeSet(aF, anESetFaces, aAllocator);
601 // Store pairs of faces with equal set of edges to check if they are really Same Domain
602 BOPAlgo_VectorOfPairOfShapeBoolean aVPSB;
604 // Back and forth map of SD faces to make the blocks
605 TopTools_IndexedDataMapOfShapeListOfShape aDMSLS(1, aAllocator);
607 Standard_Integer aNbSets = anESetFaces.Extent();
608 for (Standard_Integer i = 1; i <= aNbSets; ++i)
610 const TopTools_ListOfShape& aLF = anESetFaces(i);
611 if (aLF.Extent() < 2)
614 // All possible pairs from <aLF> should be checked
615 TopTools_ListIteratorOfListOfShape aIt1(aLF);
616 for (; aIt1.More(); aIt1.Next())
618 const TopoDS_Shape& aF1 = aIt1.Value();
619 Standard_Boolean bCheckPlanar = aMFPlanar.Contains(aF1);
621 TopTools_ListIteratorOfListOfShape aIt2 = aIt1;
622 for (aIt2.Next(); aIt2.More(); aIt2.Next())
624 const TopoDS_Shape& aF2 = aIt2.Value();
625 if (bCheckPlanar && aMFPlanar.Contains(aF2))
627 // Consider planar bounded faces as Same Domain without additional check
628 BOPAlgo_Tools::FillMap<TopoDS_Shape, TopTools_ShapeMapHasher>(aF1, aF2, aDMSLS, aAllocator);
631 // Add pair for analysis
632 BOPAlgo_PairOfShapeBoolean& aPSB = aVPSB.Appended();
635 aPSB.SetFuzzyValue(myFuzzyValue);
636 aPSB.SetProgressIndicator(myProgressIndicator);
641 //================================================================
643 BOPAlgo_BuilderSDFaceCnt::Perform(myRunParallel, aVPSB, myContext);
644 //================================================================
646 NCollection_List<TopTools_ListOfShape> aMBlocks(aAllocator);
647 // Fill map with SD faces to make the blocks
648 Standard_Integer aNbPairs = aVPSB.Length();
649 for (Standard_Integer i = 0; i < aNbPairs; ++i)
651 BOPAlgo_PairOfShapeBoolean& aPSB = aVPSB(i);
653 BOPAlgo_Tools::FillMap<TopoDS_Shape, TopTools_ShapeMapHasher>
654 (aPSB.Shape1(), aPSB.Shape2(), aDMSLS, aAllocator);
658 // Make blocks of SD faces using the back and forth map
659 BOPAlgo_Tools::MakeBlocks<TopoDS_Shape, TopTools_ShapeMapHasher>
660 (aDMSLS, aMBlocks, aAllocator);
662 // Fill same domain faces map
663 NCollection_List<TopTools_ListOfShape>::Iterator aItB(aMBlocks);
664 for (; aItB.More(); aItB.Next())
666 const TopTools_ListOfShape& aLSD = aItB.Value();
667 // If the group contains some original faces, the one with minimal
668 // index in the DS will be chosen as the SD for the whole group.
669 // If there are no original faces in the group, the first face from
670 // the group will be used as the SD face.
671 // Such SD face will be representative of the whole group in the result.
672 TopoDS_Face* pFSD = NULL;
673 Standard_Integer nFMin = ::IntegerLast();
674 TopTools_ListIteratorOfListOfShape aItLF(aLSD);
675 for (; aItLF.More(); aItLF.Next())
677 const TopoDS_Shape& aF = aItLF.Value();
678 // Check the index of the face in DS
679 const Standard_Integer nF = myDS->Index(aF);
682 // The fact that the face is found in the DS, means that
683 // the face has not been change, and thus it is original one.
685 // Such face does not have any splits, but have an SD face.
686 // Consider it being split.
687 myImages.Bound(aF, TopTools_ListOfShape())->Append(aF);
689 // For the SD face chose the one with minimal index
693 pFSD = (TopoDS_Face*)&aF;
700 // No original faces in the group, take the first one
701 pFSD = (TopoDS_Face*)&aLSD.First();
704 // Save all SD connections
705 aItLF.Initialize(aLSD);
706 for (; aItLF.More(); aItLF.Next())
708 const TopoDS_Shape& aF = aItLF.Value();
709 myShapesSD.Bind(aF, *pFSD);
713 // Update the map of images with SD faces and
714 // fill the map of origins.
715 Standard_Integer aNbS = myDS->NbSourceShapes();
716 for (Standard_Integer i = 0; i < aNbS; ++i)
718 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
719 if (aSI.ShapeType() != TopAbs_FACE)
722 const TopoDS_Shape& aF = aSI.Shape();
723 TopTools_ListOfShape* pLFIm = myImages.ChangeSeek(aF);
727 TopTools_ListIteratorOfListOfShape aItLFIm(*pLFIm);
728 for (; aItLFIm.More(); aItLFIm.Next())
730 TopoDS_Shape& aFIm = aItLFIm.ChangeValue();
731 const TopoDS_Shape* pFSD = myShapesSD.Seek(aFIm);
733 // Update image with SD face
736 // Fill the map of origins
737 TopTools_ListOfShape* pLFOr = myOrigins.ChangeSeek(aFIm);
739 pLFOr = myOrigins.Bound(aFIm, TopTools_ListOfShape());
747 //=======================================================================
748 // function: FillImagesFaces1
750 //=======================================================================
751 void BOPAlgo_Builder::FillInternalVertices()
753 // Vector of pairs of Vertex/Face for classification of the vertices
754 // relatively faces, and adding them as internal into the faces
755 BOPAlgo_VectorOfVFI aVVFI;
757 Standard_Integer aNbS = myDS->NbSourceShapes();
758 for (Standard_Integer i = 0; i < aNbS; ++i)
760 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
761 if (aSI.ShapeType() != TopAbs_FACE)
764 const TopoDS_Shape& aF = aSI.Shape();
765 const TopTools_ListOfShape* pLFIm = myImages.Seek(aF);
769 // Find vertices to add as internal into the splits
770 TColStd_ListOfInteger aLIAV;
771 myDS->AloneVertices(i, aLIAV);
773 // Add vertices and faces for classification
774 TColStd_ListIteratorOfListOfInteger aItLV(aLIAV);
775 for (; aItLV.More(); aItLV.Next())
777 TopoDS_Vertex aV = TopoDS::Vertex(myDS->Shape(aItLV.Value()));
778 aV.Orientation(TopAbs_INTERNAL);
780 TopTools_ListIteratorOfListOfShape aItLFIm(*pLFIm);
781 for (; aItLFIm.More(); aItLFIm.Next())
783 const TopoDS_Face& aFIm = TopoDS::Face(aItLFIm.Value());
785 BOPAlgo_VFI& aVFI = aVVFI.Appended();
788 aVFI.SetFuzzyValue(myFuzzyValue);
789 aVFI.SetProgressIndicator(myProgressIndicator);
794 // Perform classification
795 //================================================================
796 BOPAlgo_VFICnt::Perform(myRunParallel, aVVFI, myContext);
797 //================================================================
799 Standard_Integer aNbVFI = aVVFI.Length();
800 for (Standard_Integer i = 0; i < aNbVFI; ++i)
802 BOPAlgo_VFI& aVFI = aVVFI(i);
803 if (aVFI.IsInternal())
805 TopoDS_Vertex& aV = aVFI.Vertex();
806 TopoDS_Face& aF = aVFI.Face();
807 BRep_Builder().Add(aF, aV);
811 //=======================================================================
812 //function : HasMultiConnected
813 //purpose : Checks if the edge has multi-connected vertices.
814 //=======================================================================
815 static Standard_Boolean HasMultiConnected(const TopoDS_Edge& theEdge,
816 TopTools_DataMapOfShapeInteger& theMap)
818 TopoDS_Iterator itV(theEdge);
819 for (; itV.More(); itV.Next())
821 const TopoDS_Shape& aV = itV.Value();
822 Standard_Integer *pCounter = theMap.ChangeSeek(aV);
824 pCounter = theMap.Bound(aV, 1);
828 return Standard_True;
833 return Standard_False;
835 //=======================================================================
836 //function : BuildDraftFace
837 //purpose : Build draft faces, updating the bounding edges,
838 // according to the information stored into the <theImages> map
839 //=======================================================================
840 TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
841 const TopTools_DataMapOfShapeListOfShape& theImages,
842 Handle(IntTools_Context)& theCtx)
845 // Take the information from the original face
846 TopLoc_Location aLoc;
847 const Handle(Geom_Surface)& aS = BRep_Tool::Surface(theFace, aLoc);
848 const Standard_Real aTol = BRep_Tool::Tolerance(theFace);
849 // Make the new face, without any wires
850 TopoDS_Face aDraftFace;
851 aBB.MakeFace(aDraftFace, aS, aLoc, aTol);
853 // Check if the thin face can be split by a vertex - in this case
854 // this vertex will be contained in more than two edges. Thus, count
855 // the vertices appearance, and if the multi-connexity is met return
856 // the null face to use the BuilderFace algorithm for checking the
857 // possibility of split.
858 TopTools_DataMapOfShapeInteger aVerticesCounter;
860 // Update wires of the original face and add them to draft face
861 TopoDS_Iterator aItW(theFace.Oriented(TopAbs_FORWARD));
862 for (; aItW.More(); aItW.Next())
864 const TopoDS_Shape& aW = aItW.Value();
865 if (aW.ShapeType() != TopAbs_WIRE)
868 // Rebuild wire using images of edges
869 TopoDS_Iterator aItE(aW.Oriented(TopAbs_FORWARD));
873 TopoDS_Wire aNewWire;
874 aBB.MakeWire(aNewWire);
876 for (; aItE.More(); aItE.Next())
878 const TopoDS_Edge& aE = TopoDS::Edge(aItE.Value());
880 TopAbs_Orientation anOriE = aE.Orientation();
881 if (anOriE == TopAbs_INTERNAL)
883 // The internal edges could split the original face on halves.
884 // Thus, use the BuilderFace algorithm to build the new face.
885 return TopoDS_Face();
888 // Check for the splits of the edge
889 const TopTools_ListOfShape* pLEIm = theImages.Seek(aE);
892 // Check if the edge has multi-connected vertices
893 if (HasMultiConnected(aE, aVerticesCounter))
894 return TopoDS_Face();
896 aBB.Add(aNewWire, aE);
900 // Check if the original edge is degenerated
901 Standard_Boolean bIsDegenerated = BRep_Tool::Degenerated(aE);
902 // Check if the original edge is closed on the face
903 Standard_Boolean bIsClosed = BRep_Tool::IsClosed(aE, theFace);
905 TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
906 for (; aItLEIm.More(); aItLEIm.Next())
908 TopoDS_Edge& aSp = TopoDS::Edge(aItLEIm.Value());
910 // Check if the split has multi-connected vertices
911 if (HasMultiConnected(aSp, aVerticesCounter))
912 return TopoDS_Face();
914 aSp.Orientation(anOriE);
917 aBB.Add(aNewWire, aSp);
921 // Check closeness of the split edge and if it is not
922 // make the second PCurve
923 if (bIsClosed && !BRep_Tool::IsClosed(aSp, theFace))
924 BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, theFace);
926 // Check if the split should be reversed
927 if (BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, theCtx))
930 aBB.Add(aNewWire, aSp);
934 aNewWire.Orientation(aW.Orientation());
935 aNewWire.Closed(BRep_Tool::IsClosed(aNewWire));
936 aBB.Add(aDraftFace, aNewWire);
939 if (theFace.Orientation() == TopAbs_REVERSED)
940 aDraftFace.Reverse();