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