1 // Copyright (C) 2007-2024 CEA, EDF, 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 <TDF_Tool.hxx>
40 #include "utilities.h"
42 #include <Standard_Failure.hxx>
43 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
45 //=============================================================================
49 //=============================================================================
50 GEOMImpl_IBooleanOperations::GEOMImpl_IBooleanOperations (GEOM_Engine* theEngine)
51 : GEOM_IOperations(theEngine)
53 MESSAGE("GEOMImpl_IBooleanOperations::GEOMImpl_IBooleanOperations");
56 //=============================================================================
60 //=============================================================================
61 GEOMImpl_IBooleanOperations::~GEOMImpl_IBooleanOperations()
63 MESSAGE("GEOMImpl_IBooleanOperations::~GEOMImpl_IBooleanOperations");
67 //=============================================================================
71 //=============================================================================
72 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeBoolean
73 (Handle(GEOM_Object) theShape1,
74 Handle(GEOM_Object) theShape2,
75 const Standard_Integer theOp,
76 const Standard_Boolean IsCheckSelfInte,
77 const Standard_Real theFuzzyParam)
81 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
83 //Add a new Boolean object
84 Handle(GEOM_Object) aBool = GetEngine()->AddObject(GEOM_BOOLEAN);
86 //Add a new Boolean function
87 Handle(GEOM_Function) aFunction;
89 aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_COMMON);
90 } else if (theOp == 2) {
91 aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_CUT);
92 } else if (theOp == 3) {
93 aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_FUSE);
94 } else if (theOp == 4) {
95 aFunction = aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_SECTION);
98 if (aFunction.IsNull()) return NULL;
100 //Check if the function is set correctly
101 if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
103 GEOMImpl_IBoolean aCI (aFunction);
105 Handle(GEOM_Function) aRef1 = theShape1->GetLastFunction();
106 Handle(GEOM_Function) aRef2 = theShape2->GetLastFunction();
108 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
110 aCI.SetShape1(aRef1);
111 aCI.SetShape2(aRef2);
112 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
113 aCI.SetFuzzyParameter(theFuzzyParam);
115 //Compute the Boolean value
118 if (!GetSolver()->ComputeFunction(aFunction)) {
119 SetErrorCode("Boolean driver failed");
123 catch (Standard_Failure& aFail) {
124 SetErrorCode(aFail.GetMessageString());
128 //Make a Python command
129 GEOM::TPythonDump pd (aFunction);
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(";
136 pd << theShape1 << ", " << theShape2;
138 if (IsCheckSelfInte) {
142 if (theFuzzyParam > 0) {
143 // Use named argument for the fuzzy parameter
144 pd << ", theFuzzyParam=" << theFuzzyParam;
153 //=============================================================================
157 //=============================================================================
158 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeFuse
159 (Handle(GEOM_Object) theShape1,
160 Handle(GEOM_Object) theShape2,
161 const bool IsCheckSelfInte,
162 const bool IsRmExtraEdges,
163 const Standard_Real theFuzzyParam)
167 if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
169 //Add a new Boolean object
170 Handle(GEOM_Object) aBool = GetEngine()->AddObject(GEOM_BOOLEAN);
172 //Add a new Boolean function
173 Handle(GEOM_Function) aFunction =
174 aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_FUSE);
176 if (aFunction.IsNull()) return NULL;
178 //Check if the function is set correctly
179 if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
181 GEOMImpl_IBoolean aCI (aFunction);
183 Handle(GEOM_Function) aRef1 = theShape1->GetLastFunction();
184 Handle(GEOM_Function) aRef2 = theShape2->GetLastFunction();
186 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
188 aCI.SetShape1(aRef1);
189 aCI.SetShape2(aRef2);
190 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
191 aCI.SetRmExtraEdges(IsRmExtraEdges);
192 aCI.SetFuzzyParameter(theFuzzyParam);
194 //Compute the Boolean value
197 if (!GetSolver()->ComputeFunction(aFunction)) {
198 SetErrorCode("Boolean driver failed");
202 catch (Standard_Failure& aFail) {
203 SetErrorCode(aFail.GetMessageString());
207 //Make a Python command
208 GEOM::TPythonDump pd (aFunction);
210 pd << aBool << " = geompy.MakeFuse(";
211 pd << theShape1 << ", " << theShape2 << ", "
212 << IsCheckSelfInte << ", " << IsRmExtraEdges;
213 if (theFuzzyParam > 0) {
214 // Use named argument for the fuzzy parameter
215 pd << ", theFuzzyParam=" << theFuzzyParam;
223 //=============================================================================
227 //=============================================================================
228 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeFuseList
229 (const Handle(TColStd_HSequenceOfTransient)& theShapes,
230 const bool IsCheckSelfInte,
231 const bool IsRmExtraEdges,
232 const Standard_Real theFuzzyParam)
236 if (theShapes.IsNull()) return NULL;
238 //Add a new Boolean object
239 Handle(GEOM_Object) aBool = GetEngine()->AddObject(GEOM_BOOLEAN);
241 //Add a new Boolean function
242 Handle(GEOM_Function) aFunction =
243 aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_FUSE_LIST);
245 if (aFunction.IsNull()) return NULL;
247 //Check if the function is set correctly
248 if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
250 GEOMImpl_IBoolean aCI (aFunction);
252 TCollection_AsciiString aDescription;
253 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
254 getShapeFunctions(theShapes, aDescription);
256 if (aShapesSeq.IsNull()) return NULL;
258 aCI.SetShapes(aShapesSeq);
259 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
260 aCI.SetRmExtraEdges(IsRmExtraEdges);
261 aCI.SetFuzzyParameter(theFuzzyParam);
263 //Compute the Boolean value
266 if (!GetSolver()->ComputeFunction(aFunction)) {
267 SetErrorCode("Boolean driver failed");
271 catch (Standard_Failure& aFail) {
272 SetErrorCode(aFail.GetMessageString());
276 //Make a Python command
277 GEOM::TPythonDump pd (aFunction);
279 pd << aBool << " = geompy.MakeFuseList([" << aDescription.ToCString() << "], "
280 << IsCheckSelfInte << ", " << IsRmExtraEdges;
281 if (theFuzzyParam > 0) {
282 // Use named argument for the fuzzy parameter
283 pd << ", theFuzzyParam=" << theFuzzyParam;
291 //=============================================================================
295 //=============================================================================
296 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeCommonList
297 (const Handle(TColStd_HSequenceOfTransient)& theShapes,
298 const Standard_Boolean IsCheckSelfInte,
299 const Standard_Real theFuzzyParam)
303 if (theShapes.IsNull()) return NULL;
305 //Add a new Boolean object
306 Handle(GEOM_Object) aBool = GetEngine()->AddObject(GEOM_BOOLEAN);
308 //Add a new Boolean function
309 Handle(GEOM_Function) aFunction =
310 aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_COMMON_LIST);
312 if (aFunction.IsNull()) return NULL;
314 //Check if the function is set correctly
315 if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
317 GEOMImpl_IBoolean aCI (aFunction);
319 TCollection_AsciiString aDescription;
320 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
321 getShapeFunctions(theShapes, aDescription);
323 if (aShapesSeq.IsNull()) return NULL;
325 aCI.SetShapes(aShapesSeq);
326 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
327 aCI.SetFuzzyParameter(theFuzzyParam);
329 //Compute the Boolean value
332 if (!GetSolver()->ComputeFunction(aFunction)) {
333 SetErrorCode("Boolean driver failed");
337 catch (Standard_Failure& aFail) {
338 SetErrorCode(aFail.GetMessageString());
342 //Make a Python command
343 GEOM::TPythonDump pd (aFunction);
346 " = geompy.MakeCommonList([" << aDescription.ToCString() << "]";
348 if (IsCheckSelfInte) {
351 if (theFuzzyParam > 0) {
352 // Use named argument for the fuzzy parameter
353 pd << ", theFuzzyParam=" << theFuzzyParam;
361 //=============================================================================
365 //=============================================================================
366 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeCutList
367 (Handle(GEOM_Object) theMainShape,
368 const Handle(TColStd_HSequenceOfTransient)& theShapes,
369 const Standard_Boolean IsCheckSelfInte,
370 const Standard_Real theFuzzyParam)
374 if (theShapes.IsNull()) return NULL;
376 //Add a new Boolean object
377 Handle(GEOM_Object) aBool = GetEngine()->AddObject(GEOM_BOOLEAN);
379 //Add a new Boolean function
380 Handle(GEOM_Function) aFunction =
381 aBool->AddFunction(GEOMImpl_BooleanDriver::GetID(), BOOLEAN_CUT_LIST);
383 if (aFunction.IsNull()) return NULL;
385 //Check if the function is set correctly
386 if (aFunction->GetDriverGUID() != GEOMImpl_BooleanDriver::GetID()) return NULL;
388 GEOMImpl_IBoolean aCI (aFunction);
389 Handle(GEOM_Function) aMainRef = theMainShape->GetLastFunction();
391 if (aMainRef.IsNull()) return NULL;
393 TCollection_AsciiString aDescription;
394 Handle(TColStd_HSequenceOfTransient) aShapesSeq =
395 getShapeFunctions(theShapes, aDescription);
397 if (aShapesSeq.IsNull()) return NULL;
399 aCI.SetShape1(aMainRef);
400 aCI.SetShapes(aShapesSeq);
401 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
402 aCI.SetFuzzyParameter(theFuzzyParam);
404 //Compute the Boolean value
407 if (!GetSolver()->ComputeFunction(aFunction)) {
408 SetErrorCode("Boolean driver failed");
412 catch (Standard_Failure& aFail) {
413 SetErrorCode(aFail.GetMessageString());
417 //Make a Python command
418 GEOM::TPythonDump pd (aFunction);
420 pd << aBool << " = geompy.MakeCutList("
421 << theMainShape << ", [" << aDescription.ToCString() << "]";
423 if (IsCheckSelfInte) {
427 if (theFuzzyParam > 0) {
428 // Use named argument for the fuzzy parameter
429 pd << ", theFuzzyParam=" << theFuzzyParam;
438 //=============================================================================
442 //=============================================================================
443 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakePartition
444 (const Handle(TColStd_HSequenceOfTransient)& theShapes,
445 const Handle(TColStd_HSequenceOfTransient)& theTools,
446 const Handle(TColStd_HSequenceOfTransient)& theKeepIns,
447 const Handle(TColStd_HSequenceOfTransient)& theRemoveIns,
448 const Standard_Integer theLimit,
449 const Standard_Boolean theRemoveWebs,
450 const Handle(TColStd_HArray1OfInteger)& theMaterials,
451 const Standard_Integer theKeepNonlimitShapes,
452 const Standard_Boolean thePerformSelfIntersections,
453 const Standard_Boolean IsCheckSelfInte,
454 const Standard_Real theFuzzyParam)
458 //Add a new Partition object
459 Handle(GEOM_Object) aPartition = GetEngine()->AddObject(GEOM_PARTITION);
461 //Add a new Partition function
462 Handle(GEOM_Function) aFunction;
463 if (thePerformSelfIntersections)
464 aFunction = aPartition->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_PARTITION);
466 aFunction = aPartition->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_NO_SELF_INTERSECTIONS);
467 if (aFunction.IsNull()) return NULL;
469 //Check if the function is set correctly
470 if (aFunction->GetDriverGUID() != GEOMImpl_PartitionDriver::GetID()) return NULL;
472 GEOMImpl_IPartition aCI (aFunction);
474 Handle(TColStd_HSequenceOfTransient) aShapesSeq;
475 Handle(TColStd_HSequenceOfTransient) aToolsSeq;
476 Handle(TColStd_HSequenceOfTransient) aKeepInsSeq;
477 Handle(TColStd_HSequenceOfTransient) aRemInsSeq;
478 TCollection_AsciiString aShapesDescr, aToolsDescr, aKeepInsDescr, aRemoveInsDescr;
481 aShapesSeq = getShapeFunctions(theShapes, aShapesDescr);
483 if (aShapesSeq.IsNull()) {
484 SetErrorCode("NULL shape for Partition");
489 aToolsSeq = getShapeFunctions(theTools, aToolsDescr);
491 if (aToolsSeq.IsNull()) {
492 SetErrorCode("NULL tool shape for Partition");
497 aKeepInsSeq = getShapeFunctions(theKeepIns, aKeepInsDescr);
499 if (aKeepInsSeq.IsNull()) {
500 SetErrorCode("NULL <keep inside> shape for Partition");
505 aRemInsSeq = getShapeFunctions(theRemoveIns, aRemoveInsDescr);
507 if (aRemInsSeq.IsNull()) {
508 SetErrorCode("NULL <remove inside> shape for Partition");
512 aCI.SetShapes(aShapesSeq);
513 aCI.SetTools(aToolsSeq);
514 aCI.SetKeepIns(aKeepInsSeq);
515 aCI.SetRemoveIns(aRemInsSeq);
518 aCI.SetLimit(theLimit);
519 aCI.SetKeepNonlimitShapes(theKeepNonlimitShapes);
520 aCI.SetCheckSelfIntersection(IsCheckSelfInte);
524 if (theMaterials.IsNull()) {
525 Handle(TColStd_HArray1OfInteger) aMaterials =
526 new TColStd_HArray1OfInteger (1, aShapesSeq->Length());
528 aCI.SetMaterials(aMaterials);
530 aCI.SetMaterials(theMaterials);
535 aCI.SetFuzzyParameter(theFuzzyParam);
537 //Compute the Partition
540 if (!GetSolver()->ComputeFunction(aFunction)) {
541 SetErrorCode("Partition driver failed");
545 catch (Standard_Failure& aFail) {
546 SetErrorCode(aFail.GetMessageString());
550 //Make a Python command
551 GEOM::TPythonDump pd (aFunction);
552 if (thePerformSelfIntersections)
553 pd << aPartition << " = geompy.MakePartition([";
555 pd << aPartition << " = geompy.MakePartitionNonSelfIntersectedShape([";
558 pd << aShapesDescr.ToCString() << "], [" << aToolsDescr.ToCString() << "], [";
559 // Keep Ins, Remove Ins
560 pd << aKeepInsDescr.ToCString() << "], [" << aRemoveInsDescr.ToCString() << "], ";
561 // Limit, Remove Webs
562 pd << TopAbs_ShapeEnum(theLimit) << ", " << (int)theRemoveWebs << ", [";
564 if (!theMaterials.IsNull() && theMaterials->Length() > 0) {
565 int i = theMaterials->Lower();
566 pd << theMaterials->Value(i);
568 for (; i <= theMaterials->Upper(); i++) {
569 pd << ", " << theMaterials->Value(i);
572 pd << "], " << theKeepNonlimitShapes;
574 if (IsCheckSelfInte && !thePerformSelfIntersections) {
578 if (theFuzzyParam > 0) {
579 // Use named argument for the fuzzy parameter
580 pd << ", theFuzzyParam=" << theFuzzyParam;
589 //=============================================================================
593 //=============================================================================
594 Handle(GEOM_Object) GEOMImpl_IBooleanOperations::MakeHalfPartition
595 (Handle(GEOM_Object) theShape,
596 Handle(GEOM_Object) thePlane,
597 const Standard_Real theFuzzyParam)
601 if (theShape.IsNull() || thePlane.IsNull()) return NULL;
603 //Add a new Boolean object
604 Handle(GEOM_Object) aPart = GetEngine()->AddObject(GEOM_PARTITION);
606 //Add a new Partition function
607 Handle(GEOM_Function) aFunction =
608 aPart->AddFunction(GEOMImpl_PartitionDriver::GetID(), PARTITION_HALF);
609 if (aFunction.IsNull()) return NULL;
611 //Check if the function is set correctly
612 if (aFunction->GetDriverGUID() != GEOMImpl_PartitionDriver::GetID()) return NULL;
614 GEOMImpl_IPartition aCI (aFunction);
616 Handle(GEOM_Function) aRef1 = theShape->GetLastFunction();
617 Handle(GEOM_Function) aRef2 = thePlane->GetLastFunction();
619 if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
623 aCI.SetFuzzyParameter(theFuzzyParam);
625 //Compute the Partition value
628 if (!GetSolver()->ComputeFunction(aFunction)) {
629 SetErrorCode("Partition driver failed");
633 catch (Standard_Failure& aFail) {
634 SetErrorCode(aFail.GetMessageString());
638 //Make a Python command
639 GEOM::TPythonDump pd (aFunction);
640 pd << aPart << " = geompy.MakeHalfPartition("
641 << theShape << ", " << thePlane;
642 if (theFuzzyParam > 0) {
643 // Use named argument for the fuzzy parameter
644 pd << ", theFuzzyParam=" << theFuzzyParam;
652 //=============================================================================
656 //=============================================================================
657 Handle(TColStd_HSequenceOfTransient)
658 GEOMImpl_IBooleanOperations::getShapeFunctions
659 (const Handle(TColStd_HSequenceOfTransient)& theObjects,
660 TCollection_AsciiString &theDescription)
662 Handle(TColStd_HSequenceOfTransient) aResult =
663 new TColStd_HSequenceOfTransient;
664 Standard_Integer aNbObjects = theObjects->Length();
666 TCollection_AsciiString anEntry;
667 Handle(GEOM_Object) anObj;
668 Handle(GEOM_Function) aRefObj;
671 for (i = 1; i <= aNbObjects; i++) {
672 anObj = Handle(GEOM_Object)::DownCast(theObjects->Value(i));
673 aRefObj = anObj->GetLastFunction();
675 if (aRefObj.IsNull()) {
680 aResult->Append(aRefObj);
682 // For Python command
683 TDF_Tool::Entry(anObj->GetEntry(), anEntry);
686 theDescription += ", ";
689 theDescription += anEntry;