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 <utilities.h>
42 #include <Utils_ExceptHandlers.hxx>
44 #include <BRep_Builder.hxx>
45 #include <ShapeAnalysis_FreeBounds.hxx>
46 #include <TColStd_HArray1OfExtendedString.hxx>
47 #include <TColStd_HSequenceOfTransient.hxx>
48 #include <TCollection_AsciiString.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopTools_SequenceOfShape.hxx>
51 #include <TopoDS_Compound.hxx>
53 #include <Standard_Failure.hxx>
54 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
56 //=============================================================================
60 //=============================================================================
61 GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations (GEOM_Engine* theEngine, int theDocID)
62 : GEOM_IOperations(theEngine, theDocID)
64 myModifStats = new ShHealOper_ModifStats;
65 MESSAGE("GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations");
68 //=============================================================================
72 //=============================================================================
73 GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations()
76 MESSAGE("GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations");
80 //=============================================================================
84 //=============================================================================
85 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ShapeProcess (Handle(GEOM_Object) theObject,
86 const Handle(TColStd_HArray1OfExtendedString)& theOperators,
87 const Handle(TColStd_HArray1OfExtendedString)& theParams,
88 const Handle(TColStd_HArray1OfExtendedString)& theValues)
90 // set error code, check parameters
93 if (theObject.IsNull())
96 if (theOperators.IsNull() || theOperators->Length() <= 0) {
97 SetErrorCode("No operators requested");
101 Standard_Integer nbParams = 0, nbValues = 0;
102 if (!theParams.IsNull()) {
103 nbParams = theParams->Length();
105 if (!theValues.IsNull()) {
106 nbValues = theValues->Length();
109 if (nbParams != nbValues) {
110 SetErrorCode("Number of parameter values must be equal to the number of parameters");
114 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
115 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
118 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
121 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SHAPE_PROCESS);
123 if (aFunction.IsNull()) return NULL;
125 //Check if the function is set correctly
126 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
128 // prepare "data container" class IHealing
129 GEOMImpl_IHealing HI(aFunction);
130 HI.SetOriginal(aLastFunction);
131 HI.SetOperators( theOperators );
133 HI.SetParameters( theParams );
134 HI.SetValues( theValues );
136 HI.SetStatistics( myModifStats );
138 //Compute the translation
141 if (!GetSolver()->ComputeFunction(aFunction))
143 SetErrorCode("Shape Healing algorithm failed");
147 catch (Standard_Failure)
149 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
150 SetErrorCode(aFail->GetMessageString());
154 //Make a Python command
155 GEOM::TPythonDump pd (aFunction);
156 pd << aNewObject << " = geompy.ProcessShape(" << theObject << ", [";
159 int i = theOperators->Lower(), nb = theOperators->Upper();
160 for ( ; i <= nb; i++) {
161 pd << "\"" << TCollection_AsciiString(theOperators->Value( i )).ToCString()
162 << (( i < nb ) ? "\", " : "\"");
165 // list of parameters
166 i = theParams->Lower(); nb = theParams->Upper();
167 for ( ; i <= nb; i++) {
168 pd << "\"" << TCollection_AsciiString(theParams->Value( i )).ToCString()
169 << (( i < nb ) ? "\", " : "\"");
173 i = theValues->Lower(); nb = theValues->Upper();
174 for ( ; i <= nb; i++) {
175 pd << "\"" << TCollection_AsciiString(theValues->Value( i )).ToCString()
176 << (( i < nb ) ? "\", " : "\"");
184 //=============================================================================
188 //=============================================================================
189 void GEOMImpl_IHealingOperations::GetShapeProcessParameters (std::list<std::string>& theOperations,
190 std::list<std::string>& theParams,
191 std::list<std::string>& theValues)
193 ShHealOper_ShapeProcess aHealer;
194 TColStd_SequenceOfAsciiString anOperators;
195 int nbOperatorErrors( 0 );
196 if ( aHealer.GetOperators( anOperators ) )
198 for ( Standard_Integer i = 1; i <= anOperators.Length(); i++ )
200 std::string anOperation = anOperators.Value( i ).ToCString();
201 if ( GetOperatorParameters( anOperation, theParams, theValues ) )
202 theOperations.push_back( anOperation );
209 SetErrorCode("ERROR retrieving operators (GEOMImpl_IHealingOperations)");
212 if ( nbOperatorErrors ) {
213 TCollection_AsciiString aMsg ("ERRORS retrieving ShapeProcess parameters (GEOMImpl_IHealingOperations): nbOperatorErrors = ");
214 aMsg += TCollection_AsciiString( nbOperatorErrors );
215 MESSAGE(aMsg.ToCString());
219 //=============================================================================
221 * GetOperatorParameters
223 //=============================================================================
224 bool GEOMImpl_IHealingOperations::GetOperatorParameters( const std::string & theOperation,
225 std::list<std::string>& theParams,
226 std::list<std::string>& theValues )
228 ShHealOper_ShapeProcess aHealer;
229 int nbParamValueErrors( 0 );
230 std::list<std::string> aParams;
231 if ( GetParameters( theOperation, aParams ) ) {
232 for ( std::list<std::string>::iterator it = aParams.begin(); it != aParams.end(); ++it ) {
233 TCollection_AsciiString aParam( (Standard_CString)(*it).c_str() );
234 TCollection_AsciiString aValue;
235 if ( aHealer.GetParameter( aParam, aValue ) ) {
236 theParams.push_back( aParam.ToCString() );
237 theValues.push_back( aValue.ToCString() );
240 nbParamValueErrors++;
246 if ( nbParamValueErrors ) {
247 TCollection_AsciiString aMsg ("ERRORS retrieving ShapeProcess parameter values (GEOMImpl_IHealingOperations): nbParamValueErrors = ");
248 aMsg += TCollection_AsciiString( nbParamValueErrors );
249 MESSAGE(aMsg.ToCString());
255 //=============================================================================
259 //=============================================================================
260 bool GEOMImpl_IHealingOperations::GetParameters (const std::string theOperation,
261 std::list<std::string>& theParams)
263 if ( theOperation == "SplitAngle" ) {
264 theParams.push_back( "SplitAngle.Angle" );
265 theParams.push_back( "SplitAngle.MaxTolerance" );
267 } else if ( theOperation == "SplitClosedFaces" ) {
268 theParams.push_back( "SplitClosedFaces.NbSplitPoints" );
270 } else if ( theOperation == "FixFaceSize" ) {
271 theParams.push_back( "FixFaceSize.Tolerance" );
273 } else if( theOperation == "DropSmallEdges" ) {
274 theParams.push_back( "DropSmallEdges.Tolerance3d" );
276 } else if( theOperation == "DropSmallSolids" ) {
277 theParams.push_back( "DropSmallSolids.WidthFactorThreshold" );
278 theParams.push_back( "DropSmallSolids.VolumeThreshold" );
279 theParams.push_back( "DropSmallSolids.MergeSolids" );
281 } else if( theOperation == "BSplineRestriction" ) {
282 theParams.push_back( "BSplineRestriction.SurfaceMode" );
283 theParams.push_back( "BSplineRestriction.Curve3dMode" );
284 theParams.push_back( "BSplineRestriction.Curve2dMode" );
285 theParams.push_back( "BSplineRestriction.Tolerance3d" );
286 theParams.push_back( "BSplineRestriction.Tolerance2d" );
287 theParams.push_back( "BSplineRestriction.RequiredDegree" );
288 theParams.push_back( "BSplineRestriction.RequiredNbSegments" );
289 theParams.push_back( "BSplineRestriction.Continuity3d" );
290 theParams.push_back( "BSplineRestriction.Continuity2d" );
292 } else if( theOperation == "SplitContinuity" ) {
293 theParams.push_back( "SplitContinuity.Tolerance3d" );
294 theParams.push_back( "SplitContinuity.SurfaceContinuity" );
295 theParams.push_back( "SplitContinuity.CurveContinuity" );
297 } else if( theOperation == "ToBezier" ) {
298 theParams.push_back( "ToBezier.SurfaceMode" );
299 theParams.push_back( "ToBezier.Curve3dMode" );
300 theParams.push_back( "ToBezier.Curve2dMode" );
301 theParams.push_back( "ToBezier.MaxTolerance" );
303 } else if( theOperation == "SameParameter" ) {
304 theParams.push_back( "SameParameter.Tolerance3d" );
306 } else if( theOperation == "FixShape" ) {
307 theParams.push_back( "FixShape.Tolerance3d" );
308 theParams.push_back( "FixShape.MaxTolerance3d" );
317 //=============================================================================
321 //=============================================================================
322 Handle(GEOM_Object) GEOMImpl_IHealingOperations::SuppressFaces
323 (Handle(GEOM_Object) theObject, const Handle(TColStd_HArray1OfInteger)& theFaces)
325 // set error code, check parameters
328 if (theObject.IsNull()) // if theFaces.IsNull() - it's OK, it means that ALL faces must be removed..
331 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
332 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
335 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
338 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SUPPRESS_FACES);
340 if (aFunction.IsNull()) return NULL;
342 //Check if the function is set correctly
343 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
345 // prepare "data container" class IHealing
346 GEOMImpl_IHealing HI (aFunction);
347 HI.SetFaces(theFaces);
348 HI.SetOriginal(aLastFunction);
349 HI.SetStatistics( myModifStats );
351 //Compute the translation
354 if (!GetSolver()->ComputeFunction(aFunction))
356 SetErrorCode("Healing driver failed");
360 catch (Standard_Failure)
362 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
363 SetErrorCode(aFail->GetMessageString());
367 //Make a Python command
368 GEOM::TPythonDump pd (aFunction);
369 pd << aNewObject << " = geompy.SuppressFaces(" << theObject << ", [";
372 int i = theFaces->Lower(), nb = theFaces->Upper();
373 for ( ; i <= nb; i++)
374 pd << theFaces->Value( i ) << (( i < nb ) ? ", " : "])");
380 //=============================================================================
384 //=============================================================================
385 Handle(GEOM_Object) GEOMImpl_IHealingOperations::CloseContour
386 (Handle(GEOM_Object) theObject,
387 const Handle(TColStd_HArray1OfInteger)& theWires,
390 // set error code, check parameters
393 if (theObject.IsNull())
395 SetErrorCode("NULL object given");
399 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
400 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
403 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
406 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CLOSE_CONTOUR);
408 if (aFunction.IsNull()) return NULL;
410 //Check if the function is set correctly
411 if(aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
413 // prepare "data container" class IHealing
414 GEOMImpl_IHealing HI(aFunction);
415 HI.SetWires( theWires );
416 HI.SetIsCommonVertex( isCommonVertex );
417 HI.SetOriginal( aLastFunction );
418 HI.SetStatistics( myModifStats );
420 //Compute the translation
423 if (!GetSolver()->ComputeFunction(aFunction))
425 SetErrorCode("Healing driver failed");
429 catch (Standard_Failure)
431 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
432 SetErrorCode(aFail->GetMessageString());
436 //Make a Python command
437 GEOM::TPythonDump pd (aFunction);
438 pd << aNewObject << " = geompy.CloseContour(" << theObject << ", [";
441 if (!theWires.IsNull())
443 int i = theWires->Lower(), nb = theWires->Upper();
444 pd << theWires->Value(i++);
446 pd << ", " << theWires->Value(i++);
448 pd << "], " << (int)isCommonVertex << ")";
454 //=============================================================================
458 //=============================================================================
459 Handle(GEOM_Object) GEOMImpl_IHealingOperations::RemoveIntWires
460 (Handle(GEOM_Object) theObject, const Handle(TColStd_HArray1OfInteger)& theWires)
462 // set error code, check parameters
465 if (theObject.IsNull()) // if theWires is NULL it's OK, it means that ALL wires must be removed
468 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
469 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
472 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
475 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), REMOVE_INT_WIRES);
477 if (aFunction.IsNull()) return NULL;
479 //Check if the function is set correctly
480 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
482 // prepare "data container" class IHealing
483 GEOMImpl_IHealing HI(aFunction);
484 HI.SetWires( theWires );
485 HI.SetOriginal( aLastFunction );
486 HI.SetStatistics( myModifStats );
488 //Compute the translation
491 if (!GetSolver()->ComputeFunction(aFunction))
493 SetErrorCode("Healing driver failed");
497 catch (Standard_Failure)
499 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
500 SetErrorCode(aFail->GetMessageString());
504 //Make a Python command
505 GEOM::TPythonDump pd (aFunction);
506 pd << aNewObject << " = geompy.SuppressInternalWires(" << theObject << ", [";
509 if (!theWires.IsNull()) {
510 int i = theWires->Lower(), nb = theWires->Upper();
511 for ( ; i <= nb; i++)
512 pd << theWires->Value( i ) << (( i < nb ) ? ", " : "])");
521 //=============================================================================
525 //=============================================================================
526 Handle(GEOM_Object) GEOMImpl_IHealingOperations::FillHoles (Handle(GEOM_Object) theObject,
527 const Handle(TColStd_HArray1OfInteger)& theWires)
529 // set error code, check parameters
532 if (theObject.IsNull()) // if theWires is NULL it's OK, it means that ALL holes must be removed
535 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
536 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
539 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
542 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), FILL_HOLES);
544 if (aFunction.IsNull()) return NULL;
546 //Check if the function is set correctly
547 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
549 // prepare "data container" class IHealing
550 GEOMImpl_IHealing HI(aFunction);
551 HI.SetWires( theWires );
552 HI.SetOriginal( aLastFunction );
553 HI.SetStatistics( myModifStats );
555 //Compute the translation
558 if (!GetSolver()->ComputeFunction(aFunction))
560 SetErrorCode("Healing driver failed");
564 catch (Standard_Failure)
566 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
567 SetErrorCode(aFail->GetMessageString());
571 //Make a Python command
572 GEOM::TPythonDump pd (aFunction);
573 pd << aNewObject << " = geompy.SuppressHoles(" << theObject << ", [";
576 if ( theWires.IsNull() )
579 int i = theWires->Lower(), nb = theWires->Upper();
580 for ( ; i <= nb; i++)
581 pd << theWires->Value( i ) << (( i < nb ) ? ", " : "])");
588 //=============================================================================
592 //=============================================================================
594 GEOMImpl_IHealingOperations::Sew (std::list<Handle(GEOM_Object)>& theObjects,
596 bool isAllowNonManifold)
598 // set error code, check parameters
601 if (theObjects.empty())
604 Handle(TColStd_HSequenceOfTransient) objects =
605 GEOM_Object::GetLastFunctions( theObjects );
606 if ( objects.IsNull() || objects->IsEmpty() ) {
607 SetErrorCode("NULL argument shape");
612 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
615 int aFunctionType = (isAllowNonManifold ? SEWING_NON_MANIFOLD : SEWING);
616 Handle(GEOM_Function) aFunction =
617 aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), aFunctionType);
618 if (aFunction.IsNull()) return NULL;
620 //Check if the function is set correctly
621 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
623 // prepare "data container" class IHealing
624 GEOMImpl_IHealing HI(aFunction);
625 HI.SetTolerance( theTolerance );
626 HI.SetOriginal( theObjects.front()->GetLastFunction() ); objects->Remove(1);
627 HI.SetShapes( objects );
628 HI.SetStatistics( myModifStats );
633 if (!GetSolver()->ComputeFunction(aFunction))
635 SetErrorCode("Healing driver failed");
639 catch (Standard_Failure) {
640 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
641 SetErrorCode(aFail->GetMessageString());
645 //Make a Python command
646 GEOM::TPythonDump pd(aFunction);
648 pd << aNewObject << " = geompy.Sew(" << theObjects << ", " << theTolerance;
650 if (isAllowNonManifold) {
660 //=============================================================================
662 * RemoveInternalFaces
664 //=============================================================================
666 GEOMImpl_IHealingOperations::RemoveInternalFaces (std::list< Handle(GEOM_Object)> & theSolids)
668 // set error code, check parameters
671 if (theSolids.empty())
674 Handle(TColStd_HSequenceOfTransient) objects = GEOM_Object::GetLastFunctions( theSolids );
675 if ( objects.IsNull() || objects->IsEmpty() ) {
676 SetErrorCode("NULL argument shape");
681 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
684 Handle(GEOM_Function)
685 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), REMOVE_INTERNAL_FACES);
686 if (aFunction.IsNull()) return NULL;
688 //Check if the function is set correctly
689 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
691 // prepare "data container" class IHealing
692 GEOMImpl_IHealing HI (aFunction);
693 HI.SetOriginal( theSolids.front()->GetLastFunction() ); objects->Remove(1);
694 HI.SetShapes( objects );
695 HI.SetStatistics( myModifStats );
700 if (!GetSolver()->ComputeFunction(aFunction))
702 SetErrorCode("Healing driver failed");
706 catch (Standard_Failure) {
707 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
708 SetErrorCode(aFail->GetMessageString());
712 //Make a Python command
713 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.RemoveInternalFaces(" << theSolids << ")";
719 //=============================================================================
723 //=============================================================================
724 Handle(GEOM_Object) GEOMImpl_IHealingOperations::DivideEdge (Handle(GEOM_Object) theObject,
729 // set error code, check parameters
732 if (theObject.IsNull())
735 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
736 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
739 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
742 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), DIVIDE_EDGE);
744 if (aFunction.IsNull()) return NULL;
746 //Check if the function is set correctly
747 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
749 // prepare "data container" class IHealing
750 GEOMImpl_IHealing HI(aFunction);
751 HI.SetIndex( theIndex );
752 HI.SetDevideEdgeValue( theValue );
753 HI.SetIsByParameter( isByParameter );
754 HI.SetOriginal( aLastFunction );
755 HI.SetStatistics( myModifStats );
757 //Compute the translation
760 if (!GetSolver()->ComputeFunction(aFunction)) {
761 SetErrorCode("Healing driver failed");
765 catch (Standard_Failure) {
766 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
767 SetErrorCode(aFail->GetMessageString());
771 //Make a Python command
772 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.DivideEdge(" << theObject
773 << ", " << theIndex << ", " << theValue << ", " << (int)isByParameter << ")";
779 //=============================================================================
783 //=============================================================================
785 GEOMImpl_IHealingOperations::DivideEdgeByPoint (Handle(GEOM_Object) theObject,
787 std::list< Handle(GEOM_Object)> & thePoints)
789 // set error code, check parameters
792 if (theObject.IsNull() || thePoints.empty() )
795 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
796 if (aLastFunction.IsNull() )
797 return NULL; //There is no function which creates an object to be processed
799 Handle(TColStd_HSequenceOfTransient) aPointFunc = GEOM_Object::GetLastFunctions( thePoints );
800 if ( aPointFunc.IsNull() || aPointFunc->IsEmpty() ) {
801 SetErrorCode("NULL argument points");
806 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
809 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), DIVIDE_EDGE_BY_POINT);
811 if (aFunction.IsNull()) return NULL;
813 //Check if the function is set correctly
814 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
816 // prepare "data container" class IHealing
817 GEOMImpl_IHealing HI(aFunction);
818 HI.SetIndex ( theIndex );
819 HI.SetOriginal ( aLastFunction );
820 HI.SetShapes ( aPointFunc );
822 HI.SetStatistics( myModifStats );
824 //Compute the translation
827 if (!GetSolver()->ComputeFunction(aFunction)) {
828 SetErrorCode("Healing driver failed");
832 catch (Standard_Failure) {
833 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
834 SetErrorCode(aFail->GetMessageString());
838 //Make a Python command
839 GEOM::TPythonDump(aFunction)
840 << aNewObject << " = geompy.DivideEdgeByPoint(" << theObject
841 << ", " << theIndex << ", " << thePoints << ")";
847 //=============================================================================
849 * FuseCollinearEdgesWithinWire
851 //=============================================================================
852 Handle(GEOM_Object) GEOMImpl_IHealingOperations::FuseCollinearEdgesWithinWire
853 (Handle(GEOM_Object) theWire,
854 std::list<Handle(GEOM_Object)> theVertices)
858 if (theWire.IsNull()) return NULL;
861 Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), theWire->GetType());
863 // Add a new function
864 Handle(GEOM_Function) aFunction;
865 aFunction = aRes->AddFunction(GEOMImpl_HealingDriver::GetID(), FUSE_COLLINEAR_EDGES);
866 if (aFunction.IsNull()) return NULL;
868 // Check if the function is set correctly
869 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
871 GEOMImpl_IHealing aCI (aFunction);
872 aCI.SetStatistics( myModifStats );
874 Handle(GEOM_Function) aRefShape = theWire->GetLastFunction();
875 if (aRefShape.IsNull()) return NULL;
876 aCI.SetOriginal(aRefShape);
878 Handle(TColStd_HSequenceOfTransient) aVertices = new TColStd_HSequenceOfTransient;
879 std::list<Handle(GEOM_Object)>::iterator it = theVertices.begin();
880 for (; it != theVertices.end(); it++) {
881 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
882 if (aRefSh.IsNull()) {
883 SetErrorCode("NULL argument shape for the shape construction");
886 aVertices->Append(aRefSh);
888 aCI.SetShapes(aVertices);
890 // Compute the new wire
893 if (!GetSolver()->ComputeFunction(aFunction)) {
894 SetErrorCode("Healing driver failed");
898 catch (Standard_Failure) {
899 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
900 SetErrorCode(aFail->GetMessageString());
904 // Make a Python command
905 GEOM::TPythonDump pd (aFunction);
906 pd << aRes << " = geompy.FuseCollinearEdgesWithinWire(" << theWire << ", [";
908 it = theVertices.begin();
909 if (it != theVertices.end()) {
911 while (it != theVertices.end()) {
912 pd << ", " << (*it++);
921 //=============================================================================
925 //=============================================================================
926 bool GEOMImpl_IHealingOperations::GetFreeBoundary (Handle(TColStd_HSequenceOfTransient)& theObjects,
927 Handle(TColStd_HSequenceOfTransient)& theClosed,
928 Handle(TColStd_HSequenceOfTransient)& theOpen )
930 // set error code, check parameters
933 if ( theObjects.IsNull() || theObjects->Length() == 0 ||
934 theClosed.IsNull() || theOpen.IsNull() )
938 TopTools_SequenceOfShape shapes;
939 for ( int ind = 1; ind <= theObjects->Length(); ind++)
941 Handle(GEOM_Object) aRefShape = Handle(GEOM_Object)::DownCast( theObjects->Value(ind));
942 if ( aRefShape.IsNull() )
944 aShape = aRefShape->GetValue();
945 if ( aShape.IsNull() )
947 shapes.Append( aShape );
950 if ( shapes.Length() > 1 )
952 TopoDS_Compound compound;
953 BRep_Builder builder;
954 builder.MakeCompound( compound );
955 for ( int i = 1; i <= shapes.Length(); ++i )
956 builder.Add( compound, shapes( i ) );
961 // get free boundary shapes
963 ShapeAnalysis_FreeBounds anAnalizer(aShape, Standard_False,
964 Standard_True, Standard_True);
965 TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
966 TopoDS_Compound anOpen = anAnalizer.GetOpenWires();
968 // iterate through shapes and append them to the return sequence
969 Handle(GEOM_Object) anObj;
970 Handle(GEOM_Function) aFunction;
971 TopExp_Explorer anExp;
972 for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() )
974 anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
975 aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
976 TopoDS_Shape aValueShape = anExp.Current();
977 aFunction->SetValue( aValueShape );
978 theClosed->Append(anObj);
980 for ( anExp.Init( anOpen, TopAbs_WIRE ); anExp.More(); anExp.Next() )
982 anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
983 aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
984 TopoDS_Shape aValueShape = anExp.Current();
985 aFunction->SetValue( aValueShape );
986 theOpen->Append(anObj);
989 if(!aFunction.IsNull()) {
991 //Make a Python command
992 GEOM::TPythonDump pd (aFunction);
994 Standard_Integer i, aLen = theClosed->Length();
997 for (i = 1; i <= aLen; i++) {
998 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theClosed->Value(i));
999 pd << anObj_i << ((i < aLen) ? ", " : "");
1003 pd << "(isDone, empty_list, ";
1006 aLen = theOpen->Length();
1009 for (i = 1; i <= aLen; i++) {
1010 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theOpen->Value(i));
1011 pd << anObj_i << ((i < aLen) ? ", " : "");
1018 pd << ") = geompy.GetFreeBoundary(" << theObjects << ")";
1026 //=============================================================================
1030 //=============================================================================
1031 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientation (Handle(GEOM_Object) theObject)
1033 // set error code, check parameters
1036 if (theObject.IsNull())
1039 if (!theObject->IsMainShape()) {
1040 SetErrorCode("Sub-shape cannot be transformed - need to create a copy");
1044 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
1045 if (aLastFunction.IsNull())
1046 return NULL; //There is no function which creates an object to be processed
1048 if (theObject->GetType() == GEOM_VECTOR) { // Mantis issue 21066
1050 aFunction = theObject->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_REVERSE);
1052 //Check if the function is set correctly
1053 if (aFunction.IsNull()) return NULL;
1054 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
1056 // prepare "data container" class IVector
1057 GEOMImpl_IVector aVI (aFunction);
1058 aVI.SetCurve(aLastFunction);
1060 myModifStats->Clear();
1061 myModifStats->AddModif( "Vector reversed" );
1065 aFunction = theObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
1067 //Check if the function is set correctly
1068 if (aFunction.IsNull()) return NULL;
1069 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
1071 // prepare "data container" class IHealing
1072 GEOMImpl_IHealing HI (aFunction);
1073 HI.SetOriginal(aLastFunction);
1074 HI.SetStatistics( myModifStats );
1077 //Compute the translation
1080 if (!GetSolver()->ComputeFunction(aFunction)) {
1081 SetErrorCode("Healing driver failed");
1085 catch (Standard_Failure) {
1086 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1087 SetErrorCode(aFail->GetMessageString());
1091 //Make a Python command
1092 GEOM::TPythonDump(aFunction) << "geompy.ChangeOrientationShell("
1093 << theObject << ")";
1099 //=============================================================================
1101 * ChangeOrientationCopy
1103 //=============================================================================
1104 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientationCopy (Handle(GEOM_Object) theObject)
1106 // set error code, check parameters
1109 if (theObject.IsNull())
1112 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
1113 if (aLastFunction.IsNull())
1114 return NULL; //There is no function which creates an object to be processed
1117 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
1119 if (theObject->GetType() == GEOM_VECTOR) { // Mantis issue 21066
1121 aFunction = aNewObject->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_REVERSE);
1123 //Check if the function is set correctly
1124 if (aFunction.IsNull()) return NULL;
1125 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
1127 // prepare "data container" class IVector
1128 GEOMImpl_IVector aVI (aFunction);
1129 aVI.SetCurve(aLastFunction);
1131 myModifStats->Clear();
1132 myModifStats->AddModif( "Vector reversed" );
1136 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
1138 //Check if the function is set correctly
1139 if (aFunction.IsNull()) return NULL;
1140 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
1142 // prepare "data container" class IHealing
1143 GEOMImpl_IHealing aHI (aFunction);
1144 aHI.SetOriginal(aLastFunction);
1145 aHI.SetStatistics( myModifStats );
1148 // Compute the result
1151 if (!GetSolver()->ComputeFunction(aFunction)) {
1152 SetErrorCode("Healing driver failed");
1156 catch (Standard_Failure) {
1157 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1158 SetErrorCode(aFail->GetMessageString());
1162 //Make a Python command
1163 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.ChangeOrientationShellCopy("
1164 << theObject << ")";
1170 //=============================================================================
1174 //=============================================================================
1175 Handle(GEOM_Object) GEOMImpl_IHealingOperations::LimitTolerance (Handle(GEOM_Object) theObject,
1176 double theTolerance,
1177 TopAbs_ShapeEnum theType)
1179 // Set error code, check parameters
1182 if (theObject.IsNull())
1185 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
1186 if (aLastFunction.IsNull())
1187 return NULL; // There is no function which creates an object to be processed
1190 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), theObject->GetType());
1193 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), LIMIT_TOLERANCE);
1195 if (aFunction.IsNull())
1198 // Check if the function is set correctly
1199 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
1201 // Prepare "data container" class IHealing
1202 GEOMImpl_IHealing HI (aFunction);
1203 HI.SetOriginal(aLastFunction);
1204 HI.SetTolerance(theTolerance);
1205 HI.SetType(theType);
1206 HI.SetStatistics( myModifStats );
1211 if (!GetSolver()->ComputeFunction(aFunction)) {
1212 SetErrorCode("Healing driver failed");
1216 catch (Standard_Failure) {
1217 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1218 SetErrorCode(aFail->GetMessageString());
1222 // Make a Python command
1223 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.LimitTolerance("
1224 << theObject << ", " << theTolerance << ")";