How to get the point of intersection with isoparametric curve and Geom_Surface ?

R G W

CAD community veteran
Hello together, I'm rgw.

I want to get the point of intersection with isoparametric curve and Geom_Surface.

I created an isoparametric curve on a surface and use it to intersect with the surface.

Now I want to know the intersections of a certain isoparametric curve (yellow curves) and the surface.
The intersection result i think is two points and one segment. Take one "long" isoparametric curve for example, it intersects the edge twice and the intersection points should be where as shown below.
1679557098282.png1679557151085.png

First I use UIso to get the isoparametric curve. Then I use GeomAPI_IntCS to get the intersection result.

But the result I got only has many points and the result as shown below.
1679557423472.png

Any hints, suggestions, corrections, help? Thanks very much!
 

Quaoar

Administrator
Staff member
Well, I guess you should not do that in 3D, as your curve entirely lies on the surface, and that's just an awful case for the intersector (operands are not in "general position" as they say). Why wouldn't you narrow this task down to the UV space of the face? You take an isoparametric line as a vertical (V) or horizontal (U) line segment and then intersect it with the pcurves of the face edges. For that, a 2D curve-curve intersection should be sufficient, and then you map the obtained UV intersection points back to 3D.

That's basically what OpenCascade's "Hatcher" algorithm is doing, more or less.
 

R G W

CAD community veteran
Well, I guess you should not do that in 3D, as your curve entirely lies on the surface, and that's just an awful case for the intersector (operands are not in "general position" as they say). Why wouldn't you narrow this task down to the UV space of the face? You take an isoparametric line as a vertical (V) or horizontal (U) line segment and then intersect it with the pcurves of the face edges. For that, a 2D curve-curve intersection should be sufficient, and then you map the obtained UV intersection points back to 3D.

That's basically what OpenCascade's "Hatcher" algorithm is doing, more or less.
Thank you for your suggestion.
How to trans the UV isoparametric curve to a two-dimensional line on the surface? I am self-learning OCCT online, and I don't know how to do this.
I would appreciate it if you could provide some codes let me to learn.
Thank you so much!
 

Quaoar

Administrator
Staff member
I mean, an isoparametric curve is simply a 2D line by definition, so what you have to do is just create such a line explicitly for the selected UV origin and direction. E.g., this code would make an U-isoparametric line (directed along the V axis) from the midpoint of the parametric domain.

Code:
double uMin, uMax, vMin, vMax;
BRepTools::UVBounds(face, uMin, uMax, vMin, vMax);

double umid = (uMin + uMax)*0.5;
double vmid = (vMin + vMax)*0.5;

Handle(Geom2d_Line) iso = new Geom2d_Line( gp_Pnt2d(umid, vmid), gp::DY2d() );

Once you get this line, try using Geom2dAPI_InterCurveCurve.
 

R G W

CAD community veteran
You're welcome. Keep asking questions if you feel like.
Hi, I've tried what you said, but I found that it doesn't seem to solve my problem.

First of all, the uv isoparametric curve on a surface is a two-dimensional curve on the plane, but it is a three-dimensional curve in the global coordinate system;
Secondly, the direction of the uv isoparametric curve is not necessarily completely horizontal or vertical, as shown below As shown in the picture, the left picture is the uv line I constructed according to the method you said, and the right picture is the actual uv line I think;
Finally, if I want to use Geom2dAPI_InterCurveCurve, I need to convert the boundary of the surface to Geom2d_Curve. However, the boundary of the surface is not regular, and I think this part is more difficult to complete.

1679620694540.png1679620742353.png

The above is my personal understanding, do you have any suggestions,hints, corrections, help? Thank you very much!

And I also tried the method GeomAPI_IntCS because this surface is feels like a 3d surface, maybe I can use the 3d method to complete this.
But the result is still unsatisfactory. I got 18 points and 0 segment, and the points is view as one point because their coordinates are very close.

The complete step file is attached in the attachment.
Thank you very much!
 

Attachments

  • tutai.STEP
    11.7 KB · Views: 1

Quaoar

Administrator
Staff member
Can you share the code that you have already tried?

These are the isoparametric curves in the UV space:

