X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGEOMImpl%2FGEOMImpl_IMeasureOperations.cxx;h=7bfc35b5f19243ae780e2a1823a8ec67b8d441a0;hb=9f730900596e9412f431c23b2bd985063814a750;hp=a1b80e3664b99bb37c4c2c311445bf6b09871359;hpb=5e7cf6df5a668d1e1608ba946c59ba34234d8942;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx index a1b80e366..7bfc35b5f 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2016 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,13 +47,11 @@ // OCCT Includes #include #include -#include +#include #include -#include -#if OCC_VERSION_LARGE > 0x07010000 #include #include -#endif +#include #include #include #include @@ -55,10 +60,8 @@ #include #include #include -#if OCC_VERSION_LARGE > 0x06090000 #include #include -#endif #include #include #include @@ -154,10 +157,10 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape } 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 ); @@ -186,7 +189,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape return SK_LCS; } - // Interprete results + // Interpret results TopAbs_ShapeEnum aType = anInfo.Type(); switch (aType) { @@ -743,6 +746,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape theDoubles->Append(aP.Z()); } break; + default:; } SetErrorCode(OK); @@ -791,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; } @@ -838,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; } @@ -858,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); @@ -881,6 +884,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex GEOMImpl_IMeasure aCI (aFunction); aCI.SetBase(aRefShape); aCI.SetIndex(theIndex); + aCI.SetUseOri(theUseOri); //Compute try { @@ -890,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; @@ -947,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; } @@ -1009,9 +1014,8 @@ void GEOMImpl_IMeasureOperations::GetBasicProperties (Handle(GEOM_Object) theSha } } } - catch (Standard_Failure) { - Handle(Standard_Failure) aFail = Standard_Failure::Caught(); - SetErrorCode(aFail->GetMessageString()); + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); return; } @@ -1075,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; } @@ -1136,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; } @@ -1185,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; } @@ -1262,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; } @@ -1305,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; } @@ -1567,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 @@ -1576,39 +1575,22 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersections // 1. Launch the checker aCSI.Perform(); -#if OCC_VERSION_LARGE > 0x07010001 Standard_Boolean iErr = aCSI.HasErrors(); -#else - Standard_Integer iErr = aCSI.ErrorStatus(); -#endif // Standard_Integer aNbS, n1, n2; -#if OCC_VERSION_LARGE > 0x07010000 BOPDS_MapIteratorOfMapOfPair aItMPK; -#else - BOPDS_MapIteratorMapOfPassKey aItMPK; -#endif // // 2. Take the shapes from DS const BOPDS_DS& aDS = aCSI.DS(); aNbS=aDS.NbShapes(); // // 3. Get the pairs of interfered shapes -#if OCC_VERSION_LARGE > 0x07010000 const BOPDS_MapOfPair& aMPK=aDS.Interferences(); -#else - const BOPDS_MapOfPassKey& aMPK=aDS.Interferences(); -#endif aItMPK.Initialize(aMPK); for (; aItMPK.More(); aItMPK.Next()) { -#if OCC_VERSION_LARGE > 0x07010000 const BOPDS_Pair& aPK=aItMPK.Value(); aPK.Indices(n1, n2); -#else - const BOPDS_PassKey& aPK=aItMPK.Value(); - aPK.Ids(n1, n2); -#endif // if (n1 > aNbS || n2 > aNbS){ return false; // Error @@ -1634,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); @@ -1663,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); @@ -1691,7 +1672,6 @@ bool GEOMImpl_IMeasureOperations::CheckSelfIntersectionsFast if (aTool.IsDone()) SetErrorCode(OK); -#endif return theIntersections->IsEmpty(); } @@ -1783,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 @@ -1794,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)); @@ -1925,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()]++; } } } @@ -1944,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; } @@ -2130,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; } @@ -2171,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()) { @@ -2196,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; } @@ -2249,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() ); } } @@ -2322,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; @@ -2387,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 @@ -2433,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; } @@ -2488,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; } @@ -2540,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; } @@ -2700,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. @@ -2854,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; +}