Convert a Triangular Bezier Surface to a Quadrilateral Bezier Surface

Assume you have a Bezier surface:

ON_BezierSurface bezier_surface

and one of its edges is singular:


Is it possible to convert this triangular Bezier surface to a quadrilateral Bezier surface by splitting the largest edge in half. That means that the new Bezier surface has 2 edges from the old Bezier surface, and the other 2 are constructed by splitting the largest edge of the old Bezier surface. The new Bezier surface looks exactly like the old one, but it has 4 edges with no singularity. i.e.:


Can you explain a little more about what you are trying to do an why? How are you creating the bezier surfaces?

I get the Bezier surfaces from the 3dm file so I do not have control over them. However, triangular Bezier surfaces cause problem in the next stages of our electromagnetic development. (I could explain why but it is an electromagnetic issue and not a geometry issue). So I need to find a way to “represent” a triangular Bezier surface as a surface that has 4 distinct edges (a quadrilateral Bezier surface) without changing the shape of the surface. One way that comes to mind is to “pretend” that 2 of the edges are collinear. So we can split the largest edge in half and with the other 2 edges, we have totally 4 edges. Now using these 4 edges, we can create a quadrilateral Bezier surface that looks like a triangle.

How? Are you reading 3DM files yourself? Can you post such a file?

If you create a trimmed NURBS surface, using RhinoCreateEdgeSrf for example, then you can retain the triangular shape and not have the singularity.

Yes I read the files. If you just create a sphere in Rhino and save it as 3dm file, you will see that it has triangular Bezier elements at the poles and quadrilaterals elsewhere.

So I guess my NURBS surface is not trimmed.

Create a sphere in Rhino. When finished, run the List command and pick the sphere. Notice that the sphere is a Surface of Revolution (ON_RevSurface). When reading the 3DM file, you will find that what you really have is an ON_Brep with a single untrimmed face. The surface behind that face is a ON_RevSurface.

If you were to get the NURB form of the surface, you would find that the NURBS surface (ON_NurbsSurface) has 2 singular edges. All this can be demonstrated selecting the sphere and running the Rebuild command, which will convert the ON_RevSurface to an ON_NurbsSurface. When finished, again, use the List command.

I’m still trying to understand what you want…

Ok. Let me rephrase my question. Assuming that we have ON_BezierSurface bezier_surface, that one of its edges is singular (edge4)


Is it possible to do the following:

1- extract all non-singular edges of the bezier surface

ON_BezierCurve curve0,curve1,curve2;
bezier_surface.IsoCurve(0, 0, &curve0);
bezier_surface.IsoCurve(0, 1, &curve1);
bezier_surface.IsoCurve(1, 0, &curve2);

2- split the largest edge (let’s say curve2) into 2 curves

ON_BezierCurve left_bez,right_bez;
curve2.Split(0.5, left_bez,right_bez);

3- using all available curves, create a new bezier surface

ON_BezierSurface new_bezier_surface;

This is what I need to do.

Hi m_shafie,
it seems that you outlined a process that produces your desired result. It seems to be that it would work better for planar, triangular surfaces. I think that this could be written in all our SDKs, e.g., Python, RhinoScript, RhinoCommon (.Net) and C++. It’s just a matter of sitting there and writing the code, right?
Should we help in other ways?



Giulio Piacentino
for Robert McNeel & Associates

To implement the procedure, I first tried to do an experiment. I took a normal (without singularity) Bezier surface, and tried to reproduce it using its 4 edge curves. The code complies and runs, but it does not produce the same Bezier element. (i.e. bezier_surface != new_bezier_surface). I was wondering if you could help me out address the problem. Below is what I did:

ON_BezierCurve pCrv0;
ON_BezierCurve pCrv1;
ON_BezierCurve pCrv2;
ON_BezierCurve pCrv3;

std::vector <.ON_BezierCurve>. bezier_curve_vector; //(2 extra dots added to avoid HTML clash, please remove if copying into your editor)

bezier_surface.IsoCurve(0, 0, &pCrv0);

bezier_surface.IsoCurve(0, 1, &pCrv1);

bezier_surface.IsoCurve(1, 0, &pCrv2);

bezier_surface.IsoCurve(1, 1, &pCrv3);

int curve_list_size=bezier_curve_vector.size();

for(int i=0;i<.curve_list_size;i++) //(1 extra dot added to avoid HTML clash, please remove if copying into your editor)

ON_BezierSurface new_bezier_surface;

As far as I know, in general it is not possible. In some special cases it is possible, such as planar surfaces, but in general it is not the case.