Salome HOME
Merge from V6_main 01/04/2013
[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  *  MakePartition
145  */
146 //=============================================================================
147 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakePartition
148                              (const Handle(TColStd_HSequenceOfTransient)& theShapes,
149                               const Handle(TColStd_HSequenceOfTransient)& theTools,
150                               const Handle(TColStd_HSequenceOfTransient)& theKeepIns,
151                               const Handle(TColStd_HSequenceOfTransient)& theRemoveIns,
152                               const Standard_Integer                      theLimit,
153                               const Standard_Boolean                      theRemoveWebs,
154                               const Handle(TColStd_HArray1OfInteger)&     theMaterials,
155                               const Standard_Integer theKeepNonlimitShapes,
156                               const Standard_Boolean thePerformSelfIntersections)
157 {
158   SetErrorCode(KO);
159
160   //Add a new Partition object
161   Handle(GEOM_Object) aPartition = GetEngine()->AddObject(GetDocID(), GEOM_PARTITION);
162
163   //Add a new Partition function
164   Handle(GEOM_Function) aFunction;
165   if (thePerformSelfIntersections)
166     aFunction = aPartition->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_PARTITION);
167   else
168     aFunction = aPartition->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_NO_SELF_INTERSECTIONS);
169   if (aFunction.IsNull()) return NULL;
170
171   //Check if the function is set correctly
172   if (aFunction->GetDriverGUID() != GEOMImpl_PartitionDriver::GetID()) return NULL;
173
174   GEOMImpl_IPartition aCI (aFunction);
175
176   Handle(TColStd_HSequenceOfTransient) aShapesSeq  = new TColStd_HSequenceOfTransient;
177   Handle(TColStd_HSequenceOfTransient) aToolsSeq   = new TColStd_HSequenceOfTransient;
178   Handle(TColStd_HSequenceOfTransient) aKeepInsSeq = new TColStd_HSequenceOfTransient;
179   Handle(TColStd_HSequenceOfTransient) aRemInsSeq  = new TColStd_HSequenceOfTransient;
180
181   Standard_Integer ind, aLen;
182   TCollection_AsciiString anEntry;
183   TCollection_AsciiString aShapesDescr, aToolsDescr, aKeepInsDescr, aRemoveInsDescr;
184
185   // Shapes
186   aLen = theShapes->Length();
187   for (ind = 1; ind <= aLen; ind++) {
188     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theShapes->Value(ind));
189     Handle(GEOM_Function) aRefSh = anObj->GetLastFunction();
190     if (aRefSh.IsNull()) {
191       SetErrorCode("NULL shape for Partition");
192       return NULL;
193     }
194     aShapesSeq->Append(aRefSh);
195
196     // For Python command
197     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
198     if (ind > 1) aShapesDescr += ", ";
199     aShapesDescr += anEntry;
200   }
201   aCI.SetShapes(aShapesSeq);
202
203   // Tools
204   aLen = theTools->Length();
205   for (ind = 1; ind <= aLen; ind++) {
206     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theTools->Value(ind));
207     Handle(GEOM_Function) aRefSh = anObj->GetLastFunction();
208     if (aRefSh.IsNull()) {
209       SetErrorCode("NULL tool shape for Partition");
210       return NULL;
211     }
212     aToolsSeq->Append(aRefSh);
213
214     // For Python command
215     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
216     if (ind > 1) aToolsDescr += ", ";
217     aToolsDescr += anEntry;
218   }
219   aCI.SetTools(aToolsSeq);
220
221   // Keep Inside
222   aLen = theKeepIns->Length();
223   for (ind = 1; ind <= aLen; ind++) {
224     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theKeepIns->Value(ind));
225     Handle(GEOM_Function) aRefSh = anObj->GetLastFunction();
226     if (aRefSh.IsNull()) {
227       SetErrorCode("NULL <keep inside> shape for Partition");
228       return NULL;
229     }
230     aKeepInsSeq->Append(aRefSh);
231
232     // For Python command
233     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
234     if (ind > 1) aKeepInsDescr += ", ";
235     aKeepInsDescr += anEntry;
236   }
237   aCI.SetKeepIns(aKeepInsSeq);
238
239   // Remove Inside
240   aLen = theRemoveIns->Length();
241   for (ind = 1; ind <= aLen; ind++) {
242     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theRemoveIns->Value(ind));
243     Handle(GEOM_Function) aRefSh = anObj->GetLastFunction();
244     if (aRefSh.IsNull()) {
245       SetErrorCode("NULL <remove inside> shape for Partition");
246       return NULL;
247     }
248     aRemInsSeq->Append(aRefSh);
249
250     // For Python command
251     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
252     if (ind > 1) aRemoveInsDescr += ", ";
253     aRemoveInsDescr += anEntry;
254   }
255   aCI.SetRemoveIns(aRemInsSeq);
256
257   // Limit
258   aCI.SetLimit(theLimit);
259   aCI.SetKeepNonlimitShapes(theKeepNonlimitShapes);
260
261   // Materials
262   if (theRemoveWebs) {
263     if (theMaterials.IsNull()) {
264       Handle(TColStd_HArray1OfInteger) aMaterials =
265         new TColStd_HArray1OfInteger (1, aShapesSeq->Length());
266       aMaterials->Init(0);
267       aCI.SetMaterials(aMaterials);
268     } else {
269       aCI.SetMaterials(theMaterials);
270     }
271   }
272
273   //Compute the Partition
274   try {
275 #if OCC_VERSION_LARGE > 0x06010000
276     OCC_CATCH_SIGNALS;
277 #endif
278     if (!GetSolver()->ComputeFunction(aFunction)) {
279       SetErrorCode("Partition driver failed");
280       return NULL;
281     }
282   }
283   catch (Standard_Failure) {
284     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
285     SetErrorCode(aFail->GetMessageString());
286     return NULL;
287   }
288
289   //Make a Python command
290   GEOM::TPythonDump pd (aFunction);
291   if (thePerformSelfIntersections)
292     pd << aPartition << " = geompy.MakePartition([";
293   else
294     pd << aPartition << " = geompy.MakePartitionNonSelfIntersectedShape([";
295
296   // Shapes, Tools
297   pd << aShapesDescr.ToCString() << "], [" << aToolsDescr.ToCString() << "], [";
298   // Keep Ins, Remove Ins
299   pd << aKeepInsDescr.ToCString() << "], [" << aRemoveInsDescr.ToCString() << "], ";
300   // Limit, Remove Webs
301   pd << TopAbs_ShapeEnum(theLimit) << ", " << (int)theRemoveWebs << ", [";
302   // Materials
303   if (!theMaterials.IsNull() && theMaterials->Length() > 0) {
304     int i = theMaterials->Lower();
305     pd << theMaterials->Value(i);
306     i++;
307     for (; i <= theMaterials->Upper(); i++) {
308       pd << ", " << theMaterials->Value(i);
309     }
310   }
311   pd << "], " << theKeepNonlimitShapes <<")";
312
313   SetErrorCode(OK);
314   return aPartition;
315 }
316
317 //=============================================================================
318 /*!
319  *  MakeHalfPartition
320  */
321 //=============================================================================
322 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeHalfPartition
323        (Handle(GEOM_Object) theShape, Handle(GEOM_Object) thePlane)
324 {
325   SetErrorCode(KO);
326
327   if (theShape.IsNull() || thePlane.IsNull()) return NULL;
328
329   //Add a new Boolean object
330   Handle(GEOM_Object) aPart = GetEngine()->AddObject(GetDocID(), GEOM_PARTITION);
331
332   //Add a new Partition function
333   Handle(GEOM_Function) aFunction =
334     aPart->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_HALF);
335   if (aFunction.IsNull()) return NULL;
336
337   //Check if the function is set correctly
338   if (aFunction->GetDriverGUID() != GEOMImpl_PartitionDriver::GetID()) return NULL;
339
340   GEOMImpl_IPartition aCI (aFunction);
341
342   Handle(GEOM_Function) aRef1 = theShape->GetLastFunction();
343   Handle(GEOM_Function) aRef2 = thePlane->GetLastFunction();
344
345   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
346
347   aCI.SetShape(aRef1);
348   aCI.SetPlane(aRef2);
349
350   //Compute the Partition value
351   try {
352 #if OCC_VERSION_LARGE > 0x06010000
353     OCC_CATCH_SIGNALS;
354 #endif
355     if (!GetSolver()->ComputeFunction(aFunction)) {
356       SetErrorCode("Partition driver failed");
357       return NULL;
358     }
359   }
360   catch (Standard_Failure) {
361     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
362     SetErrorCode(aFail->GetMessageString());
363     return NULL;
364   }
365
366   //Make a Python command
367   GEOM::TPythonDump(aFunction) << aPart << " = geompy.MakeHalfPartition("
368                                << theShape << ", " << thePlane << ")";
369
370   SetErrorCode(OK);
371   return aPart;
372 }