From: jfa Date: Fri, 12 May 2023 08:46:46 +0000 (+0100) Subject: Implemented [bos #35094] [EDF] (2023-T1) X,Y,Z to U,V. X-Git-Tag: V9_11_0b1^0 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=refs%2Ftlpr%2F1%2Fhead;p=modules%2Fgeom.git Implemented [bos #35094] [EDF] (2023-T1) X,Y,Z to U,V. --- diff --git a/doc/salome/examples/XYZ_to_UV.py b/doc/salome/examples/XYZ_to_UV.py new file mode 100644 index 000000000..ef4abddf4 --- /dev/null +++ b/doc/salome/examples/XYZ_to_UV.py @@ -0,0 +1,212 @@ +# Test XYZtoUV and UVtoXYZ methods + +import salome +salome.salome_init_without_session() +import GEOM +from salome.geom import geomBuilder +geompy = geomBuilder.New() +import math +import numpy as np + +toler = 1e-04 + +# Create "Horse saddle" +OX = geompy.MakeVectorDXDYDZ(1, 0, 0, 'OX') +OY = geompy.MakeVectorDXDYDZ(0, 1, 0, 'OY') +Sphere_1 = geompy.MakeSphereR(100, 'Sphere_1') +[Edge_1,Edge_2,Edge_3] = geompy.ExtractShapes(Sphere_1, geompy.ShapeType["EDGE"], True) +geompy.addToStudyInFather( Sphere_1, Edge_1, 'Edge_1' ) +geompy.addToStudyInFather( Sphere_1, Edge_2, 'Edge_2' ) +geompy.addToStudyInFather( Sphere_1, Edge_3, 'Edge_3' ) + +Rotation_1 = geompy.MakeRotation(Edge_3, OX, 90*math.pi/180.0, 'Rotation_1') +Rotation_2 = geompy.MakeRotation(Rotation_1, OY, 180*math.pi/180.0, 'Rotation_2') +Translation_1 = geompy.MakeTranslation(Rotation_2, 200, 0, 0, 'Translation_1') +Translation_2 = geompy.MakeTranslation(Edge_3, 100, 100, 0, 'Translation_2') +Translation_3 = geompy.MakeTranslation(Translation_2, 0, -200, 0, 'Translation_3') + +Filling_1 = geompy.MakeFilling([Translation_2, Edge_3, Translation_3]) +geompy.addToStudy(Filling_1, 'Filling_1') + +HorseSaddle = geompy.LimitTolerance(Filling_1, toler, 'HorseSaddle') + +# Get 100 equidistant points on the "Horse saddle" +CompoundOfVertices = geompy.MakeVertexInsideFace(HorseSaddle, 100, "CompoundOfVertices") +assert(geompy.NumberOfSubShapes(CompoundOfVertices, geompy.ShapeType["VERTEX"]) == 100) + +# Extract the vertices +listOfVertices = geompy.ExtractShapes(CompoundOfVertices, geompy.ShapeType["VERTEX"], True) + +# Get list of coordinates of all 100 vertices +listOfCoords = [] +for aV in listOfVertices: + listOfCoords += geompy.PointCoordinates(aV) + pass + +# Test 1: with normalization of parameters + +# Convert XYZ to UV +listOfParams_norm = geompy.XYZtoUV(HorseSaddle, listOfCoords, True) +assert(len(listOfParams_norm) == 200) + +# Convert UV to XYZ +listOfCoords_new1 = geompy.UVtoXYZ(HorseSaddle, listOfParams_norm, True) +assert(len(listOfCoords_new1) == 300) + +# Compare listOfCoords_new with listOfCoords +for (c1, c2) in zip(listOfCoords, listOfCoords_new1): + assert(abs(c1 - c2) < toler) + pass + +# Test 2: without normalization of parameters + +# Convert XYZ to UV +listOfParams = geompy.XYZtoUV(HorseSaddle, listOfCoords, False) +assert(len(listOfParams) == 200) + +# Convert UV to XYZ +listOfCoords_new2 = geompy.UVtoXYZ(HorseSaddle, listOfParams, False) +assert(len(listOfCoords_new2) == 300) + +# Compare listOfCoords_new with listOfCoords +for (c1, c2) in zip(listOfCoords, listOfCoords_new2): + assert(abs(c1 - c2) < toler) + pass + +# Test 3: Check exceptions throwing if point (XYZ or UV) is out of face +listXYZ_3 = listOfCoords[:3] +listXYZ_3[2] = listXYZ_3[2] + 1.0 # move along OZ +try: + geompy.XYZtoUV(HorseSaddle, listXYZ_3, True) +except RuntimeError: + print(geompy.MeasuOp.GetErrorCode(), ", it's OK") + pass +except Exception: + assert False, 'Unexpected exception raised' +else: + assert False, 'XYZtoUV should raise an exception if input point is out of face' + +listUV_2 = [2, 2] # each parameter value should be in [0,1] range (for normalized case) +try: + geompy.UVtoXYZ(HorseSaddle, listUV_2, True) +except RuntimeError: + print(geompy.MeasuOp.GetErrorCode(), ", it's OK") + pass +except Exception: + assert False, 'Unexpected exception raised' +else: + assert False, 'UVtoXYZ should raise an exception if input parameters are out of face' + +# parameter U should be in [4.71239, 7.85398] range (on this face, for not normalized case) +# parameter V should be in [0, 1] range (on this face, for not normalized case) +listUV_2 = [10, 10] +try: + geompy.UVtoXYZ(HorseSaddle, listUV_2, True) +except RuntimeError: + print(geompy.MeasuOp.GetErrorCode(), ", it's OK") + pass +except Exception: + assert False, 'Unexpected exception raised' +else: + assert False, 'UVtoXYZ should raise an exception if input parameters are out of face' + +# Test 4: Check exceptions in case of invalid data type (wrong length of array or type of elements) + +# 1. Length of input array is not divisible by 3 (for XYZtoUV) or by 2 (for UVtoXYZ) +listXYZ_4 = listOfCoords[:4] +assert(len(listXYZ_4) == 4) +try: + geompy.XYZtoUV(HorseSaddle, listXYZ_4, True) +except RuntimeError: + print(geompy.MeasuOp.GetErrorCode(), ", it's OK") + pass +except Exception: + assert False, 'Unexpected exception raised' +else: + assert False, 'XYZtoUV should raise an exception if input list length is not divisible by 3' + +listUV_3 = listOfParams[:3] +assert(len(listUV_3) == 3) +try: + geompy.UVtoXYZ(HorseSaddle, listUV_3, True) +except RuntimeError: + print(geompy.MeasuOp.GetErrorCode(), ", it's OK") + pass +except Exception: + assert False, 'Unexpected exception raised' +else: + assert False, 'UVtoXYZ should raise an exception if input list length is not divisible by 2' + +# 2. Input array contains data of wrong type +listXYZ_w = ['a', 'b', 'c'] +try: + geompy.XYZtoUV(HorseSaddle, listXYZ_w, True) +except Exception: + pass +else: + assert False, 'XYZtoUV should raise TypeError if input list contains not numerical data' + +listXYZ_w = [10.0, '10.0', 10.0] +try: + geompy.XYZtoUV(HorseSaddle, listXYZ_w, True) +except Exception: + pass +else: + assert False, 'XYZtoUV should raise TypeError if input list contains not numerical data' + +listUV_w = ['a', 'b'] +try: + geompy.UVtoXYZ(HorseSaddle, listUV_w, True) +except Exception: + pass +else: + assert False, 'UVtoXYZ should raise TypeError if input list contains not numerical data' + +listUV_w = [10.0, '10.0'] +try: + geompy.UVtoXYZ(HorseSaddle, listUV_w, True) +except Exception: + pass +else: + assert False, 'UVtoXYZ should raise TypeError if input list contains not numerical data' + +# Test 5: a. Translate each of the 100 points by toler*2.0 along the face normal +# and check that the XYZtoUV method fails by raising an exception. +# b. Translate each of the 100 points by toler*0.7 along the face normal +# and check that we obtain a result. +for ii in range(100): + # cc - coordinates of point #ii + cc = listOfCoords[ii*3 : ii*3 + 3] + + pnt = geompy.MakeVertex(cc[0], cc[1], cc[2]) + normal = geompy.GetNormal(HorseSaddle, pnt) + vv = geompy.VectorCoordinates(normal) + norm = np.linalg.norm(vv) + if norm > toler: + vec = vv / norm + # a. Move cc by toler*2.0 (XYZtoUV should fail) + pp_2tol = [cc[0] + vec[0]*toler*2.0, + cc[1] + vec[1]*toler*2.0, + cc[2] + vec[2]*toler*2.0] + try: + geompy.XYZtoUV(HorseSaddle, pp_2tol) + except RuntimeError: + pass + except Exception: + assert False, 'Unexpected exception raised' + else: + assert False, 'XYZtoUV should raise an exception if input point is out of face' + pass + + # b. Move cc by toler*0.7 (XYZtoUV should not fail) + pp_07tol = [cc[0] + vec[0]*toler*0.7, + cc[1] + vec[1]*toler*0.7, + cc[2] + vec[2]*toler*0.7] + UV_pp = geompy.XYZtoUV(HorseSaddle, pp_07tol, False) + # compare with value from listOfParams (computed above) + UV_cc = listOfParams[ii*2 : ii*2 + 2] + for (c1, c2) in zip(UV_pp, UV_cc): + assert(abs(c1 - c2) < toler) + pass + pass + pass diff --git a/doc/salome/examples/tests.set b/doc/salome/examples/tests.set index c2c8eb81e..db69d7f57 100644 --- a/doc/salome/examples/tests.set +++ b/doc/salome/examples/tests.set @@ -136,4 +136,5 @@ SET(GOOD_TESTS GEOM_Field.py check_self_intersections_fast.py # OCC > 6.9.0 shape_proximity.py + XYZ_to_UV.py ) diff --git a/doc/salome/gui/GEOM/input/tui_measurement_tools.doc b/doc/salome/gui/GEOM/input/tui_measurement_tools.doc index a4e7f5c9d..59eea50df 100644 --- a/doc/salome/gui/GEOM/input/tui_measurement_tools.doc +++ b/doc/salome/gui/GEOM/input/tui_measurement_tools.doc @@ -23,6 +23,7 @@
  • \subpage tui_fast_intersection_page
  • \subpage tui_check_conformity_page
  • \subpage tui_shape_proximity_page
  • +
  • \subpage tui_xyz_to_uv_page
  • */ diff --git a/doc/salome/gui/GEOM/input/tui_xyz_to_uv.doc b/doc/salome/gui/GEOM/input/tui_xyz_to_uv.doc new file mode 100644 index 000000000..50378f44c --- /dev/null +++ b/doc/salome/gui/GEOM/input/tui_xyz_to_uv.doc @@ -0,0 +1,7 @@ +/*! + +\page tui_xyz_to_uv_page Get point on face parameters U and V by coordinates or coordinates by parameters + +\tui_script{XYZ_to_UV.py} + +*/ diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index d33bc140d..8d9e2ff2b 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -4745,6 +4745,34 @@ module GEOM in GEOM_Object thePoint, in GEOM_Object theDirection); + /*! + * \brief Convert X,Y,Z points coordinates to UV parameters on the given surface. + \param theSurf the given face. It can be also a shell or a compound with one face. + \param theXYZlist float list of size 3*N where N is the number of points + for which we want their U,V coordinates. + If the user enters a list of size not divisible by 3 + an exception will be thrown. + \param theIsNormalized if True, the returned parameters will be in range [0, 1]. + \return list of float of size 2*N. + */ + ListOfDouble XYZtoUV(in GEOM_Object theSurf, + in ListOfDouble theXYZlist, + in boolean theIsNormalized); + + /*! + * \brief Convert UV parameters on the given surface to 3D points coordinates. + \param theSurf the given face. It can be also a shell or a compound with one face. + \param theUVlist float list of size 2*N where N is the number of points + for which we want their X,Y,Z coordinates. + If the user enters a list of non-even size + an exception will be thrown. + \param theIsNormalized if True, the input parameters are expected to be in range [0, 1]. + \return list of float of size 3*N. + */ + ListOfDouble UVtoXYZ(in GEOM_Object theSurf, + in ListOfDouble theUVlist, + in boolean theIsNormalized); + //! Methods and structure for implement CheckConformity tool /*! diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx index 7bfc35b5f..00bcb04e0 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx @@ -2793,6 +2793,216 @@ Handle(GEOM_Object) GEOMImpl_IMeasureOperations::SurfaceCurvatureByPointAndDirec 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 + Standard_Real squareTolerance = BRep_Tool::Tolerance(F); + squareTolerance = squareTolerance * squareTolerance; + + // 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)); + Standard_Real U, V; + gp_Pnt aPonF = GEOMUtils::ProjectPointOnFace(aP, F, U, V); + 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; + } + } + + 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 diff --git a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx index 3e96a3295..af0410ba6 100644 --- a/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx @@ -244,6 +244,17 @@ class GEOMImpl_IMeasureOperations : public GEOM_IOperations { Handle(GEOM_Object) thePoint, Handle(GEOM_Object) theDirection); + // Methods to convert X,Y,Z coordinates of point to U,V parameters on surface and back + Standard_EXPORT Handle(TColStd_HArray1OfReal) XYZtoUV + (Handle(GEOM_Object) theSurf, + const Handle(TColStd_HArray1OfReal)& theXYZlist, + bool isNormalized); + + Standard_EXPORT Handle(TColStd_HArray1OfReal) UVtoXYZ + (Handle(GEOM_Object) theSurf, + const Handle(TColStd_HArray1OfReal)& theUVlist, + bool isNormalized); + // Methods to compute proximity between two shapes Standard_EXPORT Handle(GEOM_Object) ShapeProximityCalculator(Handle(GEOM_Object) theShape1, Handle(GEOM_Object) theShape2); diff --git a/src/GEOM_I/GEOM_IMeasureOperations_i.cc b/src/GEOM_I/GEOM_IMeasureOperations_i.cc index e829aceab..a740731b4 100644 --- a/src/GEOM_I/GEOM_IMeasureOperations_i.cc +++ b/src/GEOM_I/GEOM_IMeasureOperations_i.cc @@ -21,6 +21,7 @@ // #include +#include #include "GEOM_IMeasureOperations_i.hh" @@ -1244,6 +1245,92 @@ GEOM::GEOM_Object_ptr GEOM_IMeasureOperations_i::SurfaceCurvatureByPointAndDirec return GetObject(anObject); } +//============================================================================= +/*! + * XYZtoUV + */ +//============================================================================= +GEOM::ListOfDouble* GEOM_IMeasureOperations_i::XYZtoUV + (GEOM::GEOM_Object_ptr theSurf, + const GEOM::ListOfDouble& theXYZlist, + CORBA::Boolean theIsNormalized) +{ + GEOM::ListOfDouble_var resUV = new GEOM::ListOfDouble; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the reference shape + Handle(::GEOM_Object) aShape = GetObjectImpl(theSurf); + if (aShape.IsNull()) return resUV._retn(); + + //Get input XYZ list + Handle(TColStd_HArray1OfReal) aXYZlist = + new TColStd_HArray1OfReal (0, theXYZlist.length() - 1); + { + size_t nb = theXYZlist.length(); + for (size_t i = 0; i < nb; ++i) + aXYZlist->SetValue(i, theXYZlist[i]); + } + + //Call implementation + Handle(TColStd_HArray1OfReal) aUVlist = + GetOperations()->XYZtoUV(aShape, aXYZlist, theIsNormalized); + + if (GetOperations()->IsDone()) { + resUV->length(aUVlist->Length()); + int i0 = aUVlist->Lower(); + int nb = aUVlist->Upper(); + for (int i = i0; i <= nb; ++i) + resUV[ i-i0 ] = aUVlist->Value(i); + } + + return resUV._retn(); +} + +//============================================================================= +/*! + * UVtoXYZ + */ +//============================================================================= +GEOM::ListOfDouble* GEOM_IMeasureOperations_i::UVtoXYZ + (GEOM::GEOM_Object_ptr theSurf, + const GEOM::ListOfDouble& theUVlist, + CORBA::Boolean theIsNormalized) +{ + GEOM::ListOfDouble_var resXYZ = new GEOM::ListOfDouble; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the reference shape + Handle(::GEOM_Object) aShape = GetObjectImpl(theSurf); + if (aShape.IsNull()) return resXYZ._retn(); + + //Get input UV list + Handle(TColStd_HArray1OfReal) aUVlist = + new TColStd_HArray1OfReal (0, theUVlist.length() - 1); + { + size_t nb = theUVlist.length(); + for (size_t i = 0; i < nb; ++i) + aUVlist->SetValue(i, theUVlist[i]); + } + + //Call implementation + Handle(TColStd_HArray1OfReal) aXYZlist = + GetOperations()->UVtoXYZ(aShape, aUVlist, theIsNormalized); + + if (GetOperations()->IsDone()) { + resXYZ->length(aXYZlist->Length()); + int i0 = aXYZlist->Lower(); + int nb = aXYZlist->Upper(); + for (int i = i0; i <= nb; ++i) + resXYZ[ i-i0 ] = aXYZlist->Value(i); + } + + return resXYZ._retn(); +} + //============================================================================= /*! * SelfIntersected2D diff --git a/src/GEOM_I/GEOM_IMeasureOperations_i.hh b/src/GEOM_I/GEOM_IMeasureOperations_i.hh index ded2f9c41..e8cdf9c53 100644 --- a/src/GEOM_I/GEOM_IMeasureOperations_i.hh +++ b/src/GEOM_I/GEOM_IMeasureOperations_i.hh @@ -170,6 +170,15 @@ class GEOM_I_EXPORT GEOM_IMeasureOperations_i : GEOM::GEOM_Object_ptr thePoint, GEOM::GEOM_Object_ptr theDirection); + // Methods to convert X,Y,Z coordinates of point to U,V parameters on surface and back + GEOM::ListOfDouble* XYZtoUV(GEOM::GEOM_Object_ptr theSurf, + const GEOM::ListOfDouble& theXYZlist, + CORBA::Boolean theIsNormalized); + + GEOM::ListOfDouble* UVtoXYZ(GEOM::GEOM_Object_ptr theSurf, + const GEOM::ListOfDouble& theUVlist, + CORBA::Boolean theIsNormalized); + // Methods for class CheckConformity GEOM::GEOM_IMeasureOperations::SequenceOfPairOfShape* SelfIntersected2D( const GEOM::GEOM_IMeasureOperations::CheckResults& theResuts); diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index d28107781..6b7947e0d 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -11232,6 +11232,74 @@ class geomBuilder(GEOM._objref_GEOM_Gen): self._autoPublish(aVec, theName, "curvature") return aVec + ## Convert X,Y,Z points coordinates to UV parameters on the given surface. + # @param theSurf the given face. It can be also a shell or a compound with one face. + # @param theXYZlist float list of size 3*N where N is the number of points + # for which we want their U,V coordinates. + # If the user enters a list of size not divisible by 3 + # an exception will be thrown. + # @param theIsNormalized if True, the returned parameters will be in range [0, 1]. + # + # @return list of float of size 2*N. + # + # @ref tui_xyz_to_uv_page "Example" + @ManageTransactions("MeasuOp") + def XYZtoUV(self, theSurf, theXYZlist, theIsNormalized = True): + """ + Convert X,Y,Z points coordinates to UV parameters on the given surface. + + Parameters: + theSurf the given face. It can be also a shell or a compound with one face. + theXYZlist float list of size 3*N where N is the number of points + for which we want their U,V coordinates. + If the user enters a list of size not divisible by 3 + an exception will be thrown. + theIsNormalized if True, the returned parameters will be in range [0, 1]. + + Returns: + list of float of size 2*N. + + Example of usage: + [u1,v1, u2,v2] = geompy.XYZtoUV(Face_1, [0,0,0, 0,10,10]) + """ + aUVlist = self.MeasuOp.XYZtoUV(theSurf, theXYZlist, theIsNormalized) + RaiseIfFailed("XYZtoUV", self.MeasuOp) + return aUVlist + + ## Convert UV parameters on the given surface to 3D points coordinates. + # @param theSurf the given face. It can be also a shell or a compound with one face. + # @param theUVlist float list of size 2*N where N is the number of points + # for which we want their X,Y,Z coordinates. + # If the user enters a list of non-even size + # an exception will be thrown. + # @param theIsNormalized if True, the input parameters are expected to be in range [0, 1]. + # + # @return list of float of size 3*N. + # + # @ref tui_xyz_to_uv_page "Example" + @ManageTransactions("MeasuOp") + def UVtoXYZ(self, theSurf, theUVlist, theIsNormalized = True): + """ + Convert UV parameters on the given surface to 3D points coordinates. + + Parameters: + theSurf the given face. It can be also a shell or a compound with one face. + theUVlist float list of size 2*N where N is the number of points + for which we want their X,Y,Z coordinates. + If the user enters a list of non-even size + an exception will be thrown. + theIsNormalized if True, the input parameters are expected to be in range [0, 1]. + + Returns: + list of float of size 3*N. + + Example of usage: + [x1,y1,z1, x2,y2,z2] = geompy.UVtoXYZ(Face_1, [0,0, 10,10]) + """ + aXYZlist = self.MeasuOp.UVtoXYZ(theSurf, theUVlist, theIsNormalized) + RaiseIfFailed("UVtoXYZ", self.MeasuOp) + return aXYZlist + ## Get min and max tolerances of sub-shapes of theShape # @param theShape Shape, to get tolerances of. # @return [FaceMin,FaceMax, EdgeMin,EdgeMax, VertMin,VertMax]\n