1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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, or (at your option) any later version.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include <Standard_Stream.hxx>
25 #include <GEOMImpl_IBooleanOperations.hxx>
27 #include <GEOM_Function.hxx>
28 #include <GEOM_PythonDump.hxx>
30 #include <GEOMImpl_Types.hxx>
32 #include <GEOMImpl_BooleanDriver.hxx>
33 #include <GEOMImpl_IBoolean.hxx>
35 #include <GEOMImpl_PartitionDriver.hxx>
36 #include <GEOMImpl_IPartition.hxx>
38 #include <Basics_OCCTVersion.hxx>
40 #include <TDF_Tool.hxx>
42 #include "utilities.h"
44 #include <Standard_Failure.hxx>
45 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
47 //=============================================================================
51 //=============================================================================
52 GEOMImpl_IBooleanOperations::GEOMImpl_IBooleanOperations (GEOM_Engine* theEngine, int theDocID)
53 : GEOM_IOperations(theEngine, theDocID)
55 MESSAGE("GEOMImpl_IBooleanOperations::GEOMImpl_IBooleanOperations");
58 //=============================================================================
62 //=============================================================================
63 GEOMImpl_IBooleanOperations::~GEOMImpl_IBooleanOperations()
65 MESSAGE("GEOMImpl_IBooleanOperations::~GEOMImpl_IBooleanOperations");
69 //=============================================================================
73 //=============================================================================
74 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeBoolean
75 (Handle(GEOM_Object) theShape1,
76 Handle(GEOM_Object) theShape2,
77 const Standard_Integer theOp,
78 const Standard_Boolean IsCheckSelfInte)
82 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
84 //Add a new Boolean object
85 Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN);
87 //Add a new Boolean function
88 Handle(GEOM_Function) aFunction;
90 aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_COMMON);
91 } else if (theOp == 2) {
92 aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_CUT);
93 } else if (theOp == 3) {
94 aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_FUSE);
95 } else if (theOp == 4) {
96 aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_SECTION);
99 if (aFunction.IsNull()) return NULL;
101 //Check if the function is set correctly
102 if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
104 GEOMImpl_IBoolean aCI (aFunction);
106 Handle(GEOM_Function) aRef1 = theShape1->GetLastFunction();
107 Handle(GEOM_Function) aRef2 = theShape2->GetLastFunction();
109 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
111 aCI.SetShape1(aRef1);
112 aCI.SetShape2(aRef2);
113 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
115 //Compute the Boolean value
117 #if OCC_VERSION_LARGE > 0x06010000
120 if (!GetSolver()->ComputeFunction(aFunction)) {
121 SetErrorCode("Boolean driver failed");
125 catch (Standard_Failure) {
126 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
127 SetErrorCode(aFail->GetMessageString());
131 //Make a Python command
132 GEOM::TPythonDump pd (aFunction);
134 if (theOp == 1) pd << " = geompy.MakeCommon(";
135 else if (theOp == 2) pd << " = geompy.MakeCut(";
136 else if (theOp == 3) pd << " = geompy.MakeFuse(";
137 else if (theOp == 4) pd << " = geompy.MakeSection(";
139 pd << theShape1 << ", " << theShape2;
141 if (IsCheckSelfInte) {
151 //=============================================================================
155 //=============================================================================
156 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeFuse
157 (Handle(GEOM_Object) theShape1,
158 Handle(GEOM_Object) theShape2,
159 const bool IsCheckSelfInte,
160 const bool IsRmExtraEdges)
164 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
166 //Add a new Boolean object
167 Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN);
169 //Add a new Boolean function
170 Handle(GEOM_Function) aFunction =
171 aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_FUSE);
173 if (aFunction.IsNull()) return NULL;
175 //Check if the function is set correctly
176 if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
178 GEOMImpl_IBoolean aCI (aFunction);
180 Handle(GEOM_Function) aRef1 = theShape1->GetLastFunction();
181 Handle(GEOM_Function) aRef2 = theShape2->GetLastFunction();
183 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
185 aCI.SetShape1(aRef1);
186 aCI.SetShape2(aRef2);
187 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
188 aCI.SetRmExtraEdges(IsRmExtraEdges);
190 //Compute the Boolean value
192 #if OCC_VERSION_LARGE > 0x06010000
195 if (!GetSolver()->ComputeFunction(aFunction)) {
196 SetErrorCode("Boolean driver failed");
200 catch (Standard_Failure) {
201 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
202 SetErrorCode(aFail->GetMessageString());
206 //Make a Python command
207 GEOM::TPythonDump pd (aFunction);
209 pd << aBool << " = geompy.MakeFuse(";
210 pd << theShape1 << ", " << theShape2 << ", "
211 << IsCheckSelfInte << ", " << IsRmExtraEdges << ")";
217 //=============================================================================
221 //=============================================================================
222 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeFuseList
223 (const Handle(TColStd_HSequenceOfTransient)& theShapes,
224 const bool IsCheckSelfInte,
225 const bool IsRmExtraEdges)
229 if (theShapes.IsNull()) return NULL;
231 //Add a new Boolean object
232 Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN);
234 //Add a new Boolean function
235 Handle(GEOM_Function) aFunction =
236 aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_FUSE_LIST);
238 if (aFunction.IsNull()) return NULL;
240 //Check if the function is set correctly
241 if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
243 GEOMImpl_IBoolean aCI (aFunction);
245 TCollection_AsciiString aDescription;
246 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
247 getShapeFunctions(theShapes, aDescription);
249 if (aShapesSeq.IsNull()) return NULL;
251 aCI.SetShapes(aShapesSeq);
252 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
253 aCI.SetRmExtraEdges(IsRmExtraEdges);
255 //Compute the Boolean value
257 #if OCC_VERSION_LARGE > 0x06010000
260 if (!GetSolver()->ComputeFunction(aFunction)) {
261 SetErrorCode("Boolean driver failed");
265 catch (Standard_Failure) {
266 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
267 SetErrorCode(aFail->GetMessageString());
271 //Make a Python command
272 GEOM::TPythonDump pd (aFunction);
274 pd << aBool << " = geompy.MakeFuseList([" << aDescription.ToCString() << "], "
275 << IsCheckSelfInte << ", " << IsRmExtraEdges << ")";
281 //=============================================================================
285 //=============================================================================
286 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeCommonList
287 (const Handle(TColStd_HSequenceOfTransient)& theShapes,
288 const Standard_Boolean IsCheckSelfInte)
292 if (theShapes.IsNull()) return NULL;
294 //Add a new Boolean object
295 Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN);
297 //Add a new Boolean function
298 Handle(GEOM_Function) aFunction =
299 aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_COMMON_LIST);
301 if (aFunction.IsNull()) return NULL;
303 //Check if the function is set correctly
304 if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
306 GEOMImpl_IBoolean aCI (aFunction);
308 TCollection_AsciiString aDescription;
309 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
310 getShapeFunctions(theShapes, aDescription);
312 if (aShapesSeq.IsNull()) return NULL;
314 aCI.SetShapes(aShapesSeq);
315 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
317 //Compute the Boolean value
319 #if OCC_VERSION_LARGE > 0x06010000
322 if (!GetSolver()->ComputeFunction(aFunction)) {
323 SetErrorCode("Boolean driver failed");
327 catch (Standard_Failure) {
328 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
329 SetErrorCode(aFail->GetMessageString());
333 //Make a Python command
334 GEOM::TPythonDump pd (aFunction);
337 " = geompy.MakeCommonList([" << aDescription.ToCString() << "]";
339 if (IsCheckSelfInte) {
349 //=============================================================================
353 //=============================================================================
354 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeCutList
355 (Handle(GEOM_Object) theMainShape,
356 const Handle(TColStd_HSequenceOfTransient)& theShapes,
357 const Standard_Boolean IsCheckSelfInte)
361 if (theShapes.IsNull()) return NULL;
363 //Add a new Boolean object
364 Handle(GEOM_Object) aBool = GetEngine()->AddObject(GetDocID(), GEOM_BOOLEAN);
366 //Add a new Boolean function
367 Handle(GEOM_Function) aFunction =
368 aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_CUT_LIST);
370 if (aFunction.IsNull()) return NULL;
372 //Check if the function is set correctly
373 if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
375 GEOMImpl_IBoolean aCI (aFunction);
376 Handle(GEOM_Function) aMainRef = theMainShape->GetLastFunction();
378 if (aMainRef.IsNull()) return NULL;
380 TCollection_AsciiString aDescription;
381 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
382 getShapeFunctions(theShapes, aDescription);
384 if (aShapesSeq.IsNull()) return NULL;
386 aCI.SetShape1(aMainRef);
387 aCI.SetShapes(aShapesSeq);
388 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
390 //Compute the Boolean value
392 #if OCC_VERSION_LARGE > 0x06010000
395 if (!GetSolver()->ComputeFunction(aFunction)) {
396 SetErrorCode("Boolean driver failed");
400 catch (Standard_Failure) {
401 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
402 SetErrorCode(aFail->GetMessageString());
406 //Make a Python command
407 GEOM::TPythonDump pd (aFunction);
409 pd << aBool << " = geompy.MakeCutList("
410 << theMainShape << ", [" << aDescription.ToCString() << "]";
412 if (IsCheckSelfInte) {
422 //=============================================================================
426 //=============================================================================
427 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakePartition
428 (const Handle(TColStd_HSequenceOfTransient)& theShapes,
429 const Handle(TColStd_HSequenceOfTransient)& theTools,
430 const Handle(TColStd_HSequenceOfTransient)& theKeepIns,
431 const Handle(TColStd_HSequenceOfTransient)& theRemoveIns,
432 const Standard_Integer theLimit,
433 const Standard_Boolean theRemoveWebs,
434 const Handle(TColStd_HArray1OfInteger)& theMaterials,
435 const Standard_Integer theKeepNonlimitShapes,
436 const Standard_Boolean thePerformSelfIntersections,
437 const Standard_Boolean IsCheckSelfInte)
441 //Add a new Partition object
442 Handle(GEOM_Object) aPartition = GetEngine()->AddObject(GetDocID(), GEOM_PARTITION);
444 //Add a new Partition function
445 Handle(GEOM_Function) aFunction;
446 if (thePerformSelfIntersections)
447 aFunction = aPartition->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_PARTITION);
449 aFunction = aPartition->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_NO_SELF_INTERSECTIONS);
450 if (aFunction.IsNull()) return NULL;
452 //Check if the function is set correctly
453 if (aFunction->GetDriverGUID() != GEOMImpl_PartitionDriver::GetID()) return NULL;
455 GEOMImpl_IPartition aCI (aFunction);
457 Handle(TColStd_HSequenceOfTransient) aShapesSeq;
458 Handle(TColStd_HSequenceOfTransient) aToolsSeq;
459 Handle(TColStd_HSequenceOfTransient) aKeepInsSeq;
460 Handle(TColStd_HSequenceOfTransient) aRemInsSeq;
461 TCollection_AsciiString aShapesDescr, aToolsDescr, aKeepInsDescr, aRemoveInsDescr;
464 aShapesSeq = getShapeFunctions(theShapes, aShapesDescr);
466 if (aShapesSeq.IsNull()) {
467 SetErrorCode("NULL shape for Partition");
472 aToolsSeq = getShapeFunctions(theTools, aToolsDescr);
474 if (aToolsSeq.IsNull()) {
475 SetErrorCode("NULL tool shape for Partition");
480 aKeepInsSeq = getShapeFunctions(theKeepIns, aKeepInsDescr);
482 if (aKeepInsSeq.IsNull()) {
483 SetErrorCode("NULL <keep inside> shape for Partition");
488 aRemInsSeq = getShapeFunctions(theRemoveIns, aRemoveInsDescr);
490 if (aRemInsSeq.IsNull()) {
491 SetErrorCode("NULL <remove inside> shape for Partition");
495 aCI.SetShapes(aShapesSeq);
496 aCI.SetTools(aToolsSeq);
497 aCI.SetKeepIns(aKeepInsSeq);
498 aCI.SetRemoveIns(aRemInsSeq);
501 aCI.SetLimit(theLimit);
502 aCI.SetKeepNonlimitShapes(theKeepNonlimitShapes);
503 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
507 if (theMaterials.IsNull()) {
508 Handle(TColStd_HArray1OfInteger) aMaterials =
509 new TColStd_HArray1OfInteger (1, aShapesSeq->Length());
511 aCI.SetMaterials(aMaterials);
513 aCI.SetMaterials(theMaterials);
517 //Compute the Partition
519 #if OCC_VERSION_LARGE > 0x06010000
522 if (!GetSolver()->ComputeFunction(aFunction)) {
523 SetErrorCode("Partition driver failed");
527 catch (Standard_Failure) {
528 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
529 SetErrorCode(aFail->GetMessageString());
533 //Make a Python command
534 GEOM::TPythonDump pd (aFunction);
535 if (thePerformSelfIntersections)
536 pd << aPartition << " = geompy.MakePartition([";
538 pd << aPartition << " = geompy.MakePartitionNonSelfIntersectedShape([";
541 pd << aShapesDescr.ToCString() << "], [" << aToolsDescr.ToCString() << "], [";
542 // Keep Ins, Remove Ins
543 pd << aKeepInsDescr.ToCString() << "], [" << aRemoveInsDescr.ToCString() << "], ";
544 // Limit, Remove Webs
545 pd << TopAbs_ShapeEnum(theLimit) << ", " << (int)theRemoveWebs << ", [";
547 if (!theMaterials.IsNull() && theMaterials->Length() > 0) {
548 int i = theMaterials->Lower();
549 pd << theMaterials->Value(i);
551 for (; i <= theMaterials->Upper(); i++) {
552 pd << ", " << theMaterials->Value(i);
555 pd << "], " << theKeepNonlimitShapes;
557 if (IsCheckSelfInte && !thePerformSelfIntersections) {
567 //=============================================================================
571 //=============================================================================
572 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeHalfPartition
573 (Handle(GEOM_Object) theShape, Handle(GEOM_Object) thePlane)
577 if (theShape.IsNull() || thePlane.IsNull()) return NULL;
579 //Add a new Boolean object
580 Handle(GEOM_Object) aPart = GetEngine()->AddObject(GetDocID(), GEOM_PARTITION);
582 //Add a new Partition function
583 Handle(GEOM_Function) aFunction =
584 aPart->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_HALF);
585 if (aFunction.IsNull()) return NULL;
587 //Check if the function is set correctly
588 if (aFunction->GetDriverGUID() != GEOMImpl_PartitionDriver::GetID()) return NULL;
590 GEOMImpl_IPartition aCI (aFunction);
592 Handle(GEOM_Function) aRef1 = theShape->GetLastFunction();
593 Handle(GEOM_Function) aRef2 = thePlane->GetLastFunction();
595 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
600 //Compute the Partition value
602 #if OCC_VERSION_LARGE > 0x06010000
605 if (!GetSolver()->ComputeFunction(aFunction)) {
606 SetErrorCode("Partition driver failed");
610 catch (Standard_Failure) {
611 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
612 SetErrorCode(aFail->GetMessageString());
616 //Make a Python command
617 GEOM::TPythonDump pd (aFunction);
618 pd << aPart << " = geompy.MakeHalfPartition("
619 << theShape << ", " << thePlane << ")";
625 //=============================================================================
629 //=============================================================================
630 Handle(TColStd_HSequenceOfTransient)
631 GEOMImpl_IBooleanOperations::getShapeFunctions
632 (const Handle(TColStd_HSequenceOfTransient)& theObjects,
633 TCollection_AsciiString &theDescription)
635 Handle(TColStd_HSequenceOfTransient) aResult =
636 new TColStd_HSequenceOfTransient;
637 Standard_Integer aNbObjects = theObjects->Length();
639 TCollection_AsciiString anEntry;
640 Handle(GEOM_Object) anObj;
641 Handle(GEOM_Function) aRefObj;
644 for (i = 1; i <= aNbObjects; i++) {
645 anObj = Handle(GEOM_Object)::DownCast(theObjects->Value(i));
646 aRefObj = anObj->GetLastFunction();
648 if (aRefObj.IsNull()) {
653 aResult->Append(aRefObj);
655 // For Python command
656 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
659 theDescription += ", ";
662 theDescription += anEntry;