Hello Dale,

thank you for the fast response.

I studied opennurbs_array.h a bit now and set up the lofting the way you tell me.

The result is basically the same. I made a screenshot:

https://imgur.com/a/dO8hoxZ - maybe it rings a bell for someone.

In magenta the NURBS and in yellow the lofted bezier surface from the same data.

Both my old code and the modified one show the curves and loft surface successfully

lofted and valid (see second preformated text).

Since the problem may come from evaluation of the surface too, here I add the code

that renders the yellow stuff:

```
1 //___ render Bezier surface in straigt space
2 bool good;
3 int i, j;
4 double u, v, du, dv, data[4];
5 int strd = TheLoft->Dimension();
6 int uResolution {m_uResolution / 4}, vResolution {m_vResolution / 4};
7
8 ON_Interval uIvl = TheLoft->Domain(0);
9 ON_Interval vIvl = TheLoft->Domain(1);
10 du = (uIvl.m_t[1] - uIvl.m_t[0]) / double(uResolution);
11 dv = (vIvl.m_t[1] - vIvl.m_t[0]) / double(vResolution);
12
13 glColor3ub(255, 255, 0);
14 for (i = 0; i <= uResolution; i++) {
15 u = i * du + uIvl.m_t[0];
16 glBegin(GL_LINE_STRIP);
17 for (j = 0; j <= vResolution; j++) {
18 v = j * dv + vIvl.Min();
19 ON_3dPoint p = TheLoft->PointAt(u, v);
20 glVertex3d(p.x, p.y, p.z);
21 }
22 glEnd();
23 }
24 for (j = 0; j <= vResolution; j++) {
25 v = j * dv + vIvl.m_t[0];
26 glBegin(GL_LINE_STRIP);
27 for (i = 0; i <= uResolution; i++) {
28 u = i * du + uIvl.m_t[0];
29 good = TheLoft->Evaluate(u, v, // parameters
30 0, // number of derivatives
31 strd, // array stride
32 data); // array of length stride*(ndir+1)*(ndir+2)/2
33 if (!good) {
34 printf("evaluation at (%lf, %lf) failed\n", u, v);
35 } else {
36 glVertex3d(data[0], data[1], data[2]);
37 }
38 }
39 }
```

As you can see, I use 2 methods (PointAt() and Evaluate()), but that doesn’t make a difference in tests. Because your example requires more than 2 curves, I used three.

Before you ask: the NURBS profile does have a pointy tip, but the Bezier lofting uses

only the 3 profiles and should be open at the top and bottom.

The 3 cyan profile curves are what went into the loft and their rendering happened

after the lofting. One of the end curves of the yellow wire wool starts tangential

to the bottom profile.

Here some output, showing what the classes themselves think about their state:

```
0 x/y/rad: -400.000, 0.000, 150.000
0 x/y/rad: 0.000, 20.000, 150.000
0 x/y/rad: 150.000, 40.000, 150.000
0 x/y/rad: 200.000, 0.000, 150.000
0 x/y/rad: 150.000, -40.000, 150.000
0 x/y/rad: 0.000, -70.000, 150.000
0 x/y/rad: -400.000, 0.000, 150.000
loftSurface: 1. bezier curve: good, is valid: yes
1 x/y/rad: -400.000, 0.000, 500.000
1 x/y/rad: 0.000, 40.000, 500.000
1 x/y/rad: 150.000, 25.000, 500.000
1 x/y/rad: 200.000, 0.000, 500.000
1 x/y/rad: 150.000, -25.000, 500.000
1 x/y/rad: 0.000, -40.000, 500.000
1 x/y/rad: -400.000, 0.000, 500.000
loftSurface: 2. bezier curve: good, is valid: yes
2 x/y/rad: -300.000, 0.000, 1000.000
2 x/y/rad: 0.000, 30.000, 1000.000
2 x/y/rad: 100.000, 20.000, 1000.000
2 x/y/rad: 150.000, 0.000, 1000.000
2 x/y/rad: 100.000, -20.000, 1000.000
2 x/y/rad: 0.000, -30.000, 1000.000
2 x/y/rad: -300.000, 0.000, 1000.000
loftSurface: 3. bezier curve: good, is valid: yes
loftSurface: lofting of bezier surface: good
is valid: yes
u-order = 3, v-order = 7
```

Originally I used 2 to 4 curves, all resulting in fine NURBS and crooked Bezier surfaces.

Why is lofting between only 2 Bezier curves not good?

Thanks again, Armin