1 // Copyright (C) 2007-2016 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
24 #pragma warning( disable:4786 )
27 #include <Standard_Version.hxx>
29 #include <GEOMImpl_IHealingOperations.hxx>
30 #include <GEOM_PythonDump.hxx>
31 #include <GEOMImpl_HealingDriver.hxx>
32 #include <GEOMImpl_Types.hxx>
33 #include <GEOMImpl_IHealing.hxx>
34 #include <GEOMImpl_IVector.hxx>
35 #include <GEOMImpl_VectorDriver.hxx>
36 #include <GEOMImpl_CopyDriver.hxx>
37 #include <ShHealOper_ModifStats.hxx>
38 #include <ShHealOper_ShapeProcess.hxx>
40 #include <Basics_OCCTVersion.hxx>
42 #include <utilities.h>
44 #include <Utils_ExceptHandlers.hxx>
46 #include <BRep_Builder.hxx>
47 #include <ShapeAnalysis_FreeBounds.hxx>
48 #include <TColStd_HArray1OfExtendedString.hxx>
49 #include <TColStd_HSequenceOfTransient.hxx>
50 #include <TCollection_AsciiString.hxx>
51 #include <TopExp_Explorer.hxx>
52 #include <TopTools_SequenceOfShape.hxx>
53 #include <TopoDS_Compound.hxx>
55 #include <Standard_Failure.hxx>
56 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
58 //=============================================================================
62 //=============================================================================
63 GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations (GEOM_Engine* theEngine, int theDocID)
64 : GEOM_IOperations(theEngine, theDocID)
66 myModifStats = new ShHealOper_ModifStats;
67 MESSAGE("GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations");
70 //=============================================================================
74 //=============================================================================
75 GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations()
78 MESSAGE("GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations");
82 //=============================================================================
86 //=============================================================================
87 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ShapeProcess (Handle(GEOM_Object) theObject,
88 const Handle(TColStd_HArray1OfExtendedString)& theOperators,
89 const Handle(TColStd_HArray1OfExtendedString)& theParams,
90 const Handle(TColStd_HArray1OfExtendedString)& theValues)
92 // set error code, check parameters
95 if (theObject.IsNull())
98 if (theOperators.IsNull() || theOperators->Length() <= 0) {
99 SetErrorCode("No operators requested");
103 Standard_Integer nbParams = 0, nbValues = 0;
104 if (!theParams.IsNull()) {
105 nbParams = theParams->Length();
107 if (!theValues.IsNull()) {
108 nbValues = theValues->Length();
111 if (nbParams != nbValues) {
112 SetErrorCode("Number of parameter values must be equal to the number of parameters");
116 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
117 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
120 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
123 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SHAPE_PROCESS);
125 if (aFunction.IsNull()) return NULL;
127 //Check if the function is set correctly
128 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
130 // prepare "data container" class IHealing
131 GEOMImpl_IHealing HI(aFunction);
132 HI.SetOriginal(aLastFunction);
133 HI.SetOperators( theOperators );
135 HI.SetParameters( theParams );
136 HI.SetValues( theValues );
138 HI.SetStatistics( myModifStats );
140 //Compute the translation
143 if (!GetSolver()->ComputeFunction(aFunction))
145 SetErrorCode("Shape Healing algorithm failed");
149 catch (Standard_Failure)
151 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
152 SetErrorCode(aFail->GetMessageString());
156 //Make a Python command
157 GEOM::TPythonDump pd (aFunction);
158 pd << aNewObject << " = geompy.ProcessShape(" << theObject << ", [";
161 int i = theOperators->Lower(), nb = theOperators->Upper();
162 for ( ; i <= nb; i++) {
163 pd << "\"" << TCollection_AsciiString(theOperators->Value( i )).ToCString()
164 << (( i < nb ) ? "\", " : "\"");
167 // list of parameters
168 i = theParams->Lower(); nb = theParams->Upper();
169 for ( ; i <= nb; i++) {
170 pd << "\"" << TCollection_AsciiString(theParams->Value( i )).ToCString()
171 << (( i < nb ) ? "\", " : "\"");
175 i = theValues->Lower(); nb = theValues->Upper();
176 for ( ; i <= nb; i++) {
177 pd << "\"" << TCollection_AsciiString(theValues->Value( i )).ToCString()
178 << (( i < nb ) ? "\", " : "\"");
186 //=============================================================================
190 //=============================================================================
191 void GEOMImpl_IHealingOperations::GetShapeProcessParameters (std::list<std::string>& theOperations,
192 std::list<std::string>& theParams,
193 std::list<std::string>& theValues)
195 ShHealOper_ShapeProcess aHealer;
196 TColStd_SequenceOfAsciiString anOperators;
197 int nbOperatorErrors( 0 );
198 if ( aHealer.GetOperators( anOperators ) )
200 for ( Standard_Integer i = 1; i <= anOperators.Length(); i++ )
202 std::string anOperation = anOperators.Value( i ).ToCString();
203 if ( GetOperatorParameters( anOperation, theParams, theValues ) )
204 theOperations.push_back( anOperation );
211 SetErrorCode("ERROR retrieving operators (GEOMImpl_IHealingOperations)");
214 if ( nbOperatorErrors ) {
215 TCollection_AsciiString aMsg ("ERRORS retrieving ShapeProcess parameters (GEOMImpl_IHealingOperations): nbOperatorErrors = ");
216 aMsg += TCollection_AsciiString( nbOperatorErrors );
217 MESSAGE(aMsg.ToCString());
221 //=============================================================================
223 * GetOperatorParameters
225 //=============================================================================
226 bool GEOMImpl_IHealingOperations::GetOperatorParameters( const std::string & theOperation,
227 std::list<std::string>& theParams,
228 std::list<std::string>& theValues )
230 ShHealOper_ShapeProcess aHealer;
231 int nbParamValueErrors( 0 );
232 std::list<std::string> aParams;
233 if ( GetParameters( theOperation, aParams ) ) {
234 for ( std::list<std::string>::iterator it = aParams.begin(); it != aParams.end(); ++it ) {
235 TCollection_AsciiString aParam( (Standard_CString)(*it).c_str() );
236 TCollection_AsciiString aValue;
237 if ( aHealer.GetParameter( aParam, aValue ) ) {
238 theParams.push_back( aParam.ToCString() );
239 theValues.push_back( aValue.ToCString() );
242 nbParamValueErrors++;
248 if ( nbParamValueErrors ) {
249 TCollection_AsciiString aMsg ("ERRORS retrieving ShapeProcess parameter values (GEOMImpl_IHealingOperations): nbParamValueErrors = ");
250 aMsg += TCollection_AsciiString( nbParamValueErrors );
251 MESSAGE(aMsg.ToCString());
257 //=============================================================================
261 //=============================================================================
262 bool GEOMImpl_IHealingOperations::GetParameters (const std::string theOperation,
263 std::list<std::string>& theParams)
265 if ( theOperation == "SplitAngle" ) {
266 theParams.push_back( "SplitAngle.Angle" );
267 theParams.push_back( "SplitAngle.MaxTolerance" );
269 } else if ( theOperation == "SplitClosedFaces" ) {
270 theParams.push_back( "SplitClosedFaces.NbSplitPoints" );
272 } else if ( theOperation == "FixFaceSize" ) {
273 theParams.push_back( "FixFaceSize.Tolerance" );
275 } else if( theOperation == "DropSmallEdges" ) {
276 theParams.push_back( "DropSmallEdges.Tolerance3d" );
278 } else if( theOperation == "DropSmallSolids" ) {
279 theParams.push_back( "DropSmallSolids.WidthFactorThreshold" );
280 theParams.push_back( "DropSmallSolids.VolumeThreshold" );
281 theParams.push_back( "DropSmallSolids.MergeSolids" );
283 } else if( theOperation == "BSplineRestriction" ) {
284 theParams.push_back( "BSplineRestriction.SurfaceMode" );
285 theParams.push_back( "BSplineRestriction.Curve3dMode" );
286 theParams.push_back( "BSplineRestriction.Curve2dMode" );
287 theParams.push_back( "BSplineRestriction.Tolerance3d" );
288 theParams.push_back( "BSplineRestriction.Tolerance2d" );
289 theParams.push_back( "BSplineRestriction.RequiredDegree" );
290 theParams.push_back( "BSplineRestriction.RequiredNbSegments" );
291 theParams.push_back( "BSplineRestriction.Continuity3d" );
292 theParams.push_back( "BSplineRestriction.Continuity2d" );
294 } else if( theOperation == "SplitContinuity" ) {
295 theParams.push_back( "SplitContinuity.Tolerance3d" );
296 theParams.push_back( "SplitContinuity.SurfaceContinuity" );
297 theParams.push_back( "SplitContinuity.CurveContinuity" );
299 } else if( theOperation == "ToBezier" ) {
300 theParams.push_back( "ToBezier.SurfaceMode" );
301 theParams.push_back( "ToBezier.Curve3dMode" );
302 theParams.push_back( "ToBezier.Curve2dMode" );
303 theParams.push_back( "ToBezier.MaxTolerance" );
305 } else if( theOperation == "SameParameter" ) {
306 theParams.push_back( "SameParameter.Tolerance3d" );
308 } else if( theOperation == "FixShape" ) {
309 theParams.push_back( "FixShape.Tolerance3d" );
310 theParams.push_back( "FixShape.MaxTolerance3d" );
319 //=============================================================================
323 //=============================================================================
324 Handle(GEOM_Object) GEOMImpl_IHealingOperations::SuppressFaces
325 (Handle(GEOM_Object) theObject, const Handle(TColStd_HArray1OfInteger)& theFaces)
327 // set error code, check parameters
330 if (theObject.IsNull()) // if theFaces.IsNull() - it's OK, it means that ALL faces must be removed..
333 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
334 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
337 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
340 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SUPPRESS_FACES);
342 if (aFunction.IsNull()) return NULL;
344 //Check if the function is set correctly
345 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
347 // prepare "data container" class IHealing
348 GEOMImpl_IHealing HI (aFunction);
349 HI.SetFaces(theFaces);
350 HI.SetOriginal(aLastFunction);
351 HI.SetStatistics( myModifStats );
353 //Compute the translation
356 if (!GetSolver()->ComputeFunction(aFunction))
358 SetErrorCode("Healing driver failed");
362 catch (Standard_Failure)
364 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
365 SetErrorCode(aFail->GetMessageString());
369 //Make a Python command
370 GEOM::TPythonDump pd (aFunction);
371 pd << aNewObject << " = geompy.SuppressFaces(" << theObject << ", [";
374 int i = theFaces->Lower(), nb = theFaces->Upper();
375 for ( ; i <= nb; i++)
376 pd << theFaces->Value( i ) << (( i < nb ) ? ", " : "])");
382 //=============================================================================
386 //=============================================================================
387 Handle(GEOM_Object) GEOMImpl_IHealingOperations::CloseContour
388 (Handle(GEOM_Object) theObject,
389 const Handle(TColStd_HArray1OfInteger)& theWires,
392 // set error code, check parameters
395 if (theObject.IsNull())
397 SetErrorCode("NULL object given");
401 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
402 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
405 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
408 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CLOSE_CONTOUR);
410 if (aFunction.IsNull()) return NULL;
412 //Check if the function is set correctly
413 if(aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
415 // prepare "data container" class IHealing
416 GEOMImpl_IHealing HI(aFunction);
417 HI.SetWires( theWires );
418 HI.SetIsCommonVertex( isCommonVertex );
419 HI.SetOriginal( aLastFunction );
420 HI.SetStatistics( myModifStats );
422 //Compute the translation
425 if (!GetSolver()->ComputeFunction(aFunction))
427 SetErrorCode("Healing driver failed");
431 catch (Standard_Failure)
433 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
434 SetErrorCode(aFail->GetMessageString());
438 //Make a Python command
439 GEOM::TPythonDump pd (aFunction);
440 pd << aNewObject << " = geompy.CloseContour(" << theObject << ", [";
443 if (!theWires.IsNull())
445 int i = theWires->Lower(), nb = theWires->Upper();
446 pd << theWires->Value(i++);
448 pd << ", " << theWires->Value(i++);
450 pd << "], " << (int)isCommonVertex << ")";
456 //=============================================================================
460 //=============================================================================
461 Handle(GEOM_Object) GEOMImpl_IHealingOperations::RemoveIntWires
462 (Handle(GEOM_Object) theObject, const Handle(TColStd_HArray1OfInteger)& theWires)
464 // set error code, check parameters
467 if (theObject.IsNull()) // if theWires is NULL it's OK, it means that ALL wires must be removed
470 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
471 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
474 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
477 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), REMOVE_INT_WIRES);
479 if (aFunction.IsNull()) return NULL;
481 //Check if the function is set correctly
482 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
484 // prepare "data container" class IHealing
485 GEOMImpl_IHealing HI(aFunction);
486 HI.SetWires( theWires );
487 HI.SetOriginal( aLastFunction );
488 HI.SetStatistics( myModifStats );
490 //Compute the translation
493 if (!GetSolver()->ComputeFunction(aFunction))
495 SetErrorCode("Healing driver failed");
499 catch (Standard_Failure)
501 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
502 SetErrorCode(aFail->GetMessageString());
506 //Make a Python command
507 GEOM::TPythonDump pd (aFunction);
508 pd << aNewObject << " = geompy.SuppressInternalWires(" << theObject << ", [";
511 if (!theWires.IsNull()) {
512 int i = theWires->Lower(), nb = theWires->Upper();
513 for ( ; i <= nb; i++)
514 pd << theWires->Value( i ) << (( i < nb ) ? ", " : "])");
523 //=============================================================================
527 //=============================================================================
528 Handle(GEOM_Object) GEOMImpl_IHealingOperations::FillHoles (Handle(GEOM_Object) theObject,
529 const Handle(TColStd_HArray1OfInteger)& theWires)
531 // set error code, check parameters
534 if (theObject.IsNull()) // if theWires is NULL it's OK, it means that ALL holes must be removed
537 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
538 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
541 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
544 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), FILL_HOLES);
546 if (aFunction.IsNull()) return NULL;
548 //Check if the function is set correctly
549 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
551 // prepare "data container" class IHealing
552 GEOMImpl_IHealing HI(aFunction);
553 HI.SetWires( theWires );
554 HI.SetOriginal( aLastFunction );
555 HI.SetStatistics( myModifStats );
557 //Compute the translation
560 if (!GetSolver()->ComputeFunction(aFunction))
562 SetErrorCode("Healing driver failed");
566 catch (Standard_Failure)
568 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
569 SetErrorCode(aFail->GetMessageString());
573 //Make a Python command
574 GEOM::TPythonDump pd (aFunction);
575 pd << aNewObject << " = geompy.SuppressHoles(" << theObject << ", [";
578 if ( theWires.IsNull() )
581 int i = theWires->Lower(), nb = theWires->Upper();
582 for ( ; i <= nb; i++)
583 pd << theWires->Value( i ) << (( i < nb ) ? ", " : "])");
590 //=============================================================================
594 //=============================================================================
596 GEOMImpl_IHealingOperations::Sew (std::list<Handle(GEOM_Object)>& theObjects,
598 bool isAllowNonManifold)
600 // set error code, check parameters
603 if (theObjects.empty())
606 Handle(TColStd_HSequenceOfTransient) objects =
607 GEOM_Object::GetLastFunctions( theObjects );
608 if ( objects.IsNull() || objects->IsEmpty() ) {
609 SetErrorCode("NULL argument shape");
614 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
617 int aFunctionType = (isAllowNonManifold ? SEWING_NON_MANIFOLD : SEWING);
618 Handle(GEOM_Function) aFunction =
619 aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), aFunctionType);
620 if (aFunction.IsNull()) return NULL;
622 //Check if the function is set correctly
623 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
625 // prepare "data container" class IHealing
626 GEOMImpl_IHealing HI(aFunction);
627 HI.SetTolerance( theTolerance );
628 HI.SetOriginal( theObjects.front()->GetLastFunction() ); objects->Remove(1);
629 HI.SetShapes( objects );
630 HI.SetStatistics( myModifStats );
635 if (!GetSolver()->ComputeFunction(aFunction))
637 SetErrorCode("Healing driver failed");
641 catch (Standard_Failure) {
642 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
643 SetErrorCode(aFail->GetMessageString());
647 //Make a Python command
648 GEOM::TPythonDump pd(aFunction);
650 pd << aNewObject << " = geompy.Sew(" << theObjects << ", " << theTolerance;
652 if (isAllowNonManifold) {
662 //=============================================================================
664 * RemoveInternalFaces
666 //=============================================================================
668 GEOMImpl_IHealingOperations::RemoveInternalFaces (std::list< Handle(GEOM_Object)> & theSolids)
670 // set error code, check parameters
673 if (theSolids.empty())
676 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theSolids );
677 if ( objects.IsNull() || objects->IsEmpty() ) {
678 SetErrorCode("NULL argument shape");
683 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
686 Handle(GEOM_Function)
687 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), REMOVE_INTERNAL_FACES);
688 if (aFunction.IsNull()) return NULL;
690 //Check if the function is set correctly
691 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
693 // prepare "data container" class IHealing
694 GEOMImpl_IHealing HI (aFunction);
695 HI.SetOriginal( theSolids.front()->GetLastFunction() ); objects->Remove(1);
696 HI.SetShapes( objects );
697 HI.SetStatistics( myModifStats );
702 if (!GetSolver()->ComputeFunction(aFunction))
704 SetErrorCode("Healing driver failed");
708 catch (Standard_Failure) {
709 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
710 SetErrorCode(aFail->GetMessageString());
714 //Make a Python command
715 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.RemoveInternalFaces(" << theSolids << ")";
721 //=============================================================================
725 //=============================================================================
726 Handle(GEOM_Object) GEOMImpl_IHealingOperations::DivideEdge (Handle(GEOM_Object) theObject,
731 // set error code, check parameters
734 if (theObject.IsNull())
737 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
738 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
741 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
744 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), DIVIDE_EDGE);
746 if (aFunction.IsNull()) return NULL;
748 //Check if the function is set correctly
749 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
751 // prepare "data container" class IHealing
752 GEOMImpl_IHealing HI(aFunction);
753 HI.SetIndex( theIndex );
754 HI.SetDevideEdgeValue( theValue );
755 HI.SetIsByParameter( isByParameter );
756 HI.SetOriginal( aLastFunction );
757 HI.SetStatistics( myModifStats );
759 //Compute the translation
762 if (!GetSolver()->ComputeFunction(aFunction)) {
763 SetErrorCode("Healing driver failed");
767 catch (Standard_Failure) {
768 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
769 SetErrorCode(aFail->GetMessageString());
773 //Make a Python command
774 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.DivideEdge(" << theObject
775 << ", " << theIndex << ", " << theValue << ", " << (int)isByParameter << ")";
781 //=============================================================================
785 //=============================================================================
787 GEOMImpl_IHealingOperations::DivideEdgeByPoint (Handle(GEOM_Object) theObject,
789 std::list< Handle(GEOM_Object)> & thePoints)
791 // set error code, check parameters
794 if (theObject.IsNull() || thePoints.empty() )
797 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
798 if (aLastFunction.IsNull() )
799 return NULL; //There is no function which creates an object to be processed
801 Handle(TColStd_HSequenceOfTransient) aPointFunc = GEOM_Object::GetLastFunctions( thePoints );
802 if ( aPointFunc.IsNull() || aPointFunc->IsEmpty() ) {
803 SetErrorCode("NULL argument points");
808 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
811 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), DIVIDE_EDGE_BY_POINT);
813 if (aFunction.IsNull()) return NULL;
815 //Check if the function is set correctly
816 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
818 // prepare "data container" class IHealing
819 GEOMImpl_IHealing HI(aFunction);
820 HI.SetIndex ( theIndex );
821 HI.SetOriginal ( aLastFunction );
822 HI.SetShapes ( aPointFunc );
824 HI.SetStatistics( myModifStats );
826 //Compute the translation
829 if (!GetSolver()->ComputeFunction(aFunction)) {
830 SetErrorCode("Healing driver failed");
834 catch (Standard_Failure) {
835 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
836 SetErrorCode(aFail->GetMessageString());
840 //Make a Python command
841 GEOM::TPythonDump(aFunction)
842 << aNewObject << " = geompy.DivideEdgeByPoint(" << theObject
843 << ", " << theIndex << ", " << thePoints << ")";
849 //=============================================================================
851 * FuseCollinearEdgesWithinWire
853 //=============================================================================
854 Handle(GEOM_Object) GEOMImpl_IHealingOperations::FuseCollinearEdgesWithinWire
855 (Handle(GEOM_Object) theWire,
856 std::list<Handle(GEOM_Object)> theVertices)
860 if (theWire.IsNull()) return NULL;
863 Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), theWire->GetType());
865 // Add a new function
866 Handle(GEOM_Function) aFunction;
867 aFunction = aRes->AddFunction(GEOMImpl_HealingDriver::GetID(), FUSE_COLLINEAR_EDGES);
868 if (aFunction.IsNull()) return NULL;
870 // Check if the function is set correctly
871 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
873 GEOMImpl_IHealing aCI (aFunction);
874 aCI.SetStatistics( myModifStats );
876 Handle(GEOM_Function) aRefShape = theWire->GetLastFunction();
877 if (aRefShape.IsNull()) return NULL;
878 aCI.SetOriginal(aRefShape);
880 Handle(TColStd_HSequenceOfTransient) aVertices = new TColStd_HSequenceOfTransient;
881 std::list<Handle(GEOM_Object)>::iterator it = theVertices.begin();
882 for (; it != theVertices.end(); it++) {
883 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
884 if (aRefSh.IsNull()) {
885 SetErrorCode("NULL argument shape for the shape construction");
888 aVertices->Append(aRefSh);
890 aCI.SetShapes(aVertices);
892 // Compute the new wire
895 if (!GetSolver()->ComputeFunction(aFunction)) {
896 SetErrorCode("Healing driver failed");
900 catch (Standard_Failure) {
901 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
902 SetErrorCode(aFail->GetMessageString());
906 // Make a Python command
907 GEOM::TPythonDump pd (aFunction);
908 pd << aRes << " = geompy.FuseCollinearEdgesWithinWire(" << theWire << ", [";
910 it = theVertices.begin();
911 if (it != theVertices.end()) {
913 while (it != theVertices.end()) {
914 pd << ", " << (*it++);
923 //=============================================================================
927 //=============================================================================
928 bool GEOMImpl_IHealingOperations::GetFreeBoundary (Handle(TColStd_HSequenceOfTransient)& theObjects,
929 Handle(TColStd_HSequenceOfTransient)& theClosed,
930 Handle(TColStd_HSequenceOfTransient)& theOpen )
932 // set error code, check parameters
935 if ( theObjects.IsNull() || theObjects->Length() == 0 ||
936 theClosed.IsNull() || theOpen.IsNull() )
940 TopTools_SequenceOfShape shapes;
941 for ( int ind = 1; ind <= theObjects->Length(); ind++)
943 Handle(GEOM_Object) aRefShape = Handle(GEOM_Object)::DownCast( theObjects->Value(ind));
944 if ( aRefShape.IsNull() )
946 aShape = aRefShape->GetValue();
947 if ( aShape.IsNull() )
949 shapes.Append( aShape );
952 if ( shapes.Length() > 1 )
954 TopoDS_Compound compound;
955 BRep_Builder builder;
956 builder.MakeCompound( compound );
957 for ( int i = 1; i <= shapes.Length(); ++i )
958 builder.Add( compound, shapes( i ) );
963 // get free boundary shapes
965 ShapeAnalysis_FreeBounds anAnalizer(aShape, Standard_False,
966 Standard_True, Standard_True);
967 TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
968 TopoDS_Compound anOpen = anAnalizer.GetOpenWires();
970 // iterate through shapes and append them to the return sequence
971 Handle(GEOM_Object) anObj;
972 Handle(GEOM_Function) aFunction;
973 TopExp_Explorer anExp;
974 for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() )
976 anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
977 aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
978 TopoDS_Shape aValueShape = anExp.Current();
979 aFunction->SetValue( aValueShape );
980 theClosed->Append(anObj);
982 for ( anExp.Init( anOpen, TopAbs_WIRE ); anExp.More(); anExp.Next() )
984 anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
985 aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
986 TopoDS_Shape aValueShape = anExp.Current();
987 aFunction->SetValue( aValueShape );
988 theOpen->Append(anObj);
991 if(!aFunction.IsNull()) {
993 //Make a Python command
994 GEOM::TPythonDump pd (aFunction);
996 Standard_Integer i, aLen = theClosed->Length();
999 for (i = 1; i <= aLen; i++) {
1000 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theClosed->Value(i));
1001 pd << anObj_i << ((i < aLen) ? ", " : "");
1005 pd << "(isDone, empty_list, ";
1008 aLen = theOpen->Length();
1011 for (i = 1; i <= aLen; i++) {
1012 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theOpen->Value(i));
1013 pd << anObj_i << ((i < aLen) ? ", " : "");
1020 pd << ") = geompy.GetFreeBoundary(" << theObjects << ")";
1028 //=============================================================================
1032 //=============================================================================
1033 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientation (Handle(GEOM_Object) theObject)
1035 // set error code, check parameters
1038 if (theObject.IsNull())
1041 if (!theObject->IsMainShape()) {
1042 SetErrorCode("Sub-shape cannot be transformed - need to create a copy");
1046 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
1047 if (aLastFunction.IsNull())
1048 return NULL; //There is no function which creates an object to be processed
1050 if (theObject->GetType() == GEOM_VECTOR) { // Mantis issue 21066
1052 aFunction = theObject->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_REVERSE);
1054 //Check if the function is set correctly
1055 if (aFunction.IsNull()) return NULL;
1056 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
1058 // prepare "data container" class IVector
1059 GEOMImpl_IVector aVI (aFunction);
1060 aVI.SetCurve(aLastFunction);
1062 myModifStats->Clear();
1063 myModifStats->AddModif( "Vector reversed" );
1067 aFunction = theObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
1069 //Check if the function is set correctly
1070 if (aFunction.IsNull()) return NULL;
1071 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
1073 // prepare "data container" class IHealing
1074 GEOMImpl_IHealing HI (aFunction);
1075 HI.SetOriginal(aLastFunction);
1076 HI.SetStatistics( myModifStats );
1079 //Compute the translation
1082 if (!GetSolver()->ComputeFunction(aFunction)) {
1083 SetErrorCode("Healing driver failed");
1087 catch (Standard_Failure) {
1088 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1089 SetErrorCode(aFail->GetMessageString());
1093 //Make a Python command
1094 GEOM::TPythonDump(aFunction) << "geompy.ChangeOrientationShell("
1095 << theObject << ")";
1101 //=============================================================================
1103 * ChangeOrientationCopy
1105 //=============================================================================
1106 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientationCopy (Handle(GEOM_Object) theObject)
1108 // set error code, check parameters
1111 if (theObject.IsNull())
1114 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
1115 if (aLastFunction.IsNull())
1116 return NULL; //There is no function which creates an object to be processed
1119 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
1121 if (theObject->GetType() == GEOM_VECTOR) { // Mantis issue 21066
1123 aFunction = aNewObject->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_REVERSE);
1125 //Check if the function is set correctly
1126 if (aFunction.IsNull()) return NULL;
1127 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
1129 // prepare "data container" class IVector
1130 GEOMImpl_IVector aVI (aFunction);
1131 aVI.SetCurve(aLastFunction);
1133 myModifStats->Clear();
1134 myModifStats->AddModif( "Vector reversed" );
1138 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
1140 //Check if the function is set correctly
1141 if (aFunction.IsNull()) return NULL;
1142 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
1144 // prepare "data container" class IHealing
1145 GEOMImpl_IHealing aHI (aFunction);
1146 aHI.SetOriginal(aLastFunction);
1147 aHI.SetStatistics( myModifStats );
1150 // Compute the result
1153 if (!GetSolver()->ComputeFunction(aFunction)) {
1154 SetErrorCode("Healing driver failed");
1158 catch (Standard_Failure) {
1159 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1160 SetErrorCode(aFail->GetMessageString());
1164 //Make a Python command
1165 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.ChangeOrientationShellCopy("
1166 << theObject << ")";
1172 //=============================================================================
1176 //=============================================================================
1177 Handle(GEOM_Object) GEOMImpl_IHealingOperations::LimitTolerance (Handle(GEOM_Object) theObject,
1178 double theTolerance,
1179 TopAbs_ShapeEnum theType)
1181 // Set error code, check parameters
1184 if (theObject.IsNull())
1187 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
1188 if (aLastFunction.IsNull())
1189 return NULL; // There is no function which creates an object to be processed
1192 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), theObject->GetType());
1195 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), LIMIT_TOLERANCE);
1197 if (aFunction.IsNull())
1200 // Check if the function is set correctly
1201 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
1203 // Prepare "data container" class IHealing
1204 GEOMImpl_IHealing HI (aFunction);
1205 HI.SetOriginal(aLastFunction);
1206 HI.SetTolerance(theTolerance);
1207 HI.SetType(theType);
1208 HI.SetStatistics( myModifStats );
1213 if (!GetSolver()->ComputeFunction(aFunction)) {
1214 SetErrorCode("Healing driver failed");
1218 catch (Standard_Failure) {
1219 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1220 SetErrorCode(aFail->GetMessageString());
1224 // Make a Python command
1225 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.LimitTolerance("
1226 << theObject << ", " << theTolerance << ")";