Salome HOME
Implemented [bos #35094] [EDF] (2023-T1) X,Y,Z to U,V. jfa/35094_XYZtoUV V9_11_0b1 1/head
authorjfa <jfa@opencascade.com>
Fri, 12 May 2023 08:46:46 +0000 (09:46 +0100)
committerjfa <jfa@opencascade.com>
Fri, 12 May 2023 08:46:46 +0000 (09:46 +0100)
doc/salome/examples/XYZ_to_UV.py [new file with mode: 0644]
doc/salome/examples/tests.set
doc/salome/gui/GEOM/input/tui_measurement_tools.doc
doc/salome/gui/GEOM/input/tui_xyz_to_uv.doc [new file with mode: 0644]
idl/GEOM_Gen.idl
src/GEOMImpl/GEOMImpl_IMeasureOperations.cxx
src/GEOMImpl/GEOMImpl_IMeasureOperations.hxx
src/GEOM_I/GEOM_IMeasureOperations_i.cc
src/GEOM_I/GEOM_IMeasureOperations_i.hh
src/GEOM_SWIG/geomBuilder.py

diff --git a/doc/salome/examples/XYZ_to_UV.py b/doc/salome/examples/XYZ_to_UV.py
new file mode 100644 (file)
index 0000000..ef4abdd
--- /dev/null
@@ -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
index c2c8eb81ee7115c973bffcf39ee88956f31ff439..db69d7f576fe77a173f7a8a8dbcf314956984791 100644 (file)
@@ -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
 )
index a4e7f5c9df5d46e06c623869e31098022803bf39..59eea50df2afec3b7a1b2eb4b942017886a62b7d 100644 (file)
@@ -23,6 +23,7 @@
 <li>\subpage tui_fast_intersection_page</li>
 <li>\subpage tui_check_conformity_page</li>
 <li>\subpage tui_shape_proximity_page</li>
+<li>\subpage tui_xyz_to_uv_page</li>
 </ul>
 
 */
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 (file)
index 0000000..50378f4
--- /dev/null
@@ -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}
+
+*/
index d33bc140dcb1be63fc7cbb9afcf3ec5f11cbd583..8d9e2ff2b79f562240b77adefe74d25572d2c7c4 100644 (file)
@@ -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
 
     /*!
index 7bfc35b5f19243ae780e2a1823a8ec67b8d441a0..00bcb04e05f406c872801c81edc1cdf8ac1c8902 100644 (file)
@@ -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
index 3e96a329568d3ffbcbfa6e79d11e25a4838d0187..af0410ba66b76e5d6a33bb5faa4c28d5e3e7940a 100644 (file)
@@ -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);
index e829aceabec2103f9a95aacade55111c6424349b..a740731b4b648c22badcb4e0f6115774649c1274 100644 (file)
@@ -21,6 +21,7 @@
 //
 
 #include <Standard_Stream.hxx>
+#include <TColStd_HArray1OfReal.hxx>
 
 #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
index ded2f9c4122e45132d67ff728d43475315f14a24..e8cdf9c53716623fa4a104c7c7e03556e8e414fb 100644 (file)
@@ -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);
index d28107781165ebaaaa4e471a27bab5f4b06882c8..6b7947e0df628cf67fd72d857ec4ef8cb1f7b29a 100644 (file)
@@ -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