1 // Created on: 2001-09-12
2 // Created by: Peter KURNEV
3 // Copyright (c) 2001-2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
21 #include <BOPTools_DEProcessor.ixx>
24 #include <TopoDS_Shape.hxx>
25 #include <TopoDS_Edge.hxx>
27 #include <TopoDS_Face.hxx>
28 #include <TopoDS_Vertex.hxx>
29 #include <TopoDS_Solid.hxx>
32 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
33 #include <TopTools_ListOfShape.hxx>
34 #include <TopTools_ListIteratorOfListOfShape.hxx>
36 #include <gp_Pnt2d.hxx>
38 #include <gp_Sphere.hxx>
40 #include <IntRes2d_IntersectionPoint.hxx>
42 #include <Precision.hxx>
44 #include <Geom2d_Curve.hxx>
45 #include <Geom2d_Line.hxx>
46 #include <Geom2dAdaptor_Curve.hxx>
47 #include <Geom2dInt_GInter.hxx>
49 #include <BRep_Tool.hxx>
50 #include <BRep_Builder.hxx>
51 #include <BRepClass3d_SolidClassifier.hxx>
52 #include <BRepAdaptor_Surface.hxx>
54 #include <BRepExtrema_DistShapeShape.hxx>
56 #include <TColStd_ListIteratorOfListOfInteger.hxx>
57 #include <TColStd_ListOfInteger.hxx>
59 #include <BooleanOperations_ShapesDataStructure.hxx>
60 #include <BooleanOperations_AncestorsSeqAndSuccessorsSeq.hxx>
62 #include <IntTools_Range.hxx>
63 #include <IntTools_Tools.hxx>
64 #include <IntTools_Context.hxx>
66 #include <BOPTools_DEInfo.hxx>
67 #include <BOPTools_ListOfPaveBlock.hxx>
68 #include <BOPTools_SSInterference.hxx>
69 #include <BOPTools_PaveBlock.hxx>
70 #include <BOPTools_ListIteratorOfListOfPaveBlock.hxx>
71 #include <BOPTools_SequenceOfCurves.hxx>
72 #include <BOPTools_Curve.hxx>
73 #include <BOPTools_PavePool.hxx>
74 #include <BOPTools_Pave.hxx>
75 #include <BOPTools_PaveSet.hxx>
76 #include <BOPTools_Tools3D.hxx>
77 #include <BOPTools_PaveBlockIterator.hxx>
78 #include <BOPTools_ListOfPave.hxx>
79 #include <BOPTools_ListIteratorOfListOfPave.hxx>
80 #include <BOPTools_InterferencePool.hxx>
81 #include <BOPTools_CArray1OfSSInterference.hxx>
82 #include <BOPTools_ListIteratorOfListOfPaveBlock.hxx>
83 #include <BOPTools_PaveFiller.hxx>
84 #include <BOPTools_ListOfPaveBlock.hxx>
85 #include <BOPTools_SplitShapesPool.hxx>
86 #include <BOPTools_StateFiller.hxx>
88 //=======================================================================
89 // function: BOPTools_DEProcessor::BOPTools_DEProcessor
91 //=======================================================================
92 BOPTools_DEProcessor::BOPTools_DEProcessor(const BOPTools_PaveFiller& aFiller,
93 const Standard_Integer aDim)
95 myIsDone(Standard_False)
97 myFiller=(BOPTools_PaveFiller*) &aFiller;
101 if (aDim<2 || aDim>3) {
107 //=======================================================================
110 //=======================================================================
111 Standard_Boolean BOPTools_DEProcessor::IsDone() const
115 //=======================================================================
118 //=======================================================================
119 void BOPTools_DEProcessor::Do()
121 Standard_Integer aNbE;
122 myIsDone=Standard_False;
124 FindDegeneratedEdges();
125 aNbE=myDEMap.Extent();
128 myIsDone=Standard_True;
135 //=======================================================================
136 // function: FindDegeneratedEdges
138 //=======================================================================
139 void BOPTools_DEProcessor::FindDegeneratedEdges()
141 const BooleanOperations_ShapesDataStructure& aDS=*myDS;
142 const BOPTools_PaveFiller& aPaveFiller=*myFiller;
144 Standard_Integer i, aNbSourceShapes, nV, nF, nVx, ip, iRankE;
145 TopAbs_ShapeEnum aType;
147 const TopoDS_Shape& anObj=aDS.Object();
148 const TopoDS_Shape& aTool=aDS.Tool();
150 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
151 TopExp::MapShapesAndAncestors (anObj, TopAbs_EDGE, TopAbs_FACE, aMEF);
152 TopExp::MapShapesAndAncestors (aTool, TopAbs_EDGE, TopAbs_FACE, aMEF);
154 aNbSourceShapes=aDS.NumberOfSourceShapes();
155 for (i=1; i<=aNbSourceShapes; i++) {
156 const TopoDS_Shape& aS=aDS.Shape(i);
157 aType=aS.ShapeType();
158 if (aType==TopAbs_EDGE) {
159 const TopoDS_Edge& aE=TopoDS::Edge(aS);
160 if (BRep_Tool::Degenerated(aE)) {
164 TopoDS_Vertex aV=TopExp::FirstVertex(aE);
166 nVx=aDS.ShapeIndex(aV, iRankE);
169 ip=aPaveFiller.FindSDVertex(nV);
174 TColStd_ListOfInteger aLFn;
175 const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE);
176 TopTools_ListIteratorOfListOfShape anIt(aLF);
177 for (; anIt.More(); anIt.Next()) {
178 const TopoDS_Shape& aF=anIt.Value();
180 nF=aDS.ShapeIndex(aF, iRankE);
184 BOPTools_DEInfo aDEInfo;
185 aDEInfo.SetVertex(nV);
186 aDEInfo.SetFaces(aLFn);
188 myDEMap.Add (i, aDEInfo);
195 //=======================================================================
198 //=======================================================================
199 void BOPTools_DEProcessor::DoPaves()
202 Standard_Integer i, aNbE, nED, nVD, nFD=0;
204 aNbE=myDEMap.Extent();
205 for (i=1; i<=aNbE; i++) {
206 nED=myDEMap.FindKey(i);
208 const BOPTools_DEInfo& aDEInfo=myDEMap(i);
209 nVD=aDEInfo.Vertex();
210 // Fill PaveSet for the edge nED
211 const TColStd_ListOfInteger& nLF=aDEInfo.Faces();
212 TColStd_ListIteratorOfListOfInteger anIt(nLF);
213 for (; anIt.More(); anIt.Next()) {
216 BOPTools_ListOfPaveBlock aLPB;
217 FindPaveBlocks(nED, nVD, nFD, aLPB);
218 FillPaveSet (nED, nVD, nFD, aLPB);
221 // Fill aSplitEdges for the edge nED
222 FillSplitEdgesPool(nED);
225 MakeSplitEdges(nED, nFD);
227 // Compute States for Split parts
232 DoStates2D(nED, nFD);
237 //=======================================================================
238 // function: DoStates
240 //=======================================================================
241 void BOPTools_DEProcessor::DoStates (const Standard_Integer nED,
242 const Standard_Integer nFD)
246 const BOPTools_SplitShapesPool& aSplitShapesPool=myFiller->SplitShapesPool();
247 const BOPTools_ListOfPaveBlock& aSplitEdges=aSplitShapesPool(myDS->RefEdge(nED));
249 const TopoDS_Edge& aDE=TopoDS::Edge(myDS->Shape(nED));
250 const TopoDS_Face& aDF=TopoDS::Face(myDS->Shape(nFD));
252 Standard_Integer nSp, iRank;
253 Standard_Real aT, aT1, aT2, aTol=1e-7;
258 iRank=myDS->Rank(nED);
259 const TopoDS_Shape& aReference=(iRank==1) ? myDS->Tool() : myDS->Object();
261 BRepExtrema_DistShapeShape aDSS;
262 aDSS.LoadS1(aReference);
265 aF.Orientation(TopAbs_FORWARD);
267 BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aSplitEdges);
269 for (; aPBIt.More(); aPBIt.Next()) {
270 BOPTools_PaveBlock& aPB=aPBIt.Value();
273 const TopoDS_Edge& aSp=TopoDS::Edge(myDS->Shape(nSp));
275 aPB.Parameters(aT1, aT2);
276 aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
278 TopoDS_Edge aDERight, aSpRight;
282 BOPTools_Tools3D::OrientEdgeOnFace (aDE, aF, aDERight);
283 aSpRight.Orientation(aDERight.Orientation());
286 BRepAdaptor_Surface aBAS;
287 aBAS.Initialize (aDF, Standard_False);
289 if (aBAS.GetType()==GeomAbs_Sphere) {
290 Standard_Real aDt2D, aR, aDelta=1.e-14;
292 gp_Sphere aSphere=aBAS.Sphere();
295 aDt2D=acos (1.-4.*aTol/aR)+aDelta ;
297 BOPTools_Tools3D::PointNearEdge(aSpRight, aF, aT, aDt2D, aPx2DNear, aPxNear);
300 BOPTools_Tools3D::PointNearEdge(aSpRight, aF, aT, aPx2DNear, aPxNear);
306 TopAbs_ShapeEnum aTypeReference;
307 aTypeReference=aReference.ShapeType();
309 if (aTypeReference==TopAbs_SOLID) {
310 // ... \ Solid processing
311 const Handle(IntTools_Context)& aContext=myFiller->Context();
312 const TopoDS_Solid& aReferenceSolid=TopoDS::Solid(aReference);
313 BRepClass3d_SolidClassifier& SC=aContext->SolidClassifier(aReferenceSolid);
315 SC.Perform(aPxNear, aTol);
321 else if (aTypeReference==TopAbs_SHELL ||
322 aTypeReference==TopAbs_FACE) {
323 // ... \ Shell processing
324 TopoDS_Vertex aVxNear;
327 BB.MakeVertex(aVxNear, aPxNear, aTol);
329 aDSS.LoadS2(aVxNear);
334 Standard_Real aDist=aDSS.Value();
341 // unknown aTypeReference
345 BooleanOperations_StateOfShape aSt;
347 aSt=BOPTools_StateFiller::ConvertState(aState);
349 myDS->SetState(nSp, aSt);
352 //=======================================================================
353 // function: DoStates2D
355 //=======================================================================
356 void BOPTools_DEProcessor::DoStates2D (const Standard_Integer nED,
357 const Standard_Integer nFD)
361 const BOPTools_SplitShapesPool& aSplitShapesPool=myFiller->SplitShapesPool();
362 const BOPTools_ListOfPaveBlock& aSplitEdges=aSplitShapesPool(myDS->RefEdge(nED));
364 const TopoDS_Edge& aDE=TopoDS::Edge(myDS->Shape(nED));
365 const TopoDS_Face& aDF=TopoDS::Face(myDS->Shape(nFD));
367 Standard_Integer nSp, iRank;
368 Standard_Real aT, aT1, aT2;
373 iRank=myDS->Rank(nED);
374 const TopoDS_Shape& aReference=(iRank==1) ? myDS->Tool() : myDS->Object();
375 const TopoDS_Face& aFaceReference=TopoDS::Face(aReference);
378 aF.Orientation(TopAbs_FORWARD);
380 BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aSplitEdges);
382 for (; aPBIt.More(); aPBIt.Next()) {
383 BOPTools_PaveBlock& aPB=aPBIt.Value();
386 const TopoDS_Edge& aSp=TopoDS::Edge(myDS->Shape(nSp));
388 aPB.Parameters(aT1, aT2);
389 aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
391 TopoDS_Edge aDERight, aSpRight;
395 BOPTools_Tools3D::OrientEdgeOnFace (aDE, aF, aDERight);
396 aSpRight.Orientation(aDERight.Orientation());
398 BOPTools_Tools3D::PointNearEdge(aSpRight, aDF, aT, aPx2DNear, aPxNear);
400 Standard_Boolean bIsValidPoint;
401 TopAbs_State aState=TopAbs_OUT;
403 const Handle(IntTools_Context)& aContext=myFiller->Context();
404 bIsValidPoint=aContext->IsValidPointForFace(aPxNear, aFaceReference, 1.e-3);
410 BooleanOperations_StateOfShape aSt;
412 aSt=BOPTools_StateFiller::ConvertState(aState);
414 myDS->SetState(nSp, aSt);
418 //=======================================================================
419 // function: FillSplitEdgesPool
421 //=======================================================================
422 void BOPTools_DEProcessor::FillSplitEdgesPool (const Standard_Integer nED)
424 BOPTools_SplitShapesPool& aSplitShapesPool=myFiller->ChangeSplitShapesPool();
426 BOPTools_ListOfPaveBlock& aSplitEdges=aSplitShapesPool.ChangeValue(myDS->RefEdge(nED));
430 const BOPTools_PavePool& aPavePool=myFiller->PavePool();
431 BOPTools_PavePool* pPavePool=(BOPTools_PavePool*) &aPavePool;
432 BOPTools_PaveSet& aPaveSet= pPavePool->ChangeValue(myDS->RefEdge(nED));
434 BOPTools_PaveBlockIterator aPBIt(nED, aPaveSet);
435 for (; aPBIt.More(); aPBIt.Next()) {
436 BOPTools_PaveBlock& aPB=aPBIt.Value();
437 aSplitEdges.Append(aPB);
441 //=======================================================================
442 // function: MakeSplitEdges
444 //=======================================================================
445 void BOPTools_DEProcessor::MakeSplitEdges (const Standard_Integer nED,
446 const Standard_Integer nFD)
448 const BOPTools_SplitShapesPool& aSplitShapesPool=myFiller->SplitShapesPool();
449 const BOPTools_ListOfPaveBlock& aSplitEdges=aSplitShapesPool(myDS->RefEdge(nED));
451 Standard_Integer nV1, nV2, aNewShapeIndex;
452 Standard_Real t1, t2;
453 TopoDS_Edge aE, aESplit;
454 TopoDS_Vertex aV1, aV2;
456 const TopoDS_Edge aDE=TopoDS::Edge(myDS->Shape(nED));
457 const TopoDS_Face aDF=TopoDS::Face(myDS->Shape(nFD));
459 BOPTools_ListIteratorOfListOfPaveBlock aPBIt(aSplitEdges);
461 for (; aPBIt.More(); aPBIt.Next()) {
462 BOPTools_PaveBlock& aPB=aPBIt.Value();
464 const BOPTools_Pave& aPave1=aPB.Pave1();
467 aV1=TopoDS::Vertex(myDS->GetShape(nV1));
468 aV1.Orientation(TopAbs_FORWARD);
470 const BOPTools_Pave& aPave2=aPB.Pave2();
473 aV2=TopoDS::Vertex(myDS->GetShape(nV2));
474 aV2.Orientation(TopAbs_REVERSED);
476 MakeSplitEdge(aDE, aDF, aV1, t1, aV2, t2, aESplit);
478 // Add Split Part of the Original Edge to the DS
479 BooleanOperations_AncestorsSeqAndSuccessorsSeq anASSeq;
481 anASSeq.SetNewSuccessor(nV1);
482 anASSeq.SetNewOrientation(aV1.Orientation());
484 anASSeq.SetNewSuccessor(nV2);
485 anASSeq.SetNewOrientation(aV2.Orientation());
487 myDS->InsertShapeAndAncestorsSuccessors(aESplit, anASSeq);
488 aNewShapeIndex=myDS->NumberOfInsertedShapes();
489 myDS->SetState(aNewShapeIndex, BooleanOperations_UNKNOWN);
491 // Fill Split Set for the Original Edge
492 aPB.SetEdge(aNewShapeIndex);
496 //=======================================================================
497 // function: MakeSplitEdge
499 //=======================================================================
500 void BOPTools_DEProcessor::MakeSplitEdge (const TopoDS_Edge& aE,
501 const TopoDS_Face& aF,
502 const TopoDS_Vertex& aV1,
503 const Standard_Real aP1,
504 const TopoDS_Vertex& aV2,
505 const Standard_Real aP2,
506 TopoDS_Edge& aNewEdge)
508 Standard_Real aTol=1.e-7;
517 BB.Range(E, aF, aP1, aP2);
519 BB.Degenerated(E, Standard_True);
521 BB.UpdateEdge(E, aTol);
527 //=======================================================================
528 // function: FillPaveSet
530 //=======================================================================
531 void BOPTools_DEProcessor::FillPaveSet (const Standard_Integer nED,
532 const Standard_Integer nVD,
533 const Standard_Integer nFD,
534 BOPTools_ListOfPaveBlock& aLPB)
536 Standard_Boolean bIsDone, bXDir;
537 Standard_Integer nE, aNbPoints, j;
538 Standard_Real aTD1, aTD2, aT1, aT2, aTolInter, aX, aDT;
540 aDT=Precision::PConfusion();
542 BOPTools_PaveSet& aPaveSet= (myFiller->ChangePavePool()).ChangeValue(myDS->RefEdge(nED));
544 // Clear aPaveSet, aSplitEdges
545 aPaveSet.ChangeSet().Clear();
547 const TopoDS_Edge& aDE=TopoDS::Edge(myDS->Shape(nED));
548 const TopoDS_Face& aDF=TopoDS::Face(myDS->Shape(nFD));
550 // 2D Curve of degenerated edge on the face aDF
551 Handle(Geom2d_Curve) aC2DDE=BRep_Tool::CurveOnSurface(aDE, aDF, aTD1, aTD2);
553 // Choose direction for Degenerated Edge
554 gp_Pnt2d aP2d1, aP2d2;
555 aC2DDE->D0(aTD1, aP2d1);
556 aC2DDE->D0(aTD2, aP2d2);
558 bXDir=Standard_False;
559 if (fabs(aP2d1.Y()-aP2d2.Y()) < aDT){
563 // Prepare bounding Paves
564 BOPTools_Pave aPave1 (nVD, aTD1, BooleanOperations_UnknownInterference);
565 aPaveSet.Append(aPave1);
566 BOPTools_Pave aPave2 (nVD, aTD2, BooleanOperations_UnknownInterference);
567 aPaveSet.Append(aPave2);
570 BOPTools_ListIteratorOfListOfPaveBlock anIt(aLPB);
571 for (; anIt.More(); anIt.Next()) {
572 const BOPTools_PaveBlock& aPB=anIt.Value();
574 const TopoDS_Edge& aE=TopoDS::Edge(myDS->Shape(nE));
576 Handle(Geom2d_Curve) aC2D=BRep_Tool::CurveOnSurface(aE, aDF, aT1, aT2);
582 Geom2dAdaptor_Curve aGAC1, aGAC2;
584 aGAC1.Load(aC2DDE, aTD1, aTD2);
585 Handle(Geom2d_Line) aL2D= Handle(Geom2d_Line)::DownCast(aC2D);
586 if (!aL2D.IsNull()) {
590 aGAC2.Load(aC2D, aT1, aT2);
593 Geom2dInt_GInter aGInter(aGAC1, aGAC2, aTolInter, aTolInter);
595 bIsDone=aGInter.IsDone();
597 aNbPoints=aGInter.NbPoints();
599 for (j=1; j<=aNbPoints; ++j) {
600 gp_Pnt2d aP2D=aGInter.Point(j).Value();
602 aX=(bXDir) ? aP2D.X(): aP2D.Y();
604 if (fabs (aX-aTD1) < aDT || fabs (aX-aTD2) < aDT) {
607 if (aX < aTD1 || aX > aTD2) {
611 Standard_Boolean bRejectFlag=Standard_False;
612 const BOPTools_ListOfPave& aListOfPave=aPaveSet.Set();
613 BOPTools_ListIteratorOfListOfPave aPaveIt(aListOfPave);
614 for (; aPaveIt.More(); aPaveIt.Next()) {
615 const BOPTools_Pave& aPavex=aPaveIt.Value();
616 Standard_Real aXx=aPavex.Param();
617 if (fabs (aX-aXx) < aDT) {
618 bRejectFlag=Standard_True;
626 BOPTools_Pave aPave(nVD, aX, BooleanOperations_UnknownInterference);
627 aPaveSet.Append(aPave);
634 //=======================================================================
635 // function: FindPaveBlocks
637 //=======================================================================
638 void BOPTools_DEProcessor::FindPaveBlocks(const Standard_Integer ,
639 const Standard_Integer nVD,
640 const Standard_Integer nFD,
641 BOPTools_ListOfPaveBlock& aLPBOut)
644 BOPTools_CArray1OfSSInterference& aFFs=(myFiller->InterfPool())->SSInterferences();
646 BOPTools_ListIteratorOfListOfPaveBlock anIt;
647 Standard_Integer i, aNb, nF2, nSp, nV;
649 //ZZ const TopoDS_Edge& aDE=TopoDS::Edge(myDS->Shape(nED));
652 for (i=1; i<=aNb; i++) {
653 BOPTools_SSInterference& aFF=aFFs(i);
655 nF2=aFF.OppositeIndex(nFD);
661 const BOPTools_ListOfPaveBlock& aLPBSplits=aFF.PaveBlocks();
662 anIt.Initialize(aLPBSplits);
663 for (; anIt.More(); anIt.Next()) {
664 const BOPTools_PaveBlock& aPBSp=anIt.Value();
667 const BOPTools_Pave& aPave1=aPBSp.Pave1();
670 aLPBOut.Append(aPBSp);
674 const BOPTools_Pave& aPave2=aPBSp.Pave2();
677 aLPBOut.Append(aPBSp);
683 Standard_Integer j, aNbCurves;
684 BOPTools_SequenceOfCurves& aSC=aFF.Curves();
685 aNbCurves=aSC.Length();
687 for (j=1; j<=aNbCurves; j++) {
688 const BOPTools_Curve& aBC=aSC(j);
689 const BOPTools_ListOfPaveBlock& aLPBSe=aBC.NewPaveBlocks();
691 anIt.Initialize(aLPBSe);
692 for (; anIt.More(); anIt.Next()) {
693 const BOPTools_PaveBlock& aPBSe=anIt.Value();
695 const BOPTools_Pave& aPv1=aPBSe.Pave1();
698 aLPBOut.Append(aPBSe);
702 const BOPTools_Pave& aPv2=aPBSe.Pave2();
705 aLPBOut.Append(aPBSe);
711 } // for (i=1; i<=aNb; i++) Next FF interference