X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_IMeasureOperations.cxx;h=7bfc35b5f19243ae780e2a1823a8ec67b8d441a0;hb=9f730900596e9412f431c23b2bd985063814a750;hp=e1b9e08cd63d38493c730d01c0ca03fce03ed834;hpb=2146f8da308639fee66a8872470be8bbf50b8310;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx index e1b9e08cd..7bfc35b5f 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -20,13 +20,20 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -#include - #include #include #include + +#include +#include +#include +#include + #include +#include +#include + #include #include @@ -40,9 +47,11 @@ // OCCT Includes #include #include -#include +#include #include -#include +#include +#include +#include #include #include #include @@ -51,10 +60,8 @@ #include #include #include -#if OCC_VERSION_LARGE > 0x06090000 #include #include -#endif #include #include #include @@ -86,8 +93,8 @@ * Constructor */ //============================================================================= -GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine, int theDocID) -: GEOM_IOperations(theEngine, theDocID) +GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations (GEOM_Engine* theEngine) +: GEOM_IOperations(theEngine) { MESSAGE("GEOMImpl_IMeasureOperations::GEOMImpl_IMeasureOperations"); } @@ -141,17 +148,19 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape GEOMAlgo_ShapeInfoFiller aSF; aSF.SetShape(aShape); aSF.Perform(); + Standard_Integer iErr = aSF.ErrorStatus(); + if (iErr) { SetErrorCode("Error in GEOMAlgo_ShapeInfoFiller"); return SK_NO_SHAPE; } const GEOMAlgo_ShapeInfo& anInfo = aSF.Info(); - // specific processing for some "advandced" objects + // specific processing for some "advanced" objects switch ( geom_type ) { case GEOM_MARKER: - // local coordinate systen + // local coordinate system // (+) geompy.kind.LCS xc yc zc xx xy xz yx yy yz zx zy zz TopoDS_Face aFace = TopoDS::Face( aShape ); @@ -180,7 +189,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape return SK_LCS; } - // Interprete results + // Interpret results TopAbs_ShapeEnum aType = anInfo.Type(); switch (aType) { @@ -737,6 +746,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape theDoubles->Append(aP.Z()); } break; + default:; } SetErrorCode(OK); @@ -785,9 +795,8 @@ void GEOMImpl_IMeasureOperations::GetPosition aDirZ.Coord(Zx, Zy, Zz); aDirX.Coord(Xx, Xy, Xz); } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -807,7 +816,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass if (theShape.IsNull()) return NULL; //Add a new CentreOfMass object - Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GetDocID(), GEOM_CDG); + Handle(GEOM_Object) aCDG = GetEngine()->AddObject(GEOM_CDG); //Add a new CentreOfMass function Handle(GEOM_Function) aFunction = @@ -832,9 +841,8 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -852,7 +860,8 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetCentreOfMass //============================================================================= Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex (Handle(GEOM_Object) theShape, - Standard_Integer theIndex) + Standard_Integer theIndex, + Standard_Boolean theUseOri) { SetErrorCode(KO); @@ -862,7 +871,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex if (aRefShape.IsNull()) return NULL; //Add a new Vertex object - Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GetDocID(), GEOM_POINT); + Handle(GEOM_Object) aVertex = GetEngine()->AddObject(GEOM_POINT); //Add a function Handle(GEOM_Function) aFunction = @@ -875,6 +884,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex GEOMImpl_IMeasure aCI (aFunction); aCI.SetBase(aRefShape); aCI.SetIndex(theIndex); + aCI.SetUseOri(theUseOri); //Compute try { @@ -884,14 +894,16 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } //Make a Python command - GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex(" << theShape << ", " << theIndex << ")"; + GEOM::TPythonDump(aFunction) << aVertex << " = geompy.GetVertexByIndex(" + << theShape << ", " + << theIndex << ", " + << theUseOri << ")"; SetErrorCode(OK); return aVertex; @@ -911,7 +923,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal if (theFace.IsNull()) return NULL; //Add a new Normale object - Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GetDocID(), GEOM_VECTOR); + Handle(GEOM_Object) aNorm = GetEngine()->AddObject(GEOM_VECTOR); //Add a new Normale function Handle(GEOM_Function) aFunction = @@ -941,9 +953,8 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -965,6 +976,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetNormal */ //============================================================================= void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theShape, + const Standard_Real theTolerance, Standard_Real& theLength, Standard_Real& theSurfArea, Standard_Real& theVolume) @@ -984,26 +996,26 @@ void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theSha //Compute the parameters GProp_GProps LProps, SProps; + Standard_Real anEps = theTolerance >= 0 ? theTolerance : 1.e-6; try { OCC_CATCH_SIGNALS; - BRepGProp::LinearProperties(aShape, LProps); + BRepGProp::LinearProperties(aShape, LProps, Standard_True); theLength = LProps.Mass(); - BRepGProp::SurfaceProperties(aShape, SProps); + BRepGProp::SurfaceProperties(aShape, SProps, anEps, Standard_True); theSurfArea = SProps.Mass(); theVolume = 0.0; if (aShape.ShapeType() < TopAbs_SHELL) { for (TopExp_Explorer Exp (aShape, TopAbs_SOLID); Exp.More(); Exp.Next()) { GProp_GProps VProps; - BRepGProp::VolumeProperties(Exp.Current(), VProps); + BRepGProp::VolumeProperties(Exp.Current(), VProps, anEps, Standard_True); theVolume += VProps.Mass(); } } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -1043,12 +1055,12 @@ void GEOMImpl_IMeasureOperations::GetInertia if (aShape.ShapeType() == TopAbs_VERTEX || aShape.ShapeType() == TopAbs_EDGE || aShape.ShapeType() == TopAbs_WIRE) { - BRepGProp::LinearProperties(aShape, System); + BRepGProp::LinearProperties(aShape, System, Standard_True); } else if (aShape.ShapeType() == TopAbs_FACE || aShape.ShapeType() == TopAbs_SHELL) { - BRepGProp::SurfaceProperties(aShape, System); + BRepGProp::SurfaceProperties(aShape, System, Standard_True); } else { - BRepGProp::VolumeProperties(aShape, System); + BRepGProp::VolumeProperties(aShape, System, Standard_True); } gp_Mat I = System.MatrixOfInertia(); @@ -1067,9 +1079,8 @@ void GEOMImpl_IMeasureOperations::GetInertia GProp_PrincipalProps Pr = System.PrincipalProperties(); Pr.Moments(Ix,Iy,Iz); } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -1128,9 +1139,8 @@ void GEOMImpl_IMeasureOperations::GetBoundingBox B.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax); } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -1151,7 +1161,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox if (theShape.IsNull()) return NULL; //Add a new BoundingBox object - Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GetDocID(), GEOM_BOX); + Handle(GEOM_Object) aBnd = GetEngine()->AddObject(GEOM_BOX); //Add a new BoundingBox function const int aType = (precise ? BND_BOX_MEASURE_PRECISE : BND_BOX_MEASURE); @@ -1177,9 +1187,8 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetBoundingBox return NULL; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return NULL; } @@ -1254,9 +1263,8 @@ void GEOMImpl_IMeasureOperations::GetTolerance VertMin = T; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -1297,9 +1305,8 @@ bool GEOMImpl_IMeasureOperations::CheckShape (Handle(GEOM_Object) theShape, FillErrors(ana, aShape, theErrors); } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return false; } @@ -1559,7 +1566,7 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aScopy, anIndices); - BOPCol_ListOfShape aLCS; + TopTools_ListOfShape aLCS; aLCS.Append(aScopy); // BOPAlgo_CheckerSI aCSI; // checker of self-interferences @@ -1568,22 +1575,22 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections // 1. Launch the checker aCSI.Perform(); - Standard_Integer iErr = aCSI.ErrorStatus(); + Standard_Boolean iErr = aCSI.HasErrors(); // Standard_Integer aNbS, n1, n2; - BOPDS_MapIteratorMapOfPassKey aItMPK; + BOPDS_MapIteratorOfMapOfPair aItMPK; // // 2. Take the shapes from DS const BOPDS_DS& aDS = aCSI.DS(); aNbS=aDS.NbShapes(); // // 3. Get the pairs of interfered shapes - const BOPDS_MapOfPassKey& aMPK=aDS.Interferences(); + const BOPDS_MapOfPair& aMPK=aDS.Interferences(); aItMPK.Initialize(aMPK); for (; aItMPK.More(); aItMPK.Next()) { - const BOPDS_PassKey& aPK=aItMPK.Value(); - aPK.Ids(n1, n2); + const BOPDS_Pair& aPK=aItMPK.Value(); + aPK.Indices(n1, n2); // if (n1 > aNbS || n2 > aNbS){ return false; // Error @@ -1609,7 +1616,7 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections //============================================================================= bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast (Handle(GEOM_Object) theShape, - float theDeflection, double theTolerance, + float theDeflection, double theTolerance, Handle(TColStd_HSequenceOfInteger)& theIntersections) { SetErrorCode(KO); @@ -1638,7 +1645,6 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aScopy, anIndices); -#if OCC_VERSION_LARGE > 0x06090000 // Checker of fast interferences BRepExtrema_SelfIntersection aTool(aScopy, (theTolerance <= 0.) ? 0.0 : theTolerance); @@ -1666,11 +1672,44 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast if (aTool.IsDone()) SetErrorCode(OK); -#endif return theIntersections->IsEmpty(); } +//============================================================================= +/*! + * CheckBOPArguments + */ +//============================================================================= +bool GEOMImpl_IMeasureOperations::CheckBOPArguments + (const Handle(GEOM_Object) &theShape) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) { + return false; + } + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + + if (aRefShape.IsNull()) { + return false; + } + + TopoDS_Shape aShape = aRefShape->GetValue(); + + if (aShape.IsNull()) { + return false; + } + + //Compute the parameters + bool isValid = GEOMUtils::CheckBOPArguments(aShape); + + SetErrorCode(OK); + + return isValid; +} + //============================================================================= /*! * FastIntersect @@ -1724,7 +1763,7 @@ bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, TopExp::MapShapes(aScopy1, anIndices1); TopExp::MapShapes(aScopy2, anIndices2); - BOPCol_ListOfShape aLCS1, aLCS2; + TopTools_ListOfShape aLCS1, aLCS2; aLCS1.Append(aScopy1); aLCS2.Append(aScopy2); // BRepExtrema_ShapeProximity aBSP; // checker of fast interferences @@ -1735,21 +1774,13 @@ bool GEOMImpl_IMeasureOperations::FastIntersect (Handle(GEOM_Object) theShape1, aBSP.Perform(); // 2. Get sets of IDs of overlapped faces -#if OCC_VERSION_LARGE > 0x06090000 for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next()) -#else - for (BRepExtrema_OverlappedSubShapes::Iterator anIt1 (aBSP.OverlapSubShapes1()); anIt1.More(); anIt1.Next()) -#endif { const TopoDS_Shape& aS1 = aBSP.GetSubShape1(anIt1.Key()); theIntersections1->Append(anIndices1.FindIndex(aS1)); } -#if OCC_VERSION_LARGE > 0x06090000 for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next()) -#else - for (BRepExtrema_OverlappedSubShapes::Iterator anIt2 (aBSP.OverlapSubShapes2()); anIt2.More(); anIt2.Next()) -#endif { const TopoDS_Shape& aS2 = aBSP.GetSubShape2(anIt2.Key()); theIntersections2->Append(anIndices2.FindIndex(aS2)); @@ -1866,7 +1897,7 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) aListOfShape.Append(s); nbTypes[s.ShapeType()]++; if ((sp.ShapeType() == TopAbs_COMPOUND) || (sp.ShapeType() == TopAbs_COMPSOLID)) { - nbFlatType[s.ShapeType()]++; + nbFlatType[s.ShapeType()]++; } } } @@ -1885,22 +1916,21 @@ TCollection_AsciiString GEOMImpl_IMeasureOperations::WhatIs (Handle(GEOM_Object) if ((aShape.ShapeType() == TopAbs_COMPOUND) || (aShape.ShapeType() == TopAbs_COMPSOLID)){ Astr = Astr + " --------------------- \n Flat content : \n"; if (nbFlatType[TopAbs_VERTEX] > 0) - Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n"; + Astr = Astr + " VERTEX : " + TCollection_AsciiString(nbFlatType[TopAbs_VERTEX]) + "\n"; if (nbFlatType[TopAbs_EDGE] > 0) - Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n"; + Astr = Astr + " EDGE : " + TCollection_AsciiString(nbFlatType[TopAbs_EDGE]) + "\n"; if (nbFlatType[TopAbs_WIRE] > 0) - Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n"; + Astr = Astr + " WIRE : " + TCollection_AsciiString(nbFlatType[TopAbs_WIRE]) + "\n"; if (nbFlatType[TopAbs_FACE] > 0) - Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n"; + Astr = Astr + " FACE : " + TCollection_AsciiString(nbFlatType[TopAbs_FACE]) + "\n"; if (nbFlatType[TopAbs_SHELL] > 0) - Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n"; + Astr = Astr + " SHELL : " + TCollection_AsciiString(nbFlatType[TopAbs_SHELL]) + "\n"; if (nbFlatType[TopAbs_SOLID] > 0) - Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n"; + Astr = Astr + " SOLID : " + TCollection_AsciiString(nbFlatType[TopAbs_SOLID]) + "\n"; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return Astr; } @@ -1976,7 +2006,7 @@ GEOMImpl_IMeasureOperations::AreCoordsInside(Handle(GEOM_Object) theShape project.NbPoints() > 0 && project.LowerDistance() <= tolerance ) { - Quantity_Parameter u, v; + Standard_Real u, v; project.LowerDistanceParameters(u, v); gp_Pnt2d uv( u, v ); BRepClass_FaceClassifier FC ( face, uv, tolerance ); @@ -2071,9 +2101,8 @@ GEOMImpl_IMeasureOperations::GetMinDistance (Handle(GEOM_Object) theShape1, return MinDist; } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return MinDist; } @@ -2112,21 +2141,9 @@ Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) // skl 30.06.2008 // additional workaround for bugs 19899, 19908 and 19910 from Mantis - gp_Pnt P1, P2; - double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1, P2); - if (dist > -1.0) { - nbSolutions = 1; - - theDoubles->Append(P1.X()); - theDoubles->Append(P1.Y()); - theDoubles->Append(P1.Z()); - theDoubles->Append(P2.X()); - theDoubles->Append(P2.Y()); - theDoubles->Append(P2.Z()); - - SetErrorCode(OK); - return nbSolutions; - } + gp_Pnt P1s, P2s; + double dist = GEOMUtils::GetMinDistanceSingular(aShape1, aShape2, P1s, P2s); + bool singularBetter = dist >= 0; BRepExtrema_DistShapeShape dst (aShape1, aShape2); if (dst.IsDone()) { @@ -2137,19 +2154,35 @@ Standard_Integer GEOMImpl_IMeasureOperations::ClosestPoints (Handle(GEOM_Object) for (int i = 1; i <= nbSolutions; i++) { P1 = dst.PointOnShape1(i); P2 = dst.PointOnShape2(i); - + theDoubles->Append(P1.X()); theDoubles->Append(P1.Y()); theDoubles->Append(P1.Z()); theDoubles->Append(P2.X()); theDoubles->Append(P2.Y()); theDoubles->Append(P2.Z()); + + Standard_Real Dist = P1.Distance(P2); + singularBetter = singularBetter && dist < Dist; } } + + if (singularBetter) { + if (theDoubles.IsNull()) theDoubles = new TColStd_HSequenceOfReal; + else theDoubles->Clear(); + + nbSolutions = 1; + + theDoubles->Append(P1s.X()); + theDoubles->Append(P1s.Y()); + theDoubles->Append(P1s.Z()); + theDoubles->Append(P2s.X()); + theDoubles->Append(P2s.Y()); + theDoubles->Append(P2s.Z()); + } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return nbSolutions; } @@ -2190,10 +2223,9 @@ void GEOMImpl_IMeasureOperations::PointCoordinates (Handle(GEOM_Object) theShape SetErrorCode(OK); } - catch (Standard_Failure) + catch (Standard_Failure& aFail) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode( aFail->GetMessageString() ); + SetErrorCode( aFail.GetMessageString() ); } } @@ -2263,10 +2295,9 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngle (Handle(GEOM_Object) theLine SetErrorCode(OK); } - catch (Standard_Failure) + catch (Standard_Failure& aFail) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + SetErrorCode(aFail.GetMessageString()); } return anAngle; @@ -2328,16 +2359,83 @@ Standard_Real GEOMImpl_IMeasureOperations::GetAngleBtwVectors (Handle(GEOM_Objec SetErrorCode(OK); } - catch (Standard_Failure) + catch (Standard_Failure& aFail) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + SetErrorCode(aFail.GetMessageString()); } return anAngle; } +//============================================================================= +/*! + * PatchFace + */ + //============================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::PatchFace(Handle(GEOM_Object) theShape) +{ + SetErrorCode(KO); + + if (theShape.IsNull()) return NULL; + + Handle(GEOM_Object) aPatchFace = GetEngine()->AddObject(GEOM_PATCH_FACE); + Handle(GEOM_Function) aFunction = aPatchFace->AddFunction(GEOMImpl_PatchFaceDriver::GetID(), 1); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_PatchFaceDriver::GetID()) return NULL; + + GEOMImpl_IPatchFace aPI(aFunction); + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return NULL; + + aPI.SetShape(aRefShape); + Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient; + + // Perform + try + { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) + { + SetErrorCode("patch face driver failed"); + return NULL; + } + + // Get result compound and collect all faces into result sequence + TopoDS_Shape aResCompound = aFunction->GetValue(); + TopTools_IndexedMapOfShape anIndices; + TopExp::MapShapes(aResCompound, anIndices); + + Handle(TColStd_HArray1OfInteger) anArray; + for (TopExp_Explorer anExpW(aResCompound, TopAbs_FACE); anExpW.More(); anExpW.Next()) + { + TopoDS_Shape aValue = anExpW.Value(); + anArray = new TColStd_HArray1OfInteger(1, 1); + anArray->SetValue(1, anIndices.FindIndex(aValue)); + + Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(aPatchFace, anArray); + if (!anObj.IsNull()) + { + aSeq->Append(anObj); + } + } + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return aSeq; + } + + //Make a Python command + GEOM::TPythonDump(aFunction, true) + << "[" << aSeq << "] = geompy.PatchFace(" << theShape << ")"; + + SetErrorCode(OK); + return aSeq; +} + //============================================================================= /*! * CurveCurvatureByParam @@ -2374,9 +2472,8 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByParam aRes = fabs(Prop.Curvature()); SetErrorCode(OK); } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return aRes; } @@ -2429,9 +2526,8 @@ Standard_Real GEOMImpl_IMeasureOperations::CurveCurvatureByPoint SetErrorCode(OK); } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return aRes; } @@ -2481,9 +2577,8 @@ Standard_Real GEOMImpl_IMeasureOperations::getSurfaceCurvatures SetErrorCode(OK); } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return aRes; } @@ -2641,6 +2736,396 @@ Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByPoint return getSurfaceCurvatures(aSurf, UV.X(), UV.Y(), false); } +//============================================================================= +/*! + * SurfaceCurvatureByPointAndDirection + */ +//============================================================================= +Handle(GEOM_Object) GEOMImpl_IMeasureOperations::SurfaceCurvatureByPointAndDirection + (Handle(GEOM_Object) theSurf, + Handle(GEOM_Object) thePoint, + Handle(GEOM_Object) theDirection) +{ + SetErrorCode(KO); + + if (theSurf.IsNull() || thePoint.IsNull() || theDirection.IsNull()) return NULL; + + Handle(GEOM_Function) aSurf = theSurf->GetLastFunction(); + Handle(GEOM_Function) aPoint = thePoint->GetLastFunction(); + Handle(GEOM_Function) aDirection = theDirection->GetLastFunction(); + if (aSurf.IsNull() || aPoint.IsNull() || aDirection.IsNull()) return NULL; + + //Add a new CurvatureVector object + //Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_CURVATURE_VEC); + Handle(GEOM_Object) aCV = GetEngine()->AddObject(GEOM_VECTOR); + + //Add a new CurvatureVector function + Handle(GEOM_Function) aFunction = + aCV->AddFunction(GEOMImpl_MeasureDriver::GetID(), CURVATURE_VEC_MEASURE); + if (aFunction.IsNull()) return NULL; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_MeasureDriver::GetID()) return NULL; + + GEOMImpl_IMeasure aCI (aFunction); + aCI.SetBase(aSurf); + aCI.SetPoint(aPoint); + aCI.SetDirection(aDirection); + + //Compute the CurvatureVector + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) { + SetErrorCode("Measure driver failed to compute a surface curvature"); + return NULL; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + return NULL; + } + + //Make a Python command + GEOM::TPythonDump(aFunction) << aCV << " = geompy.CurvatureOnFace(" << theSurf + << ", " << thePoint << ", " << theDirection << ")"; + + SetErrorCode(OK); + return aCV; +} + +//============================================================================= +/*! + * SelfIntersected2D + * Find all self-intersected 2D curves. + * \param theChecks list of failed checks, contains type of check and failed shapes + */ + //============================================================================= +std::list + GEOMImpl_IMeasureOperations::SelfIntersected2D(const std::list& theChecks) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::selfIntersected2D"); + + std::list aSelfInters2D; + try + { + OCC_CATCH_SIGNALS; + for (std::list::const_iterator anIter(theChecks.begin()); + anIter != theChecks.end(); ++anIter) + { + if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface) + aSelfInters2D.push_back(anIter->FailedShapes); + } + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return aSelfInters2D; + } + + SetErrorCode(OK); + return aSelfInters2D; +} + +namespace +{ + static bool checkTypes(const GEOMImpl_IMeasureOperations::CoupleOfObjects& theShapes, + const int theShapeType1, + const int theShapeType2) + { + if (theShapeType1 == -1 && theShapeType2 == -1) + return true; + + TopAbs_ShapeEnum aShapeType1 = theShapes.first.IsNull() + ? TopAbs_SHAPE + : theShapes.first->GetValue().ShapeType(); + TopAbs_ShapeEnum aShapeType2 = theShapes.second.IsNull() + ? TopAbs_SHAPE + : theShapes.second->GetValue().ShapeType(); + + if (theShapeType1 == -1) + return aShapeType1 == theShapeType2 || aShapeType2 == theShapeType2; + else if (theShapeType2 == -1) + return aShapeType1 == theShapeType1 || aShapeType2 == theShapeType1; + return (aShapeType1 == theShapeType1 && aShapeType2 == theShapeType2) || + (aShapeType1 == theShapeType2 && aShapeType2 == theShapeType1); + } +} // namespace + +//============================================================================= +/*! + * InterferingSubshapes + * Find pairs of interfering sub-shapes, by default all pairs of interfering shapes are returned. + * \param theChecks list of failed checks, contains type of check and failed shapes + * \param theShapeType1 Type of shape. + * \param theShapeType2 Type of shape. + */ + //============================================================================= +std::list + GEOMImpl_IMeasureOperations::InterferingSubshapes + (const std::list& theChecks, + const int theShapeType1, + const int theShapeType2) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::interferingSubshapes"); + + std::list anInterfer; + try + { + OCC_CATCH_SIGNALS; + for (std::list::const_iterator anIter(theChecks.begin()); + anIter != theChecks.end(); ++anIter) + { + if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_SelfIntersect && + checkTypes(anIter->FailedShapes, theShapeType1, theShapeType2)) + anInterfer.push_back(anIter->FailedShapes); + } + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return anInterfer; + } + + SetErrorCode(OK); + return anInterfer; +} + +//============================================================================= +/*! + * SmallEdges + * Find edges, which are fully covered by tolerances of vertices. + * \param theChecks list of failed checks, contains type of check and failed shapes + */ + //============================================================================= +Handle(TColStd_HSequenceOfTransient) GEOMImpl_IMeasureOperations::SmallEdges( + const std::list& theChecks) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::smallEdges"); + + Handle(TColStd_HSequenceOfTransient) aSmallEdges = new TColStd_HSequenceOfTransient; + try + { + OCC_CATCH_SIGNALS; + for (std::list::const_iterator anIter(theChecks.begin()); + anIter != theChecks.end(); ++anIter) + { + if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_TooSmallEdge) + aSmallEdges->Append(anIter->FailedShapes.first); + } + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return NULL; + } + + SetErrorCode(OK); + return aSmallEdges; +} + +//============================================================================= +/*! + * DistantShapes + * find remote objects (sub-shape on a shape). + * \param theShape Shape for check. + * \param theShapeType Type of shape. + * \param theSubShapeType Type of sub-shape. + * \param theTolerance tolerance. + */ + //============================================================================= +std::list + GEOMImpl_IMeasureOperations::DistantShapes + (const std::list& theChecks, + const int theShapeType, + const int theSubShapeType, + double theTolerance) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::distantShapes"); + + std::list aDistShapes; + try + { + OCC_CATCH_SIGNALS; + for (std::list::const_iterator anIter(theChecks.begin()); + anIter != theChecks.end(); ++anIter) + { + Handle(GEOM_Object) aSubShape = anIter->FailedShapes.first; + Handle(GEOM_Object) aShape = anIter->FailedShapes.second; + if ((anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface || + anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfVertex || + anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfEdge || + anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_IncompatibilityOfFace) && + aShape && (theShapeType == -1 || aShape->GetValue().ShapeType() == theShapeType) && + aSubShape && (theSubShapeType == -1 || aSubShape->GetValue().ShapeType() == theSubShapeType)) + { + gp_XYZ aP1, aP2; + Standard_Real aDist = Precision::Infinite(); + if (anIter->TypeOfCheck == BOPAlgo_CheckStatus::BOPAlgo_InvalidCurveOnSurface) + aDist = ComputeTolerance(aSubShape, aShape); + if (aDist > theTolerance) + aDistShapes.push_back(anIter->FailedShapes); + } + } + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return aDistShapes; + } + + SetErrorCode(OK); + return aDistShapes; +} + +//============================================================================= +/*! + * CheckConformityShape + * Perform analyse of shape and find imperfections in the shape. + * \param theShape Shape for analyse. + */ + //============================================================================= +void GEOMImpl_IMeasureOperations::CheckConformityShape(Handle(GEOM_Object) theShape, std::list& theChecks) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::checkShape"); + + Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY); + Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_CHECK_SHAPE); + if (aFunction.IsNull()) return; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return; + + GEOMImpl_IConformity aCI(aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return; + + aCI.SetShape(aRefShape); + + try + { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) + { + SetErrorCode("Failed: checkShape"); + return; + } + Handle(TColStd_HArray1OfInteger) aTypesChecks = aFunction->GetIntegerArray(CHECKCONFORMITY_RET_TYPES_CHECKS); + Handle(TColStd_HArray2OfInteger) aRes = aCI.GetListOfShapesIndices(); + if (aRes.IsNull()) + return; + + for (Standard_Integer anIndex = 1; anIndex <= aRes->NbRows(); ++anIndex) + { + std::pair aPair; + Handle(TColStd_HArray1OfInteger) anArray; + anArray = new TColStd_HArray1OfInteger(1, 1); + anArray->SetValue(1, aRes->Value(anIndex, 1)); + + Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray); + if (!anObj.IsNull()) + aPair.first = anObj; + + anArray = new TColStd_HArray1OfInteger(1, 1); + anArray->SetValue(1, aRes->Value(anIndex, 2)); + + anObj = GetEngine()->AddSubShape(theShape, anArray); + if (!anObj.IsNull()) + aPair.second = anObj; + theChecks.push_back({ aTypesChecks->Value(anIndex), aPair }); + } + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return; + } + + SetErrorCode(OK); + return; +} + +//============================================================================= +/*! + * UpdateTolerance + * Compute possible tolerance for the shape, minimize tolerance of shape as well + * as tolerance of sub-shapes as much as possible + * \param theShape Shape for compute tolerance. + */ + //============================================================================= +double GEOMImpl_IMeasureOperations::UpdateTolerance(Handle(GEOM_Object) theShape) +{ + SetErrorCode(KO); + MESSAGE("GEOMImpl_IMeasureOperations::updateTolerance"); + + double aResTol = -1; + Handle(GEOM_Object) aConformity = GetEngine()->AddObject(GEOM_CHECKCONFORMITY); + Handle(GEOM_Function) aFunction = aConformity->AddFunction(GEOMImpl_ConformityDriver::GetID(), CONFORMITY_UPDATE_TOL); + if (aFunction.IsNull()) return aResTol; + + //Check if the function is set correctly + if (aFunction->GetDriverGUID() != GEOMImpl_ConformityDriver::GetID()) return aResTol; + + GEOMImpl_IConformity aCI(aFunction); + + Handle(GEOM_Function) aRefShape = theShape->GetLastFunction(); + if (aRefShape.IsNull()) return aResTol; + + aCI.SetShape(aRefShape); + + try + { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aFunction)) + { + SetErrorCode("Failed: updateTolerance"); + return aResTol; + } + aResTol = aFunction->GetReal(CHECKCONFORMITY_RET_TOLERANCE); + } + catch (Standard_Failure& aFail) + { + SetErrorCode(aFail.GetMessageString()); + return aResTol; + } + + SetErrorCode(OK); + return aResTol; +} + +//============================================================================= +/*! + * ComputeTolerance + * Compute distance from the edge to the face. + */ + //============================================================================= +double GEOMImpl_IMeasureOperations::ComputeTolerance(Handle(GEOM_Object) theEdge, + Handle(GEOM_Object) theFace) +{ + double aMaxDist = Precision::Infinite(); + if (theEdge.IsNull() || theFace.IsNull()) + return aMaxDist; + + Handle(GEOM_Function) aRefEdge = theEdge->GetLastFunction(); + Handle(GEOM_Function) aRefFace = theFace->GetLastFunction(); + if (aRefEdge.IsNull() || aRefFace.IsNull()) + return aMaxDist; + + TopoDS_Edge aEdge = TopoDS::Edge(aRefEdge->GetValue()); + TopoDS_Face aFace = TopoDS::Face(aRefFace->GetValue()); + if (aEdge.IsNull() || aFace.IsNull()) + return aMaxDist; + + double aParam = 0.0; + BOPTools_AlgoTools::ComputeTolerance(aFace, aEdge, aMaxDist, aParam); + return aMaxDist; +} + //======================================================================= //function : FillErrorsSub //purpose : Fill the errors list of subshapes on shape. @@ -2795,3 +3280,191 @@ void GEOMImpl_IMeasureOperations::FillErrors } } } + +//======================================================================= +//function : ShapeProximityCalculator +//purpose : returns an object to compute the proximity value +//======================================================================= +Handle(GEOM_Object) GEOMImpl_IMeasureOperations::ShapeProximityCalculator + (Handle(GEOM_Object) theShape1, + Handle(GEOM_Object) theShape2) +{ + SetErrorCode(KO); + + if (theShape1.IsNull() || theShape2.IsNull()) + return NULL; + + Handle(GEOM_Function) aShapeFunc1 = theShape1->GetLastFunction(); + Handle(GEOM_Function) aShapeFunc2 = theShape2->GetLastFunction(); + if (aShapeFunc1.IsNull() || aShapeFunc2.IsNull()) + return NULL; + + Handle(GEOM_Object) aProximityCalc = GetEngine()->AddObject(GEOM_SHAPE_PROXIMITY); + if (aProximityCalc.IsNull()) + return NULL; + + Handle(GEOM_Function) aProximityFuncCoarse = + aProximityCalc->AddFunction(GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_COARSE); + //Check if the function is set correctly + if (aProximityFuncCoarse.IsNull() || + aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID()) + return NULL; + + GEOMImpl_IProximity aProximity (aProximityFuncCoarse); + aProximity.SetShapes(aShapeFunc1, aShapeFunc2); + + //Make a Python command + GEOM::TPythonDump pd (aProximityFuncCoarse); + pd << "p = geompy.ShapeProximity()\n"; + pd << "p.setShapes(" << theShape1 << ", " << theShape2 << ")"; + + SetErrorCode(OK); + return aProximityCalc; +} + +//======================================================================= +//function : SetShapeSampling +//purpose : set number sample points to compute the coarse proximity +//======================================================================= +void GEOMImpl_IMeasureOperations::SetShapeSampling(Handle(GEOM_Object) theCalculator, + Handle(GEOM_Object) theShape, + const Standard_Integer theNbSamples) +{ + SetErrorCode(KO); + if (theShape.IsNull() || + theCalculator.IsNull() || + theCalculator->GetNbFunctions() <= 0 || + theNbSamples <= 0) + return ; + + Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1); + if (aProximityFuncCoarse.IsNull() || + aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID()) + return ; + + Handle(GEOM_Function) aShapeFunc = theShape->GetLastFunction(); + if (aShapeFunc.IsNull()) + return ; + + GEOMImpl_IProximity aProximity(aProximityFuncCoarse); + Handle(GEOM_Function) aShape1, aShape2; + aProximity.GetShapes(aShape1, aShape2); + if (aShape1->GetValue() == aShapeFunc->GetValue()) + aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES1, theNbSamples); + else if (aShape2->GetValue() == aShapeFunc->GetValue()) + aProximity.SetNbSamples(PROXIMITY_ARG_SAMPLES2, theNbSamples); + + //Make a Python command + GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << + "p.setSampling(" << theShape << ", " << theNbSamples << ")"; + + SetErrorCode(OK); +} + +//======================================================================= +//function : GetCoarseProximity +//purpose : compute coarse proximity +//======================================================================= +Standard_Real GEOMImpl_IMeasureOperations::GetCoarseProximity(Handle(GEOM_Object) theCalculator, + bool doPythonDump) +{ + SetErrorCode(KO); + if (theCalculator.IsNull()) + return -1; + + Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1); + if (aProximityFuncCoarse.IsNull() || + aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() || + aProximityFuncCoarse->GetType() != PROXIMITY_COARSE) + return -1; + + // Perform + // We have to recompute the function each time, + // because the number of samples can be changed + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aProximityFuncCoarse)) { + SetErrorCode("shape proximity driver failed"); + return -1; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + return -1; + } + + //Make a Python command + if (doPythonDump) + GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.coarseProximity()"; + + SetErrorCode(OK); + GEOMImpl_IProximity aProximity (aProximityFuncCoarse); + return aProximity.GetValue(); +} + +//======================================================================= +//function : GetPreciseProximity +//purpose : compute precise proximity +//======================================================================= +Standard_Real GEOMImpl_IMeasureOperations::GetPreciseProximity(Handle(GEOM_Object) theCalculator) +{ + SetErrorCode(KO); + if (theCalculator.IsNull()) + return -1; + + Handle(GEOM_Function) aProximityFuncCoarse = theCalculator->GetFunction(1); + Handle(GEOM_Function) aProximityFuncFine = theCalculator->GetFunction(2); + if (aProximityFuncFine.IsNull()) + aProximityFuncFine = theCalculator->AddFunction + (GEOMImpl_ShapeProximityDriver::GetID(), PROXIMITY_PRECISE); + + //Check if the functions are set correctly + if (aProximityFuncCoarse.IsNull() || + aProximityFuncCoarse->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID() || + aProximityFuncFine.IsNull() || + aProximityFuncFine->GetDriverGUID() != GEOMImpl_ShapeProximityDriver::GetID()) + return -1; + + // perform coarse computation beforehand + GetCoarseProximity(theCalculator, /*doPythonDump=*/false); + + // transfer parameters from the coarse to precise calculator + GEOMImpl_IProximity aCoarseProximity (aProximityFuncCoarse); + Handle(GEOM_Function) aShape1, aShape2; + aCoarseProximity.GetShapes(aShape1, aShape2); + if (aShape1.IsNull() || aShape2.IsNull()) + return -1; + gp_Pnt aProxPnt1, aProxPnt2; + Standard_Integer intStatus1, intStatus2; + aCoarseProximity.GetProximityPoints(aProxPnt1, aProxPnt2); + aCoarseProximity.GetStatusOfPoints(intStatus1, intStatus2); + Standard_Real aResultValue = aCoarseProximity.GetValue(); + + GEOMImpl_IProximity aFineProximity (aProximityFuncFine); + aFineProximity.SetShapes(aShape1, aShape2); + aFineProximity.SetProximityPoints(aProxPnt1, aProxPnt2); + aFineProximity.SetStatusOfPoints(intStatus1, intStatus2); + aFineProximity.SetValue(aResultValue); // in some cases this value cannot be precised + + // Perform + try { + OCC_CATCH_SIGNALS; + if (!GetSolver()->ComputeFunction(aProximityFuncFine)) { + SetErrorCode("shape proximity driver failed"); + return -1; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + return -1; + } + + aResultValue = aFineProximity.GetValue(); + aFineProximity.GetProximityPoints(aProxPnt1, aProxPnt2); + + //Make a Python command + GEOM::TPythonDump(aProximityFuncCoarse, /*append=*/true) << "value = p.preciseProximity()"; + + SetErrorCode(OK); + return aResultValue; +}