1679662765374.png

... the direction of the uv isoparametric curve is not necessarily completely horizontal or vertical, as shown below As shown in the picture, the left picture is the uv line I constructed according to the method you said
The isoparametric line "lives" entirely in the domain of a face, so it has no mathematical chance to lie outside a surface.
Finally, if I want to use Geom2dAPI_InterCurveCurve, I need to convert the boundary of the surface to Geom2d_Curve. However, the boundary of the surface is not regular
That's exactly why I proposed to use the UV domain: all the boundaries of a face are already pcurves there. What do you mean saying that "boundary is not regular"?
I got 18 points and 0 segment, and the points is view as one point because their coordinates are very close.
Running a 3D intersector for a spatial curve lying on a surface is desperate. The solution would be the curve itself, and OpenCascade wouldn't handle that situation for you. You can possibly try to find the minimal distance between the 3D curve of an isoline and a 3D boundary of a face, but that's also a very bad idea given that you can simplify the task a lot working in 2D.

Maybe I misunderstand something in your question, so you may want to provide the code and we'll see from there.
 

R G W

CAD community veteran
Here is my code, just what you gave me...

Code:
    double uMin, uMax, vMin, vMax;
    BRepTools::UVBounds(faceo, uMin, uMax, vMin, vMax);

    double umid = (uMin + uMax)*0.5;
    double vmid = (vMin + vMax)*0.5;

    Handle(Geom2d_Line) iso = new Geom2d_Line(gp_Pnt2d(umid, vmid), gp::DY2d());

Because when I was writing these code, I don't know how I can convert the boundary of the face into a Geom2d_Line, because I want to use Geom2dAPI_InterCurveCurve.

Like the boundary of this face, it is an arc, how can I use a 2d_line to represent it?

The isoparametric line "lives" entirely in the domain of a face, so it has no mathematical chance to lie outside a surface.
Yes, I agree with you and this is exactly where my another confusion lies.
Using the code above, I create a line outside the face. Then how can I do the intersection operation with the line is outside the face.(red line)
1679664420982.png
 

R G W

CAD community veteran
Oh! Maybe I know what you meaning.

Are you saying that the intersection is performed in uv space, and then the intersection points are mapped to the physical domain?
1679665206871.png
Yes, I think what you said makes sense.
Thank you as always!!


But here is another question, if the face is a circle, does this way works too? Because u=0/1(or v=0/1) may not represent the position of the boundary of the circle in the parameter space. I will think about it.

Thank you so much for your help.
 

Quaoar

Administrator
Staff member
1679666040394.png

Prototyped in Analysis Situs:

Code:
int MISC_Test(const Handle(asiTcl_Interp)& interp,
              int                          argc,
              const char**                 argv)
{
  asiEngine_Part partApi( cmdMisc::cf->Model,
                          cmdMisc::cf->ViewerPart->PrsMgr() );

  // Access selected faces (if any).
  asiAlgo_Feature selected;
  //
  if ( !cmdMisc::cf.IsNull() )
  {
    partApi.GetHighlightedFaces(selected);
  }

  // Get the face in question.
  int fid = 0;
  interp->GetKeyValue<int>(argc, argv, "fid", fid);
  //
  if ( fid ) selected.Add(fid);

  if ( selected.Extent() != 1 )
  {
    interp->GetProgress().SendLogMessage(LogErr(Normal) << "Please, select exactly one face.");
    return TCL_ERROR;
  }

  fid = selected.GetMinimalMapped();

  const TopoDS_Face& face = partApi.GetAAG()->GetFace(fid);

  double uMin, uMax, vMin, vMax;
  BRepTools::UVBounds(face, uMin, uMax, vMin, vMax);

  const double uMid = (uMin + uMax)*0.5;
  const double vMid = (vMin + vMax)*0.5;

  Handle(Geom_Surface) surf    = BRep_Tool::Surface(face);
  Handle(Geom2d_Line)  isoLine = new Geom2d_Line( gp_Lin2d( gp_Pnt2d(uMid, vMid), gp::DY2d() ) );

  interp->GetPlotter().DRAW_CURVE( surf->UIso(uMid), Color_Green, false, "uIso" );

  for ( TopExp_Explorer eexp(face, TopAbs_EDGE); eexp.More(); eexp.Next() )
  {
    const TopoDS_Edge& edge = TopoDS::Edge( eexp.Current() );

    // Get pcurve of an edge.
    double f, l;
    Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface(edge, face, f, l);

    Geom2dAPI_InterCurveCurve intersector(isoLine, pcurve);

    if ( intersector.NbPoints() )
    {
      const int nsol = intersector.NbPoints();
      for ( int isol = 1; isol <= nsol; ++isol )
      {
        gp_Pnt2d pt2d = intersector.Point(isol);
        gp_Pnt   pt   = surf->Value( pt2d.X(), pt2d.Y() );

        interp->GetPlotter().DRAW_POINT(pt, Color_Red, "intersectionPoint");
      }
    }
  }

  return TCL_OK;
}
 

