Salome HOME
Update copyrights 2014.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_BooleanDriver.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <GEOMImpl_BooleanDriver.hxx>
24 #include <GEOMImpl_IBoolean.hxx>
25 #include <GEOMImpl_Types.hxx>
26 #include <GEOMImpl_GlueDriver.hxx>
27 #include <GEOM_Function.hxx>
28 #include <GEOMUtils.hxx>
29
30 #include <TNaming_CopyShape.hxx>
31
32 #include <ShapeFix_ShapeTolerance.hxx>
33 #include <ShapeFix_Shape.hxx>
34
35 #include <BRep_Builder.hxx>
36 #include <BRepAlgo.hxx>
37 #include <BRepAlgoAPI_Common.hxx>
38 #include <BRepAlgoAPI_Cut.hxx>
39 #include <BRepAlgoAPI_Fuse.hxx>
40 #include <BRepAlgoAPI_Section.hxx>
41 #include <BRepCheck_Analyzer.hxx>
42 #include <BOPAlgo_CheckerSI.hxx>
43 #include <BOPDS_DS.hxx>
44
45 #include <TopExp_Explorer.hxx>
46 #include <TopoDS_Compound.hxx>
47 #include <TopoDS_Iterator.hxx>
48 #include <TopTools_MapOfShape.hxx>
49 #include <TopTools_ListOfShape.hxx>
50 #include <TopTools_ListIteratorOfListOfShape.hxx>
51
52 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
53
54 #include <Precision.hxx>
55
56 #include <Standard_ConstructionError.hxx>
57 #include <StdFail_NotDone.hxx>
58
59 // Depth of self-intersection check (see BOPAlgo_CheckerSI::SetLevelOfCheck() for more details)
60 // Default value for BOPAlgo_CheckerSI gives very long computation when checking face-to-face intersections;
61 // here check level is decreased to more appropriate value to avoid problems with performance).
62 #define BOP_SELF_INTERSECTIONS_LEVEL 4
63
64 //=======================================================================
65 //function : GetID
66 //purpose  :
67 //=======================================================================
68 const Standard_GUID& GEOMImpl_BooleanDriver::GetID()
69 {
70   static Standard_GUID aBooleanDriver("FF1BBB21-5D14-4df2-980B-3A668264EA16");
71   return aBooleanDriver;
72 }
73
74 //=======================================================================
75 //function : GEOMImpl_BooleanDriver
76 //purpose  :
77 //=======================================================================
78 GEOMImpl_BooleanDriver::GEOMImpl_BooleanDriver()
79 {
80 }
81
82 //=======================================================================
83 //function : Execute
84 //purpose  :
85 //=======================================================================
86 Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const
87 {
88   if (Label().IsNull()) return 0;
89   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
90
91   GEOMImpl_IBoolean aCI (aFunction);
92   Standard_Integer aType = aFunction->GetType();
93   const Standard_Boolean isCheckSelfInte = aCI.GetCheckSelfIntersection();
94
95   TopoDS_Shape aShape;
96
97   switch (aType) {
98   case BOOLEAN_COMMON:
99   case BOOLEAN_CUT:
100   case BOOLEAN_FUSE:
101   case BOOLEAN_SECTION:
102     {
103       Handle(GEOM_Function) aRefShape1 = aCI.GetShape1();
104       Handle(GEOM_Function) aRefShape2 = aCI.GetShape2();
105       TopoDS_Shape aShape1 = aRefShape1->GetValue();
106       TopoDS_Shape aShape2 = aRefShape2->GetValue();
107
108       if (!aShape1.IsNull() && !aShape2.IsNull()) {
109         // check arguments for Mantis issue 0021019
110         BRepCheck_Analyzer ana (aShape1, Standard_True);
111         if (!ana.IsValid())
112           StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
113         ana.Init(aShape2);
114         if (!ana.IsValid())
115           StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
116
117         if (isCheckSelfInte) {
118           BOPAlgo_CheckerSI aCSI;  // checker of self-interferences
119           aCSI.SetLevelOfCheck(BOP_SELF_INTERSECTIONS_LEVEL);
120           BOPCol_ListOfShape aList1, aList2;
121           aList1.Append(aShape1);
122           aList2.Append(aShape2);
123           aCSI.SetArguments(aList1);
124           aCSI.Perform();
125           if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0)
126             StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected");
127           aCSI.SetArguments(aList2);
128           aCSI.Perform();
129           if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0)
130             StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected");
131         }
132
133         // Make a copy to prevent the original shape changes.
134         TopoDS_Shape aShapeCopy1;
135         TopoDS_Shape aShapeCopy2;
136         TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
137         TNaming_CopyShape::CopyTool(aShape1, aMapTShapes, aShapeCopy1);
138         TNaming_CopyShape::CopyTool(aShape2, aMapTShapes, aShapeCopy2);
139
140         aShape = performOperation (aShapeCopy1, aShapeCopy2, aType);
141
142         if (aShape.IsNull())
143           return 0;
144       }
145     }
146     break;
147   case BOOLEAN_COMMON_LIST:
148   case BOOLEAN_FUSE_LIST:
149     {
150       Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
151       const Standard_Integer nbShapes = aShapes->Length();
152       Standard_Integer i;
153       Handle(GEOM_Function) aRefShape;
154       TopoDS_Shape aShape2;
155       Standard_Integer aSimpleType =
156         (aType == BOOLEAN_FUSE_LIST ? BOOLEAN_FUSE : BOOLEAN_COMMON);
157
158       if (nbShapes > 0) {
159         aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(1));
160         aShape = aRefShape->GetValue();
161         
162         if (!aShape.IsNull()) {
163           BRepCheck_Analyzer anAna (aShape, Standard_True);
164           if (!anAna.IsValid()) {
165             StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
166           }
167
168           BOPAlgo_CheckerSI aCSI;  // checker of self-interferences
169
170           if (isCheckSelfInte) {
171             aCSI.SetLevelOfCheck(BOP_SELF_INTERSECTIONS_LEVEL);
172             BOPCol_ListOfShape aList1;
173             aList1.Append(aShape);
174             aCSI.SetArguments(aList1);
175             aCSI.Perform();
176             if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) {
177               StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected");
178             }
179           }
180
181           // Copy shape
182           TopoDS_Shape aShapeCopy;
183           TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
184
185           TNaming_CopyShape::CopyTool(aShape, aMapTShapes, aShapeCopy);
186           aShape = aShapeCopy;
187
188           for (i = 2; i <= nbShapes; i++) {
189             aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(i));
190             aShape2 = aRefShape->GetValue();
191             anAna.Init(aShape2);
192             
193             if (!anAna.IsValid()) {
194               StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
195             }
196             
197             if (isCheckSelfInte) {
198               BOPCol_ListOfShape aList2;
199               aList2.Append(aShape2);
200               aCSI.SetArguments(aList2);
201               aCSI.Perform();
202               if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) {
203                 StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected");
204               }
205             }
206
207             // Copy shape
208             aShapeCopy.Nullify();
209             TNaming_CopyShape::CopyTool(aShape2, aMapTShapes, aShapeCopy);
210             aShape = performOperation (aShape, aShapeCopy, aSimpleType);
211             
212             if (aShape.IsNull()) {
213               return 0;
214             }
215           }
216         }
217       }
218     }
219     break;
220   case BOOLEAN_CUT_LIST:
221     {
222       Handle(GEOM_Function) aRefObject = aCI.GetShape1();
223
224       aShape = aRefObject->GetValue();
225
226       if (!aShape.IsNull()) {
227         // check arguments for Mantis issue 0021019
228         BRepCheck_Analyzer anAna (aShape, Standard_True);
229
230         if (!anAna.IsValid()) {
231           StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
232         }
233
234         BOPAlgo_CheckerSI aCSI;  // checker of self-interferences
235
236         if (isCheckSelfInte) {
237           aCSI.SetLevelOfCheck(BOP_SELF_INTERSECTIONS_LEVEL);
238           BOPCol_ListOfShape aList1;
239           aList1.Append(aShape);
240           aCSI.SetArguments(aList1);
241           aCSI.Perform();
242           if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) {
243             StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected");
244           }
245         }
246
247         // Copy shape
248         TopoDS_Shape aShapeCopy;
249         TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
250
251         TNaming_CopyShape::CopyTool(aShape, aMapTShapes, aShapeCopy);
252         aShape = aShapeCopy;
253         
254         Handle(TColStd_HSequenceOfTransient) aTools = aCI.GetShapes();
255         const Standard_Integer nbShapes = aTools->Length();
256         Standard_Integer i;
257         Handle(GEOM_Function) aRefTool;
258         TopoDS_Shape aTool;
259
260         for (i = 1; i <= nbShapes; i++) {
261           aRefTool = Handle(GEOM_Function)::DownCast(aTools->Value(i));
262           aTool = aRefTool->GetValue();
263           anAna.Init(aTool);
264
265           if (!anAna.IsValid()) {
266             StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
267           }
268
269           if (isCheckSelfInte) {
270             BOPCol_ListOfShape aList2;
271             aList2.Append(aTool);
272             aCSI.SetArguments(aList2);
273             aCSI.Perform();
274             if (aCSI.ErrorStatus() || aCSI.DS().Interferences().Extent() > 0) {
275               StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is self-intersected");
276             }
277           }
278
279           // Copy shape
280           aShapeCopy.Nullify();
281           TNaming_CopyShape::CopyTool(aTool, aMapTShapes, aShapeCopy);
282           aShape = performOperation (aShape, aShapeCopy, BOOLEAN_CUT);
283
284           if (aShape.IsNull()) {
285             return 0;
286           }
287         }
288       }
289     }
290     break;
291   default:
292     break;
293   }
294
295   aFunction->SetValue(aShape);
296
297   log.SetTouched(Label());
298
299   return 1;
300 }
301
302 //=======================================================================
303 //function : performOperation
304 //purpose  :
305 //=======================================================================
306 TopoDS_Shape GEOMImpl_BooleanDriver::performOperation
307                                (const TopoDS_Shape theShape1,
308                                 const TopoDS_Shape theShape2,
309                                 const Standard_Integer theType)const
310 {
311   TopoDS_Shape aShape;
312
313   // perform COMMON operation
314   if (theType == BOOLEAN_COMMON) {
315     BRep_Builder B;
316     TopoDS_Compound C;
317     B.MakeCompound(C);
318
319     TopTools_ListOfShape listShape1, listShape2;
320     GEOMUtils::AddSimpleShapes(theShape1, listShape1);
321     GEOMUtils::AddSimpleShapes(theShape2, listShape2);
322
323     Standard_Boolean isCompound =
324       (listShape1.Extent() > 1 || listShape2.Extent() > 1);
325
326     TopTools_ListIteratorOfListOfShape itSub1 (listShape1);
327     for (; itSub1.More(); itSub1.Next()) {
328       TopoDS_Shape aValue1 = itSub1.Value();
329       TopTools_ListIteratorOfListOfShape itSub2 (listShape2);
330       for (; itSub2.More(); itSub2.Next()) {
331         TopoDS_Shape aValue2 = itSub2.Value();
332         BRepAlgoAPI_Common BO (aValue1, aValue2);
333         if (!BO.IsDone()) {
334           StdFail_NotDone::Raise("Common operation can not be performed on the given shapes");
335         }
336         if (isCompound) {
337           TopoDS_Shape aStepResult = BO.Shape();
338
339           // check result of this step: if it is a compound (boolean operations
340           // allways return a compound), we add all sub-shapes of it.
341           // This allows to avoid adding empty compounds,
342           // resulting from COMMON on two non-intersecting shapes.
343           if (aStepResult.ShapeType() == TopAbs_COMPOUND) {
344             TopoDS_Iterator aCompIter (aStepResult);
345             for (; aCompIter.More(); aCompIter.Next()) {
346               // add shape in a result
347               B.Add(C, aCompIter.Value());
348             }
349           }
350           else {
351             // add shape in a result
352             B.Add(C, aStepResult);
353           }
354         }
355         else
356           aShape = BO.Shape();
357       }
358     }
359
360     if (isCompound) {
361       // As GlueFaces has been improved to keep all kind of shapes
362       TopExp_Explorer anExp (C, TopAbs_VERTEX);
363       if (anExp.More())
364         aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
365       else
366         aShape = C;
367     }
368   }
369
370   // perform CUT operation
371   else if (theType == BOOLEAN_CUT) {
372     BRep_Builder B;
373     TopoDS_Compound C;
374     B.MakeCompound(C);
375
376     TopTools_ListOfShape listShapes, listTools;
377     GEOMUtils::AddSimpleShapes(theShape1, listShapes);
378     GEOMUtils::AddSimpleShapes(theShape2, listTools);
379
380     Standard_Boolean isCompound = (listShapes.Extent() > 1);
381
382     TopTools_ListIteratorOfListOfShape itSub1 (listShapes);
383     for (; itSub1.More(); itSub1.Next()) {
384       TopoDS_Shape aCut = itSub1.Value();
385       // tools
386       TopTools_ListIteratorOfListOfShape itSub2 (listTools);
387       for (; itSub2.More(); itSub2.Next()) {
388         TopoDS_Shape aTool = itSub2.Value();
389         BRepAlgoAPI_Cut BO (aCut, aTool);
390         if (!BO.IsDone()) {
391           StdFail_NotDone::Raise("Cut operation can not be performed on the given shapes");
392         }
393         aCut = BO.Shape();
394       }
395       if (isCompound) {
396         // check result of this step: if it is a compound (boolean operations
397         // allways return a compound), we add all sub-shapes of it.
398         // This allows to avoid adding empty compounds,
399         // resulting from CUT of parts
400         if (aCut.ShapeType() == TopAbs_COMPOUND) {
401           TopoDS_Iterator aCompIter (aCut);
402           for (; aCompIter.More(); aCompIter.Next()) {
403             // add shape in a result
404             B.Add(C, aCompIter.Value());
405           }
406         }
407         else {
408           // add shape in a result
409           B.Add(C, aCut);
410         }
411       }
412       else
413         aShape = aCut;
414     }
415
416     if (isCompound) {
417       // As GlueFaces has been improved to keep all kind of shapes
418       TopExp_Explorer anExp (C, TopAbs_VERTEX);
419       if (anExp.More())
420         aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
421       else
422         aShape = C;
423     }
424   }
425
426   // perform FUSE operation
427   else if (theType == BOOLEAN_FUSE) {
428     // Perform
429     BRepAlgoAPI_Fuse BO (theShape1, theShape2);
430     if (!BO.IsDone()) {
431       StdFail_NotDone::Raise("Fuse operation can not be performed on the given shapes");
432     }
433     aShape = BO.Shape();
434   }
435
436   // perform SECTION operation
437   else if (theType == BOOLEAN_SECTION) {
438     BRep_Builder B;
439     TopoDS_Compound C;
440     B.MakeCompound(C);
441
442     TopTools_ListOfShape listShape1, listShape2;
443     GEOMUtils::AddSimpleShapes(theShape1, listShape1);
444     GEOMUtils::AddSimpleShapes(theShape2, listShape2);
445
446     Standard_Boolean isCompound =
447       (listShape1.Extent() > 1 || listShape2.Extent() > 1);
448
449     TopTools_ListIteratorOfListOfShape itSub1 (listShape1);
450     for (; itSub1.More(); itSub1.Next()) {
451       TopoDS_Shape aValue1 = itSub1.Value();
452       TopTools_ListIteratorOfListOfShape itSub2 (listShape2);
453       for (; itSub2.More(); itSub2.Next()) {
454         TopoDS_Shape aValue2 = itSub2.Value();
455         BRepAlgoAPI_Section BO (aValue1, aValue2, Standard_False);
456         // Set approximation to have an attached 3D BSpline geometry to each edge,
457         // where analytic curve is not possible. Without this flag in some cases
458         // we obtain BSpline curve of degree 1 (C0), which is slowly
459         // processed by some algorithms (Partition for example).
460         BO.Approximation(Standard_True);
461         //modified by NIZNHY-PKV Tue Oct 18 14:34:16 2011f
462         BO.ComputePCurveOn1(Standard_True);
463         BO.ComputePCurveOn2(Standard_True);
464         //modified by NIZNHY-PKV Tue Oct 18 14:34:18 2011t
465   
466         BO.Build();
467         if (!BO.IsDone()) {
468           StdFail_NotDone::Raise("Section operation can not be performed on the given shapes");
469         }
470         if (isCompound) {
471           TopoDS_Shape aStepResult = BO.Shape();
472
473           // check result of this step: if it is a compound (boolean operations
474           // allways return a compound), we add all sub-shapes of it.
475           // This allows to avoid adding empty compounds,
476           // resulting from SECTION on two non-intersecting shapes.
477           if (aStepResult.ShapeType() == TopAbs_COMPOUND) {
478             TopoDS_Iterator aCompIter (aStepResult);
479             for (; aCompIter.More(); aCompIter.Next()) {
480               // add shape in a result
481               B.Add(C, aCompIter.Value());
482             }
483           }
484           else {
485             // add shape in a result
486             B.Add(C, aStepResult);
487           }
488         }
489         else
490           aShape = BO.Shape();
491       }
492     }
493
494     if (isCompound) {
495       // As GlueFaces has been improved to keep all kind of shapes
496       TopExp_Explorer anExp (C, TopAbs_VERTEX);
497       if (anExp.More())
498         aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
499       else
500         aShape = C;
501     }
502   }
503
504   // UNKNOWN operation
505   else {
506   }
507
508   if (aShape.IsNull()) return aShape;
509
510   // as boolean operations always produce compound, lets simplify it
511   // for the case, if it contains only one sub-shape
512   TopTools_ListOfShape listShapeRes;
513   GEOMUtils::AddSimpleShapes(aShape, listShapeRes);
514   if (listShapeRes.Extent() == 1) {
515     aShape = listShapeRes.First();
516     if (aShape.IsNull()) return aShape;
517   }
518
519   // 08.07.2008 skl for bug 19761 from Mantis
520   BRepCheck_Analyzer ana (aShape, Standard_True);
521   ana.Init(aShape);
522   if (!ana.IsValid()) {
523     ShapeFix_ShapeTolerance aSFT;
524     aSFT.LimitTolerance(aShape, Precision::Confusion(),
525                         Precision::Confusion(), TopAbs_SHAPE);
526     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape);
527     aSfs->Perform();
528     aShape = aSfs->Shape();
529     ana.Init(aShape);
530     if (!ana.IsValid())
531       Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result");
532   }
533
534   // BEGIN: Mantis issue 0021060: always limit tolerance of BOP result
535   // 1. Get shape parameters for comparison
536   int nbTypes [TopAbs_SHAPE];
537   {
538     for (int iType = 0; iType < TopAbs_SHAPE; ++iType)
539       nbTypes[iType] = 0;
540     nbTypes[aShape.ShapeType()]++;
541
542     TopTools_MapOfShape aMapOfShape;
543     aMapOfShape.Add(aShape);
544     TopTools_ListOfShape aListOfShape;
545     aListOfShape.Append(aShape);
546
547     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
548     for (; itL.More(); itL.Next()) {
549       TopoDS_Iterator it (itL.Value());
550       for (; it.More(); it.Next()) {
551         TopoDS_Shape s = it.Value();
552         if (aMapOfShape.Add(s)) {
553           aListOfShape.Append(s);
554           nbTypes[s.ShapeType()]++;
555         }
556       }
557     }
558   }
559
560   // 2. Limit tolerance
561   TopoDS_Shape aShapeCopy;
562   TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
563   TNaming_CopyShape::CopyTool(aShape, aMapTShapes, aShapeCopy);
564   ShapeFix_ShapeTolerance aSFT;
565   aSFT.LimitTolerance(aShapeCopy, Precision::Confusion(), Precision::Confusion(), TopAbs_SHAPE);
566   Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShapeCopy);
567   aSfs->Perform();
568   aShapeCopy = aSfs->Shape();
569
570   // 3. Check parameters
571   ana.Init(aShapeCopy);
572   if (ana.IsValid()) {
573     int iType, nbTypesCopy [TopAbs_SHAPE];
574
575     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
576       nbTypesCopy[iType] = 0;
577     nbTypesCopy[aShapeCopy.ShapeType()]++;
578
579     TopTools_MapOfShape aMapOfShape;
580     aMapOfShape.Add(aShapeCopy);
581     TopTools_ListOfShape aListOfShape;
582     aListOfShape.Append(aShapeCopy);
583
584     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
585     for (; itL.More(); itL.Next()) {
586       TopoDS_Iterator it (itL.Value());
587       for (; it.More(); it.Next()) {
588         TopoDS_Shape s = it.Value();
589         if (aMapOfShape.Add(s)) {
590           aListOfShape.Append(s);
591           nbTypesCopy[s.ShapeType()]++;
592         }
593       }
594     }
595
596     bool isEqual = true;
597     for (iType = 0; iType < TopAbs_SHAPE && isEqual; ++iType) {
598       if (nbTypes[iType] != nbTypesCopy[iType])
599         isEqual = false;
600     }
601     if (isEqual)
602       aShape = aShapeCopy;
603   }
604   // END: Mantis issue 0021060
605
606   return aShape;
607 }
608
609 //================================================================================
610 /*!
611  * \brief Returns a name of creation operation and names and values of creation parameters
612  */
613 //================================================================================
614
615 bool GEOMImpl_BooleanDriver::
616 GetCreationInformation(std::string&             theOperationName,
617                        std::vector<GEOM_Param>& theParams)
618 {
619   if (Label().IsNull()) return 0;
620   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
621
622   GEOMImpl_IBoolean aCI (function);
623   Standard_Integer aType = function->GetType();
624
625   switch ( aType ) {
626   case BOOLEAN_COMMON:
627     theOperationName = "COMMON";
628     AddParam( theParams, "Object 1", aCI.GetShape1() );
629     AddParam( theParams, "Object 2", aCI.GetShape2() );
630     break;
631   case BOOLEAN_CUT:
632     theOperationName = "CUT";
633     AddParam( theParams, "Main Object", aCI.GetShape1() );
634     AddParam( theParams, "Tool Object", aCI.GetShape2() );
635     break;
636   case BOOLEAN_FUSE:
637     theOperationName = "FUSE";
638     AddParam( theParams, "Object 1", aCI.GetShape1() );
639     AddParam( theParams, "Object 2", aCI.GetShape2() );
640     break;
641   case BOOLEAN_SECTION:
642     theOperationName = "SECTION";
643     AddParam( theParams, "Object 1", aCI.GetShape1() );
644     AddParam( theParams, "Object 2", aCI.GetShape2() );
645     break;
646   case BOOLEAN_COMMON_LIST:
647     theOperationName = "COMMON";
648     AddParam( theParams, "Selected objects", aCI.GetShapes() );
649     break;
650   case BOOLEAN_FUSE_LIST:
651     theOperationName = "FUSE";
652     AddParam( theParams, "Selected objects", aCI.GetShapes() );
653     break;
654   case BOOLEAN_CUT_LIST:
655     theOperationName = "CUT";
656     AddParam( theParams, "Main Object", aCI.GetShape1() );
657     AddParam( theParams, "Tool Objects", aCI.GetShapes() );
658     break;
659   default:
660     return false;
661   }
662
663   return true;
664 }
665
666 IMPLEMENT_STANDARD_HANDLE (GEOMImpl_BooleanDriver,GEOM_BaseDriver);
667
668 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_BooleanDriver,GEOM_BaseDriver);