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