X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FGEOMImpl%2FGEOMImpl_IMeasureOperations.cxx;h=9489d4ea37f43977b937202f4a5a3edf77fad4d0;hb=3bfb88115e12b64d01e3e5606e4b84184deaceb2;hp=e601505627a3e9521f67e675f570d4689d3b5e16;hpb=1f1f0404456a71488cbcbc49574aeb65edd26c6b;p=modules%2Fgeom.git diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx index e60150562..9489d4ea3 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-2024 CEA, EDF, 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,10 @@ // OCCT Includes #include #include -#include #include -#include +#include +#include +#include #include #include #include @@ -51,31 +59,34 @@ #include #include #include -#if OCC_VERSION_LARGE > 0x06090000 #include #include -#endif #include #include #include + #include +#include #include #include #include #include #include #include -#include + +#include #include + +#include #include #include #include #include -#include #include -#include +#include #include #include + #include // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC #include @@ -85,8 +96,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"); } @@ -140,14 +151,48 @@ 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(); - // Interprete results + // specific processing for some "advanced" objects + switch ( geom_type ) { + case GEOM_MARKER: + // local coordinate system + // (+) geompy.kind.LCS xc yc zc xx xy xz yx yy yz zx zy zz + + TopoDS_Face aFace = TopoDS::Face( aShape ); + Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast( BRep_Tool::Surface( aFace ) ); + gp_Pnt aC = aPlane->Pln().Location(); + gp_Ax3 anAx3 = aPlane->Pln().Position(); + + theDoubles->Append(aC.X()); + theDoubles->Append(aC.Y()); + theDoubles->Append(aC.Z()); + + gp_Dir aD = anAx3.XDirection(); + theDoubles->Append(aD.X()); + theDoubles->Append(aD.Y()); + theDoubles->Append(aD.Z()); + aD = anAx3.YDirection(); + theDoubles->Append(aD.X()); + theDoubles->Append(aD.Y()); + theDoubles->Append(aD.Z()); + aD = anAx3.Direction(); + theDoubles->Append(aD.X()); + theDoubles->Append(aD.Y()); + theDoubles->Append(aD.Z()); + + SetErrorCode(OK); + return SK_LCS; + } + + // Interpret results TopAbs_ShapeEnum aType = anInfo.Type(); switch (aType) { @@ -532,20 +577,8 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape if (anInfo.KindOfBounds() != GEOMAlgo_KB_INFINITE) { // (+) geompy.kind.PLANAR xo yo zo dx dy dz nb_edges nb_vertices - aKind = SK_PLANAR; - gp_Pnt aC = anInfo.Location(); - theDoubles->Append(aC.X()); - theDoubles->Append(aC.Y()); - theDoubles->Append(aC.Z()); - - gp_Ax3 anAx3 = anInfo.Position(); - gp_Dir aD = anAx3.Direction(); - theDoubles->Append(aD.X()); - theDoubles->Append(aD.Y()); - theDoubles->Append(aD.Z()); - theIntegers->Append(anInfo.NbSubShapes(TopAbs_EDGE)); theIntegers->Append(anInfo.NbSubShapes(TopAbs_VERTEX)); } @@ -616,7 +649,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape break; case GEOMAlgo_KN_ELLIPSE: { - // (+) geompy.kind.ELLIPSE xc yc zc dx dy dz R_1 R_2 + // (+) geompy.kind.ELLIPSE xc yc zc dx dy dz R_1 R_2 xVx yVx zVx xVy yVy zVy aKind = SK_ELLIPSE; gp_Pnt aC = anInfo.Location(); @@ -632,11 +665,21 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape theDoubles->Append(anInfo.Radius1()); theDoubles->Append(anInfo.Radius2()); + + gp_Dir aXD = anAx3.XDirection(); + theDoubles->Append(aXD.X()); + theDoubles->Append(aXD.Y()); + theDoubles->Append(aXD.Z()); + + gp_Dir aYD = anAx3.YDirection(); + theDoubles->Append(aYD.X()); + theDoubles->Append(aYD.Y()); + theDoubles->Append(aYD.Z()); } break; case GEOMAlgo_KN_ARCELLIPSE: { - // (+) geompy.kind.ARC_ELLIPSE xc yc zc dx dy dz R_1 R_2 x1 y1 z1 x2 y2 z2 + // (+) geompy.kind.ARC_ELLIPSE xc yc zc dx dy dz R_1 R_2 x1 y1 z1 x2 y2 z2 xVx yVx zVx xVy yVy zVy aKind = SK_ARC_ELLIPSE; gp_Pnt aC = anInfo.Location(); @@ -662,6 +705,16 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape theDoubles->Append(aP2.X()); theDoubles->Append(aP2.Y()); theDoubles->Append(aP2.Z()); + + gp_Dir aXD = anAx3.XDirection(); + theDoubles->Append(aXD.X()); + theDoubles->Append(aXD.Y()); + theDoubles->Append(aXD.Z()); + + gp_Dir aYD = anAx3.YDirection(); + theDoubles->Append(aYD.X()); + theDoubles->Append(aYD.Y()); + theDoubles->Append(aYD.Z()); } break; case GEOMAlgo_KN_LINE: @@ -697,6 +750,163 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape theDoubles->Append(aP2.Z()); } break; + case GEOMAlgo_KN_CURVEBSPLINE: + { + // (+) geompy.kind.CRV_BSPLINE p d np nk nw nm x1 y1 z1 ... xnp ynp znp k1 ... knk w1 ... wnw m1 ... mnm + aKind = SK_CRV_BSPLINE; + Standard_Integer aNbPoles = anInfo.NbPoles(); + Standard_Integer aNbKnots = anInfo.NbKnots(); + Standard_Integer aNbWeights = anInfo.NbWeights(); + Standard_Integer aNbMultiplicities = anInfo.NbMultiplicities(); + + theIntegers->Append(anInfo.KindOfPeriod() == GEOMAlgo_KP_PERIODIC ? 1 : 0); + theIntegers->Append(anInfo.Degree()); + theIntegers->Append(aNbPoles); + theIntegers->Append(aNbKnots); + theIntegers->Append(aNbWeights); + theIntegers->Append(aNbMultiplicities); + // + Standard_Integer i; + if (aNbPoles > 0) { + Handle(TColgp_HArray1OfPnt) aPoles = anInfo.Poles(); + if (aPoles.IsNull() || aPoles->Length() != aNbPoles) { + SetErrorCode("B-Spline Curve: no or wrong number of poles given"); + return aKind; + } + for (i=1; i<=aNbPoles; i++) { + const gp_Pnt &aP = aPoles->Value(i); + theDoubles->Append(aP.X()); + theDoubles->Append(aP.Y()); + theDoubles->Append(aP.Z()); + } + } + // + if (aNbKnots > 0) { + Handle(TColStd_HArray1OfReal) aKnots = anInfo.Knots(); + if (aKnots.IsNull() || aKnots->Length() != aNbKnots) { + SetErrorCode("B-Spline Curve: no or wrong number of knots given"); + return aKind; + } + for (i=1; i<=aNbKnots; i++) + theDoubles->Append(aKnots->Value(i)); + } + // + if (aNbWeights > 0) { + Handle(TColStd_HArray1OfReal) aWeights = anInfo.Weights(); + if (aNbWeights > 0 && (aWeights.IsNull() || aWeights->Length() != aNbWeights)) { + SetErrorCode("B-Spline Curve: no or wrong number of weights given"); + return aKind; + } + for (i=1; i<=aNbWeights; i++) + theDoubles->Append(aWeights->Value(i)); + } + // + if (aNbMultiplicities > 0) { + Handle(TColStd_HArray1OfInteger) aMults = anInfo.Multiplicities(); + if (aMults.IsNull() || aMults->Length() != aNbMultiplicities) { + SetErrorCode("B-Spline Curve: no or wrong number of multiplicities given"); + return aKind; + } + for (i=1; i<=aNbMultiplicities; i++) + theIntegers->Append(aMults->Value(i)); + } + } + break; + case GEOMAlgo_KN_CURVEBEZIER: + { + // (+) geompy.kind.CRV_BEZIER np nw x1 y1 z1 ... xnp ynp znp w1 ... wnw + aKind = SK_CRV_BEZIER; + Standard_Integer aNbPoles = anInfo.NbPoles(); + Standard_Integer aNbWeights = anInfo.NbWeights(); + + theIntegers->Append(aNbPoles); + theIntegers->Append(aNbWeights); + // + Standard_Integer i; + if (aNbPoles > 0) { + Handle(TColgp_HArray1OfPnt) aPoles = anInfo.Poles(); + if (aPoles.IsNull() || aPoles->Length() != aNbPoles) { + SetErrorCode("Bezier Curve: no or wrong number of poles given"); + return aKind; + } + for (i=1; i<=aNbPoles; i++) { + const gp_Pnt &aP = aPoles->Value(i); + theDoubles->Append(aP.X()); + theDoubles->Append(aP.Y()); + theDoubles->Append(aP.Z()); + } + } + // + if (aNbWeights > 0) { + Handle(TColStd_HArray1OfReal) aWeights = anInfo.Weights(); + if (aNbWeights > 0 && (aWeights.IsNull() || aWeights->Length() != aNbWeights)) { + SetErrorCode("B-Spline Curve: no or wrong number of weights given"); + return aKind; + } + for (i=1; i<=aNbWeights; i++) + theDoubles->Append(aWeights->Value(i)); + } + } + break; + case GEOMAlgo_KN_HYPERBOLA: + { + // (+) geompy.kind.HYPERBOLA xc yc zc dx dy dz R_1 R_2 xVx yVx zVx xVy yVy zVy + aKind = SK_HYPERBOLA; + + gp_Pnt aC = anInfo.Location(); + theDoubles->Append(aC.X()); + theDoubles->Append(aC.Y()); + theDoubles->Append(aC.Z()); + + gp_Ax3 anAx3 = anInfo.Position(); + gp_Dir aD = anAx3.Direction(); + theDoubles->Append(aD.X()); + theDoubles->Append(aD.Y()); + theDoubles->Append(aD.Z()); + + theDoubles->Append(anInfo.Radius1()); + theDoubles->Append(anInfo.Radius2()); + + gp_Dir aXD = anAx3.XDirection(); + theDoubles->Append(aXD.X()); + theDoubles->Append(aXD.Y()); + theDoubles->Append(aXD.Z()); + + gp_Dir aYD = anAx3.YDirection(); + theDoubles->Append(aYD.X()); + theDoubles->Append(aYD.Y()); + theDoubles->Append(aYD.Z()); + } + break; + case GEOMAlgo_KN_PARABOLA: + { + // (+) geompy.kind.PARABOLA xc yc zc dx dy dz F xVx yVx zVx xVy yVy zVy + aKind = SK_PARABOLA; + + gp_Pnt aC = anInfo.Location(); + theDoubles->Append(aC.X()); + theDoubles->Append(aC.Y()); + theDoubles->Append(aC.Z()); + + gp_Ax3 anAx3 = anInfo.Position(); + gp_Dir aD = anAx3.Direction(); + theDoubles->Append(aD.X()); + theDoubles->Append(aD.Y()); + theDoubles->Append(aD.Z()); + + theDoubles->Append(anInfo.Radius1()); + + gp_Dir aXD = anAx3.XDirection(); + theDoubles->Append(aXD.X()); + theDoubles->Append(aXD.Y()); + theDoubles->Append(aXD.Z()); + + gp_Dir aYD = anAx3.YDirection(); + theDoubles->Append(aYD.X()); + theDoubles->Append(aYD.Y()); + theDoubles->Append(aYD.Z()); + } + break; default: // ??? geompy.kind.EDGE nb_vertices _curve_type_id_ // (+) geompy.kind.EDGE nb_vertices @@ -716,6 +926,7 @@ GEOMImpl_IMeasureOperations::ShapeKind GEOMImpl_IMeasureOperations::KindOfShape theDoubles->Append(aP.Z()); } break; + default:; } SetErrorCode(OK); @@ -764,9 +975,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; } @@ -786,7 +996,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 = @@ -811,9 +1021,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; } @@ -831,7 +1040,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); @@ -841,7 +1051,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 = @@ -854,6 +1064,7 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::GetVertexByIndex GEOMImpl_IMeasure aCI (aFunction); aCI.SetBase(aRefShape); aCI.SetIndex(theIndex); + aCI.SetUseOri(theUseOri); //Compute try { @@ -863,14 +1074,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; @@ -890,7 +1103,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 = @@ -920,9 +1133,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; } @@ -944,6 +1156,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) @@ -963,26 +1176,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; } @@ -1022,12 +1235,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(); @@ -1046,9 +1259,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; } @@ -1107,9 +1319,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; } @@ -1130,7 +1341,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); @@ -1156,9 +1367,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; } @@ -1233,9 +1443,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; } @@ -1276,9 +1485,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; } @@ -1538,7 +1746,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 @@ -1547,22 +1755,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 @@ -1588,7 +1796,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); @@ -1617,7 +1825,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); @@ -1645,11 +1852,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 @@ -1703,7 +1943,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 @@ -1714,21 +1954,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)); @@ -1845,7 +2077,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()]++; } } } @@ -1864,22 +2096,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; } @@ -1955,7 +2186,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 ); @@ -2050,9 +2281,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; } @@ -2091,21 +2321,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()) { @@ -2116,19 +2334,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; } @@ -2169,10 +2403,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() ); } } @@ -2242,10 +2475,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; @@ -2307,16 +2539,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 @@ -2353,9 +2652,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; } @@ -2408,9 +2706,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; } @@ -2460,9 +2757,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; } @@ -2504,7 +2800,7 @@ Standard_Real GEOMImpl_IMeasureOperations::MaxSurfaceCurvatureByParam //Compute the parameters Standard_Real U1,U2,V1,V2; - ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2); + BRepTools::UVBounds(F,U1,U2,V1,V2); Standard_Real U = U1 + (U2-U1)*theUParam; Standard_Real V = V1 + (V2-V1)*theVParam; @@ -2577,7 +2873,7 @@ Standard_Real GEOMImpl_IMeasureOperations::MinSurfaceCurvatureByParam //Compute the parameters Standard_Real U1,U2,V1,V2; - ShapeAnalysis::GetFaceUVBounds(F,U1,U2,V1,V2); + BRepTools::UVBounds(F,U1,U2,V1,V2); Standard_Real U = U1 + (U2-U1)*theUParam; Standard_Real V = V1 + (V2-V1)*theVParam; @@ -2620,6 +2916,615 @@ 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; +} + +//============================================================================= +/*! + * XYZtoUV + */ + //============================================================================= +Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::XYZtoUV + (Handle(GEOM_Object) theSurf, + const Handle(TColStd_HArray1OfReal)& theXYZlist, + bool isNormalized) +{ + SetErrorCode(KO); + + Handle(TColStd_HArray1OfReal) aRet; + + // Check list of coordinates + int nbC = theXYZlist->Length(); + int nbP = nbC / 3; + if (nbP * 3 != nbC) { + SetErrorCode("Coordinates list length is not divisible by 3"); + return aRet; + } + + // Check face + if (theSurf.IsNull()) { + SetErrorCode("The shape is NULL"); + return aRet; + } + + Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction(); + if (aRefShape.IsNull()) { + SetErrorCode("The shape is NULL"); + return aRet; + } + + TopoDS_Shape aShape = aRefShape->GetValue(); + if (aShape.IsNull()) { + SetErrorCode("The shape is NULL"); + return aRet; + } + + // The shape can be a face, a shell of one face or a compound with one face + TopoDS_Face F; + if (aShape.ShapeType() == TopAbs_FACE) { + F = TopoDS::Face(aShape); + } + else if (aShape.ShapeType() < TopAbs_FACE) { + TopExp_Explorer Exp (aShape, TopAbs_FACE); + if (Exp.More()) { + F = TopoDS::Face(Exp.Current()); + Exp.Next(); + if (Exp.More()) { + SetErrorCode("There should be only one face"); + return aRet; + } + } + } + if (F.IsNull()) { + SetErrorCode("There are no faces"); + return aRet; + } + + // Face tolerance + ShapeAnalysis_ShapeTolerance sat; + sat.InitTolerance(); + sat.AddTolerance(F); + Standard_Real aTol = sat.GlobalTolerance(1); + Standard_Real squareTolerance = aTol * aTol; + + // Compute parameters + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F); + aRet = new TColStd_HArray1OfReal (0, nbP * 2 - 1); + + Standard_Real U1,U2, V1,V2; + BRepTools::UVBounds(F, U1, U2, V1, V2); + Standard_Real dU = U2 - U1; + Standard_Real dV = V2 - V1; + + int iCLower = theXYZlist->Lower(); + for (int iP = 0; iP < nbP; iP++) { + gp_Pnt aP (theXYZlist->Value(iCLower + iP * 3), + theXYZlist->Value(iCLower + iP * 3 + 1), + theXYZlist->Value(iCLower + iP * 3 + 2)); + try { // as GEOMUtils::ProjectPointOnFace can throw exceptions + Standard_Real U, V; + gp_Pnt aPonF = GEOMUtils::ProjectPointOnFace(aP, F, U, V, aTol); + if (aP.SquareDistance(aPonF) < squareTolerance) { + if (isNormalized) { + // Normalize parameters to be in [0, 1] + U = (U - U1) / dU; + V = (V - V1) / dV; + } + aRet->SetValue(iP * 2 , U); + aRet->SetValue(iP * 2 + 1, V); + } + else { + SetErrorCode("Point too far from face"); + return aRet; + } + } + catch (Standard_Failure& aFail) { + SetErrorCode(aFail.GetMessageString()); + return aRet; + } + } + + SetErrorCode(OK); + return aRet; +} + +//============================================================================= +/*! + * UVtoXYZ + */ + //============================================================================= +Handle(TColStd_HArray1OfReal) GEOMImpl_IMeasureOperations::UVtoXYZ + (Handle(GEOM_Object) theSurf, + const Handle(TColStd_HArray1OfReal)& theUVlist, + bool isNormalized) +{ + SetErrorCode(KO); + + Handle(TColStd_HArray1OfReal) aRet; + + // Check list of parameters + int nbC = theUVlist->Length(); + int nbP = nbC / 2; + if (nbP * 2 != nbC) { + SetErrorCode("Parameters list length is not divisible by 2"); + return aRet; + } + + // Check face + if (theSurf.IsNull()) { + SetErrorCode("The shape is NULL"); + return aRet; + } + + Handle(GEOM_Function) aRefShape = theSurf->GetLastFunction(); + if (aRefShape.IsNull()) { + SetErrorCode("The shape is NULL"); + return aRet; + } + + TopoDS_Shape aShape = aRefShape->GetValue(); + if (aShape.IsNull()) { + SetErrorCode("The shape is NULL"); + return aRet; + } + + // The shape can be a face, a shell of one face or a compound with one face + TopoDS_Face F; + if (aShape.ShapeType() == TopAbs_FACE) { + F = TopoDS::Face(aShape); + } + else if (aShape.ShapeType() < TopAbs_FACE) { + TopExp_Explorer Exp (aShape, TopAbs_FACE); + if (Exp.More()) { + F = TopoDS::Face(Exp.Current()); + Exp.Next(); + if (Exp.More()) { + SetErrorCode("There should be only one face"); + return aRet; + } + } + } + if (F.IsNull()) { + SetErrorCode("There are no faces"); + return aRet; + } + + // Face tolerance + Standard_Real squareTolerance = BRep_Tool::Tolerance(F); + squareTolerance = squareTolerance * squareTolerance; + + // Compute coordinates + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F); + aRet = new TColStd_HArray1OfReal (0, nbP * 3 - 1); + + Standard_Real U1,U2, V1,V2; + BRepTools::UVBounds(F, U1, U2, V1, V2); + Standard_Real dU = U2 - U1; + Standard_Real dV = V2 - V1; + + Standard_Real tol = 1.e-4; + Standard_Real pc = Precision::Confusion(); + + int iCLower = theUVlist->Lower(); + for (int iP = 0; iP < nbP; iP++) { + Standard_Real U = theUVlist->Value(iCLower + iP * 2); + Standard_Real V = theUVlist->Value(iCLower + iP * 2 + 1); + + if (isNormalized) { + // Get real parameters from given normalized ones in [0, 1] + if (!(-pc < U && U < 1 + pc) || !(-pc < V && V < 1 + pc)) { + SetErrorCode("Normalized parameter is out of range [0,1]"); + return aRet; + } + U = U1 + dU * U; + V = V1 + dV * V; + } + + gp_Pnt2d aP2d (U, V); + + BRepClass_FaceClassifier aClsf (F, aP2d, tol); + if (aClsf.State() != TopAbs_IN && aClsf.State() != TopAbs_ON) { + SetErrorCode("Given parameters are out of face"); + return aRet; + } + gp_Pnt surfPnt = aSurf->Value(U, V); + + aRet->SetValue(iP * 3 , surfPnt.X()); + aRet->SetValue(iP * 3 + 1, surfPnt.Y()); + aRet->SetValue(iP * 3 + 2, surfPnt.Z()); + } + + SetErrorCode(OK); + return aRet; +} + +//============================================================================= +/*! + * 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. @@ -2774,3 +3679,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; +}