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.
18 #include <BOPAlgo_PaveFiller.hxx>
19 #include <BOPAlgo_SectionAttribute.hxx>
20 #include <BOPAlgo_Tools.hxx>
21 #include <BOPCol_IndexedMapOfShape.hxx>
22 #include <BOPCol_NCVector.hxx>
23 #include <BOPCol_Parallel.hxx>
24 #include <BOPDS_CommonBlock.hxx>
25 #include <BOPDS_Curve.hxx>
26 #include <BOPDS_DS.hxx>
27 #include <BOPDS_FaceInfo.hxx>
28 #include <BOPDS_Interf.hxx>
29 #include <BOPDS_Iterator.hxx>
30 #include <BOPDS_ListOfPaveBlock.hxx>
31 #include <BOPDS_MapOfPaveBlock.hxx>
32 #include <BOPDS_Pave.hxx>
33 #include <BOPDS_PaveBlock.hxx>
34 #include <BOPDS_ShapeInfo.hxx>
35 #include <BOPDS_VectorOfCurve.hxx>
36 #include <BOPDS_VectorOfFaceInfo.hxx>
37 #include <BOPDS_VectorOfInterfFF.hxx>
38 #include <BOPDS_VectorOfListOfPaveBlock.hxx>
39 #include <BOPTools_AlgoTools.hxx>
40 #include <BOPTools_AlgoTools2D.hxx>
41 #include <BRep_Builder.hxx>
42 #include <BRep_Tool.hxx>
43 #include <BRepBndLib.hxx>
44 #include <Geom2d_Curve.hxx>
45 #include <Geom_Curve.hxx>
46 #include <Geom_Plane.hxx>
47 #include <Geom_RectangularTrimmedSurface.hxx>
48 #include <Geom_Surface.hxx>
49 #include <GeomAPI_ProjectPointOnCurve.hxx>
50 #include <GeomAPI_ProjectPointOnSurf.hxx>
52 #include <IntTools_Context.hxx>
53 #include <IntTools_Tools.hxx>
55 #include <TopExp_Explorer.hxx>
57 #include <TopoDS_Edge.hxx>
58 #include <TopoDS_Face.hxx>
59 #include <TopoDS_Vertex.hxx>
63 Standard_Boolean IsBasedOnPlane(const TopoDS_Face& aF);
66 static void UpdateVertices(const TopoDS_Edge& aE,
67 const TopoDS_Face& aF);
69 //=======================================================================
70 //class : BOPAlgo_SplitEdge
72 //=======================================================================
73 class BOPAlgo_SplitEdge : public BOPAlgo_Algo {
85 virtual ~BOPAlgo_SplitEdge() {
88 void SetData(const TopoDS_Edge& aE,
89 const TopoDS_Vertex& aV1,
90 const Standard_Real aT1,
91 const TopoDS_Vertex& aV2,
92 const Standard_Real aT2) {
101 void SetPaveBlock(const Handle(BOPDS_PaveBlock)& aPB) {
105 Handle(BOPDS_PaveBlock)& PaveBlock() {
109 void SetCommonBlock(const Handle(BOPDS_CommonBlock)& aCB) {
113 Handle(BOPDS_CommonBlock)& CommonBlock() {
117 const TopoDS_Edge& SplitEdge() const {
121 const Bnd_Box Box() {
125 Standard_Real Tolerance() const {
129 void SetDS(const BOPDS_PDS theDS) {
133 void SetContext(const Handle(IntTools_Context)& aContext) {
134 myContext = aContext;
137 virtual void Perform () {
138 BOPAlgo_Algo::UserBreak();
139 myTol = BOPAlgo_Tools::ComputeToleranceOfCB(myCB, myDS, myContext);
140 BOPTools_AlgoTools::MakeSplitEdge(myE,
144 BRepBndLib::Add(myESp, myBox);
145 myBox.SetGap(myBox.GetGap() + Precision::Confusion());
156 Handle(BOPDS_PaveBlock) myPB;
157 Handle(BOPDS_CommonBlock) myCB;
164 Handle(IntTools_Context) myContext;
167 //=======================================================================
168 typedef BOPCol_NCVector
169 <BOPAlgo_SplitEdge> BOPAlgo_VectorOfSplitEdge;
171 typedef BOPCol_ContextFunctor
173 BOPAlgo_VectorOfSplitEdge,
174 Handle(IntTools_Context),
175 IntTools_Context> BOPAlgo_SplitEdgeFunctor;
177 typedef BOPCol_ContextCnt
178 <BOPAlgo_SplitEdgeFunctor,
179 BOPAlgo_VectorOfSplitEdge,
180 Handle(IntTools_Context)> BOPAlgo_SplitEdgeCnt;
182 //=======================================================================
183 //class : BOPAlgo_MPC
185 //=======================================================================
186 class BOPAlgo_MPC : public BOPAlgo_Algo {
189 DEFINE_STANDARD_ALLOC
193 myFlag(Standard_False) {
196 virtual ~BOPAlgo_MPC(){
199 void SetEdge(const TopoDS_Edge& aE) {
203 const TopoDS_Edge& Edge() const {
207 void SetFace(const TopoDS_Face& aF) {
211 const TopoDS_Face& Face() const {
215 void SetFlag(const Standard_Boolean bFlag) {
219 Standard_Boolean Flag() const {
223 void SetData(const TopoDS_Edge& aEz,
224 const TopoDS_Vertex& aV1,
225 const Standard_Real aT1,
226 const TopoDS_Vertex& aV2,
227 const Standard_Real aT2) {
235 void SetContext(const Handle(IntTools_Context)& aContext) {
239 const Handle(IntTools_Context)& Context()const {
243 virtual void Perform() {
244 Standard_Integer iErr;
247 if (!myEz.IsNull()) {
250 BOPTools_AlgoTools::MakeSplitEdge(myEz,myV1, myT1,
254 BOPTools_AlgoTools2D::AttachExistingPCurve(aSpz,
261 BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(myE, myF);
265 UpdateVertices(myE, myF);
270 Standard_Boolean myFlag;
279 Handle(IntTools_Context) myContext;
282 //=======================================================================
283 typedef BOPCol_NCVector
284 <BOPAlgo_MPC> BOPAlgo_VectorOfMPC;
286 typedef BOPCol_ContextFunctor
289 Handle(IntTools_Context),
290 IntTools_Context> BOPAlgo_MPCFunctor;
292 typedef BOPCol_ContextCnt
295 Handle(IntTools_Context)> BOPAlgo_MPCCnt;
297 //=======================================================================
298 //class : BOPAlgo_BPC
300 //=======================================================================
309 void SetFace(const TopoDS_Face& aF) {
313 void SetEdge(const TopoDS_Edge& aE) {
317 const TopoDS_Edge& GetEdge() const {
320 const TopoDS_Face& GetFace() const {
323 const Handle(Geom2d_Curve)& GetCurve2d() const {
326 Standard_Boolean IsToUpdate() const {
331 BOPTools_AlgoTools2D::BuildPCurveForEdgeOnPlane (myE, myF, myCurve, myToUpdate);
337 Handle(Geom2d_Curve) myCurve;
338 Standard_Boolean myToUpdate;
340 //=======================================================================
341 typedef BOPCol_NCVector
342 <BOPAlgo_BPC> BOPAlgo_VectorOfBPC;
344 typedef BOPCol_Functor
346 BOPAlgo_VectorOfBPC> BOPAlgo_BPCFunctor;
350 BOPAlgo_VectorOfBPC> BOPAlgo_BPCCnt;
353 //=======================================================================
354 // function: MakeSplitEdges
356 //=======================================================================
357 void BOPAlgo_PaveFiller::MakeSplitEdges()
359 Standard_Integer aNbPBP;
363 BOPDS_VectorOfListOfPaveBlock& aPBP=myDS->ChangePaveBlocksPool();
364 aNbPBP=aPBP.Extent();
369 Standard_Boolean bCB, bV1, bV2;
370 Standard_Integer i, nE, nV1, nV2, nSp, aNbPB, aNbVBSE, k;
371 Standard_Real aT1, aT2;
372 BOPDS_ListIteratorOfListOfPaveBlock aItPB;
373 Handle(BOPDS_PaveBlock) aPB;
374 BOPDS_MapOfPaveBlock aMPB(100);
375 TopoDS_Vertex aV1, aV2;
377 BOPAlgo_VectorOfSplitEdge aVBSE;
380 UpdateCommonBlocksWithSDVertices();
382 aNbPBP=aPBP.Extent();
384 for (i=0; i<aNbPBP; ++i) {
385 BOPDS_ListOfPaveBlock& aLPB=aPBP(i);
390 aPB->Indices(nV1, nV2);
391 bV1=myDS->IsNewShape(nV1);
392 bV2=myDS->IsNewShape(nV2);
393 bCB=myDS->IsCommonBlock(aPB);
395 if (!(bV1 || bV2)) { // no new vertices here
396 if (!myNonDestructive || (myNonDestructive && !bCB)) {
397 nE = aPB->OriginalEdge();
399 if (!myNonDestructive && bCB) {
400 const Handle(BOPDS_CommonBlock)& aCB = myDS->CommonBlock(aPB);
401 Standard_Real aTol = BOPAlgo_Tools::ComputeToleranceOfCB(aCB, myDS, myContext);
402 myDS->UpdateEdgeTolerance(nE, aTol);
409 aItPB.Initialize(aLPB);
410 for (; aItPB.More(); aItPB.Next()) {
412 nE=aPB->OriginalEdge();
413 const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
418 const Handle(BOPDS_CommonBlock)& aCB=myDS->CommonBlock(aPB);
421 myDS->SortPaveBlocks(aCB);
422 aPB=aCB->PaveBlock1();
426 nE=aPB->OriginalEdge();
427 aPB->Indices(nV1, nV2);
428 aPB->Range(aT1, aT2);
430 aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
431 aE.Orientation(TopAbs_FORWARD);
433 aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
434 aV1.Orientation(TopAbs_FORWARD);
436 aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
437 aV2.Orientation(TopAbs_REVERSED);
439 BOPAlgo_SplitEdge& aBSE=aVBSE.Append1();
441 aBSE.SetData(aE, aV1, aT1, aV2, aT2);
442 aBSE.SetPaveBlock(aPB);
444 aBSE.SetCommonBlock(aCB);
447 aBSE.SetProgressIndicator(myProgressIndicator);
449 } // for (; aItPB.More(); aItPB.Next()) {
450 } // for (i=0; i<aNbPBP; ++i) {
452 aNbVBSE=aVBSE.Extent();
453 //======================================================
454 BOPAlgo_SplitEdgeCnt::Perform(myRunParallel, aVBSE, myContext);
455 //======================================================
459 aSI.SetShapeType(TopAbs_EDGE);
461 for (k=0; k < aNbVBSE; ++k) {
462 BOPAlgo_SplitEdge& aBSE=aVBSE(k);
464 const TopoDS_Edge& aSp=aBSE.SplitEdge();
465 const Bnd_Box& aBox=aBSE.Box();
467 Handle(BOPDS_PaveBlock) aPBk=aBSE.PaveBlock();
468 Handle(BOPDS_CommonBlock)& aCBk=aBSE.CommonBlock();
471 aSI.ChangeBox()=aBox;
473 nSp=myDS->Append(aSI);
475 if (!aCBk.IsNull()) {
476 myDS->UpdateEdgeTolerance(nSp, aBSE.Tolerance());
485 //=======================================================================
486 // function: SplitEdge
488 //=======================================================================
489 Standard_Integer BOPAlgo_PaveFiller::SplitEdge(const Standard_Integer nE,
490 const Standard_Integer nV1,
491 const Standard_Real aT1,
492 const Standard_Integer nV2,
493 const Standard_Real aT2)
495 Standard_Integer nSp;
496 TopoDS_Vertex aV1, aV2;
500 aSI.SetShapeType(TopAbs_EDGE);
502 aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
503 aE.Orientation(TopAbs_FORWARD);
505 aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
506 aV1.Orientation(TopAbs_FORWARD);
508 aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
509 aV2.Orientation(TopAbs_REVERSED);
511 BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aSp);
515 Bnd_Box& aBox=aSI.ChangeBox();
516 BRepBndLib::Add(aSp, aBox);
517 aBox.SetGap(aBox.GetGap() + Precision::Confusion());
519 nSp=myDS->Append(aSI);
522 //=======================================================================
523 // function: MakePCurves
525 //=======================================================================
526 void BOPAlgo_PaveFiller::MakePCurves()
528 Standard_Boolean bHasPC;
529 Standard_Integer i, nF1, nF2, aNbC, k, nE, aNbFF, aNbFI, nEx;
530 Standard_Integer j, aNbPBIn, aNbPBOn;
531 BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
532 TopoDS_Face aF1F, aF2F;
533 BOPAlgo_VectorOfMPC aVMPC;
537 // 1. Process Common Blocks
538 const BOPDS_VectorOfFaceInfo& aFIP=myDS->FaceInfoPool();
541 for (i=0; i<aNbFI; ++i) {
542 const BOPDS_FaceInfo& aFI=aFIP(i);
545 aF1F=(*(TopoDS_Face *)(&myDS->Shape(nF1)));
546 aF1F.Orientation(TopAbs_FORWARD);
548 const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
549 aNbPBIn = aMPBIn.Extent();
550 for (j = 1; j <= aNbPBIn; ++j) {
551 const Handle(BOPDS_PaveBlock)& aPB = aMPBIn(j);
553 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
555 BOPAlgo_MPC& aMPC=aVMPC.Append1();
558 aMPC.SetProgressIndicator(myProgressIndicator);
562 const BOPDS_IndexedMapOfPaveBlock& aMPBOn=aFI.PaveBlocksOn();
563 aNbPBOn = aMPBOn.Extent();
564 for (j = 1; j <= aNbPBOn; ++j) {
565 const Handle(BOPDS_PaveBlock)& aPB = aMPBOn(j);
567 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
568 bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aE, aF1F);
573 Handle(BOPDS_CommonBlock) aCB=myDS->CommonBlock(aPB);
578 const BOPDS_ListOfPaveBlock& aLPB=aCB->PaveBlocks();
579 if (aLPB.Extent()<2) {
583 BOPAlgo_MPC& aMPC=aVMPC.Append1();
585 aItLPB.Initialize(aLPB);
586 for(; aItLPB.More(); aItLPB.Next()) {
587 const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value();
592 nEx=aPBx->OriginalEdge();
593 const TopoDS_Edge& aEx=(*(TopoDS_Edge *)(&myDS->Shape(nEx)));
594 bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aEx, aF1F);
599 Standard_Integer nV1x, nV2x;
600 Standard_Real aT1x, aT2x;
601 TopoDS_Vertex aV1x, aV2x;
605 aEz.Orientation(TopAbs_FORWARD);
607 aPBx->Indices(nV1x, nV2x);
608 aPBx->Range(aT1x, aT2x);
610 aV1x=(*(TopoDS_Vertex *)(&myDS->Shape(nV1x)));
611 aV1x.Orientation(TopAbs_FORWARD);
613 aV2x=(*(TopoDS_Vertex *)(&myDS->Shape(nV2x)));
614 aV2x.Orientation(TopAbs_REVERSED);
616 aMPC.SetData(aEz, aV1x, aT1x, aV2x, aT2x);
623 aMPC.SetProgressIndicator(myProgressIndicator);
625 }// for (i=0; i<aNbFI; ++i) {
627 // 2. Process section edges
628 Standard_Boolean bPCurveOnS[2];
632 bPCurveOnS[0]=mySectionAttribute.PCurveOnS1();
633 bPCurveOnS[1]=mySectionAttribute.PCurveOnS2();
635 if (bPCurveOnS[0] || bPCurveOnS[1]) {
636 BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
638 for (i=0; i<aNbFF; ++i) {
639 const BOPDS_InterfFF& aFF=aFFs(i);
640 aFF.Indices(nF1, nF2);
642 aFf[0]=(*(TopoDS_Face *)(&myDS->Shape(nF1)));
643 aFf[0].Orientation(TopAbs_FORWARD);
645 aFf[1]=(*(TopoDS_Face *)(&myDS->Shape(nF2)));
646 aFf[1].Orientation(TopAbs_FORWARD);
648 const BOPDS_VectorOfCurve& aVNC=aFF.Curves();
650 for (k=0; k<aNbC; ++k) {
651 const BOPDS_Curve& aNC=aVNC(k);
652 const BOPDS_ListOfPaveBlock& aLPB=aNC.PaveBlocks();
653 aItLPB.Initialize(aLPB);
654 for(; aItLPB.More(); aItLPB.Next()) {
655 const Handle(BOPDS_PaveBlock)& aPB=aItLPB.Value();
657 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
659 for (m=0; m<2; ++m) {
661 BOPAlgo_MPC& aMPC=aVMPC.Append1();
663 aMPC.SetFace(aFf[m]);
664 aMPC.SetFlag(bPCurveOnS[m]);
665 aMPC.SetProgressIndicator(myProgressIndicator);
670 }// for (i=0; i<aNbFF; ++i) {
671 }//if (bPCurveOnS1 || bPCurveOnS2 ) {
673 //======================================================
674 BOPAlgo_MPCCnt::Perform(myRunParallel, aVMPC, myContext);
675 //======================================================
677 //=======================================================================
678 // function: RefineFaceInfoOn
680 //=======================================================================
681 void BOPAlgo_PaveFiller::RefineFaceInfoOn()
683 Standard_Integer aNbPBP;
687 BOPDS_VectorOfListOfPaveBlock& aPBP=myDS->ChangePaveBlocksPool();
688 aNbPBP=aPBP.Extent();
693 Standard_Boolean bV1, bV2;
694 Standard_Integer i, nV1, nV2, aNbPB;
695 Handle(BOPDS_PaveBlock) aPB;
697 for (i=0; i<aNbPBP; ++i) {
698 BOPDS_ListOfPaveBlock& aLPB=aPBP(i);
703 aPB->Indices(nV1, nV2);
704 bV1=myDS->IsNewShape(nV1);
705 bV2=myDS->IsNewShape(nV2);
708 if (!myDS->IsCommonBlock(aPB)) {
709 // the PB seems to be untouced
711 Standard_Integer nE = aPB->OriginalEdge();
713 myDS->ChangeShapeInfo(nE).SetReference(-1);
717 }//if (!(bV1 || bV2)) {
719 }//for (i=0; i<aNbPBP; ++i) {
720 myDS->RefineFaceInfoOn();
722 //=======================================================================
723 //function : UpdateVertices
724 //purpose : update tolerances of vertices comparing extremities of
726 //=======================================================================
727 void UpdateVertices(const TopoDS_Edge& aE,
728 const TopoDS_Face& aF)
731 Standard_Real aT[2], aUx, aVx, aTolV2, aD2, aD;
734 Handle(Geom_Surface) aS;
735 Handle(Geom_Curve) aC3D;
736 Handle(Geom2d_Curve) aC2D;
742 aEf.Orientation(TopAbs_FORWARD);
744 TopExp::Vertices(aEf, aV[0], aV[1]);
746 aS=BRep_Tool::Surface(aF);
747 aC3D=BRep_Tool::Curve(aEf, aT[0], aT[1]);
748 aC2D=BRep_Tool::CurveOnSurface(aEf, aF, aT[0], aT[1]);
750 for (j=0; j<2; ++j) {
751 aTolV2=BRep_Tool::Tolerance(aV[j]);
752 aTolV2=aTolV2*aTolV2;
754 aC3D->D0(aT[j], aP3D);
755 aC2D->D0(aT[j], aP2Dx);
756 aP2Dx.Coord(aUx, aVx);
757 aS->D0(aUx, aVx, aP3Dx);
758 aD2=aP3D.SquareDistance(aP3Dx);
761 aBB.UpdateVertex(aV[j], aD);
765 //=======================================================================
768 //=======================================================================
769 void BOPAlgo_PaveFiller::Prepare()
771 if (myNonDestructive) {
772 // do not allow storing pcurves in original edges if non-destructive mode is on
775 TopAbs_ShapeEnum aType[] = {
780 Standard_Boolean bJustAdd, bIsBasedOnPlane;
781 Standard_Integer i, aNb, n1, nF, aNbF;
782 TopExp_Explorer aExp;
783 BOPCol_IndexedMapOfShape aMF;
788 for(i=0; i<aNb; ++i) {
789 myIterator->Initialize(aType[i], aType[2]);
790 for (; myIterator->More(); myIterator->Next()) {
791 myIterator->Value(n1, nF, bJustAdd);
792 const TopoDS_Face& aF=(*(TopoDS_Face *)(&myDS->Shape(nF)));
794 bIsBasedOnPlane=IsBasedOnPlane(aF);
795 if (bIsBasedOnPlane) {
806 // Build pcurves of edges on planes; first collect pairs edge-face.
807 BOPAlgo_VectorOfBPC aVBPC;
809 for (i = 1; i <= aNbF; ++i) {
810 const TopoDS_Face& aF = *(TopoDS_Face*)&aMF(i);
811 aExp.Init(aF, aType[1]);
812 for (; aExp.More(); aExp.Next()) {
813 const TopoDS_Edge& aE=*((TopoDS_Edge *)&aExp.Current());
814 BOPAlgo_BPC& aBPC=aVBPC.Append1();
820 //======================================================
821 BOPAlgo_BPCCnt::Perform(myRunParallel, aVBPC);
822 //======================================================
824 // pcurves are built, and now update edges
827 for (i = 0; i < aVBPC.Extent(); i++) {
828 const BOPAlgo_BPC& aBPC=aVBPC(i);
829 if (aBPC.IsToUpdate()) {
830 Standard_Real aTolE = BRep_Tool::Tolerance(aBPC.GetEdge());
831 aBB.UpdateEdge(aBPC.GetEdge(), aBPC.GetCurve2d(), aBPC.GetFace(), aTolE);
835 //=======================================================================
836 //function : IsBasedOnPlane
838 //=======================================================================
839 Standard_Boolean IsBasedOnPlane(const TopoDS_Face& aF)
841 TopLoc_Location aLoc;
842 Handle(Geom_RectangularTrimmedSurface) aGRTS;
843 Handle(Geom_Plane) aGP;
845 const Handle(Geom_Surface)& aS = BRep_Tool::Surface(aF, aLoc);
846 aGRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
847 if(!aGRTS.IsNull()) {
848 aGP = Handle(Geom_Plane)::DownCast(aGRTS->BasisSurface());
851 aGP = Handle(Geom_Plane)::DownCast(aS);
854 return (!aGP.IsNull());