1 // Created on: 2004-09-02
2 // Copyright (c) 2004-2012 OPEN CASCADE SAS
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
19 #include <BOPAlgo_ArgumentAnalyzer.ixx>
21 #include <Standard_ErrorHandler.hxx>
22 #include <Standard_Failure.hxx>
24 #include <TopExp_Explorer.hxx>
25 #include <BRep_Builder.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRepExtrema_DistShapeShape.hxx>
29 #include <TopoDS_Iterator.hxx>
31 #include <TopoDS_Vertex.hxx>
32 #include <TopoDS_Edge.hxx>
33 #include <TopoDS_Wire.hxx>
34 #include <TopoDS_Shell.hxx>
35 #include <TopoDS_Solid.hxx>
36 #include <BOPCol_ListOfShape.hxx>
37 #include <BOPCol_SequenceOfShape.hxx>
38 #include <BOPCol_MapOfShape.hxx>
40 #include <TColStd_Array2OfBoolean.hxx>
42 #include <IntTools_Range.hxx>
43 #include <IntTools_EdgeEdge.hxx>
44 #include <IntTools_CommonPrt.hxx>
46 #include <BOPAlgo_Operation.hxx>
47 #include <BOPAlgo_CheckerSI.hxx>
48 #include <BOPAlgo_BuilderFace.hxx>
50 #include <BOPDS_DS.hxx>
51 #include <BOPDS_VectorOfInterfVV.hxx>
52 #include <BOPDS_VectorOfInterfVE.hxx>
53 #include <BOPDS_VectorOfInterfEE.hxx>
54 #include <BOPDS_VectorOfInterfVF.hxx>
55 #include <BOPDS_VectorOfInterfEF.hxx>
56 #include <BOPDS_VectorOfInterfFF.hxx>
58 #include <BOPInt_Context.hxx>
60 #include <BOPTools_AlgoTools3D.hxx>
61 #include <BOPTools_AlgoTools.hxx>
62 #include <BOPCol_ListOfShape.hxx>
64 // ================================================================================
65 // function: Constructor
67 // ================================================================================
68 BOPAlgo_ArgumentAnalyzer::BOPAlgo_ArgumentAnalyzer() :
69 myStopOnFirst(Standard_False),
70 myOperation(BOPAlgo_UNKNOWN),
71 myArgumentTypeMode(Standard_False),
72 mySelfInterMode(Standard_False),
73 mySmallEdgeMode(Standard_False),
74 myRebuildFaceMode(Standard_False),
75 myTangentMode(Standard_False),
76 myMergeVertexMode(Standard_False),
77 myMergeEdgeMode(Standard_False),
78 myEmpty1(Standard_False),
79 myEmpty2(Standard_False)
80 // myMergeFaceMode(Standard_False)
84 // ================================================================================
85 // function: SetShape1
87 // ================================================================================
88 void BOPAlgo_ArgumentAnalyzer::SetShape1(const TopoDS_Shape & TheShape)
93 // ================================================================================
94 // function: SetShape2
96 // ================================================================================
97 void BOPAlgo_ArgumentAnalyzer::SetShape2(const TopoDS_Shape & TheShape)
102 // ================================================================================
103 // function: GetShape1
105 // ================================================================================
106 const TopoDS_Shape & BOPAlgo_ArgumentAnalyzer::GetShape1() const
111 // ================================================================================
112 // function: GetShape2
114 // ================================================================================
115 const TopoDS_Shape & BOPAlgo_ArgumentAnalyzer::GetShape2() const
120 // ================================================================================
121 // function: OperationType
123 // ================================================================================
124 BOPAlgo_Operation& BOPAlgo_ArgumentAnalyzer::OperationType()
129 // ================================================================================
130 // function: StopOnFirstFaulty
132 // ================================================================================
133 Standard_Boolean & BOPAlgo_ArgumentAnalyzer::StopOnFirstFaulty()
135 return myStopOnFirst;
138 // ================================================================================
141 // ================================================================================
142 void BOPAlgo_ArgumentAnalyzer::Prepare()
144 Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull();
146 myEmpty1 = BOPTools_AlgoTools3D::IsEmptyShape(myShape1);
149 myEmpty2 = BOPTools_AlgoTools3D::IsEmptyShape(myShape2);
152 // ================================================================================
155 // ================================================================================
156 void BOPAlgo_ArgumentAnalyzer::Perform()
164 if(myArgumentTypeMode) {
168 if(mySelfInterMode) {
169 TestSelfInterferences();
172 if(mySmallEdgeMode) {
173 if(!(!myResult.IsEmpty() && myStopOnFirst))
177 if(myRebuildFaceMode) {
178 if(!(!myResult.IsEmpty() && myStopOnFirst))
183 if(!(!myResult.IsEmpty() && myStopOnFirst))
187 if(myMergeVertexMode) {
188 if(!(!myResult.IsEmpty() && myStopOnFirst))
192 if(myMergeEdgeMode) {
193 if(!(!myResult.IsEmpty() && myStopOnFirst))
197 catch(Standard_Failure) {
198 BOPAlgo_CheckResult aResult;
199 aResult.SetCheckStatus(BOPAlgo_CheckUnknown);
200 myResult.Append(aResult);
204 // ================================================================================
205 // function: HasFaulty
207 // ================================================================================
208 Standard_Boolean BOPAlgo_ArgumentAnalyzer::HasFaulty() const
210 return ( !myResult.IsEmpty());
213 // ================================================================================
214 // function: GetCheckResult
216 // ================================================================================
217 const BOPAlgo_ListOfCheckResult& BOPAlgo_ArgumentAnalyzer::GetCheckResult() const
222 // ================================================================================
223 // function: TestTypes
225 // ================================================================================
226 void BOPAlgo_ArgumentAnalyzer::TestTypes()
228 Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull();
231 BOPAlgo_CheckResult aResult;
232 aResult.SetCheckStatus(BOPAlgo_BadType);
233 myResult.Append(aResult);
238 if((isS1 && !isS2) || (!isS1 && isS2)) {
239 Standard_Boolean bIsEmpty = (isS1) ? myEmpty2 : myEmpty1;
241 if(bIsEmpty || myOperation!=BOPAlgo_UNKNOWN) {
242 const TopoDS_Shape & aS = (isS1) ? myShape2 : myShape1;
243 BOPAlgo_CheckResult aResult;
244 aResult.SetShape1(aS);
245 aResult.SetCheckStatus(BOPAlgo_BadType);
246 myResult.Append(aResult);
250 // two shapes check (begin)
252 if(myEmpty1 || myEmpty2) {
253 BOPAlgo_CheckResult aResult;
254 if(myEmpty1 && myEmpty2) {
255 aResult.SetShape1(myShape1);
256 aResult.SetShape2(myShape2);
259 const TopoDS_Shape & aS = myEmpty1 ? myShape1 : myShape2;
261 aResult.SetShape1(aS);
263 aResult.SetShape2(aS);
265 aResult.SetCheckStatus(BOPAlgo_BadType);
266 myResult.Append(aResult);
270 Standard_Integer aDim1, aDim2;
271 Standard_Boolean bBadTypes = Standard_False;
273 aDim1 = BOPTools_AlgoTools::Dimension(myShape1);
274 aDim2 = BOPTools_AlgoTools::Dimension(myShape2);
276 if (myOperation == BOPAlgo_FUSE ||
277 myOperation == BOPAlgo_CUT21) {
278 bBadTypes = Standard_True;
281 else if (aDim1 > aDim2) {
282 if (myOperation == BOPAlgo_FUSE ||
283 myOperation == BOPAlgo_CUT) {
284 bBadTypes = Standard_True;
288 BOPAlgo_CheckResult aResult;
289 aResult.SetShape1(myShape1);
290 aResult.SetShape2(myShape2);
291 aResult.SetCheckStatus(BOPAlgo_BadType);
292 myResult.Append(aResult);
297 // ================================================================================
298 // function: TestSelfInterferences
300 // ================================================================================
301 void BOPAlgo_ArgumentAnalyzer::TestSelfInterferences()
303 Standard_Integer ii = 0, j;
304 Standard_Boolean bSelfInt;
306 for(ii = 0; ii < 2; ii++) {
307 TopoDS_Shape aS = (ii == 0) ? myShape1 : myShape2;
312 Standard_Boolean bIsEmpty = (ii == 0) ? myEmpty1 : myEmpty2;
317 BOPAlgo_CheckerSI aChecker;
318 BOPCol_ListOfShape anArgs;
320 aChecker.SetArguments(anArgs);
323 Standard_Integer iErr = aChecker.ErrorStatus();
325 const BOPDS_PDS& theDS = aChecker.PDS();
326 BOPDS_VectorOfInterfVV& aVVs=theDS->InterfVV();
327 BOPDS_VectorOfInterfVE& aVEs=theDS->InterfVE();
328 BOPDS_VectorOfInterfEE& aEEs=theDS->InterfEE();
329 BOPDS_VectorOfInterfVF& aVFs=theDS->InterfVF();
330 BOPDS_VectorOfInterfEF& aEFs=theDS->InterfEF();
331 BOPDS_VectorOfInterfFF& aFFs=theDS->InterfFF();
333 Standard_Integer aNb[6] = {aVVs.Extent(), aVEs.Extent(), aEEs.Extent(),
334 aVFs.Extent(), aEFs.Extent(), aFFs.Extent()};
336 Standard_Integer ind = 0;
337 for (Standard_Integer aTypeInt = 0; aTypeInt < 6; ++aTypeInt) {
338 for (Standard_Integer i = 0; i < aNb[aTypeInt]; ++i) {
339 BOPDS_Interf* aInt = (aTypeInt==0) ? (BOPDS_Interf*)(&aVVs(i)) :
340 ((aTypeInt==1) ? (BOPDS_Interf*)(&aVEs(i)) :
341 ((aTypeInt==2) ? (BOPDS_Interf*)(&aEEs(i)) :
342 ((aTypeInt==3) ? (BOPDS_Interf*)(&aVFs(i)) :
343 ((aTypeInt==4) ? (BOPDS_Interf*)(&aEFs(i)) : (BOPDS_Interf*)(&aFFs(i))))));
345 Standard_Integer nI1 = aInt->Index1();
346 Standard_Integer nI2 = aInt->Index2();
352 BOPDS_InterfEF& aEF=aEFs(i);
353 if (aEF.CommonPart().Type()==TopAbs_SHAPE) {
358 const TopoDS_Shape& aS1 = theDS->Shape(nI1);
359 const TopoDS_Shape& aS2 = theDS->Shape(nI2);
362 bSelfInt = Standard_False;
363 BOPDS_InterfFF& aFF = aFFs(i);
364 BOPDS_VectorOfPoint& aVP=aFF.ChangePoints();
365 Standard_Integer aNbP=aVP.Extent();
366 BOPDS_VectorOfCurve& aVC=aFF.ChangeCurves();
367 Standard_Integer aNbC=aVC.Extent();
368 if (!aNbP && !aNbC) {
371 for (j=0; j<aNbC; ++j) {
372 BOPDS_Curve& aNC=aVC(j);
373 BOPDS_ListOfPaveBlock& aLPBC=aNC.ChangePaveBlocks();
374 if (aLPBC.Extent()) {
375 bSelfInt = Standard_True;
384 BOPAlgo_CheckResult aResult;
386 aResult.SetShape1(myShape1);
388 aResult.SetShape2(myShape2);
391 aResult.AddFaultyShape1(aS1);
392 aResult.AddFaultyShape1(aS2);
395 aResult.AddFaultyShape2(aS1);
396 aResult.AddFaultyShape2(aS2);
398 aResult.SetCheckStatus(BOPAlgo_SelfIntersect);
399 myResult.Append(aResult);
403 BOPAlgo_CheckResult aResult;
405 aResult.SetShape1(myShape1);
407 aResult.SetShape2(myShape2);
410 aResult.AddFaultyShape1(myShape1);
413 aResult.AddFaultyShape2(myShape2);
415 aResult.SetCheckStatus(BOPAlgo_OperationAborted);
416 myResult.Append(aResult);
422 // ================================================================================
423 // function: TestSmallEdge
425 // ================================================================================
426 void BOPAlgo_ArgumentAnalyzer::TestSmallEdge()
428 Standard_Integer i = 0;
429 BRepExtrema_DistShapeShape aDist;
430 Handle(BOPInt_Context) aCtx;
432 aCtx = new BOPInt_Context;
434 for(i = 0; i < 2; i++) {
435 TopoDS_Shape aS = (i == 0) ? myShape1 : myShape2;
440 TopExp_Explorer anExp(aS, TopAbs_EDGE);
442 for(; anExp.More(); anExp.Next()) {
443 TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
445 if(BOPTools_AlgoTools::IsMicroEdge(anEdge, aCtx)) {
446 Standard_Boolean bKeepResult = Standard_True;
448 if(myOperation == BOPAlgo_SECTION) {
449 TopoDS_Shape anOtherS = (i == 0) ? myShape2 : myShape1;
451 if(!anOtherS.IsNull()) {
452 aDist.LoadS2(anOtherS);
454 Standard_Boolean bVertexIsOnShape = Standard_False;
455 Standard_Integer ii = 0;
456 TopExp_Explorer anExpV(anEdge, TopAbs_VERTEX);
458 for(; anExpV.More(); anExpV.Next()) {
459 TopoDS_Shape aV = anExpV.Current();
466 for(ii = 1; ii <= aDist.NbSolution(); ii++) {
467 Standard_Real aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aV));
468 TopoDS_Shape aSupportShape = aDist.SupportOnShape2(ii);
470 switch(aSupportShape.ShapeType()) {
471 case TopAbs_VERTEX: {
472 aTolerance += BRep_Tool::Tolerance(TopoDS::Vertex(aSupportShape));
476 aTolerance += BRep_Tool::Tolerance(TopoDS::Edge(aSupportShape));
480 aTolerance += BRep_Tool::Tolerance(TopoDS::Face(aSupportShape));
487 if(aDist.Value() < aTolerance) {
488 bVertexIsOnShape = Standard_True;
495 if(!bVertexIsOnShape) {
496 bKeepResult = Standard_False;
502 BOPAlgo_CheckResult aResult;
505 aResult.SetShape1(myShape1);
506 aResult.AddFaultyShape1(anEdge);
509 aResult.SetShape2(myShape2);
510 aResult.AddFaultyShape2(anEdge);
513 aResult.SetCheckStatus(BOPAlgo_TooSmallEdge);
514 myResult.Append(aResult);
525 // ================================================================================
526 // function: TestRebuildFace
528 // ================================================================================
529 void BOPAlgo_ArgumentAnalyzer::TestRebuildFace()
531 if((myOperation == BOPAlgo_SECTION) ||
532 (myOperation == BOPAlgo_UNKNOWN))
534 Standard_Integer i = 0;
536 for(i = 0; i < 2; i++) {
537 TopoDS_Shape aS = (i == 0) ? myShape1 : myShape2;
542 TopExp_Explorer anExp(aS, TopAbs_FACE);
543 BOPCol_ListOfShape aLS;
545 for(; anExp.More(); anExp.Next()) {
546 TopoDS_Face aFace = TopoDS::Face(anExp.Current());
548 TopoDS_Face aFF = aFace;
549 aFF.Orientation(TopAbs_FORWARD);
550 TopExp_Explorer anExpE(aFF, TopAbs_EDGE);
551 Standard_Integer nbstartedges = 0;
554 for(; anExpE.More(); anExpE.Next()) {
555 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&anExpE.Current()));
556 TopAbs_Orientation anOriE=aE.Orientation();
558 if (anOriE==TopAbs_INTERNAL) {
560 aEE.Orientation(TopAbs_FORWARD);
562 aEE.Orientation(TopAbs_REVERSED);
570 BOPAlgo_BuilderFace aBF;
574 const BOPCol_ListOfShape& aLF = aBF.Areas();
575 Standard_Boolean bBadFace = Standard_False;
577 if(aLF.Extent() != 1) {
578 bBadFace = Standard_True;
581 Standard_Integer nbedgeused = 0;
582 anExpE.Init(aLF.First(), TopAbs_EDGE);
584 for(; anExpE.More(); anExpE.Next(), nbedgeused++);
586 if(nbstartedges != nbedgeused) {
587 bBadFace = Standard_True;
592 BOPAlgo_CheckResult aResult;
595 aResult.SetShape1(myShape1);
596 aResult.AddFaultyShape1(aFace);
599 aResult.SetShape2(myShape2);
600 aResult.AddFaultyShape2(aFace);
603 aResult.SetCheckStatus(BOPAlgo_NonRecoverableFace);
604 myResult.Append(aResult);
614 // ================================================================================
615 // function: TestTangent
617 // ================================================================================
618 void BOPAlgo_ArgumentAnalyzer::TestTangent()
623 // ================================================================================
624 // function: TestMergeSubShapes
626 // ================================================================================
627 void BOPAlgo_ArgumentAnalyzer::TestMergeSubShapes(const TopAbs_ShapeEnum theType)
629 if(myShape1.IsNull() || myShape2.IsNull())
632 if (myEmpty1 || myEmpty2)
635 BOPAlgo_CheckStatus aStatus = BOPAlgo_CheckUnknown;
638 case TopAbs_VERTEX: {
639 aStatus = BOPAlgo_IncompatibilityOfVertex;
643 aStatus = BOPAlgo_IncompatibilityOfEdge;
647 aStatus = BOPAlgo_IncompatibilityOfFace;
653 TopExp_Explorer anExp1(myShape1, theType);
654 TopExp_Explorer anExp2(myShape2, theType);
655 BOPCol_SequenceOfShape aSeq1, aSeq2;
656 BOPCol_MapOfShape aMap1, aMap2;
658 for(; anExp1.More(); anExp1.Next()) {
659 TopoDS_Shape aS1 = anExp1.Current();
661 if(aMap1.Contains(aS1))
667 for(; anExp2.More(); anExp2.Next()) {
668 TopoDS_Shape aS2 = anExp2.Current();
669 if(aMap2.Contains(aS2))
675 TColStd_Array2OfBoolean anArrayOfFlag(1, aSeq1.Length(), 1, aSeq2.Length());
676 Standard_Integer i = 0, j = 0;
677 for(i = 1; i <= aSeq1.Length(); i++)
678 for(j = 1; j <= aSeq2.Length(); j++)
679 anArrayOfFlag.SetValue(i, j, Standard_False);
681 for(i = 1; i <= aSeq1.Length(); i++) {
682 TopoDS_Shape aS1 = aSeq1.Value(i);
683 BOPCol_ListOfShape aListOfS2;
684 Standard_Integer nbs = 0;
686 for(j = 1; j <= aSeq2.Length(); j++) {
687 TopoDS_Shape aS2 = aSeq2.Value(j);
688 Standard_Boolean bIsEqual = Standard_False;
690 if(theType == TopAbs_VERTEX) {
692 TopoDS_Vertex aV1 = TopoDS::Vertex(aS1);
693 TopoDS_Vertex aV2 = TopoDS::Vertex(aS2);
694 gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
695 gp_Pnt aP2 = BRep_Tool::Pnt(aV2);
696 Standard_Real aDist = aP1.Distance(aP2);
698 if(aDist <= (BRep_Tool::Tolerance(aV1) + BRep_Tool::Tolerance(aV2))) {
699 bIsEqual = Standard_True;
702 else if(theType == TopAbs_EDGE) {
703 Standard_Integer aDiscretize = 30;
704 Standard_Real aDeflection = 0.01;
705 TopoDS_Edge aE1 = TopoDS::Edge(aS1);
706 TopoDS_Edge aE2 = TopoDS::Edge(aS2);
708 IntTools_EdgeEdge aEE;
711 aEE.SetTolerance1 (BRep_Tool::Tolerance(aE1));
712 aEE.SetTolerance2 (BRep_Tool::Tolerance(aE2));
713 aEE.SetDiscretize (aDiscretize);
714 aEE.SetDeflection (aDeflection);
716 Standard_Real f = 0., l = 0.;
717 BRep_Tool::Range(aE1, f, l);
720 BRep_Tool::Range(aE2, f, l);
726 const IntTools_SequenceOfCommonPrts& aCPrts = aEE.CommonParts();
727 Standard_Integer ii = 0;
729 for (ii = 1; ii <= aCPrts.Length(); ii++) {
730 const IntTools_CommonPrt& aCPart = aCPrts(ii);
732 if (aCPart.Type() == TopAbs_EDGE) {
733 bIsEqual = Standard_True;
738 else if(theType == TopAbs_FACE) {
739 // not yet implemented!
743 anArrayOfFlag.SetValue(i, j, Standard_True );
744 aListOfS2.Append(aS2);
750 BOPAlgo_CheckResult aResult;
752 aResult.SetShape1(myShape1);
753 aResult.SetShape2(myShape2);
754 aResult.AddFaultyShape1(aS1);
755 BOPCol_ListIteratorOfListOfShape anIt(aListOfS2);
757 for(; anIt.More(); anIt.Next()) {
758 aResult.AddFaultyShape2(anIt.Value());
761 aResult.SetCheckStatus(aStatus);
762 myResult.Append(aResult);
770 for(i = 1; i <= aSeq2.Length(); i++) {
771 TopoDS_Shape aS2 = aSeq2.Value(i);
772 BOPCol_ListOfShape aListOfS1;
773 Standard_Integer nbs = 0;
775 for(j = 1; j <= aSeq1.Length(); j++) {
776 TopoDS_Shape aS1 = aSeq1.Value(j);
778 if(anArrayOfFlag.Value(j, i)) {
779 aListOfS1.Append(aS1);
785 BOPAlgo_CheckResult aResult;
787 aResult.SetShape1(myShape1);
788 aResult.SetShape2(myShape2);
789 BOPCol_ListIteratorOfListOfShape anIt(aListOfS1);
791 for(; anIt.More(); anIt.Next()) {
792 aResult.AddFaultyShape1(anIt.Value());
794 aResult.AddFaultyShape2(aS2);
796 aResult.SetCheckStatus(aStatus);
797 myResult.Append(aResult);
806 // ================================================================================
807 // function: TestMergeVertex
809 // ================================================================================
810 void BOPAlgo_ArgumentAnalyzer::TestMergeVertex()
812 TestMergeSubShapes(TopAbs_VERTEX);
815 // ================================================================================
816 // function: TestMergeEdge
818 // ================================================================================
819 void BOPAlgo_ArgumentAnalyzer::TestMergeEdge()
821 TestMergeSubShapes(TopAbs_EDGE);
824 // ================================================================================
825 // function: TestMergeFace
827 // ================================================================================
828 // void BOPAlgo_ArgumentAnalyzer::TestMergeFace()