R G W

CAD community veteran
View attachment 538

Prototyped in Analysis Situs:

Code:
int MISC_Test(const Handle(asiTcl_Interp)& interp,
              int                          argc,
              const char**                 argv)
{
  asiEngine_Part partApi( cmdMisc::cf->Model,
                          cmdMisc::cf->ViewerPart->PrsMgr() );

  // Access selected faces (if any).
  asiAlgo_Feature selected;
  //
  if ( !cmdMisc::cf.IsNull() )
  {
    partApi.GetHighlightedFaces(selected);
  }

  // Get the face in question.
  int fid = 0;
  interp->GetKeyValue<int>(argc, argv, "fid", fid);
  //
  if ( fid ) selected.Add(fid);

  if ( selected.Extent() != 1 )
  {
    interp->GetProgress().SendLogMessage(LogErr(Normal) << "Please, select exactly one face.");
    return TCL_ERROR;
  }

  fid = selected.GetMinimalMapped();

  const TopoDS_Face& face = partApi.GetAAG()->GetFace(fid);

  double uMin, uMax, vMin, vMax;
  BRepTools::UVBounds(face, uMin, uMax, vMin, vMax);

  const double uMid = (uMin + uMax)*0.5;
  const double vMid = (vMin + vMax)*0.5;

  Handle(Geom_Surface) surf    = BRep_Tool::Surface(face);
  Handle(Geom2d_Line)  isoLine = new Geom2d_Line( gp_Lin2d( gp_Pnt2d(uMid, vMid), gp::DY2d() ) );

  interp->GetPlotter().DRAW_CURVE( surf->UIso(uMid), Color_Green, false, "uIso" );

  for ( TopExp_Explorer eexp(face, TopAbs_EDGE); eexp.More(); eexp.Next() )
  {
    const TopoDS_Edge& edge = TopoDS::Edge( eexp.Current() );

    // Get pcurve of an edge.
    double f, l;
    Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface(edge, face, f, l);

    Geom2dAPI_InterCurveCurve intersector(isoLine, pcurve);

    if ( intersector.NbPoints() )
    {
      const int nsol = intersector.NbPoints();
      for ( int isol = 1; isol <= nsol; ++isol )
      {
        gp_Pnt2d pt2d = intersector.Point(isol);
        gp_Pnt   pt   = surf->Value( pt2d.X(), pt2d.Y() );

        interp->GetPlotter().DRAW_POINT(pt, Color_Red, "intersectionPoint");
      }
    }
  }

  return TCL_OK;
}
Oh,Thank you so much!
Sry for make some stupid questions here.:oops:
 

Quaoar

Administrator
Staff member
Are you saying that the intersection is performed in uv space, and then the intersection points are mapped to the physical domain?
Exactly.
But here is another question, if the face is a circle, does this way works too? Because u=0/1(or v=0/1) may not represent the position of the boundary of the circle in the parameter space.
Whichever surface type you have, the UV domain is still bounded by the so-called "pcurves" (images of 3D edges in the UV domain of a face). Then, you do not necessarily have to make the assumption that UV is bound by [0,1]. You just make sure to set the origin point of a line strictly within your UV domain (using BRepTools::UVBounds()) and let the intersector do its job.
 
Top