Salome HOME
33744cce56334d637cb4935134c3a809064fcd8a
[modules/geom.git] / src / GEOMImpl / GEOMImpl_IBooleanOperations.cxx
1 //  Copyright (C) 2007-2008  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 #include <Standard_Stream.hxx>
23
24 #include <GEOMImpl_IBooleanOperations.hxx>
25
26 #include <GEOM_Function.hxx>
27 #include <GEOM_PythonDump.hxx>
28
29 #include <GEOMImpl_Types.hxx>
30
31 #include <GEOMImpl_BooleanDriver.hxx>
32 #include <GEOMImpl_IBoolean.hxx>
33
34 #include <GEOMImpl_PartitionDriver.hxx>
35 #include <GEOMImpl_IPartition.hxx>
36
37 #include <TDF_Tool.hxx>
38
39 #include "utilities.h"
40
41 #include <Standard_Failure.hxx>
42 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
43
44 //=============================================================================
45 /*!
46  *   constructor:
47  */
48 //=============================================================================
49 GEOMImpl_IBooleanOperations::GEOMImpl_IBooleanOperations (GEOM_Engine* theEngine, int theDocID)
50 : GEOM_IOperations(theEngine, theDocID)
51 {
52   MESSAGE("GEOMImpl_IBooleanOperations::GEOMImpl_IBooleanOperations");
53 }
54
55 //=============================================================================
56 /*!
57  *  destructor
58  */
59 //=============================================================================
60 GEOMImpl_IBooleanOperations::~GEOMImpl_IBooleanOperations()
61 {
62   MESSAGE("GEOMImpl_IBooleanOperations::~GEOMImpl_IBooleanOperations");
63 }
64
65
66 //=============================================================================
67 /*!
68  *  MakeBoolean
69  */
70 //=============================================================================
71 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeBoolean (Handle(GEOM_Object) theShape1,
72                                                               Handle(GEOM_Object) theShape2,
73                                                               Standard_Integer    theOp)
74 {
75   SetErrorCode(KO);
76
77   if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
78
79   //Add a new Boolean object
80   Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN);
81
82   //Add a new Boolean function
83   Handle(GEOM_Function) aFunction;
84   if (theOp == 1) {
85     aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_COMMON);
86   } else if (theOp == 2) {
87     aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_CUT);
88   } else if (theOp == 3) {
89     aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_FUSE);
90   } else if (theOp == 4) {
91     aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_SECTION);
92   } else {
93   }
94   if (aFunction.IsNull()) return NULL;
95
96   //Check if the function is set correctly
97   if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
98
99   GEOMImpl_IBoolean aCI (aFunction);
100
101   Handle(GEOM_Function) aRef1 = theShape1->GetLastFunction();
102   Handle(GEOM_Function) aRef2 = theShape2->GetLastFunction();
103
104   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
105
106   aCI.SetShape1(aRef1);
107   aCI.SetShape2(aRef2);
108
109   //Compute the Boolean value
110   try {
111 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
112     OCC_CATCH_SIGNALS;
113 #endif
114     if (!GetSolver()->ComputeFunction(aFunction)) {
115       SetErrorCode("Boolean driver failed");
116       return NULL;
117     }
118   }
119   catch (Standard_Failure) {
120     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
121     SetErrorCode(aFail->GetMessageString());
122     return NULL;
123   }
124
125   //Make a Python command
126   GEOM::TPythonDump pd (aFunction);
127   pd << aBool;
128   if      (theOp == 1) pd << " = geompy.MakeCommon(";
129   else if (theOp == 2) pd << " = geompy.MakeCut(";
130   else if (theOp == 3) pd << " = geompy.MakeFuse(";
131   else if (theOp == 4) pd << " = geompy.MakeSection(";
132   else {}
133   pd << theShape1 << ", " << theShape2 << ")";
134
135   SetErrorCode(OK);
136   return aBool;
137 }
138
139 //=============================================================================
140 /*!
141  *  MakePartition
142  */
143 //=============================================================================
144 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakePartition
145                              (const Handle(TColStd_HSequenceOfTransient)& theShapes,
146                               const Handle(TColStd_HSequenceOfTransient)& theTools,
147                               const Handle(TColStd_HSequenceOfTransient)& theKeepIns,
148                               const Handle(TColStd_HSequenceOfTransient)& theRemoveIns,
149                               const Standard_Integer                      theLimit,
150                               const Standard_Boolean                      theRemoveWebs,
151                               const Handle(TColStd_HArray1OfInteger)&     theMaterials,
152                               const Standard_Integer theKeepNonlimitShapes,
153                               const Standard_Boolean thePerformSelfIntersections)
154 {
155   SetErrorCode(KO);
156
157   //Add a new Partition object
158   Handle(GEOM_Object) aPartition = GetEngine()->AddObject(GetDocID(), GEOM_PARTITION);
159
160   //Add a new Partition function
161   Handle(GEOM_Function) aFunction;
162   if (thePerformSelfIntersections)
163     aFunction = aPartition->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_PARTITION);
164   else
165     aFunction = aPartition->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_NO_SELF_INTERSECTIONS);
166   if (aFunction.IsNull()) return NULL;
167
168   //Check if the function is set correctly
169   if (aFunction->GetDriverGUID() != GEOMImpl_PartitionDriver::GetID()) return NULL;
170
171   GEOMImpl_IPartition aCI (aFunction);
172
173   Handle(TColStd_HSequenceOfTransient) aShapesSeq  = new TColStd_HSequenceOfTransient;
174   Handle(TColStd_HSequenceOfTransient) aToolsSeq   = new TColStd_HSequenceOfTransient;
175   Handle(TColStd_HSequenceOfTransient) aKeepInsSeq = new TColStd_HSequenceOfTransient;
176   Handle(TColStd_HSequenceOfTransient) aRemInsSeq  = new TColStd_HSequenceOfTransient;
177
178   Standard_Integer ind, aLen;
179   TCollection_AsciiString anEntry;
180   TCollection_AsciiString aShapesDescr, aToolsDescr, aKeepInsDescr, aRemoveInsDescr;
181
182   // Shapes
183   aLen = theShapes->Length();
184   for (ind = 1; ind <= aLen; ind++) {
185     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theShapes->Value(ind));
186     Handle(GEOM_Function) aRefSh = anObj->GetLastFunction();
187     if (aRefSh.IsNull()) {
188       SetErrorCode("NULL shape for Partition");
189       return NULL;
190     }
191     aShapesSeq->Append(aRefSh);
192
193     // For Python command
194     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
195     if (ind > 1) aShapesDescr += ", ";
196     aShapesDescr += anEntry;
197   }
198   aCI.SetShapes(aShapesSeq);
199
200   // Tools
201   aLen = theTools->Length();
202   for (ind = 1; ind <= aLen; ind++) {
203     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theTools->Value(ind));
204     Handle(GEOM_Function) aRefSh = anObj->GetLastFunction();
205     if (aRefSh.IsNull()) {
206       SetErrorCode("NULL tool shape for Partition");
207       return NULL;
208     }
209     aToolsSeq->Append(aRefSh);
210
211     // For Python command
212     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
213     if (ind > 1) aToolsDescr += ", ";
214     aToolsDescr += anEntry;
215   }
216   aCI.SetTools(aToolsSeq);
217
218   // Keep Inside
219   aLen = theKeepIns->Length();
220   for (ind = 1; ind <= aLen; ind++) {
221     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theKeepIns->Value(ind));
222     Handle(GEOM_Function) aRefSh = anObj->GetLastFunction();
223     if (aRefSh.IsNull()) {
224       SetErrorCode("NULL <keep inside> shape for Partition");
225       return NULL;
226     }
227     aKeepInsSeq->Append(aRefSh);
228
229     // For Python command
230     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
231     if (ind > 1) aKeepInsDescr += ", ";
232     aKeepInsDescr += anEntry;
233   }
234   aCI.SetKeepIns(aKeepInsSeq);
235
236   // Remove Inside
237   aLen = theRemoveIns->Length();
238   for (ind = 1; ind <= aLen; ind++) {
239     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theRemoveIns->Value(ind));
240     Handle(GEOM_Function) aRefSh = anObj->GetLastFunction();
241     if (aRefSh.IsNull()) {
242       SetErrorCode("NULL <remove inside> shape for Partition");
243       return NULL;
244     }
245     aRemInsSeq->Append(aRefSh);
246
247     // For Python command
248     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
249     if (ind > 1) aRemoveInsDescr += ", ";
250     aRemoveInsDescr += anEntry;
251   }
252   aCI.SetRemoveIns(aRemInsSeq);
253
254   // Limit
255   aCI.SetLimit(theLimit);
256   aCI.SetKeepNonlimitShapes(theKeepNonlimitShapes);
257
258   // Materials
259   if (theRemoveWebs) {
260     if (theMaterials.IsNull()) {
261       Handle(TColStd_HArray1OfInteger) aMaterials =
262         new TColStd_HArray1OfInteger (1, aShapesSeq->Length());
263       aMaterials->Init(0);
264       aCI.SetMaterials(aMaterials);
265     } else {
266       aCI.SetMaterials(theMaterials);
267     }
268   }
269
270   //Compute the Partition
271   try {
272 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
273     OCC_CATCH_SIGNALS;
274 #endif
275     if (!GetSolver()->ComputeFunction(aFunction)) {
276       SetErrorCode("Partition driver failed");
277       return NULL;
278     }
279   }
280   catch (Standard_Failure) {
281     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
282     SetErrorCode(aFail->GetMessageString());
283     return NULL;
284   }
285
286   //Make a Python command
287   GEOM::TPythonDump pd (aFunction);
288   if (thePerformSelfIntersections)
289     pd << aPartition << " = geompy.MakePartition([";
290   else
291     pd << aPartition << " = geompy.MakePartitionNonSelfIntersectedShape([";
292
293   // Shapes, Tools
294   pd << aShapesDescr.ToCString() << "], [" << aToolsDescr.ToCString() << "], [";
295   // Keep Ins, Remove Ins
296   pd << aKeepInsDescr.ToCString() << "], [" << aRemoveInsDescr.ToCString() << "], ";
297   // Limit, Remove Webs
298   pd << TopAbs_ShapeEnum(theLimit) << ", " << (int)theRemoveWebs << ", [";
299   // Materials
300   if (!theMaterials.IsNull() && theMaterials->Length() > 0) {
301     int i = theMaterials->Lower();
302     pd << theMaterials->Value(i);
303     i++;
304     for (; i <= theMaterials->Upper(); i++) {
305       pd << ", " << theMaterials->Value(i);
306     }
307   }
308   pd << "], " << theKeepNonlimitShapes <<")";
309
310   SetErrorCode(OK);
311   return aPartition;
312 }
313
314 //=============================================================================
315 /*!
316  *  MakeHalfPartition
317  */
318 //=============================================================================
319 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeHalfPartition
320        (Handle(GEOM_Object) theShape, Handle(GEOM_Object) thePlane)
321 {
322   SetErrorCode(KO);
323
324   if (theShape.IsNull() || thePlane.IsNull()) return NULL;
325
326   //Add a new Boolean object
327   Handle(GEOM_Object) aPart = GetEngine()->AddObject(GetDocID(), GEOM_PARTITION);
328
329   //Add a new Partition function
330   Handle(GEOM_Function) aFunction =
331     aPart->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_HALF);
332   if (aFunction.IsNull()) return NULL;
333
334   //Check if the function is set correctly
335   if (aFunction->GetDriverGUID() != GEOMImpl_PartitionDriver::GetID()) return NULL;
336
337   GEOMImpl_IPartition aCI (aFunction);
338
339   Handle(GEOM_Function) aRef1 = theShape->GetLastFunction();
340   Handle(GEOM_Function) aRef2 = thePlane->GetLastFunction();
341
342   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
343
344   aCI.SetShape(aRef1);
345   aCI.SetPlane(aRef2);
346
347   //Compute the Partition value
348   try {
349 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
350     OCC_CATCH_SIGNALS;
351 #endif
352     if (!GetSolver()->ComputeFunction(aFunction)) {
353       SetErrorCode("Partition driver failed");
354       return NULL;
355     }
356   }
357   catch (Standard_Failure) {
358     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
359     SetErrorCode(aFail->GetMessageString());
360     return NULL;
361   }
362
363   //Make a Python command
364   GEOM::TPythonDump(aFunction) << aPart << " = geompy.MakeHalfPartition("
365                                << theShape << ", " << thePlane << ")";
366
367   SetErrorCode(OK);
368   return aPart;
369 }