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
24 #pragma warning( disable:4786 )
27 #include <Standard_Version.hxx>
28 #include <Standard_Stream.hxx>
30 #include <GEOMImpl_IHealingOperations.hxx>
31 #include <GEOM_PythonDump.hxx>
32 #include <GEOMImpl_HealingDriver.hxx>
33 #include <GEOMImpl_Types.hxx>
34 #include <GEOMImpl_IHealing.hxx>
35 #include <GEOMImpl_IVector.hxx>
36 #include <GEOMImpl_VectorDriver.hxx>
37 #include <GEOMImpl_CopyDriver.hxx>
39 #include <Basics_OCCTVersion.hxx>
41 #include <utilities.h>
43 #include <Utils_ExceptHandlers.hxx>
45 #include <BRep_Builder.hxx>
46 #include <ShHealOper_ShapeProcess.hxx>
47 #include <ShapeAnalysis_FreeBounds.hxx>
48 #include <TColStd_HArray1OfExtendedString.hxx>
49 #include <TColStd_HSequenceOfTransient.hxx>
50 #include <TCollection_AsciiString.hxx>
51 #include <TDF_Tool.hxx>
52 #include <TopExp_Explorer.hxx>
53 #include <TopTools_SequenceOfShape.hxx>
54 #include <TopoDS_Compound.hxx>
56 #include <Standard_Failure.hxx>
57 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
59 //=============================================================================
63 //=============================================================================
64 GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations (GEOM_Engine* theEngine, int theDocID)
65 : GEOM_IOperations(theEngine, theDocID)
67 MESSAGE("GEOMImpl_IHealingOperations::GEOMImpl_IHealingOperations");
70 //=============================================================================
74 //=============================================================================
75 GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations()
77 MESSAGE("GEOMImpl_IHealingOperations::~GEOMImpl_IHealingOperations");
81 //=============================================================================
85 //=============================================================================
86 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ShapeProcess (Handle(GEOM_Object) theObject,
87 const Handle(TColStd_HArray1OfExtendedString)& theOperators,
88 const Handle(TColStd_HArray1OfExtendedString)& theParams,
89 const Handle(TColStd_HArray1OfExtendedString)& theValues)
91 // set error code, check parameters
94 if (theObject.IsNull())
97 if (theOperators.IsNull() || theOperators->Length() <= 0) {
98 SetErrorCode("No operators requested");
102 Standard_Integer nbParams = 0, nbValues = 0;
103 if (!theParams.IsNull()) {
104 nbParams = theParams->Length();
106 if (!theValues.IsNull()) {
107 nbValues = theValues->Length();
110 if (nbParams != nbValues) {
111 SetErrorCode("Number of parameter values must be equal to the number of parameters");
115 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
116 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
119 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
122 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SHAPE_PROCESS);
124 if (aFunction.IsNull()) return NULL;
126 //Check if the function is set correctly
127 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
129 // prepare "data container" class IHealing
130 GEOMImpl_IHealing HI(aFunction);
131 HI.SetOriginal(aLastFunction);
132 HI.SetOperators( theOperators );
134 HI.SetParameters( theParams );
135 HI.SetValues( theValues );
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 == "BSplineRestriction" ) {
277 theParams.push_back( "BSplineRestriction.SurfaceMode" );
278 theParams.push_back( "BSplineRestriction.Curve3dMode" );
279 theParams.push_back( "BSplineRestriction.Curve2dMode" );
280 theParams.push_back( "BSplineRestriction.Tolerance3d" );
281 theParams.push_back( "BSplineRestriction.Tolerance2d" );
282 theParams.push_back( "BSplineRestriction.RequiredDegree" );
283 theParams.push_back( "BSplineRestriction.RequiredNbSegments" );
284 theParams.push_back( "BSplineRestriction.Continuity3d" );
285 theParams.push_back( "BSplineRestriction.Continuity2d" );
287 } else if( theOperation == "SplitContinuity" ) {
288 theParams.push_back( "SplitContinuity.Tolerance3d" );
289 theParams.push_back( "SplitContinuity.SurfaceContinuity" );
290 theParams.push_back( "SplitContinuity.CurveContinuity" );
292 } else if( theOperation == "ToBezier" ) {
293 theParams.push_back( "ToBezier.SurfaceMode" );
294 theParams.push_back( "ToBezier.Curve3dMode" );
295 theParams.push_back( "ToBezier.Curve2dMode" );
296 theParams.push_back( "ToBezier.MaxTolerance" );
298 } else if( theOperation == "SameParameter" ) {
299 theParams.push_back( "SameParameter.Tolerance3d" );
301 } else if( theOperation == "FixShape" ) {
302 theParams.push_back( "FixShape.Tolerance3d" );
303 theParams.push_back( "FixShape.MaxTolerance3d" );
312 //=============================================================================
316 //=============================================================================
317 Handle(GEOM_Object) GEOMImpl_IHealingOperations::SuppressFaces
318 (Handle(GEOM_Object) theObject, const Handle(TColStd_HArray1OfInteger)& theFaces)
320 // set error code, check parameters
323 if (theObject.IsNull()) // if theFaces.IsNull() - it's OK, it means that ALL faces must be removed..
326 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
327 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
330 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
333 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), SUPPRESS_FACES);
335 if (aFunction.IsNull()) return NULL;
337 //Check if the function is set correctly
338 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
340 // prepare "data container" class IHealing
341 GEOMImpl_IHealing HI (aFunction);
342 HI.SetFaces(theFaces);
343 HI.SetOriginal(aLastFunction);
345 //Compute the translation
348 if (!GetSolver()->ComputeFunction(aFunction))
350 SetErrorCode("Healing driver failed");
354 catch (Standard_Failure)
356 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
357 SetErrorCode(aFail->GetMessageString());
361 //Make a Python command
362 GEOM::TPythonDump pd (aFunction);
363 pd << aNewObject << " = geompy.SuppressFaces(" << theObject << ", [";
366 int i = theFaces->Lower(), nb = theFaces->Upper();
367 for ( ; i <= nb; i++)
368 pd << theFaces->Value( i ) << (( i < nb ) ? ", " : "])");
374 //=============================================================================
378 //=============================================================================
379 Handle(GEOM_Object) GEOMImpl_IHealingOperations::CloseContour
380 (Handle(GEOM_Object) theObject,
381 const Handle(TColStd_HArray1OfInteger)& theWires,
384 // set error code, check parameters
387 if (theObject.IsNull())
389 SetErrorCode("NULL object given");
393 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
394 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
397 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
400 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CLOSE_CONTOUR);
402 if (aFunction.IsNull()) return NULL;
404 //Check if the function is set correctly
405 if(aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
407 // prepare "data container" class IHealing
408 GEOMImpl_IHealing HI(aFunction);
409 HI.SetWires( theWires );
410 HI.SetIsCommonVertex( isCommonVertex );
411 HI.SetOriginal( aLastFunction );
413 //Compute the translation
416 if (!GetSolver()->ComputeFunction(aFunction))
418 SetErrorCode("Healing driver failed");
422 catch (Standard_Failure)
424 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
425 SetErrorCode(aFail->GetMessageString());
429 //Make a Python command
430 GEOM::TPythonDump pd (aFunction);
431 pd << aNewObject << " = geompy.CloseContour(" << theObject << ", [";
434 if (!theWires.IsNull())
436 int i = theWires->Lower(), nb = theWires->Upper();
437 pd << theWires->Value(i++);
439 pd << ", " << theWires->Value(i++);
441 pd << "], " << (int)isCommonVertex << ")";
447 //=============================================================================
451 //=============================================================================
452 Handle(GEOM_Object) GEOMImpl_IHealingOperations::RemoveIntWires
453 (Handle(GEOM_Object) theObject, const Handle(TColStd_HArray1OfInteger)& theWires)
455 // set error code, check parameters
458 if (theObject.IsNull()) // if theWires is NULL it's OK, it means that ALL wires must be removed
461 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
462 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
465 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
468 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), REMOVE_INT_WIRES);
470 if (aFunction.IsNull()) return NULL;
472 //Check if the function is set correctly
473 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
475 // prepare "data container" class IHealing
476 GEOMImpl_IHealing HI(aFunction);
477 HI.SetWires( theWires );
478 HI.SetOriginal( aLastFunction );
480 //Compute the translation
483 if (!GetSolver()->ComputeFunction(aFunction))
485 SetErrorCode("Healing driver failed");
489 catch (Standard_Failure)
491 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
492 SetErrorCode(aFail->GetMessageString());
496 //Make a Python command
497 GEOM::TPythonDump pd (aFunction);
498 pd << aNewObject << " = geompy.SuppressInternalWires(" << theObject << ", [";
501 if (!theWires.IsNull()) {
502 int i = theWires->Lower(), nb = theWires->Upper();
503 for ( ; i <= nb; i++)
504 pd << theWires->Value( i ) << (( i < nb ) ? ", " : "])");
513 //=============================================================================
517 //=============================================================================
518 Handle(GEOM_Object) GEOMImpl_IHealingOperations::FillHoles (Handle(GEOM_Object) theObject,
519 const Handle(TColStd_HArray1OfInteger)& theWires)
521 // set error code, check parameters
524 if (theObject.IsNull()) // if theWires is NULL it's OK, it means that ALL holes must be removed
527 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
528 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
531 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
534 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), FILL_HOLES);
536 if (aFunction.IsNull()) return NULL;
538 //Check if the function is set correctly
539 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
541 // prepare "data container" class IHealing
542 GEOMImpl_IHealing HI(aFunction);
543 HI.SetWires( theWires );
544 HI.SetOriginal( aLastFunction );
546 //Compute the translation
549 if (!GetSolver()->ComputeFunction(aFunction))
551 SetErrorCode("Healing driver failed");
555 catch (Standard_Failure)
557 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
558 SetErrorCode(aFail->GetMessageString());
562 //Make a Python command
563 GEOM::TPythonDump pd (aFunction);
564 pd << aNewObject << " = geompy.SuppressHoles(" << theObject << ", [";
567 if ( theWires.IsNull() )
570 int i = theWires->Lower(), nb = theWires->Upper();
571 for ( ; i <= nb; i++)
572 pd << theWires->Value( i ) << (( i < nb ) ? ", " : "])");
579 //=============================================================================
583 //=============================================================================
585 GEOMImpl_IHealingOperations::Sew (std::list<Handle(GEOM_Object)>& theObjects,
587 bool isAllowNonManifold)
589 // set error code, check parameters
592 if (theObjects.empty())
595 Handle(TColStd_HSequenceOfTransient) objects =
596 GEOM_Object::GetLastFunctions( theObjects );
597 if ( objects.IsNull() || objects->IsEmpty() ) {
598 SetErrorCode("NULL argument shape");
603 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
606 int aFunctionType = (isAllowNonManifold ? SEWING_NON_MANIFOLD : SEWING);
607 Handle(GEOM_Function) aFunction =
608 aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), aFunctionType);
609 if (aFunction.IsNull()) return NULL;
611 //Check if the function is set correctly
612 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
614 // prepare "data container" class IHealing
615 GEOMImpl_IHealing HI(aFunction);
616 HI.SetTolerance( theTolerance );
617 HI.SetOriginal( theObjects.front()->GetLastFunction() ); objects->Remove(1);
618 HI.SetShapes( objects );
623 if (!GetSolver()->ComputeFunction(aFunction))
625 SetErrorCode("Healing driver failed");
629 catch (Standard_Failure) {
630 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
631 SetErrorCode(aFail->GetMessageString());
635 //Make a Python command
636 GEOM::TPythonDump pd(aFunction);
638 pd << aNewObject << " = geompy.Sew(" << theObjects << ", " << theTolerance;
640 if (isAllowNonManifold) {
650 //=============================================================================
652 * RemoveInternalFaces
654 //=============================================================================
655 Handle(GEOM_Object) GEOMImpl_IHealingOperations::RemoveInternalFaces (Handle(GEOM_Object) theObject)
657 // set error code, check parameters
660 if (theObject.IsNull())
663 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
664 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
667 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
670 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), REMOVE_INTERNAL_FACES);
671 if (aFunction.IsNull()) return NULL;
673 //Check if the function is set correctly
674 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
676 // prepare "data container" class IHealing
677 GEOMImpl_IHealing HI (aFunction);
678 HI.SetOriginal(aLastFunction);
683 if (!GetSolver()->ComputeFunction(aFunction))
685 SetErrorCode("Healing driver failed");
689 catch (Standard_Failure) {
690 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
691 SetErrorCode(aFail->GetMessageString());
695 //Make a Python command
696 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.RemoveInternalFaces(" << theObject << ")";
702 //=============================================================================
706 //=============================================================================
707 Handle(GEOM_Object) GEOMImpl_IHealingOperations::DivideEdge (Handle(GEOM_Object) theObject,
712 // set error code, check parameters
715 if (theObject.IsNull())
718 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
719 if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be processed
722 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject( GetDocID(), GEOM_COPY );
725 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), DIVIDE_EDGE);
727 if (aFunction.IsNull()) return NULL;
729 //Check if the function is set correctly
730 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
732 // prepare "data container" class IHealing
733 GEOMImpl_IHealing HI(aFunction);
734 HI.SetIndex( theIndex );
735 HI.SetDevideEdgeValue( theValue );
736 HI.SetIsByParameter( isByParameter );
737 HI.SetOriginal( aLastFunction );
739 //Compute the translation
742 if (!GetSolver()->ComputeFunction(aFunction)) {
743 SetErrorCode("Healing driver failed");
747 catch (Standard_Failure) {
748 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
749 SetErrorCode(aFail->GetMessageString());
753 //Make a Python command
754 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.DivideEdge(" << theObject
755 << ", " << theIndex << ", " << theValue << ", " << (int)isByParameter << ")";
761 //=============================================================================
763 * FuseCollinearEdgesWithinWire
765 //=============================================================================
766 Handle(GEOM_Object) GEOMImpl_IHealingOperations::FuseCollinearEdgesWithinWire
767 (Handle(GEOM_Object) theWire,
768 std::list<Handle(GEOM_Object)> theVertices)
772 if (theWire.IsNull()) return NULL;
775 Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), theWire->GetType());
777 // Add a new function
778 Handle(GEOM_Function) aFunction;
779 aFunction = aRes->AddFunction(GEOMImpl_HealingDriver::GetID(), FUSE_COLLINEAR_EDGES);
780 if (aFunction.IsNull()) return NULL;
782 // Check if the function is set correctly
783 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
785 GEOMImpl_IHealing aCI (aFunction);
787 Handle(GEOM_Function) aRefShape = theWire->GetLastFunction();
788 if (aRefShape.IsNull()) return NULL;
789 aCI.SetOriginal(aRefShape);
791 Handle(TColStd_HSequenceOfTransient) aVertices = new TColStd_HSequenceOfTransient;
792 std::list<Handle(GEOM_Object)>::iterator it = theVertices.begin();
793 for (; it != theVertices.end(); it++) {
794 Handle(GEOM_Function) aRefSh = (*it)->GetLastFunction();
795 if (aRefSh.IsNull()) {
796 SetErrorCode("NULL argument shape for the shape construction");
799 aVertices->Append(aRefSh);
801 aCI.SetShapes(aVertices);
803 // Compute the new wire
806 if (!GetSolver()->ComputeFunction(aFunction)) {
807 SetErrorCode("Healing driver failed");
811 catch (Standard_Failure) {
812 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
813 SetErrorCode(aFail->GetMessageString());
817 // Make a Python command
818 GEOM::TPythonDump pd (aFunction);
819 pd << aRes << " = geompy.FuseCollinearEdgesWithinWire(" << theWire << ", [";
821 it = theVertices.begin();
822 if (it != theVertices.end()) {
824 while (it != theVertices.end()) {
825 pd << ", " << (*it++);
834 //=============================================================================
838 //=============================================================================
839 bool GEOMImpl_IHealingOperations::GetFreeBoundary (Handle(TColStd_HSequenceOfTransient)& theObjects,
840 Handle(TColStd_HSequenceOfTransient)& theClosed,
841 Handle(TColStd_HSequenceOfTransient)& theOpen )
843 // set error code, check parameters
846 if ( theObjects.IsNull() || theObjects->Length() == 0 ||
847 theClosed.IsNull() || theOpen.IsNull() )
851 TopTools_SequenceOfShape shapes;
852 for ( int ind = 1; ind <= theObjects->Length(); ind++)
854 Handle(GEOM_Object) aRefShape = Handle(GEOM_Object)::DownCast( theObjects->Value(ind));
855 if ( aRefShape.IsNull() )
857 aShape = aRefShape->GetValue();
858 if ( aShape.IsNull() )
860 shapes.Append( aShape );
863 if ( shapes.Length() > 1 )
865 TopoDS_Compound compound;
866 BRep_Builder builder;
867 builder.MakeCompound( compound );
868 for ( int i = 1; i <= shapes.Length(); ++i )
869 builder.Add( compound, shapes( i ) );
874 // get free boundary shapes
876 ShapeAnalysis_FreeBounds anAnalizer(aShape, Standard_False,
877 Standard_True, Standard_True);
878 TopoDS_Compound aClosed = anAnalizer.GetClosedWires();
879 TopoDS_Compound anOpen = anAnalizer.GetOpenWires();
881 // iterate through shapes and append them to the return sequence
882 Handle(GEOM_Object) anObj;
883 Handle(GEOM_Function) aFunction;
884 TopExp_Explorer anExp;
885 for ( anExp.Init( aClosed, TopAbs_WIRE ); anExp.More(); anExp.Next() )
887 anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
888 aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
889 TopoDS_Shape aValueShape = anExp.Current();
890 aFunction->SetValue( aValueShape );
891 theClosed->Append(anObj);
893 for ( anExp.Init( anOpen, TopAbs_WIRE ); anExp.More(); anExp.Next() )
895 anObj = GetEngine()->AddObject( GetDocID(), GEOM_FREE_BOUNDS );
896 aFunction = anObj->AddFunction( GEOMImpl_CopyDriver::GetID(), COPY_WITHOUT_REF );
897 TopoDS_Shape aValueShape = anExp.Current();
898 aFunction->SetValue( aValueShape );
899 theOpen->Append(anObj);
902 if(!aFunction.IsNull()) {
904 //Make a Python command
905 GEOM::TPythonDump pd (aFunction);
907 Standard_Integer i, aLen = theClosed->Length();
910 for (i = 1; i <= aLen; i++) {
911 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theClosed->Value(i));
912 pd << anObj_i << ((i < aLen) ? ", " : "");
916 pd << "(isDone, empty_list, ";
919 aLen = theOpen->Length();
922 for (i = 1; i <= aLen; i++) {
923 Handle(GEOM_Object) anObj_i = Handle(GEOM_Object)::DownCast(theOpen->Value(i));
924 pd << anObj_i << ((i < aLen) ? ", " : "");
931 pd << ") = geompy.GetFreeBoundary(" << theObjects << ")";
939 //=============================================================================
943 //=============================================================================
944 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientation (Handle(GEOM_Object) theObject)
946 // set error code, check parameters
949 if (theObject.IsNull())
952 if (!theObject->IsMainShape()) {
953 SetErrorCode("Sub-shape cannot be transformed - need to create a copy");
957 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
958 if (aLastFunction.IsNull())
959 return NULL; //There is no function which creates an object to be processed
961 if (theObject->GetType() == GEOM_VECTOR) { // Mantis issue 21066
963 aFunction = theObject->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_REVERSE);
965 //Check if the function is set correctly
966 if (aFunction.IsNull()) return NULL;
967 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
969 // prepare "data container" class IVector
970 GEOMImpl_IVector aVI (aFunction);
971 aVI.SetCurve(aLastFunction);
975 aFunction = theObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
977 //Check if the function is set correctly
978 if (aFunction.IsNull()) return NULL;
979 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
981 // prepare "data container" class IHealing
982 GEOMImpl_IHealing HI (aFunction);
983 HI.SetOriginal(aLastFunction);
986 //Compute the translation
989 if (!GetSolver()->ComputeFunction(aFunction)) {
990 SetErrorCode("Healing driver failed");
994 catch (Standard_Failure) {
995 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
996 SetErrorCode(aFail->GetMessageString());
1000 //Make a Python command
1001 GEOM::TPythonDump(aFunction) << "geompy.ChangeOrientationShell("
1002 << theObject << ")";
1008 //=============================================================================
1010 * ChangeOrientationCopy
1012 //=============================================================================
1013 Handle(GEOM_Object) GEOMImpl_IHealingOperations::ChangeOrientationCopy (Handle(GEOM_Object) theObject)
1015 // set error code, check parameters
1018 if (theObject.IsNull())
1021 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
1022 if (aLastFunction.IsNull())
1023 return NULL; //There is no function which creates an object to be processed
1026 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), theObject->GetType());
1028 if (theObject->GetType() == GEOM_VECTOR) { // Mantis issue 21066
1030 aFunction = aNewObject->AddFunction(GEOMImpl_VectorDriver::GetID(), VECTOR_REVERSE);
1032 //Check if the function is set correctly
1033 if (aFunction.IsNull()) return NULL;
1034 if (aFunction->GetDriverGUID() != GEOMImpl_VectorDriver::GetID()) return NULL;
1036 // prepare "data container" class IVector
1037 GEOMImpl_IVector aVI (aFunction);
1038 aVI.SetCurve(aLastFunction);
1042 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), CHANGE_ORIENTATION);
1044 //Check if the function is set correctly
1045 if (aFunction.IsNull()) return NULL;
1046 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
1048 // prepare "data container" class IHealing
1049 GEOMImpl_IHealing aHI (aFunction);
1050 aHI.SetOriginal(aLastFunction);
1053 // Compute the result
1056 if (!GetSolver()->ComputeFunction(aFunction)) {
1057 SetErrorCode("Healing driver failed");
1061 catch (Standard_Failure) {
1062 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1063 SetErrorCode(aFail->GetMessageString());
1067 //Make a Python command
1068 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.ChangeOrientationShellCopy("
1069 << theObject << ")";
1075 //=============================================================================
1079 //=============================================================================
1080 Handle(GEOM_Object) GEOMImpl_IHealingOperations::LimitTolerance (Handle(GEOM_Object) theObject,
1081 double theTolerance)
1083 // Set error code, check parameters
1086 if (theObject.IsNull())
1089 Handle(GEOM_Function) aFunction, aLastFunction = theObject->GetLastFunction();
1090 if (aLastFunction.IsNull())
1091 return NULL; // There is no function which creates an object to be processed
1094 Handle(GEOM_Object) aNewObject = GetEngine()->AddObject(GetDocID(), theObject->GetType());
1097 aFunction = aNewObject->AddFunction(GEOMImpl_HealingDriver::GetID(), LIMIT_TOLERANCE);
1099 if (aFunction.IsNull())
1102 // Check if the function is set correctly
1103 if (aFunction->GetDriverGUID() != GEOMImpl_HealingDriver::GetID()) return NULL;
1105 // Prepare "data container" class IHealing
1106 GEOMImpl_IHealing HI (aFunction);
1107 HI.SetOriginal(aLastFunction);
1108 HI.SetTolerance(theTolerance);
1113 if (!GetSolver()->ComputeFunction(aFunction)) {
1114 SetErrorCode("Healing driver failed");
1118 catch (Standard_Failure) {
1119 Handle(Standard_Failure) aFail = Standard_Failure::Caught();
1120 SetErrorCode(aFail->GetMessageString());
1124 // Make a Python command
1125 GEOM::TPythonDump(aFunction) << aNewObject << " = geompy.LimitTolerance("
1126 << theObject << ", " << theTolerance << ")";