0026619: Tolerances of operands are modified using bop
[occt.git] / src / BRepAlgoAPI / BRepAlgoAPI_BooleanOperation.cxx
1 // Created on: 1993-10-15
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BOPAlgo_BOP.hxx>
19 #include <BOPAlgo_PaveFiller.hxx>
20 #include <BOPAlgo_Section.hxx>
21 #include <BOPDS_Curve.hxx>
22 #include <BOPDS_DS.hxx>
23 #include <BOPDS_Interf.hxx>
24 #include <BOPDS_ListOfPaveBlock.hxx>
25 #include <BOPDS_PDS.hxx>
26 #include <BOPDS_VectorOfCurve.hxx>
27 #include <BRepAlgoAPI_BooleanOperation.hxx>
28 #include <BRepAlgoAPI_Check.hxx>
29 #include <BRepLib_FuseEdges.hxx>
30 #include <BRepTools.hxx>
31 #include <OSD_File.hxx>
32 #include <TCollection_AsciiString.hxx>
33 #include <TopExp.hxx>
34 #include <TopoDS_Shape.hxx>
35 #include <TopTools_DataMapOfIntegerListOfShape.hxx>
36 #include <TopTools_DataMapOfIntegerShape.hxx>
37 #include <TopTools_IndexedMapOfShape.hxx>
38 #include <TopTools_ListIteratorOfListOfShape.hxx>
39 #include <TopTools_ListOfShape.hxx>
40 #include <TopTools_MapOfShape.hxx>
41
42 #include <stdio.h>
43 ///XXXXXXXXXX
44 //XXXXXXXXXX
45 //XXXX
46 //=======================================================================
47 //class : BRepAlgoAPI_DumpOper
48 //purpose  : 
49 //=======================================================================
50 class BRepAlgoAPI_DumpOper {
51  public:
52   BRepAlgoAPI_DumpOper() :
53     myIsDump(Standard_False),
54     myIsDumpArgs(Standard_False),
55     myIsDumpRes(Standard_False)  {
56       char *pathdump = getenv("CSF_DEBUG_BOP");
57       myIsDump=(pathdump!=NULL);
58       myPath=pathdump;
59   };
60   //
61   virtual ~BRepAlgoAPI_DumpOper() {
62   };
63   //
64   Standard_Boolean IsDump()const {
65     return myIsDump;
66   };
67   //
68   void SetIsDumpArgs(const Standard_Boolean bFlag) {
69     myIsDumpArgs=bFlag;
70   }
71   //
72   Standard_Boolean IsDumpArgs()const {
73     return myIsDumpArgs;
74   };
75   //
76   void SetIsDumpRes(const Standard_Boolean bFlag) {
77     myIsDumpRes=bFlag;
78   };
79   //
80   Standard_Boolean IsDumpRes()const {
81     return myIsDumpRes;
82   };
83   //
84   void Dump(
85             const TopoDS_Shape& theShape1,
86             const TopoDS_Shape& theShape2,
87             const TopoDS_Shape& theResult,
88             BOPAlgo_Operation theOperation);
89   //
90  protected:
91   Standard_Boolean myIsDump;
92   Standard_Boolean myIsDumpArgs;
93   Standard_Boolean myIsDumpRes;
94   Standard_CString myPath;
95 };
96 //XXXX
97 //=======================================================================
98 //function : BRepAlgoAPI_BooleanOperation
99 //purpose  : 
100 //=======================================================================
101 BRepAlgoAPI_BooleanOperation::BRepAlgoAPI_BooleanOperation()
102 :
103   BRepAlgoAPI_BuilderAlgo(),  
104   myOperation(BOPAlgo_UNKNOWN),
105   myBuilderCanWork(Standard_False),
106   myFuseEdges(Standard_False)
107
108   myEntryType=1;
109 }
110 //=======================================================================
111 //function : BRepAlgoAPI_BooleanOperation
112 //purpose  : 
113 //=======================================================================
114 BRepAlgoAPI_BooleanOperation::BRepAlgoAPI_BooleanOperation
115   (const BOPAlgo_PaveFiller& aPF)
116 :
117   BRepAlgoAPI_BuilderAlgo(aPF),  
118   myOperation(BOPAlgo_UNKNOWN),
119   myBuilderCanWork(Standard_False),
120   myFuseEdges(Standard_False)
121
122   myEntryType=0;
123 }
124 //=======================================================================
125 //function : BRepAlgoAPI_BooleanOperation
126 //purpose  : 
127 //=======================================================================
128 BRepAlgoAPI_BooleanOperation::BRepAlgoAPI_BooleanOperation
129   (const TopoDS_Shape& aS1, 
130    const TopoDS_Shape& aS2,
131    const BOPAlgo_Operation anOp)
132
133   BRepAlgoAPI_BuilderAlgo(),
134   myOperation(anOp),
135   myBuilderCanWork(Standard_False),
136   myFuseEdges(Standard_False)
137 {
138   myEntryType=1;
139   //
140   myArguments.Append(aS1);
141   myTools.Append(aS2);
142 }
143 //=======================================================================
144 //function : BRepAlgoAPI_BooleanOperation
145 //purpose  : 
146 //=======================================================================
147 BRepAlgoAPI_BooleanOperation::BRepAlgoAPI_BooleanOperation
148   (const TopoDS_Shape& aS1, 
149    const TopoDS_Shape& aS2,
150    const BOPAlgo_PaveFiller& aPF,
151    const BOPAlgo_Operation anOp)
152
153   BRepAlgoAPI_BuilderAlgo(aPF),
154   myOperation(anOp),
155   myBuilderCanWork(Standard_False),
156   myFuseEdges(Standard_False)
157
158   myEntryType=0;
159   //
160   myArguments.Append(aS1);
161   myTools.Append(aS2);
162   //
163   myDSFiller=(BOPAlgo_PaveFiller*)&aPF;
164 }
165 //=======================================================================
166 //function : ~
167 //purpose  : 
168 //=======================================================================
169 BRepAlgoAPI_BooleanOperation::~BRepAlgoAPI_BooleanOperation()
170 {
171   Clear();
172 }
173 //=======================================================================
174 //function : Clear
175 //purpose  : 
176 //=======================================================================
177 void BRepAlgoAPI_BooleanOperation::Clear()
178 {
179   BRepAlgoAPI_BuilderAlgo::Clear();
180  
181   myModifFaces.Clear();
182   myEdgeMap.Clear();
183 }
184 //=======================================================================
185 //function : SetTools
186 //purpose  : 
187 //=======================================================================
188 void BRepAlgoAPI_BooleanOperation::SetTools
189   (const TopTools_ListOfShape& theLS)
190 {
191   myTools=theLS;
192 }
193 //=======================================================================
194 //function : Tools
195 //purpose  : 
196 //=======================================================================
197 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Tools()const
198 {
199   return myTools;
200 }
201 //=======================================================================
202 //function : SetOperation
203 //purpose  : 
204 //=======================================================================
205 void BRepAlgoAPI_BooleanOperation::SetOperation 
206   (const BOPAlgo_Operation anOp)
207 {
208   myOperation=anOp;
209 }
210 //=======================================================================
211 //function : Operation
212 //purpose  : 
213 //=======================================================================
214 BOPAlgo_Operation BRepAlgoAPI_BooleanOperation::Operation()const
215 {
216   return myOperation;
217 }
218 //=======================================================================
219 //function : Shape1
220 //purpose  : 
221 //=======================================================================
222 const TopoDS_Shape& BRepAlgoAPI_BooleanOperation::Shape1() const 
223 {
224   return myArguments.First();
225 }
226 //=======================================================================
227 //function : Shape2
228 //purpose  : 
229 //=======================================================================
230 const TopoDS_Shape& BRepAlgoAPI_BooleanOperation::Shape2() const 
231 {
232   return myTools.First();
233 }
234 //=======================================================================
235 //function : BuilderCanWork
236 //purpose  : 
237 //=======================================================================
238 Standard_Boolean BRepAlgoAPI_BooleanOperation::BuilderCanWork() const
239 {
240   return myBuilderCanWork;
241 }
242 //=======================================================================
243 //function : FuseEdges
244 //purpose  : 
245 //=======================================================================
246 Standard_Boolean BRepAlgoAPI_BooleanOperation::FuseEdges ()const
247 {
248   return myFuseEdges;
249 }
250 //=======================================================================
251 //function : SetAttributes
252 //purpose  : 
253 //=======================================================================
254 void BRepAlgoAPI_BooleanOperation::SetAttributes()
255 {
256 }
257 //=======================================================================
258 //function : Build2
259 //purpose  : 
260 //=======================================================================
261 void BRepAlgoAPI_BooleanOperation::Build()
262 {
263   Standard_Integer iErr, aNbArgs, aNbTools;  
264   BRepAlgoAPI_DumpOper aDumpOper;
265   //
266   myBuilderCanWork=Standard_False;
267   myErrorStatus=0;
268   NotDone();
269   //
270   aNbArgs=myArguments.Extent();
271   aNbTools=myTools.Extent();
272   if (aNbArgs<1 && aNbTools<1) {
273     myErrorStatus=2;
274     return;
275   }
276   if (myOperation==BOPAlgo_UNKNOWN) {
277     myErrorStatus=6;
278     return;
279   }
280   //
281   //-----------------------------------------------
282   TopTools_ListOfShape aLS;
283   TopTools_ListIteratorOfListOfShape aIt;
284   //
285   aIt.Initialize(myArguments);
286   for (; aIt.More(); aIt.Next()) {
287     const TopoDS_Shape& aS = aIt.Value();
288     aLS.Append(aS);
289   }
290   aIt.Initialize(myTools);
291   for (; aIt.More(); aIt.Next()) {
292     const TopoDS_Shape& aS = aIt.Value();
293     aLS.Append(aS);
294   }
295   //-----------------------------------------------
296   //
297   if (myEntryType) {
298     if (myDSFiller) {
299       delete myDSFiller;
300     }
301     myDSFiller=new BOPAlgo_PaveFiller(myAllocator);
302     //
303     myDSFiller->SetArguments(aLS);
304     //
305     myDSFiller->SetRunParallel(myRunParallel);
306     myDSFiller->SetProgressIndicator(myProgressIndicator);
307     myDSFiller->SetFuzzyValue(myFuzzyValue);
308     myDSFiller->SetNonDestructive(myNonDestructive);
309     //
310     SetAttributes();
311     //
312     myDSFiller->Perform(); 
313     iErr=myDSFiller->ErrorStatus();
314     if (iErr) {
315       myErrorStatus=100+iErr;
316       return;
317     }
318   }// if (myEntryType) {
319   //
320   //XXXX
321   const TopoDS_Shape& aS1 = myArguments.First();
322   const TopoDS_Shape& aS2 = myTools.First();
323   if (aDumpOper.IsDump()) {
324     BRepAlgoAPI_Check aChekArgs(aS1, aS2, myOperation);
325     aDumpOper.SetIsDumpArgs(!aChekArgs.IsValid());
326   }
327   //XXXX
328   // 
329   if (myBuilder) {
330     delete myBuilder;
331   }
332   //
333   BOPAlgo_BOP *pBOP;
334   //
335   if(myOperation==BOPAlgo_SECTION) {
336     myBuilder=new BOPAlgo_Section(myAllocator);
337     myBuilder->SetArguments(aLS);
338   }
339   else{
340     pBOP=new BOPAlgo_BOP(myAllocator); 
341     pBOP->SetArguments(myArguments);
342     pBOP->SetTools(myTools); 
343     pBOP->SetOperation(myOperation);
344     myBuilder=pBOP;
345   }
346   //
347   myBuilder->SetRunParallel(myRunParallel);
348   myBuilder->SetProgressIndicator(myProgressIndicator);
349   //
350   myBuilder->PerformWithFiller(*myDSFiller);
351   iErr = myBuilder->ErrorStatus();
352   if (iErr) {
353     myErrorStatus=200+iErr;
354     return;
355   }
356   //
357   myShape=myBuilder->Shape();
358   //
359   myBuilderCanWork=Standard_True;
360   Done(); 
361   //
362   //XXXX
363   if (aDumpOper.IsDump()) {
364     BRepAlgoAPI_Check aCheckRes(myShape);
365     aDumpOper.SetIsDumpRes(!aCheckRes.IsValid());
366     aDumpOper.Dump(aS1, aS2, myShape,myOperation);
367   }
368   //XXXX
369 }
370 //=======================================================================
371 //function : RefineEdges
372 //purpose  : 
373 //=======================================================================
374 void BRepAlgoAPI_BooleanOperation::RefineEdges ()
375 {
376   if(myFuseEdges) { 
377     return; //Edges have been refined
378   }
379   //
380   TopTools_IndexedMapOfShape mapOldEdges;
381   TopTools_ListOfShape aLS;
382   TopTools_ListIteratorOfListOfShape aIt;
383   //
384   aIt.Initialize(myArguments);
385   for (; aIt.More(); aIt.Next()) {
386     const TopoDS_Shape& aS = aIt.Value();
387     aLS.Append(aS);
388   }
389   aIt.Initialize(myTools);
390   for (; aIt.More(); aIt.Next()) {
391     const TopoDS_Shape& aS = aIt.Value();
392     aLS.Append(aS);
393   }
394   //
395   aIt.Initialize(aLS);
396   for (; aIt.More(); aIt.Next()) {
397     const TopoDS_Shape& aS = aIt.Value();
398     TopExp::MapShapes (aS, TopAbs_EDGE, mapOldEdges);
399   }
400   //----------------------------------------------
401   BRepLib_FuseEdges FE(myShape);
402   FE.SetConcatBSpl(Standard_True);
403   FE.AvoidEdges (mapOldEdges);
404   //
405   // Get List of edges that have been fused
406   myFuseEdges = Standard_False;
407   myModifFaces.Clear();
408   myEdgeMap.Clear();
409   TopTools_DataMapOfIntegerListOfShape aFusedEdges;
410
411   FE.Edges(aFusedEdges);
412   Standard_Integer nle = aFusedEdges.Extent();
413   if (nle != 0) {
414     FE.Perform();
415     myShape = FE.Shape();
416
417     TopTools_DataMapOfIntegerShape aResultEdges;
418
419     FE.ResultEdges(aResultEdges);
420     FE.Faces(myModifFaces);
421     myFuseEdges = Standard_True;
422     
423     Standard_Integer i;
424     for(i = 1; i <= nle; ++i) {
425       const TopoDS_Shape& aNewE = aResultEdges(i);
426       const TopTools_ListOfShape& aListOfOldEdges = aFusedEdges(i);
427       TopTools_ListIteratorOfListOfShape anIter(aListOfOldEdges);
428       for(; anIter.More(); anIter.Next()) {
429         myEdgeMap.Bind(anIter.Value(), aNewE);
430       }
431     }
432   }
433 }
434 //=======================================================================
435 //function : RefinedList
436 //purpose  : 
437 //=======================================================================
438 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::RefinedList
439   (const TopTools_ListOfShape& theL) 
440 {
441   myGenerated.Clear();
442   TopTools_MapOfShape aMap;
443
444   TopTools_ListIteratorOfListOfShape anIter(theL);
445
446   for(; anIter.More(); anIter.Next()) {
447     const TopoDS_Shape& anS = anIter.Value();
448
449     if(anS.ShapeType() == TopAbs_EDGE) {
450       if(myEdgeMap.IsBound(anS)) {
451         const TopoDS_Shape& aNewEdge = myEdgeMap.Find(anS);
452         if(aMap.Add(aNewEdge)) {
453           myGenerated.Append(aNewEdge);
454         }
455       }
456       else {
457         myGenerated.Append(anS);
458       }
459     }
460     else if (anS.ShapeType() == TopAbs_FACE) {
461       if(myModifFaces.IsBound(anS)) {
462         myGenerated.Append(myModifFaces.Find(anS));
463       }
464       else {
465         myGenerated.Append(anS);
466       }
467     }
468     else {
469       myGenerated.Append(anS);
470     }
471   }
472
473   return myGenerated;
474
475 }
476 //=======================================================================
477 //function : SectionEdges
478 //purpose  : 
479 //=======================================================================
480 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::SectionEdges()
481 {
482   if (myBuilder==NULL) {
483     myGenerated.Clear();
484     return myGenerated;
485   }
486   //
487   Standard_Integer aNb, i, j, aNbCurves, nE;
488   BOPDS_ListIteratorOfListOfPaveBlock anIt;
489   //
490   const BOPDS_PDS& pDS = myDSFiller->PDS();
491   BOPDS_VectorOfInterfFF& aFFs=pDS->InterfFF();
492   myGenerated.Clear();
493   //
494   aNb=aFFs.Extent();
495   for (i = 0; i < aNb; i++) {
496     BOPDS_InterfFF& aFFi=aFFs(i);
497     const BOPDS_VectorOfCurve& aSeqOfCurve=aFFi.Curves();
498     //
499     aNbCurves=aSeqOfCurve.Extent();
500     for (j=0; j<aNbCurves; j++) {
501       const BOPDS_Curve& aCurve=aSeqOfCurve(j);
502       const BOPDS_ListOfPaveBlock& aSectEdges = aCurve.PaveBlocks();
503       //
504       anIt.Initialize(aSectEdges);
505       for(; anIt.More(); anIt.Next()) {
506         const Handle(BOPDS_PaveBlock)& aPB = anIt.Value();
507         nE = aPB->Edge();
508         const TopoDS_Shape& aE = pDS->Shape(nE);
509         myGenerated.Append(aE);
510       }
511     }
512   }
513   //
514   if(myFuseEdges) {
515     TopTools_ListOfShape theLS;
516     theLS.Assign(myGenerated);
517     //
518     RefinedList(theLS);
519   }
520   //
521   return myGenerated;
522 }
523 //=======================================================================
524 //function : Generated
525 //purpose  : 
526 //=======================================================================
527 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Generated
528   (const TopoDS_Shape& S) 
529 {
530   if (myBuilder==NULL) {
531     myGenerated.Clear();
532     return myGenerated;
533   }
534   //
535   if(myFuseEdges) {
536     const TopTools_ListOfShape& aL = myBuilder->Generated(S);
537     return RefinedList(aL);
538   }
539   
540   return myBuilder->Generated(S);
541 }
542
543 //=======================================================================
544 //function : Modified
545 //purpose  : 
546 //=======================================================================
547 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Modified
548   (const TopoDS_Shape& aS) 
549 {
550   if (myBuilder==NULL) {
551     myGenerated.Clear();
552     return myGenerated;
553   }
554   else {
555     myGenerated = myBuilder->Modified(aS);
556
557     if(myFuseEdges) {
558       TopTools_ListOfShape theLS;
559       theLS.Assign(myGenerated);
560       //
561       RefinedList(theLS);
562     }
563     return myGenerated;
564   }
565 }
566 //=======================================================================
567 //function : IsDeleted
568 //purpose  : 
569 //=======================================================================
570 Standard_Boolean BRepAlgoAPI_BooleanOperation::IsDeleted
571   (const TopoDS_Shape& aS) 
572 {
573   Standard_Boolean bDeleted = Standard_True; 
574   if (myBuilder != NULL) {
575     bDeleted=myBuilder->IsDeleted(aS);
576   }
577   return bDeleted; 
578 }
579 //=======================================================================
580 //function : HasModified
581 //purpose  : 
582 //=======================================================================
583 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasModified() const
584 {
585   if (myBuilder==NULL) {
586     return Standard_False;
587   }
588   return myBuilder->HasModified();
589 }
590 //=======================================================================
591 //function : HasGenerated
592 //purpose  : 
593 //=======================================================================
594 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasGenerated() const
595 {
596   if (myBuilder==NULL) {
597     return Standard_False;
598   }
599   return myBuilder->HasGenerated();
600 }
601 //=======================================================================
602 //function : HasDeleted
603 //purpose  : 
604 //=======================================================================
605 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasDeleted() const
606 {
607   if (myBuilder==NULL) {
608     return Standard_False;
609   }
610   return myBuilder->HasDeleted();
611 }
612 //XXXX
613 //=======================================================================
614 //function : Dump
615 //purpose  : 
616 //=======================================================================
617 void BRepAlgoAPI_DumpOper::Dump (const TopoDS_Shape& theShape1,
618                                  const TopoDS_Shape& theShape2,
619                                  const TopoDS_Shape& theResult,
620                                  BOPAlgo_Operation theOperation)
621 {
622   if (!(myIsDumpArgs && myIsDumpRes)) {
623     return;
624   }
625   //
626   TCollection_AsciiString aPath(myPath);
627   aPath += "/";
628   Standard_Integer aNumOper = 1;
629   Standard_Boolean isExist = Standard_True;
630   TCollection_AsciiString aFileName;
631  
632   while(isExist)
633   {
634     aFileName = aPath + "BO_" + TCollection_AsciiString(aNumOper) +".tcl";
635     OSD_File aScript(aFileName);
636     isExist = aScript.Exists();
637     if(isExist)
638       aNumOper++;
639   }
640
641   FILE* afile = fopen(aFileName.ToCString(), "w+");
642   if(!afile)
643     return;
644   if(myIsDumpArgs)
645     fprintf(afile,"%s\n","# Arguments are invalid");
646
647   TCollection_AsciiString aName1;
648   TCollection_AsciiString aName2;
649   TCollection_AsciiString aNameRes;
650   if(!theShape1.IsNull())
651   {
652     aName1 = aPath +
653       "Arg1_" + TCollection_AsciiString(aNumOper) + ".brep";
654     BRepTools::Write(theShape1, aName1.ToCString());
655   }
656   else
657     fprintf(afile,"%s\n","# First argument is Null ");
658    
659   if(!theShape2.IsNull())
660   {
661     aName2 =  aPath +
662       "Arg2_"+ TCollection_AsciiString(aNumOper) + ".brep";
663
664     BRepTools::Write(theShape2, aName2.ToCString());
665   }
666   else
667     fprintf(afile,"%s\n","# Second argument is Null ");
668    
669    if(!theResult.IsNull())
670   {
671     aNameRes =  aPath +
672       "Result_"+ TCollection_AsciiString(aNumOper) + ".brep";
673
674     BRepTools::Write(theResult, aNameRes.ToCString());
675   }
676   else
677     fprintf(afile,"%s\n","# Result is Null ");
678   
679   fprintf(afile, "%s %s %s\n","restore",  aName1.ToCString(), "arg1");
680   fprintf(afile, "%s %s %s\n","restore",  aName2.ToCString(), "arg2");;
681   TCollection_AsciiString aBopString;
682   switch (theOperation)
683   {
684     case BOPAlgo_COMMON : aBopString += "bcommon Res "; break;
685     case BOPAlgo_FUSE   : aBopString += "bfuse Res "; break;
686     case BOPAlgo_CUT    : 
687     case BOPAlgo_CUT21  : aBopString += "bcut Res "; break;
688     case BOPAlgo_SECTION : aBopString += "bsection Res "; break;
689     default : break;
690   };
691   aBopString += ("arg1 arg2");
692   if(theOperation == BOPAlgo_CUT21)
693     aBopString += " 1";
694
695   fprintf(afile, "%s\n",aBopString.ToCString());
696   fclose(afile);
697 }
698 //XXXX