@@ -44,24 +44,65 @@ lwnurbs_construct(int32_t srid, GBOX *bbox, uint32_t degree,
44
44
/* Basic validation */
45
45
if (degree < NURBS_MIN_DEGREE || degree > NURBS_MAX_DEGREE )
46
46
{
47
- lwerror ("lwnurbs_construct: invalid degree %d" , degree );
47
+ lwnotice ("lwnurbs_construct: invalid degree %d" , degree );
48
48
return NULL ;
49
49
}
50
50
51
- if (ctrl_pts && ctrl_pts -> npoints < NURBS_MIN_POINTS )
51
+ if (! ctrl_pts )
52
52
{
53
- lwerror ("lwnurbs_construct: minimum %d control points required" , NURBS_MIN_POINTS );
53
+ lwnotice ("lwnurbs_construct: ctrl_pts is NULL" );
54
54
return NULL ;
55
55
}
56
56
57
+ if (ctrl_pts -> npoints < NURBS_MIN_POINTS )
58
+ {
59
+ lwnotice ("lwnurbs_construct: minimum %d control points required, got %d" ,
60
+ NURBS_MIN_POINTS , ctrl_pts -> npoints );
61
+ return NULL ;
62
+ }
63
+
64
+ /* Validate knots */
65
+ uint32_t expected_knots = ctrl_pts -> npoints + degree + 1 ;
66
+ if (nknots != expected_knots )
67
+ {
68
+ lwnotice ("lwnurbs_construct: expected %d knots, got %d" , expected_knots , nknots );
69
+ return NULL ;
70
+ }
71
+
72
+ if (!knots )
73
+ {
74
+ lwnotice ("lwnurbs_construct: knots array is NULL" );
75
+ return NULL ;
76
+ }
77
+
78
+ /* Validate weights if provided */
79
+ if (weights && nweights != ctrl_pts -> npoints )
80
+ {
81
+ lwnotice ("lwnurbs_construct: weights count (%d) doesn't match control points (%d)" ,
82
+ nweights , ctrl_pts -> npoints );
83
+ return NULL ;
84
+ }
85
+
86
+ lwnotice ("lwnurbs_construct: creating NURBS with degree=%d, npoints=%d, nknots=%d" ,
87
+ degree , ctrl_pts -> npoints , nknots );
88
+
57
89
result = (LWNURBSCURVE * ) lwalloc (sizeof (LWNURBSCURVE ));
58
90
result -> type = NURBSCURVETYPE ;
59
- result -> flags = ctrl_pts ? ctrl_pts -> flags : lwflags ( 0 , 0 , 0 ) ;
91
+ result -> flags = ctrl_pts -> flags ;
60
92
FLAGS_SET_BBOX (result -> flags , bbox ? 1 : 0 );
61
93
result -> srid = srid ;
62
- result -> bbox = bbox ;
94
+ result -> bbox = bbox ? gbox_clone ( bbox ) : NULL ;
63
95
result -> degree = degree ;
64
- result -> ctrl_pts = ctrl_pts ;
96
+
97
+ /* Clone the control points array */
98
+ result -> ctrl_pts = ptarray_clone_deep (ctrl_pts );
99
+ if (!result -> ctrl_pts )
100
+ {
101
+ lwnotice ("lwnurbs_construct: failed to clone control points" );
102
+ lwfree (result );
103
+ return NULL ;
104
+ }
105
+
65
106
result -> nweights = nweights ;
66
107
result -> nknots = nknots ;
67
108
@@ -70,23 +111,26 @@ lwnurbs_construct(int32_t srid, GBOX *bbox, uint32_t degree,
70
111
{
71
112
result -> weights = (double * ) lwalloc (sizeof (double ) * nweights );
72
113
memcpy (result -> weights , weights , sizeof (double ) * nweights );
114
+ lwnotice ("lwnurbs_construct: copied %d weights" , nweights );
73
115
}
74
116
else
75
117
{
76
118
result -> weights = NULL ;
119
+ lwnotice ("lwnurbs_construct: no weights provided" );
77
120
}
78
121
79
- /* Copy knots if provided */
80
- if ( knots && nknots > 0 )
81
- {
82
- result -> knots = ( double * ) lwalloc ( sizeof ( double ) * nknots );
83
- memcpy ( result -> knots , knots , sizeof ( double ) * nknots );
84
- }
85
- else
86
- {
87
- result -> knots = NULL ;
88
- }
122
+ /* Copy knots */
123
+ result -> knots = ( double * ) lwalloc ( sizeof ( double ) * nknots );
124
+ memcpy ( result -> knots , knots , sizeof ( double ) * nknots );
125
+ lwnotice ( "lwnurbs_construct: copied %d knots" , nknots );
126
+
127
+ /* Debug: print first few knots */
128
+ lwnotice ( "lwnurbs_construct: knots[0]=%g, knots[1]=%g, knots[%d]=%g" ,
129
+ result -> knots [ 0 ],
130
+ nknots > 1 ? result -> knots [ 1 ] : 0.0 ,
131
+ nknots - 1 , result -> knots [ nknots - 1 ]);
89
132
133
+ lwnotice ("lwnurbs_construct: NURBS curve created successfully" );
90
134
return result ;
91
135
}
92
136
@@ -141,34 +185,71 @@ lwnurbs_release(LWNURBSCURVE *nurbs)
141
185
/**
142
186
* B-spline basis function implementation (De Boor algorithm)
143
187
*/
188
+ /* Dans lwgeom_nurbs.c, fonction bspline_basis avec debug */
189
+
144
190
double
145
191
bspline_basis (int i , int p , double t , const double * knots , int nknots )
146
192
{
193
+ if (!knots || nknots <= 0 )
194
+ {
195
+ lwnotice ("bspline_basis: NULL knots or invalid nknots=%d" , nknots );
196
+ return 0.0 ;
197
+ }
198
+
199
+ if (i < 0 || i >= nknots - p - 1 )
200
+ {
201
+ lwnotice ("bspline_basis: index i=%d out of range [0, %d]" , i , nknots - p - 1 );
202
+ return 0.0 ;
203
+ }
204
+
147
205
if (p == 0 )
148
206
{
149
207
if (i >= 0 && i < nknots - 1 && t >= knots [i ] && t < knots [i + 1 ])
208
+ {
209
+ lwnotice ("bspline_basis: p=0, i=%d, t=%g in [%g, %g) -> 1.0" ,
210
+ i , t , knots [i ], knots [i + 1 ]);
150
211
return 1.0 ;
212
+ }
151
213
else if (i == nknots - 2 && fabs (t - knots [nknots - 1 ]) < NURBS_TOLERANCE )
214
+ {
215
+ lwnotice ("bspline_basis: p=0, i=%d, t=%g at end knot %g -> 1.0" ,
216
+ i , t , knots [nknots - 1 ]);
152
217
return 1.0 ;
218
+ }
153
219
else
220
+ {
221
+ if (i < 3 ) // Debug
222
+ {
223
+ lwnotice ("bspline_basis: p=0, i=%d, t=%g not in [%g, %g) -> 0.0" ,
224
+ i , t , knots [i ], knots [i + 1 ]);
225
+ }
154
226
return 0.0 ;
227
+ }
155
228
}
156
229
157
230
double left = 0.0 , right = 0.0 ;
158
231
159
232
if (i + p < nknots && fabs (knots [i + p ] - knots [i ]) > NURBS_TOLERANCE )
160
233
{
161
234
left = (t - knots [i ]) / (knots [i + p ] - knots [i ]) *
162
- bspline_basis (i , p - 1 , t , knots , nknots );
235
+ bspline_basis (i , p - 1 , t , knots , nknots );
163
236
}
164
237
165
238
if (i + p + 1 < nknots && fabs (knots [i + p + 1 ] - knots [i + 1 ]) > NURBS_TOLERANCE )
166
239
{
167
240
right = (knots [i + p + 1 ] - t ) / (knots [i + p + 1 ] - knots [i + 1 ]) *
168
- bspline_basis (i + 1 , p - 1 , t , knots , nknots );
241
+ bspline_basis (i + 1 , p - 1 , t , knots , nknots );
169
242
}
170
243
171
- return left + right ;
244
+ double result = left + right ;
245
+
246
+ if (i < 3 && p <= 2 ) // Debug
247
+ {
248
+ lwnotice ("bspline_basis: i=%d, p=%d, t=%g -> %g (left=%g, right=%g)" ,
249
+ i , p , t , result , left , right );
250
+ }
251
+
252
+ return result ;
172
253
}
173
254
174
255
/**
@@ -183,6 +264,20 @@ lwnurbs_interpolate_point(const LWNURBSCURVE *nurbs, double t, POINT4D *pt)
183
264
if (nurbs -> ctrl_pts -> npoints == 0 )
184
265
return LW_FAILURE ;
185
266
267
+
268
+ if (!nurbs -> knots || nurbs -> nknots == 0 )
269
+ {
270
+ lwnotice ("NURBS curve has no knot vector" );
271
+ return LW_FAILURE ;
272
+ }
273
+ uint32_t expected_knots = nurbs -> ctrl_pts -> npoints + nurbs -> degree + 1 ;
274
+ if (nurbs -> nknots != expected_knots )
275
+ {
276
+ lwnotice ("NURBS curve has incorrect number of knots: %d expected, %d found" ,
277
+ expected_knots , nurbs -> nknots );
278
+ return LW_FAILURE ;
279
+ }
280
+
186
281
/* Clamp parameter to [0,1] */
187
282
if (t < 0.0 ) t = 0.0 ;
188
283
if (t > 1.0 ) t = 1.0 ;
@@ -198,14 +293,21 @@ lwnurbs_interpolate_point(const LWNURBSCURVE *nurbs, double t, POINT4D *pt)
198
293
double weight_sum = 0.0 ;
199
294
POINT4D ctrl_pt ;
200
295
296
+
297
+ lwnotice ("Evaluating NURBS at t=%g with %d control points, degree %d, %d knots" ,
298
+ t , n , p , nurbs -> nknots );
299
+
201
300
for (uint32_t i = 0 ; i < n ; i ++ )
202
301
{
203
302
getPoint4d_p (nurbs -> ctrl_pts , i , & ctrl_pt );
204
303
205
304
double basis = bspline_basis (i , p , t , nurbs -> knots , nurbs -> nknots );
206
305
double weight = (nurbs -> weights && i < nurbs -> nweights ) ? nurbs -> weights [i ] : 1.0 ;
207
306
double w_basis = weight * basis ;
208
-
307
+ if (i < 3 ) // Debug only fro first three points
308
+ {
309
+ lwnotice ("Point %d: basis=%g, weight=%g, w_basis=%g" , i , basis , weight , w_basis );
310
+ }
209
311
pt -> x += w_basis * ctrl_pt .x ;
210
312
pt -> y += w_basis * ctrl_pt .y ;
211
313
if (hasz ) pt -> z += w_basis * ctrl_pt .z ;
@@ -214,15 +316,19 @@ lwnurbs_interpolate_point(const LWNURBSCURVE *nurbs, double t, POINT4D *pt)
214
316
weight_sum += w_basis ;
215
317
}
216
318
217
- /* Normalize by weight sum for rational curves */
218
- if (weight_sum > NURBS_TOLERANCE )
319
+ if (weight_sum <= NURBS_TOLERANCE )
219
320
{
220
- pt -> x /= weight_sum ;
221
- pt -> y /= weight_sum ;
222
- if (hasz ) pt -> z /= weight_sum ;
223
- if (hasm ) pt -> m /= weight_sum ;
321
+ lwnotice ("NURBS evaluation failed: weight sum too small (%g)" , weight_sum );
322
+ return LW_FAILURE ;
224
323
}
225
324
325
+ /* Normalize by weight sum for rational curves */
326
+ pt -> x /= weight_sum ;
327
+ pt -> y /= weight_sum ;
328
+ if (hasz ) pt -> z /= weight_sum ;
329
+ if (hasm ) pt -> m /= weight_sum ;
330
+
331
+ lwnotice ("NURBS evaluated to point (%g, %g)" , pt -> x , pt -> y );
226
332
return LW_SUCCESS ;
227
333
}
228
334
@@ -412,21 +518,65 @@ lwnurbs_uniform_knots(uint32_t degree, uint32_t nctrl)
412
518
double *
413
519
lwnurbs_clamped_knots (uint32_t degree , uint32_t nctrl )
414
520
{
521
+ if (degree < 1 || nctrl < 2 )
522
+ {
523
+ lwnotice ("lwnurbs_clamped_knots: invalid parameters degree=%d, nctrl=%d" , degree , nctrl );
524
+ return NULL ;
525
+ }
526
+
415
527
uint32_t nknots = nctrl + degree + 1 ;
416
528
double * knots = lwalloc (sizeof (double ) * nknots );
417
529
418
- /* Clamp start */
530
+ if (!knots )
531
+ {
532
+ lwnotice ("lwnurbs_clamped_knots: failed to allocate memory for %d knots" , nknots );
533
+ return NULL ;
534
+ }
535
+
536
+ lwnotice ("lwnurbs_clamped_knots: generating %d knots for degree=%d, nctrl=%d" ,
537
+ nknots , degree , nctrl );
538
+
539
+ /* Clamp start: first (degree+1) knots = 0.0 */
419
540
for (uint32_t i = 0 ; i <= degree ; i ++ )
420
541
knots [i ] = 0.0 ;
421
542
422
- /* Internal knots */
543
+ /* Internal knots: linearly spaced between 0 and 1 */
423
544
for (uint32_t i = degree + 1 ; i < nctrl ; i ++ )
545
+ {
424
546
knots [i ] = (double )(i - degree ) / (double )(nctrl - degree );
547
+ }
425
548
426
- /* Clamp end */
549
+ /* Clamp end: last (degree+1) knots = 1.0 */
427
550
for (uint32_t i = nctrl ; i < nknots ; i ++ )
428
551
knots [i ] = 1.0 ;
429
552
553
+ /* Debug: print the knot vector */
554
+ lwnotice ("lwnurbs_clamped_knots: generated knots:" );
555
+ for (uint32_t i = 0 ; i < nknots ; i ++ )
556
+ {
557
+ if (i < 10 || i >= nknots - 5 ) // Print first 10 and last 5
558
+ {
559
+ lwnotice (" knots[%d] = %g" , i , knots [i ]);
560
+ }
561
+ else if (i == 10 )
562
+ {
563
+ lwnotice (" ... (%d more knots) ..." , nknots - 15 );
564
+ }
565
+ }
566
+
567
+ /* Validate the knot vector */
568
+ for (uint32_t i = 1 ; i < nknots ; i ++ )
569
+ {
570
+ if (knots [i ] < knots [i - 1 ])
571
+ {
572
+ lwnotice ("lwnurbs_clamped_knots: ERROR - non-monotonic knots at index %d: %g < %g" ,
573
+ i , knots [i ], knots [i - 1 ]);
574
+ lwfree (knots );
575
+ return NULL ;
576
+ }
577
+ }
578
+
579
+ lwnotice ("lwnurbs_clamped_knots: knot vector generated successfully" );
430
580
return knots ;
431
581
}
432
582
0 commit comments