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_Alerts.hxx>
20 #include <BOPAlgo_SectionAttribute.hxx>
21 #include <BOPAlgo_Tools.hxx>
22 #include <BOPCol_IndexedMapOfShape.hxx>
23 #include <BOPCol_NCVector.hxx>
24 #include <BOPCol_Parallel.hxx>
25 #include <BOPDS_CommonBlock.hxx>
26 #include <BOPDS_Curve.hxx>
27 #include <BOPDS_DS.hxx>
28 #include <BOPDS_FaceInfo.hxx>
29 #include <BOPDS_Interf.hxx>
30 #include <BOPDS_Iterator.hxx>
31 #include <BOPDS_ListOfPaveBlock.hxx>
32 #include <BOPDS_MapOfPaveBlock.hxx>
33 #include <BOPDS_Pave.hxx>
34 #include <BOPDS_PaveBlock.hxx>
35 #include <BOPDS_ShapeInfo.hxx>
36 #include <BOPDS_VectorOfCurve.hxx>
37 #include <BOPDS_VectorOfFaceInfo.hxx>
38 #include <BOPDS_VectorOfInterfFF.hxx>
39 #include <BOPDS_VectorOfListOfPaveBlock.hxx>
40 #include <BOPTools_AlgoTools.hxx>
41 #include <BOPTools_AlgoTools2D.hxx>
42 #include <BRep_Builder.hxx>
43 #include <BRep_Tool.hxx>
44 #include <BRepBndLib.hxx>
45 #include <Geom2d_Curve.hxx>
46 #include <Geom_Curve.hxx>
47 #include <Geom_Plane.hxx>
48 #include <Geom_RectangularTrimmedSurface.hxx>
49 #include <Geom_Surface.hxx>
50 #include <GeomAPI_ProjectPointOnCurve.hxx>
51 #include <GeomAPI_ProjectPointOnSurf.hxx>
53 #include <IntTools_Context.hxx>
54 #include <IntTools_Tools.hxx>
56 #include <TopExp_Explorer.hxx>
58 #include <TopoDS_Edge.hxx>
59 #include <TopoDS_Face.hxx>
60 #include <TopoDS_Vertex.hxx>
64 Standard_Boolean IsBasedOnPlane(const TopoDS_Face& aF);
67 static void UpdateVertices(const TopoDS_Edge& aE,
68 const TopoDS_Face& aF);
70 //=======================================================================
71 //class : BOPAlgo_SplitEdge
73 //=======================================================================
74 class BOPAlgo_SplitEdge : public BOPAlgo_Algo {
86 virtual ~BOPAlgo_SplitEdge() {
89 void SetData(const TopoDS_Edge& aE,
90 const TopoDS_Vertex& aV1,
91 const Standard_Real aT1,
92 const TopoDS_Vertex& aV2,
93 const Standard_Real aT2) {
102 void SetPaveBlock(const Handle(BOPDS_PaveBlock)& aPB) {
106 Handle(BOPDS_PaveBlock)& PaveBlock() {
110 void SetCommonBlock(const Handle(BOPDS_CommonBlock)& aCB) {
114 Handle(BOPDS_CommonBlock)& CommonBlock() {
118 const TopoDS_Edge& SplitEdge() const {
122 const Bnd_Box Box() {
126 Standard_Real Tolerance() const {
130 void SetDS(const BOPDS_PDS theDS) {
134 void SetContext(const Handle(IntTools_Context)& aContext) {
135 myContext = aContext;
138 virtual void Perform () {
139 BOPAlgo_Algo::UserBreak();
140 myTol = BOPAlgo_Tools::ComputeToleranceOfCB(myCB, myDS, myContext);
141 BOPTools_AlgoTools::MakeSplitEdge(myE,
145 BRepBndLib::Add(myESp, myBox);
146 myBox.SetGap(myBox.GetGap() + Precision::Confusion());
157 Handle(BOPDS_PaveBlock) myPB;
158 Handle(BOPDS_CommonBlock) myCB;
165 Handle(IntTools_Context) myContext;
168 //=======================================================================
169 typedef BOPCol_NCVector
170 <BOPAlgo_SplitEdge> BOPAlgo_VectorOfSplitEdge;
172 typedef BOPCol_ContextFunctor
174 BOPAlgo_VectorOfSplitEdge,
175 Handle(IntTools_Context),
176 IntTools_Context> BOPAlgo_SplitEdgeFunctor;
178 typedef BOPCol_ContextCnt
179 <BOPAlgo_SplitEdgeFunctor,
180 BOPAlgo_VectorOfSplitEdge,
181 Handle(IntTools_Context)> BOPAlgo_SplitEdgeCnt;
183 //=======================================================================
184 //class : BOPAlgo_MPC
186 //=======================================================================
187 class BOPAlgo_MPC : public BOPAlgo_Algo {
190 DEFINE_STANDARD_ALLOC
194 myFlag(Standard_False) {
197 virtual ~BOPAlgo_MPC(){
200 void SetEdge(const TopoDS_Edge& aE) {
204 const TopoDS_Edge& Edge() const {
208 void SetFace(const TopoDS_Face& aF) {
212 const TopoDS_Face& Face() const {
216 void SetFlag(const Standard_Boolean bFlag) {
220 Standard_Boolean Flag() const {
224 void SetData(const TopoDS_Edge& aEz,
225 const TopoDS_Vertex& aV1,
226 const Standard_Real aT1,
227 const TopoDS_Vertex& aV2,
228 const Standard_Real aT2) {
236 void SetContext(const Handle(IntTools_Context)& aContext) {
240 const Handle(IntTools_Context)& Context()const {
244 virtual void Perform() {
249 Standard_Integer iErr;
252 if (!myEz.IsNull()) {
255 BOPTools_AlgoTools::MakeSplitEdge(myEz,myV1, myT1,
259 BOPTools_AlgoTools2D::AttachExistingPCurve(aSpz,
266 BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(myE, myF, myContext);
270 UpdateVertices(myE, myF);
273 catch (Standard_Failure)
275 AddError(new BOPAlgo_AlertBuildingPCurveFailed(TopoDS_Shape()));
280 Standard_Boolean myFlag;
289 Handle(IntTools_Context) myContext;
292 //=======================================================================
293 typedef BOPCol_NCVector
294 <BOPAlgo_MPC> BOPAlgo_VectorOfMPC;
296 typedef BOPCol_ContextFunctor
299 Handle(IntTools_Context),
300 IntTools_Context> BOPAlgo_MPCFunctor;
302 typedef BOPCol_ContextCnt
305 Handle(IntTools_Context)> BOPAlgo_MPCCnt;
307 //=======================================================================
308 //class : BOPAlgo_BPC
310 //=======================================================================
319 void SetFace(const TopoDS_Face& aF) {
323 void SetEdge(const TopoDS_Edge& aE) {
327 const TopoDS_Edge& GetEdge() const {
330 const TopoDS_Face& GetFace() const {
333 const Handle(Geom2d_Curve)& GetCurve2d() const {
336 Standard_Boolean IsToUpdate() const {
341 BOPTools_AlgoTools2D::BuildPCurveForEdgeOnPlane (myE, myF, myCurve, myToUpdate);
347 Handle(Geom2d_Curve) myCurve;
348 Standard_Boolean myToUpdate;
350 //=======================================================================
351 typedef BOPCol_NCVector
352 <BOPAlgo_BPC> BOPAlgo_VectorOfBPC;
354 typedef BOPCol_Functor
356 BOPAlgo_VectorOfBPC> BOPAlgo_BPCFunctor;
360 BOPAlgo_VectorOfBPC> BOPAlgo_BPCCnt;
363 //=======================================================================
364 // function: MakeSplitEdges
366 //=======================================================================
367 void BOPAlgo_PaveFiller::MakeSplitEdges()
369 BOPDS_VectorOfListOfPaveBlock& aPBP=myDS->ChangePaveBlocksPool();
370 Standard_Integer aNbPBP = aPBP.Extent();
375 Standard_Boolean bCB, bV1, bV2;
376 Standard_Integer i, nE, nV1, nV2, nSp, aNbPB, aNbVBSE, k;
377 Standard_Real aT1, aT2;
378 BOPDS_ListIteratorOfListOfPaveBlock aItPB;
379 Handle(BOPDS_PaveBlock) aPB;
380 BOPDS_MapOfPaveBlock aMPB(100);
381 TopoDS_Vertex aV1, aV2;
383 BOPAlgo_VectorOfSplitEdge aVBSE;
386 UpdateCommonBlocksWithSDVertices();
388 aNbPBP=aPBP.Extent();
390 for (i=0; i<aNbPBP; ++i) {
391 BOPDS_ListOfPaveBlock& aLPB=aPBP(i);
396 aPB->Indices(nV1, nV2);
397 bV1=myDS->IsNewShape(nV1);
398 bV2=myDS->IsNewShape(nV2);
399 bCB=myDS->IsCommonBlock(aPB);
401 if (!(bV1 || bV2)) { // no new vertices here
402 if (!myNonDestructive || !bCB) {
404 if (!aPB->HasEdge()) {
405 const Handle(BOPDS_CommonBlock)& aCB = myDS->CommonBlock(aPB);
406 nE = aCB->PaveBlock1()->OriginalEdge();
408 // Compute tolerance of the common block and update the edge
409 Standard_Real aTol = BOPAlgo_Tools::ComputeToleranceOfCB(aCB, myDS, myContext);
410 myDS->UpdateEdgeTolerance(nE, aTol);
414 nE = aPB->OriginalEdge();
422 aItPB.Initialize(aLPB);
423 for (; aItPB.More(); aItPB.Next()) {
425 nE=aPB->OriginalEdge();
426 const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
431 const Handle(BOPDS_CommonBlock)& aCB=myDS->CommonBlock(aPB);
434 aPB=aCB->PaveBlock1();
438 nE=aPB->OriginalEdge();
439 aPB->Indices(nV1, nV2);
440 aPB->Range(aT1, aT2);
442 aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
443 aE.Orientation(TopAbs_FORWARD);
445 aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
446 aV1.Orientation(TopAbs_FORWARD);
448 aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
449 aV2.Orientation(TopAbs_REVERSED);
451 BOPAlgo_SplitEdge& aBSE=aVBSE.Append1();
453 aBSE.SetData(aE, aV1, aT1, aV2, aT2);
454 aBSE.SetPaveBlock(aPB);
456 aBSE.SetCommonBlock(aCB);
459 aBSE.SetProgressIndicator(myProgressIndicator);
461 } // for (; aItPB.More(); aItPB.Next()) {
462 } // for (i=0; i<aNbPBP; ++i) {
464 aNbVBSE=aVBSE.Extent();
465 //======================================================
466 BOPAlgo_SplitEdgeCnt::Perform(myRunParallel, aVBSE, myContext);
467 //======================================================
471 aSI.SetShapeType(TopAbs_EDGE);
473 for (k=0; k < aNbVBSE; ++k) {
474 BOPAlgo_SplitEdge& aBSE=aVBSE(k);
476 const TopoDS_Edge& aSp=aBSE.SplitEdge();
477 const Bnd_Box& aBox=aBSE.Box();
479 Handle(BOPDS_PaveBlock) aPBk=aBSE.PaveBlock();
480 Handle(BOPDS_CommonBlock)& aCBk=aBSE.CommonBlock();
483 aSI.ChangeBox()=aBox;
485 nSp=myDS->Append(aSI);
487 if (!aCBk.IsNull()) {
488 myDS->UpdateEdgeTolerance(nSp, aBSE.Tolerance());
497 //=======================================================================
498 // function: SplitEdge
500 //=======================================================================
501 Standard_Integer BOPAlgo_PaveFiller::SplitEdge(const Standard_Integer nE,
502 const Standard_Integer nV1,
503 const Standard_Real aT1,
504 const Standard_Integer nV2,
505 const Standard_Real aT2)
507 Standard_Integer nSp;
508 TopoDS_Vertex aV1, aV2;
512 aSI.SetShapeType(TopAbs_EDGE);
514 aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
515 aE.Orientation(TopAbs_FORWARD);
517 aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
518 aV1.Orientation(TopAbs_FORWARD);
520 aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
521 aV2.Orientation(TopAbs_REVERSED);
523 BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aSp);
527 Bnd_Box& aBox=aSI.ChangeBox();
528 BRepBndLib::Add(aSp, aBox);
529 aBox.SetGap(aBox.GetGap() + Precision::Confusion());
531 nSp=myDS->Append(aSI);
534 //=======================================================================
535 // function: MakePCurves
537 //=======================================================================
538 void BOPAlgo_PaveFiller::MakePCurves()
540 if (myAvoidBuildPCurve ||
541 (!mySectionAttribute.PCurveOnS1() && !mySectionAttribute.PCurveOnS2()))
543 Standard_Boolean bHasPC;
544 Standard_Integer i, nF1, nF2, aNbC, k, nE, aNbFF, aNbFI, nEx;
545 Standard_Integer j, aNbPBIn, aNbPBOn;
546 BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
547 TopoDS_Face aF1F, aF2F;
548 BOPAlgo_VectorOfMPC aVMPC;
550 // 1. Process Common Blocks
551 const BOPDS_VectorOfFaceInfo& aFIP=myDS->FaceInfoPool();
554 for (i=0; i<aNbFI; ++i) {
555 const BOPDS_FaceInfo& aFI=aFIP(i);
558 aF1F=(*(TopoDS_Face *)(&myDS->Shape(nF1)));
559 aF1F.Orientation(TopAbs_FORWARD);
561 const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
562 aNbPBIn = aMPBIn.Extent();
563 for (j = 1; j <= aNbPBIn; ++j) {
564 const Handle(BOPDS_PaveBlock)& aPB = aMPBIn(j);
566 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
568 BOPAlgo_MPC& aMPC=aVMPC.Append1();
571 aMPC.SetProgressIndicator(myProgressIndicator);
575 const BOPDS_IndexedMapOfPaveBlock& aMPBOn=aFI.PaveBlocksOn();
576 aNbPBOn = aMPBOn.Extent();
577 for (j = 1; j <= aNbPBOn; ++j) {
578 const Handle(BOPDS_PaveBlock)& aPB = aMPBOn(j);
580 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
581 bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aE, aF1F);
586 Handle(BOPDS_CommonBlock) aCB=myDS->CommonBlock(aPB);
591 const BOPDS_ListOfPaveBlock& aLPB=aCB->PaveBlocks();
592 if (aLPB.Extent()<2) {
596 BOPAlgo_MPC& aMPC=aVMPC.Append1();
598 aItLPB.Initialize(aLPB);
599 for(; aItLPB.More(); aItLPB.Next()) {
600 const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value();
605 nEx=aPBx->OriginalEdge();
606 const TopoDS_Edge& aEx=(*(TopoDS_Edge *)(&myDS->Shape(nEx)));
607 bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aEx, aF1F);
612 Standard_Integer nV1x, nV2x;
613 Standard_Real aT1x, aT2x;
614 TopoDS_Vertex aV1x, aV2x;
618 aEz.Orientation(TopAbs_FORWARD);
620 aPBx->Indices(nV1x, nV2x);
621 aPBx->Range(aT1x, aT2x);
623 aV1x=(*(TopoDS_Vertex *)(&myDS->Shape(nV1x)));
624 aV1x.Orientation(TopAbs_FORWARD);
626 aV2x=(*(TopoDS_Vertex *)(&myDS->Shape(nV2x)));
627 aV2x.Orientation(TopAbs_REVERSED);
629 aMPC.SetData(aEz, aV1x, aT1x, aV2x, aT2x);
636 aMPC.SetProgressIndicator(myProgressIndicator);
638 }// for (i=0; i<aNbFI; ++i) {
640 // 2. Process section edges
641 Standard_Boolean bPCurveOnS[2];
645 bPCurveOnS[0]=mySectionAttribute.PCurveOnS1();
646 bPCurveOnS[1]=mySectionAttribute.PCurveOnS2();
648 if (bPCurveOnS[0] || bPCurveOnS[1]) {
649 BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
651 for (i=0; i<aNbFF; ++i) {
652 const BOPDS_InterfFF& aFF=aFFs(i);
653 aFF.Indices(nF1, nF2);
655 aFf[0]=(*(TopoDS_Face *)(&myDS->Shape(nF1)));
656 aFf[0].Orientation(TopAbs_FORWARD);
658 aFf[1]=(*(TopoDS_Face *)(&myDS->Shape(nF2)));
659 aFf[1].Orientation(TopAbs_FORWARD);
661 const BOPDS_VectorOfCurve& aVNC=aFF.Curves();
663 for (k=0; k<aNbC; ++k) {
664 const BOPDS_Curve& aNC=aVNC(k);
665 const BOPDS_ListOfPaveBlock& aLPB=aNC.PaveBlocks();
666 aItLPB.Initialize(aLPB);
667 for(; aItLPB.More(); aItLPB.Next()) {
668 const Handle(BOPDS_PaveBlock)& aPB=aItLPB.Value();
670 const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE)));
672 for (m=0; m<2; ++m) {
674 BOPAlgo_MPC& aMPC=aVMPC.Append1();
676 aMPC.SetFace(aFf[m]);
677 aMPC.SetFlag(bPCurveOnS[m]);
678 aMPC.SetProgressIndicator(myProgressIndicator);
683 }// for (i=0; i<aNbFF; ++i) {
684 }//if (bPCurveOnS1 || bPCurveOnS2 ) {
686 //======================================================
687 BOPAlgo_MPCCnt::Perform(myRunParallel, aVMPC, myContext);
688 //======================================================
690 // Add warnings of the failed projections
691 Standard_Integer aNb = aVMPC.Extent();
692 for (i = 0; i < aNb; ++i)
694 if (aVMPC(i).HasErrors())
697 BRep_Builder().MakeCompound(aWC);
698 BRep_Builder().Add(aWC, aVMPC(i).Edge());
699 BRep_Builder().Add(aWC, aVMPC(i).Face());
700 AddWarning(new BOPAlgo_AlertBuildingPCurveFailed(aWC));
704 //=======================================================================
705 //function : UpdateVertices
706 //purpose : update tolerances of vertices comparing extremities of
708 //=======================================================================
709 void UpdateVertices(const TopoDS_Edge& aE,
710 const TopoDS_Face& aF)
713 Standard_Real aT[2], aUx, aVx, aTolV2, aD2, aD;
716 Handle(Geom_Surface) aS;
717 Handle(Geom_Curve) aC3D;
718 Handle(Geom2d_Curve) aC2D;
724 aEf.Orientation(TopAbs_FORWARD);
726 TopExp::Vertices(aEf, aV[0], aV[1]);
728 aS=BRep_Tool::Surface(aF);
729 aC3D=BRep_Tool::Curve(aEf, aT[0], aT[1]);
730 aC2D=BRep_Tool::CurveOnSurface(aEf, aF, aT[0], aT[1]);
732 for (j=0; j<2; ++j) {
733 aTolV2=BRep_Tool::Tolerance(aV[j]);
734 aTolV2=aTolV2*aTolV2;
736 aC3D->D0(aT[j], aP3D);
737 aC2D->D0(aT[j], aP2Dx);
738 aP2Dx.Coord(aUx, aVx);
739 aS->D0(aUx, aVx, aP3Dx);
740 aD2=aP3D.SquareDistance(aP3Dx);
743 aBB.UpdateVertex(aV[j], aD);
747 //=======================================================================
750 //=======================================================================
751 void BOPAlgo_PaveFiller::Prepare()
753 if (myNonDestructive) {
754 // do not allow storing pcurves in original edges if non-destructive mode is on
757 TopAbs_ShapeEnum aType[] = {
762 Standard_Boolean bIsBasedOnPlane;
763 Standard_Integer i, aNb, n1, nF, aNbF;
764 TopExp_Explorer aExp;
765 BOPCol_IndexedMapOfShape aMF;
768 for(i=0; i<aNb; ++i) {
769 myIterator->Initialize(aType[i], aType[2]);
770 for (; myIterator->More(); myIterator->Next()) {
771 myIterator->Value(n1, nF);
772 const TopoDS_Face& aF=(*(TopoDS_Face *)(&myDS->Shape(nF)));
774 bIsBasedOnPlane=IsBasedOnPlane(aF);
775 if (bIsBasedOnPlane) {
786 // Build pcurves of edges on planes; first collect pairs edge-face.
787 BOPAlgo_VectorOfBPC aVBPC;
789 for (i = 1; i <= aNbF; ++i) {
790 const TopoDS_Face& aF = *(TopoDS_Face*)&aMF(i);
791 aExp.Init(aF, aType[1]);
792 for (; aExp.More(); aExp.Next()) {
793 const TopoDS_Edge& aE=*((TopoDS_Edge *)&aExp.Current());
794 BOPAlgo_BPC& aBPC=aVBPC.Append1();
800 //======================================================
801 BOPAlgo_BPCCnt::Perform(myRunParallel, aVBPC);
802 //======================================================
804 // pcurves are built, and now update edges
807 for (i = 0; i < aVBPC.Extent(); i++) {
808 const BOPAlgo_BPC& aBPC=aVBPC(i);
809 if (aBPC.IsToUpdate()) {
810 Standard_Real aTolE = BRep_Tool::Tolerance(aBPC.GetEdge());
811 aBB.UpdateEdge(aBPC.GetEdge(), aBPC.GetCurve2d(), aBPC.GetFace(), aTolE);
815 //=======================================================================
816 //function : IsBasedOnPlane
818 //=======================================================================
819 Standard_Boolean IsBasedOnPlane(const TopoDS_Face& aF)
821 TopLoc_Location aLoc;
822 Handle(Geom_RectangularTrimmedSurface) aGRTS;
823 Handle(Geom_Plane) aGP;
825 const Handle(Geom_Surface)& aS = BRep_Tool::Surface(aF, aLoc);
826 aGRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
827 if(!aGRTS.IsNull()) {
828 aGP = Handle(Geom_Plane)::DownCast(aGRTS->BasisSurface());
831 aGP = Handle(Geom_Plane)::DownCast(aS);
834 return (!aGP.IsNull());