]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_IBooleanOperations.cxx
Salome HOME
0022081: EDF 2386 GEOM: Union of a list of objects
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IBooleanOperations.cxx
1 // Copyright (C) 2007-2013  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.
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 <Standard_Stream.hxx>
24
25 #include <GEOMImpl_IBooleanOperations.hxx>
26
27 #include <GEOM_Function.hxx>
28 #include <GEOM_PythonDump.hxx>
29
30 #include <GEOMImpl_Types.hxx>
31
32 #include <GEOMImpl_BooleanDriver.hxx>
33 #include <GEOMImpl_IBoolean.hxx>
34
35 #include <GEOMImpl_PartitionDriver.hxx>
36 #include <GEOMImpl_IPartition.hxx>
37
38 #include <Basics_OCCTVersion.hxx>
39
40 #include <TDF_Tool.hxx>
41
42 #include "utilities.h"
43
44 #include <Standard_Failure.hxx>
45 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
46
47 //=============================================================================
48 /*!
49  *   constructor:
50  */
51 //=============================================================================
52 GEOMImpl_IBooleanOperations::GEOMImpl_IBooleanOperations (GEOM_Engine* theEngine, int theDocID)
53 : GEOM_IOperations(theEngine, theDocID)
54 {
55   MESSAGE("GEOMImpl_IBooleanOperations::GEOMImpl_IBooleanOperations");
56 }
57
58 //=============================================================================
59 /*!
60  *  destructor
61  */
62 //=============================================================================
63 GEOMImpl_IBooleanOperations::~GEOMImpl_IBooleanOperations()
64 {
65   MESSAGE("GEOMImpl_IBooleanOperations::~GEOMImpl_IBooleanOperations");
66 }
67
68
69 //=============================================================================
70 /*!
71  *  MakeBoolean
72  */
73 //=============================================================================
74 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeBoolean (Handle(GEOM_Object) theShape1,
75                                                               Handle(GEOM_Object) theShape2,
76                                                               Standard_Integer    theOp)
77 {
78   SetErrorCode(KO);
79
80   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
81
82   //Add a new Boolean object
83   Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN);
84
85   //Add a new Boolean function
86   Handle(GEOM_Function) aFunction;
87   if (theOp == 1) {
88     aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_COMMON);
89   } else if (theOp == 2) {
90     aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_CUT);
91   } else if (theOp == 3) {
92     aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_FUSE);
93   } else if (theOp == 4) {
94     aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_SECTION);
95   } else {
96   }
97   if (aFunction.IsNull()) return NULL;
98
99   //Check if the function is set correctly
100   if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
101
102   GEOMImpl_IBoolean aCI (aFunction);
103
104   Handle(GEOM_Function) aRef1 = theShape1->GetLastFunction();
105   Handle(GEOM_Function) aRef2 = theShape2->GetLastFunction();
106
107   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
108
109   aCI.SetShape1(aRef1);
110   aCI.SetShape2(aRef2);
111
112   //Compute the Boolean value
113   try {
114 #if OCC_VERSION_LARGE > 0x06010000
115     OCC_CATCH_SIGNALS;
116 #endif
117     if (!GetSolver()->ComputeFunction(aFunction)) {
118       SetErrorCode("Boolean driver failed");
119       return NULL;
120     }
121   }
122   catch (Standard_Failure) {
123     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
124     SetErrorCode(aFail->GetMessageString());
125     return NULL;
126   }
127
128   //Make a Python command
129   GEOM::TPythonDump pd (aFunction);
130   pd << aBool;
131   if      (theOp == 1) pd << " = geompy.MakeCommon(";
132   else if (theOp == 2) pd << " = geompy.MakeCut(";
133   else if (theOp == 3) pd << " = geompy.MakeFuse(";
134   else if (theOp == 4) pd << " = geompy.MakeSection(";
135   else {}
136   pd << theShape1 << ", " << theShape2 << ")";
137
138   SetErrorCode(OK);
139   return aBool;
140 }
141
142 //=============================================================================
143 /*!
144  *  MakeFuseList
145  */
146 //=============================================================================
147 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeFuseList
148                   (const Handle(TColStd_HSequenceOfTransient)& theShapes)
149 {
150   SetErrorCode(KO);
151
152   if (theShapes.IsNull()) return NULL;
153
154   //Add a new Boolean object
155   Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN);
156
157   //Add a new Boolean function
158   Handle(GEOM_Function) aFunction =
159     aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_FUSE_LIST);
160
161   if (aFunction.IsNull()) return NULL;
162
163   //Check if the function is set correctly
164   if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
165
166   GEOMImpl_IBoolean aCI (aFunction);
167
168   TCollection_AsciiString aDescription;
169   Handle(TColStd_HSequenceOfTransient) aShapesSeq =
170     getShapeFunctions(theShapes, aDescription);
171
172   if (aShapesSeq.IsNull()) return NULL;
173
174   aCI.SetShapes(aShapesSeq);
175
176   //Compute the Boolean value
177   try {
178 #if OCC_VERSION_LARGE > 0x06010000
179     OCC_CATCH_SIGNALS;
180 #endif
181     if (!GetSolver()->ComputeFunction(aFunction)) {
182       SetErrorCode("Boolean driver failed");
183       return NULL;
184     }
185   }
186   catch (Standard_Failure) {
187     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
188     SetErrorCode(aFail->GetMessageString());
189     return NULL;
190   }
191
192   //Make a Python command
193   GEOM::TPythonDump(aFunction) << aBool <<
194     " = geompy.MakeFuseList([" << aDescription.ToCString() << "])";
195
196   SetErrorCode(OK);
197   return aBool;
198 }
199
200 //=============================================================================
201 /*!
202  *  MakeCommonList
203  */
204 //=============================================================================
205 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeCommonList
206                   (const Handle(TColStd_HSequenceOfTransient)& theShapes)
207 {
208   SetErrorCode(KO);
209
210   if (theShapes.IsNull()) return NULL;
211
212   //Add a new Boolean object
213   Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN);
214
215   //Add a new Boolean function
216   Handle(GEOM_Function) aFunction =
217     aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_COMMON_LIST);
218
219   if (aFunction.IsNull()) return NULL;
220
221   //Check if the function is set correctly
222   if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
223
224   GEOMImpl_IBoolean aCI (aFunction);
225
226   TCollection_AsciiString aDescription;
227   Handle(TColStd_HSequenceOfTransient) aShapesSeq =
228     getShapeFunctions(theShapes, aDescription);
229
230   if (aShapesSeq.IsNull()) return NULL;
231
232   aCI.SetShapes(aShapesSeq);
233
234   //Compute the Boolean value
235   try {
236 #if OCC_VERSION_LARGE > 0x06010000
237     OCC_CATCH_SIGNALS;
238 #endif
239     if (!GetSolver()->ComputeFunction(aFunction)) {
240       SetErrorCode("Boolean driver failed");
241       return NULL;
242     }
243   }
244   catch (Standard_Failure) {
245     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
246     SetErrorCode(aFail->GetMessageString());
247     return NULL;
248   }
249
250   //Make a Python command
251   GEOM::TPythonDump(aFunction) << aBool <<
252     " = geompy.MakeCommonList([" << aDescription.ToCString() << "])";
253
254   SetErrorCode(OK);
255   return aBool;
256 }
257
258 //=============================================================================
259 /*!
260  *  MakeCutList
261  */
262 //=============================================================================
263 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeCutList
264                   (Handle(GEOM_Object) theMainShape,
265                    const Handle(TColStd_HSequenceOfTransient)& theShapes)
266 {
267   SetErrorCode(KO);
268
269   if (theShapes.IsNull()) return NULL;
270
271   //Add a new Boolean object
272   Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN);
273
274   //Add a new Boolean function
275   Handle(GEOM_Function) aFunction =
276     aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_CUT_LIST);
277
278   if (aFunction.IsNull()) return NULL;
279
280   //Check if the function is set correctly
281   if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
282
283   GEOMImpl_IBoolean aCI (aFunction);
284   Handle(GEOM_Function) aMainRef = theMainShape->GetLastFunction();
285
286   if (aMainRef.IsNull()) return NULL;
287
288   TCollection_AsciiString aDescription;
289   Handle(TColStd_HSequenceOfTransient) aShapesSeq =
290     getShapeFunctions(theShapes, aDescription);
291
292   if (aShapesSeq.IsNull()) return NULL;
293
294   aCI.SetShape1(aMainRef);
295   aCI.SetShapes(aShapesSeq);
296
297   //Compute the Boolean value
298   try {
299 #if OCC_VERSION_LARGE > 0x06010000
300     OCC_CATCH_SIGNALS;
301 #endif
302     if (!GetSolver()->ComputeFunction(aFunction)) {
303       SetErrorCode("Boolean driver failed");
304       return NULL;
305     }
306   }
307   catch (Standard_Failure) {
308     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
309     SetErrorCode(aFail->GetMessageString());
310     return NULL;
311   }
312
313   //Make a Python command
314   GEOM::TPythonDump(aFunction) << aBool << " = geompy.MakeCutList("
315     << theMainShape << ", [" << aDescription.ToCString() << "])";
316
317   SetErrorCode(OK);
318   return aBool;
319 }
320
321 //=============================================================================
322 /*!
323  *  MakePartition
324  */
325 //=============================================================================
326 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakePartition
327                              (const Handle(TColStd_HSequenceOfTransient)& theShapes,
328                               const Handle(TColStd_HSequenceOfTransient)& theTools,
329                               const Handle(TColStd_HSequenceOfTransient)& theKeepIns,
330                               const Handle(TColStd_HSequenceOfTransient)& theRemoveIns,
331                               const Standard_Integer                      theLimit,
332                               const Standard_Boolean                      theRemoveWebs,
333                               const Handle(TColStd_HArray1OfInteger)&     theMaterials,
334                               const Standard_Integer theKeepNonlimitShapes,
335                               const Standard_Boolean thePerformSelfIntersections)
336 {
337   SetErrorCode(KO);
338
339   //Add a new Partition object
340   Handle(GEOM_Object) aPartition = GetEngine()->AddObject(GetDocID(), GEOM_PARTITION);
341
342   //Add a new Partition function
343   Handle(GEOM_Function) aFunction;
344   if (thePerformSelfIntersections)
345     aFunction = aPartition->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_PARTITION);
346   else
347     aFunction = aPartition->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_NO_SELF_INTERSECTIONS);
348   if (aFunction.IsNull()) return NULL;
349
350   //Check if the function is set correctly
351   if (aFunction->GetDriverGUID() != GEOMImpl_PartitionDriver::GetID()) return NULL;
352
353   GEOMImpl_IPartition aCI (aFunction);
354
355   Handle(TColStd_HSequenceOfTransient) aShapesSeq;
356   Handle(TColStd_HSequenceOfTransient) aToolsSeq;
357   Handle(TColStd_HSequenceOfTransient) aKeepInsSeq;
358   Handle(TColStd_HSequenceOfTransient) aRemInsSeq;
359   TCollection_AsciiString aShapesDescr, aToolsDescr, aKeepInsDescr, aRemoveInsDescr;
360
361   // Shapes
362   aShapesSeq = getShapeFunctions(theShapes, aShapesDescr);
363
364   if (aShapesSeq.IsNull()) {
365     SetErrorCode("NULL shape for Partition");
366     return NULL;
367   }
368
369   // Tools
370   aToolsSeq = getShapeFunctions(theTools, aToolsDescr);
371
372   if (aToolsSeq.IsNull()) {
373     SetErrorCode("NULL tool shape for Partition");
374     return NULL;
375   }
376
377   // Keep Inside
378   aKeepInsSeq = getShapeFunctions(theKeepIns, aKeepInsDescr);
379
380   if (aKeepInsSeq.IsNull()) {
381     SetErrorCode("NULL <keep inside> shape for Partition");
382     return NULL;
383   }
384
385   // Remove Inside
386   aRemInsSeq  = getShapeFunctions(theRemoveIns, aRemoveInsDescr);
387
388   if (aRemInsSeq.IsNull()) {
389     SetErrorCode("NULL <remove inside> shape for Partition");
390     return NULL;
391   }
392
393   aCI.SetShapes(aShapesSeq);
394   aCI.SetTools(aToolsSeq);
395   aCI.SetKeepIns(aKeepInsSeq);
396   aCI.SetRemoveIns(aRemInsSeq);
397
398   // Limit
399   aCI.SetLimit(theLimit);
400   aCI.SetKeepNonlimitShapes(theKeepNonlimitShapes);
401
402   // Materials
403   if (theRemoveWebs) {
404     if (theMaterials.IsNull()) {
405       Handle(TColStd_HArray1OfInteger) aMaterials =
406         new TColStd_HArray1OfInteger (1, aShapesSeq->Length());
407       aMaterials->Init(0);
408       aCI.SetMaterials(aMaterials);
409     } else {
410       aCI.SetMaterials(theMaterials);
411     }
412   }
413
414   //Compute the Partition
415   try {
416 #if OCC_VERSION_LARGE > 0x06010000
417     OCC_CATCH_SIGNALS;
418 #endif
419     if (!GetSolver()->ComputeFunction(aFunction)) {
420       SetErrorCode("Partition driver failed");
421       return NULL;
422     }
423   }
424   catch (Standard_Failure) {
425     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
426     SetErrorCode(aFail->GetMessageString());
427     return NULL;
428   }
429
430   //Make a Python command
431   GEOM::TPythonDump pd (aFunction);
432   if (thePerformSelfIntersections)
433     pd << aPartition << " = geompy.MakePartition([";
434   else
435     pd << aPartition << " = geompy.MakePartitionNonSelfIntersectedShape([";
436
437   // Shapes, Tools
438   pd << aShapesDescr.ToCString() << "], [" << aToolsDescr.ToCString() << "], [";
439   // Keep Ins, Remove Ins
440   pd << aKeepInsDescr.ToCString() << "], [" << aRemoveInsDescr.ToCString() << "], ";
441   // Limit, Remove Webs
442   pd << TopAbs_ShapeEnum(theLimit) << ", " << (int)theRemoveWebs << ", [";
443   // Materials
444   if (!theMaterials.IsNull() && theMaterials->Length() > 0) {
445     int i = theMaterials->Lower();
446     pd << theMaterials->Value(i);
447     i++;
448     for (; i <= theMaterials->Upper(); i++) {
449       pd << ", " << theMaterials->Value(i);
450     }
451   }
452   pd << "], " << theKeepNonlimitShapes <<")";
453
454   SetErrorCode(OK);
455   return aPartition;
456 }
457
458 //=============================================================================
459 /*!
460  *  MakeHalfPartition
461  */
462 //=============================================================================
463 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeHalfPartition
464        (Handle(GEOM_Object) theShape, Handle(GEOM_Object) thePlane)
465 {
466   SetErrorCode(KO);
467
468   if (theShape.IsNull() || thePlane.IsNull()) return NULL;
469
470   //Add a new Boolean object
471   Handle(GEOM_Object) aPart = GetEngine()->AddObject(GetDocID(), GEOM_PARTITION);
472
473   //Add a new Partition function
474   Handle(GEOM_Function) aFunction =
475     aPart->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_HALF);
476   if (aFunction.IsNull()) return NULL;
477
478   //Check if the function is set correctly
479   if (aFunction->GetDriverGUID() != GEOMImpl_PartitionDriver::GetID()) return NULL;
480
481   GEOMImpl_IPartition aCI (aFunction);
482
483   Handle(GEOM_Function) aRef1 = theShape->GetLastFunction();
484   Handle(GEOM_Function) aRef2 = thePlane->GetLastFunction();
485
486   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
487
488   aCI.SetShape(aRef1);
489   aCI.SetPlane(aRef2);
490
491   //Compute the Partition value
492   try {
493 #if OCC_VERSION_LARGE > 0x06010000
494     OCC_CATCH_SIGNALS;
495 #endif
496     if (!GetSolver()->ComputeFunction(aFunction)) {
497       SetErrorCode("Partition driver failed");
498       return NULL;
499     }
500   }
501   catch (Standard_Failure) {
502     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
503     SetErrorCode(aFail->GetMessageString());
504     return NULL;
505   }
506
507   //Make a Python command
508   GEOM::TPythonDump(aFunction) << aPart << " = geompy.MakeHalfPartition("
509                                << theShape << ", " << thePlane << ")";
510
511   SetErrorCode(OK);
512   return aPart;
513 }
514
515 //=============================================================================
516 /*!
517  *  getShapeFunctions
518  */
519 //=============================================================================
520 Handle(TColStd_HSequenceOfTransient)
521   GEOMImpl_IBooleanOperations::getShapeFunctions
522                   (const Handle(TColStd_HSequenceOfTransient)& theObjects,
523                          TCollection_AsciiString &theDescription)
524 {
525   Handle(TColStd_HSequenceOfTransient) aResult =
526     new TColStd_HSequenceOfTransient;
527   Standard_Integer aNbObjects = theObjects->Length();
528   Standard_Integer i;
529   TCollection_AsciiString anEntry;
530   Handle(GEOM_Object) anObj;
531   Handle(GEOM_Function) aRefObj;
532
533   // Shapes
534   for (i = 1; i <= aNbObjects; i++) {
535     anObj = Handle(GEOM_Object)::DownCast(theObjects->Value(i));
536     aRefObj = anObj->GetLastFunction();
537
538     if (aRefObj.IsNull()) {
539       aResult.Nullify();
540       break;
541     }
542
543     aResult->Append(aRefObj);
544
545     // For Python command
546     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
547
548     if (i > 1) {
549       theDescription += ", ";
550     }
551
552     theDescription += anEntry;
553   }
554
555   return aResult;
556 }