Get surface parameters of an arbitrary point on a bounding curve

Hello fellow OCCT users, for a mesh algorithm I need to interpolate between the vertices of mesh cells. These mesh cells are lying on a OCCT surface and sometimes the vertices lie on a bounding curve of the surface (I added a picture to this post). In this case I know the parameters of the vertices on the curve, but not on the suface. This makes interpolating between the parameters of the vertices impossible. Therefore, I need to convert the parameter of a vertex on the curve to the parameters of the vertex on the surface. Currently, I use ShapeAnalysis_Surface and GeomAPI_ProjectPointOnSurf to do this, but even the combination of both algorithms doesn't give consistent results (I also added a code example). In some cases both algorithms cannot find a set of parameters, even if I know exactly, that the point is on the surface. Is there an alternate algorithm I haven't found yet? Or can I even use the parameter of the curve, the curve or the topology information to convert the curve parameter into the surface parameters?

int get_occ_surface_parameters (Handle_Geom_Surface surface,
                                                double *coords,
                                                double *param,
                                                double tol,
                                                double *near_param)
{
  ShapeAnalysis_Surface surface_analyzer(surface);
  const gp_Pnt pnt(coords[0], coords[1], coords[2]);
  gp_Pnt2d uv;
  /* Get parameters with ShapeAnalysis_Surface 
   * if we have some nearby parameters we use these as start point of the newton method */
  if (near_param == nullptr)
  {
    uv = surface_analyzer.ValueOfUV(pnt, tol);
  }
  else
  {
    gp_Pnt2d next_uv(near_param[0], near_param[1]);
    uv = surface_analyzer.NextValueOfUV(next_uv, pnt, tol);
  }
  /* Check the tolerance and if the parameters are inside the bounds */
  double u1, u2, v1, v2;
  surface->Bounds(u1, u2, v1, v2);
  if (surface_analyzer.Gap() <= tol &&
      ((u1 <= uv.X() && uv.X() <= u2) || (u2 <= uv.X() && uv.X() <= u1)) &&
      ((v1 <= uv.Y() && uv.Y() <= v2) || (v2 <= uv.Y() && uv.Y() <= v1)))
  {
    param[0] = uv.X();
    param[1] = uv.Y();
    return 1;
  }

  /* If ShapeAnalysis_Surface fails we try the same with GeomAPI_ProjectPointOnSurf */
  const GeomAPI_ProjectPointOnSurf proj_on_surf(pnt, surface, tol);
  if (proj_on_surf.NbPoints() > 0)
  {
    if (proj_on_surf.LowerDistance() <= tol)
    {
      proj_on_surf.LowerDistanceParameters(param[0], param[1]);
      return 1;
    }
  }

  /* Return 0 if no parameters were found */
  return 0;
}
Attachments: 
Francois Lauzon's picture

Hello Sandro,
have a look at the BRep_Tool class, there is a lot of methods there to access various sub-object, in particular BRep_Tool::Parameters() return the uv coordinate for a TopoDS_Vertex on a TopoDS_Face. If your TopoDS_Shape is correctly build and contains p-curves (ShapeFix_Edge::FixAddPCurve() ) you should be able to retrieve the uv coordinates.
Best regards,
François.