
Fri, 05/15/2015 - 20:01
Hello,
I am doing two-dimensional computations on a TopoDS_Face. When I want to have the three-dimensional representations of my two-dimensional data, I use:
gp_Pnt spacePoint;
BRep_Tool::Surface(face)->D0(position.X(), position.Y(), spacePoint);
Now I was really surprised to find two two-dimensional positions on my surface that differ a lot (more than 6.0 length units), but are identical in the space (distance less than 1.0e-8). I thought that there might be a numerical instability, but at least with a tolerance of 1.0e-2 my BRepTopAdaptor_FClass2d claims that they are both TopAbs_ON the face.
Isn't the mapping from a Geom_Surface made out of a TopoDS_Face to the three-dimensional space bijective (one-to-one)???
Any hint is greatly appreciated!
Greetings,
Benjamin
Fri, 05/29/2015 - 13:02
I have found out more about this topic: no, in general the mapping from a Geom_Surface made out of a TopoDS_Face to the three-dimensional space is not bijective.
Please see the attached picture. You see a shell here (the yellow area) and a face (with green boundary edges) that is part of the shell. One edge of the face (visualized with red color shining through) is exciting. The edge and its p-curve are not closed. The first point of the edge (visualized with white color on the left) has the coordinates (0 / 1.5708), the last point (visualized with blue color and on the right) has the coordinates (1.5708 / 1.5708) with respect to the Geom_Surface made out of the face.
I have a position (6.28319 / 1.5708) on the surface now that was computed by some algorithm before. This position obviously has a great distance from the first point of the edge (exactly 6.28319 length units). But when I compute their three-dimensional equivalents, the distance is zero. Also both points, (0 / 1.5708) and (6.28319 / 1.5708), are TopAbs_ON with respect to the face.
It is striking, that the coordinates look like 2 * M_PI and M_PI / 2. Could it be that the p-curve of the edge is a segment of a circle and therefore is somehow periodic?
For checking now whether two two-dimensional points on the Geom_Surface are identical, it does not suffice to compute their distance, because the mapping to the space is not one-to-one. Instead I have to compute the three-dimensional representations with BRep_Tool::Surface(face)->D0(position.X(), position.Y(), spacePoint) and then compute the distance in the space. This works, but might be costly from a performance point of view.
Still I would like to ask you: is this an OCC bug? Or is this usual behaviour? Is there a cheaper way to find out whether two different two-dimensional coordinates represent the same space point than using D0 of the Geom_Surface?
Thank you.
Fri, 05/29/2015 - 13:25
Benjamin,
surfaces may be periodic (cylinders, surfaces of revolution, ...) or just closed (e.g. a NURBS surface with the last column of control points coincident with the first).
They also may have a degenerate side (e.g. a "triangular" surface of revolution built from a curve with an end on the rotation axis), where all the UV's on a side of the domain map on the same 3d point.
In all these cases the UV-3d mapping is not bijective.
Mauro
Fri, 05/29/2015 - 13:54
Thanks for the answer. Can I very easily and cheaply recognize those cases in my algorithms? Then my distance check in the 3d space was only necessary in such cases and I could use the cheap 2d distance measurement in the other cases. Or is it best to always measure distance in the 3d space?
Fri, 05/29/2015 - 14:05
In Geom_Surface you have methods IsUPeriodic/IsVPeriodic and IsUClosed/IsVClosed.
For "triangular" surfaces I don't know; so, if you can encounter them in your application, I am afraid that you need either to write some code to recognize them or alwasy measure distances in 3d space.
Fri, 05/29/2015 - 16:07
Great! Doing the computation in space only when either U or V are periodic really speeds up the check. I have added an assert to ensure that the results are the same. With this I am confident to find out situations where this check does not suffice, if such situations exist at all.
Thank you again.
Fri, 11/27/2015 - 15:24
Hi,
I still have problems with periodic surfaces. When I create a Geom2d_BSplineCurve interpolating two points on a surface that are taken from different periods and then create a 3d curve with Adaptor3d_CurveOnSurface, the curve leaves the face and forms something like a complementary circle to the actually expected curve. In the attached picture the green/red curve should stay on the surface. But because of the described problem it changes direction, leaves the surface and approaches the target point from the other side.
If I could force all 2d points onto the same period of the Geom_Surface, this should be solved. Is there a way to do that or at least recognize such a situation? To be clearer: in my example the point (6.28319, 134.072) and the point (0.0, 134.072) have the same 3d coordinates. I can create a curve from (0.0, 134.072) to (1.0, 134.072), but creating a curve from (6.28319, 134.072) to (1.0, 134.072) leads to the error you see in Curve.png.
Sometimes computing the 3d representation of a 2d point and projecting it onto the Geom_Surface again helps, but not always. :-(
Any help is greatly appreciated!
Benjamin
Fri, 11/27/2015 - 16:13
I guess I have found a solution: ShapeAnalysis::AdjustByPeriod can be used to get rid of the period. I use it like this:
double newX = point.X() + ShapeAnalysis::AdjustByPeriod(point.X(), 0.0, surface->UPeriod());
and the same for Y. This seems to move all points into the same period and then the curve interpolation works fine!
Wed, 12/02/2015 - 15:16
Dear Mauro,
I have a bijective similar issue related on this post : http://www.opencascade.com/content/geomlibtoolparameters-failure
In my case it is not a periodic surface or surface of revolution, it is a quarter of disk-like surface that gives the same parameter for 2 distincts points on the real space.
Any idea ?
Thanks,
Sâm