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