0024002: Overall code and build procedure refactoring -- automatic
[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     //
309     SetAttributes();
310     //
311     myDSFiller->Perform(); 
312     iErr=myDSFiller->ErrorStatus();
313     if (iErr) {
314       myErrorStatus=100+iErr;
315       return;
316     }
317   }// if (myEntryType) {
318   //
319   //XXXX
320   const TopoDS_Shape& aS1 = myArguments.First();
321   const TopoDS_Shape& aS2 = myTools.First();
322   if (aDumpOper.IsDump()) {
323     BRepAlgoAPI_Check aChekArgs(aS1, aS2, myOperation);
324     aDumpOper.SetIsDumpArgs(!aChekArgs.IsValid());
325   }
326   //XXXX
327   // 
328   if (myBuilder) {
329     delete myBuilder;
330   }
331   //
332   BOPAlgo_BOP *pBOP;
333   //
334   if(myOperation==BOPAlgo_SECTION) {
335     myBuilder=new BOPAlgo_Section(myAllocator);
336     myBuilder->SetArguments(aLS);
337   }
338   else{
339     pBOP=new BOPAlgo_BOP(myAllocator); 
340     pBOP->SetArguments(myArguments);
341     pBOP->SetTools(myTools); 
342     pBOP->SetOperation(myOperation);
343     myBuilder=pBOP;
344   }
345   //
346   myBuilder->SetRunParallel(myRunParallel);
347   myBuilder->SetProgressIndicator(myProgressIndicator);
348   //
349   myBuilder->PerformWithFiller(*myDSFiller);
350   iErr = myBuilder->ErrorStatus();
351   if (iErr) {
352     myErrorStatus=200+iErr;
353     return;
354   }
355   //
356   myShape=myBuilder->Shape();
357   //
358   myBuilderCanWork=Standard_True;
359   Done(); 
360   //
361   //XXXX
362   if (aDumpOper.IsDump()) {
363     BRepAlgoAPI_Check aCheckRes(myShape);
364     aDumpOper.SetIsDumpRes(!aCheckRes.IsValid());
365     aDumpOper.Dump(aS1, aS2, myShape,myOperation);
366   }
367   //XXXX
368 }
369 //=======================================================================
370 //function : RefineEdges
371 //purpose  : 
372 //=======================================================================
373 void BRepAlgoAPI_BooleanOperation::RefineEdges ()
374 {
375   if(myFuseEdges) { 
376     return; //Edges have been refined
377   }
378   //
379   TopTools_IndexedMapOfShape mapOldEdges;
380   TopTools_ListOfShape aLS;
381   TopTools_ListIteratorOfListOfShape aIt;
382   //
383   aIt.Initialize(myArguments);
384   for (; aIt.More(); aIt.Next()) {
385     const TopoDS_Shape& aS = aIt.Value();
386     aLS.Append(aS);
387   }
388   aIt.Initialize(myTools);
389   for (; aIt.More(); aIt.Next()) {
390     const TopoDS_Shape& aS = aIt.Value();
391     aLS.Append(aS);
392   }
393   //
394   aIt.Initialize(aLS);
395   for (; aIt.More(); aIt.Next()) {
396     const TopoDS_Shape& aS = aIt.Value();
397     TopExp::MapShapes (aS, TopAbs_EDGE, mapOldEdges);
398   }
399   //----------------------------------------------
400   BRepLib_FuseEdges FE(myShape);
401   FE.SetConcatBSpl(Standard_True);
402   FE.AvoidEdges (mapOldEdges);
403   //
404   // Get List of edges that have been fused
405   myFuseEdges = Standard_False;
406   myModifFaces.Clear();
407   myEdgeMap.Clear();
408   TopTools_DataMapOfIntegerListOfShape aFusedEdges;
409
410   FE.Edges(aFusedEdges);
411   Standard_Integer nle = aFusedEdges.Extent();
412   if (nle != 0) {
413     FE.Perform();
414     myShape = FE.Shape();
415
416     TopTools_DataMapOfIntegerShape aResultEdges;
417
418     FE.ResultEdges(aResultEdges);
419     FE.Faces(myModifFaces);
420     myFuseEdges = Standard_True;
421     
422     Standard_Integer i;
423     for(i = 1; i <= nle; ++i) {
424       const TopoDS_Shape& aNewE = aResultEdges(i);
425       const TopTools_ListOfShape& aListOfOldEdges = aFusedEdges(i);
426       TopTools_ListIteratorOfListOfShape anIter(aListOfOldEdges);
427       for(; anIter.More(); anIter.Next()) {
428         myEdgeMap.Bind(anIter.Value(), aNewE);
429       }
430     }
431   }
432 }
433 //=======================================================================
434 //function : RefinedList
435 //purpose  : 
436 //=======================================================================
437 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::RefinedList
438   (const TopTools_ListOfShape& theL) 
439 {
440   myGenerated.Clear();
441   TopTools_MapOfShape aMap;
442
443   TopTools_ListIteratorOfListOfShape anIter(theL);
444
445   for(; anIter.More(); anIter.Next()) {
446     const TopoDS_Shape& anS = anIter.Value();
447
448     if(anS.ShapeType() == TopAbs_EDGE) {
449       if(myEdgeMap.IsBound(anS)) {
450         const TopoDS_Shape& aNewEdge = myEdgeMap.Find(anS);
451         if(aMap.Add(aNewEdge)) {
452           myGenerated.Append(aNewEdge);
453         }
454       }
455       else {
456         myGenerated.Append(anS);
457       }
458     }
459     else if (anS.ShapeType() == TopAbs_FACE) {
460       if(myModifFaces.IsBound(anS)) {
461         myGenerated.Append(myModifFaces.Find(anS));
462       }
463       else {
464         myGenerated.Append(anS);
465       }
466     }
467     else {
468       myGenerated.Append(anS);
469     }
470   }
471
472   return myGenerated;
473
474 }
475 //=======================================================================
476 //function : SectionEdges
477 //purpose  : 
478 //=======================================================================
479 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::SectionEdges()
480 {
481   if (myBuilder==NULL) {
482     myGenerated.Clear();
483     return myGenerated;
484   }
485   //
486   Standard_Integer aNb, i, j, aNbCurves, nE;
487   BOPDS_ListIteratorOfListOfPaveBlock anIt;
488   //
489   const BOPDS_PDS& pDS = myDSFiller->PDS();
490   BOPDS_VectorOfInterfFF& aFFs=pDS->InterfFF();
491   myGenerated.Clear();
492   //
493   aNb=aFFs.Extent();
494   for (i = 0; i < aNb; i++) {
495     BOPDS_InterfFF& aFFi=aFFs(i);
496     const BOPDS_VectorOfCurve& aSeqOfCurve=aFFi.Curves();
497     //
498     aNbCurves=aSeqOfCurve.Extent();
499     for (j=0; j<aNbCurves; j++) {
500       const BOPDS_Curve& aCurve=aSeqOfCurve(j);
501       const BOPDS_ListOfPaveBlock& aSectEdges = aCurve.PaveBlocks();
502       //
503       anIt.Initialize(aSectEdges);
504       for(; anIt.More(); anIt.Next()) {
505         const Handle(BOPDS_PaveBlock)& aPB = anIt.Value();
506         nE = aPB->Edge();
507         const TopoDS_Shape& aE = pDS->Shape(nE);
508         myGenerated.Append(aE);
509       }
510     }
511   }
512   //
513   if(myFuseEdges) {
514     TopTools_ListOfShape theLS;
515     theLS.Assign(myGenerated);
516     //
517     RefinedList(theLS);
518   }
519   //
520   return myGenerated;
521 }
522 //=======================================================================
523 //function : Generated
524 //purpose  : 
525 //=======================================================================
526 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Generated
527   (const TopoDS_Shape& S) 
528 {
529   if (myBuilder==NULL) {
530     myGenerated.Clear();
531     return myGenerated;
532   }
533   //
534   if(myFuseEdges) {
535     const TopTools_ListOfShape& aL = myBuilder->Generated(S);
536     return RefinedList(aL);
537   }
538   
539   return myBuilder->Generated(S);
540 }
541
542 //=======================================================================
543 //function : Modified
544 //purpose  : 
545 //=======================================================================
546 const TopTools_ListOfShape& BRepAlgoAPI_BooleanOperation::Modified
547   (const TopoDS_Shape& aS) 
548 {
549   if (myBuilder==NULL) {
550     myGenerated.Clear();
551     return myGenerated;
552   }
553   else {
554     myGenerated = myBuilder->Modified(aS);
555
556     if(myFuseEdges) {
557       TopTools_ListOfShape theLS;
558       theLS.Assign(myGenerated);
559       //
560       RefinedList(theLS);
561     }
562     return myGenerated;
563   }
564 }
565 //=======================================================================
566 //function : IsDeleted
567 //purpose  : 
568 //=======================================================================
569 Standard_Boolean BRepAlgoAPI_BooleanOperation::IsDeleted
570   (const TopoDS_Shape& aS) 
571 {
572   Standard_Boolean bDeleted = Standard_True; 
573   if (myBuilder != NULL) {
574     bDeleted=myBuilder->IsDeleted(aS);
575   }
576   return bDeleted; 
577 }
578 //=======================================================================
579 //function : HasModified
580 //purpose  : 
581 //=======================================================================
582 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasModified() const
583 {
584   if (myBuilder==NULL) {
585     return Standard_False;
586   }
587   return myBuilder->HasModified();
588 }
589 //=======================================================================
590 //function : HasGenerated
591 //purpose  : 
592 //=======================================================================
593 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasGenerated() const
594 {
595   if (myBuilder==NULL) {
596     return Standard_False;
597   }
598   return myBuilder->HasGenerated();
599 }
600 //=======================================================================
601 //function : HasDeleted
602 //purpose  : 
603 //=======================================================================
604 Standard_Boolean BRepAlgoAPI_BooleanOperation::HasDeleted() const
605 {
606   if (myBuilder==NULL) {
607     return Standard_False;
608   }
609   return myBuilder->HasDeleted();
610 }
611 //XXXX
612 //=======================================================================
613 //function : Dump
614 //purpose  : 
615 //=======================================================================
616 void BRepAlgoAPI_DumpOper::Dump (const TopoDS_Shape& theShape1,
617                                  const TopoDS_Shape& theShape2,
618                                  const TopoDS_Shape& theResult,
619                                  BOPAlgo_Operation theOperation)
620 {
621   if (!(myIsDumpArgs && myIsDumpRes)) {
622     return;
623   }
624   //
625   TCollection_AsciiString aPath(myPath);
626   aPath += "/";
627   Standard_Integer aNumOper = 1;
628   Standard_Boolean isExist = Standard_True;
629   TCollection_AsciiString aFileName;
630  
631   while(isExist)
632   {
633     aFileName = aPath + "BO_" + TCollection_AsciiString(aNumOper) +".tcl";
634     OSD_File aScript(aFileName);
635     isExist = aScript.Exists();
636     if(isExist)
637       aNumOper++;
638   }
639
640   FILE* afile = fopen(aFileName.ToCString(), "w+");
641   if(!afile)
642     return;
643   if(myIsDumpArgs)
644     fprintf(afile,"%s\n","# Arguments are invalid");
645
646   TCollection_AsciiString aName1;
647   TCollection_AsciiString aName2;
648   TCollection_AsciiString aNameRes;
649   if(!theShape1.IsNull())
650   {
651     aName1 = aPath +
652       "Arg1_" + TCollection_AsciiString(aNumOper) + ".brep";
653     BRepTools::Write(theShape1, aName1.ToCString());
654   }
655   else
656     fprintf(afile,"%s\n","# First argument is Null ");
657    
658   if(!theShape2.IsNull())
659   {
660     aName2 =  aPath +
661       "Arg2_"+ TCollection_AsciiString(aNumOper) + ".brep";
662
663     BRepTools::Write(theShape2, aName2.ToCString());
664   }
665   else
666     fprintf(afile,"%s\n","# Second argument is Null ");
667    
668    if(!theResult.IsNull())
669   {
670     aNameRes =  aPath +
671       "Result_"+ TCollection_AsciiString(aNumOper) + ".brep";
672
673     BRepTools::Write(theResult, aNameRes.ToCString());
674   }
675   else
676     fprintf(afile,"%s\n","# Result is Null ");
677   
678   fprintf(afile, "%s %s %s\n","restore",  aName1.ToCString(), "arg1");
679   fprintf(afile, "%s %s %s\n","restore",  aName2.ToCString(), "arg2");;
680   TCollection_AsciiString aBopString;
681   switch (theOperation)
682   {
683     case BOPAlgo_COMMON : aBopString += "bcommon Res "; break;
684     case BOPAlgo_FUSE   : aBopString += "bfuse Res "; break;
685     case BOPAlgo_CUT    : 
686     case BOPAlgo_CUT21  : aBopString += "bcut Res "; break;
687     case BOPAlgo_SECTION : aBopString += "bsection Res "; break;
688     default : break;
689   };
690   aBopString += ("arg1 arg2");
691   if(theOperation == BOPAlgo_CUT21)
692     aBopString += " 1";
693
694   fprintf(afile, "%s\n",aBopString.ToCString());
695   fclose(afile);
696 }
697 //XXXX