11
11
namespace webifc ::geometry{
12
12
13
13
void Nurbs::fill_geometry (){
14
+ if (!_initialized) {
15
+ return ;
16
+ }
14
17
auto uv_points {this ->get_uv_points ()};
15
18
auto indices {get_triangulation_uv_points (uv_points)};
16
19
@@ -78,14 +81,89 @@ namespace webifc::geometry{
78
81
this ->init ();
79
82
}
80
83
81
- void Nurbs::init (){
84
+ void Nurbs::init () {
85
+ // Check that the control point grid has sufficient dimensions.
86
+ // We need at least (degree + 1) control points in each direction.
87
+ if (this ->num_u < static_cast <size_t >(this ->bspline_surface .UDegree ) + 1 ) {
88
+ spdlog::error (" Insufficient control point rows: num_u = {} but UDegree = {} requires at least {} rows" ,
89
+ this ->num_u , this ->bspline_surface .UDegree , this ->bspline_surface .UDegree + 1 );
90
+ return ; // Or throw an exception.
91
+ }
92
+ if (this ->num_v < static_cast <size_t >(this ->bspline_surface .VDegree ) + 1 ) {
93
+ spdlog::error (" Insufficient control point columns: num_v = {} but VDegree = {} requires at least {} columns" ,
94
+ this ->num_v , this ->bspline_surface .VDegree , this ->bspline_surface .VDegree + 1 );
95
+ return ; // Or throw an exception.
96
+ }
97
+
98
+ // Validate degrees.
99
+ if (this ->bspline_surface .UDegree < 0 || this ->bspline_surface .VDegree < 0 ) {
100
+ spdlog::error (" Invalid degree values: UDegree={}, VDegree={}" ,
101
+ this ->bspline_surface .UDegree , this ->bspline_surface .VDegree );
102
+ return ;
103
+ }
104
+
105
+ // Validate control points count.
106
+ size_t expectedCount = this ->num_u * this ->num_v ;
107
+ auto controlPoints = this ->get_control_points ();
108
+ if (controlPoints.size () != expectedCount) {
109
+ spdlog::error (" Control points count mismatch: expected {}, got {}" , expectedCount, controlPoints.size ());
110
+ return ;
111
+ }
112
+ auto weights = this ->get_weights ();
113
+ if (weights.size () != expectedCount) {
114
+ spdlog::error (" Weights count mismatch: expected {}, got {}" , expectedCount, weights.size ());
115
+ return ;
116
+ }
117
+
118
+ // Create the NURBS surface.
82
119
this ->nurbs = std::make_shared<tinynurbs::RationalSurface3d>(
83
- static_cast <int >(static_cast <uint32_t >(this ->bspline_surface .UDegree )),
84
- static_cast <int >(static_cast <uint32_t >(this ->bspline_surface .VDegree )),
85
- this ->get_knots (this ->bspline_surface .UKnots , this ->bspline_surface .UMultiplicity ),
86
- this ->get_knots (this ->bspline_surface .VKnots , this ->bspline_surface .VMultiplicity ),
87
- tinynurbs::array2<glm::dvec3>{this ->num_u , this ->num_v , this ->get_control_points ()},
88
- tinynurbs::array2<double >{this ->num_u , this ->num_v , this ->get_weights ()});
120
+ static_cast <int >(this ->bspline_surface .UDegree ),
121
+ static_cast <int >(this ->bspline_surface .VDegree ),
122
+ this ->get_knots (this ->bspline_surface .UKnots , this ->bspline_surface .UMultiplicity ),
123
+ this ->get_knots (this ->bspline_surface .VKnots , this ->bspline_surface .VMultiplicity ),
124
+ tinynurbs::array2<glm::dvec3>{this ->num_u , this ->num_v , controlPoints},
125
+ tinynurbs::array2<double >{this ->num_u , this ->num_v , weights}
126
+ );
127
+
128
+ // Check that the knot vectors are large enough.
129
+ if (this ->nurbs ->knots_u .size () < static_cast <size_t >(this ->nurbs ->degree_u + 1 )) {
130
+ spdlog::error (" Invalid knots_u: size {} is less than degree_u+1 ({})" ,
131
+ this ->nurbs ->knots_u .size (), this ->nurbs ->degree_u + 1 );
132
+ return ;
133
+ }
134
+ if (this ->nurbs ->knots_v .size () < static_cast <size_t >(this ->nurbs ->degree_v + 1 )) {
135
+ spdlog::error (" Invalid knots_v: size {} is less than degree_v+1 ({})" ,
136
+ this ->nurbs ->knots_v .size (), this ->nurbs ->degree_v + 1 );
137
+ return ;
138
+ }
139
+
140
+ // Helper lambda to check if a knot vector is monotonic increasing.
141
+ auto check_monotonic = [](const std::vector<double >& knots, const std::string& name) -> bool {
142
+ for (size_t i = 1 ; i < knots.size (); i++) {
143
+ if (knots[i] < knots[i - 1 ]) {
144
+ spdlog::error (" {} is not monotonic increasing at index {} ({} < {})" , name, i, knots[i], knots[i - 1 ]);
145
+ return false ;
146
+ }
147
+ }
148
+ return true ;
149
+ };
150
+
151
+ if (!check_monotonic (this ->nurbs ->knots_u , " knots_u" )) return ;
152
+ if (!check_monotonic (this ->nurbs ->knots_v , " knots_v" )) return ;
153
+
154
+ // Ensure that we have enough knots to set the range.
155
+ if (this ->nurbs ->knots_u .size () <= this ->nurbs ->degree_u ||
156
+ this ->nurbs ->knots_u .size () <= this ->nurbs ->degree_u + 1 ) {
157
+ spdlog::error (" Not enough knots in knots_u to determine range, size={}, degree_u={}" ,
158
+ this ->nurbs ->knots_u .size (), this ->nurbs ->degree_u );
159
+ return ;
160
+ }
161
+ if (this ->nurbs ->knots_v .size () <= this ->nurbs ->degree_v ||
162
+ this ->nurbs ->knots_v .size () <= this ->nurbs ->degree_v + 1 ) {
163
+ spdlog::error (" Not enough knots in knots_v to determine range, size={}, degree_v={}" ,
164
+ this ->nurbs ->knots_v .size (), this ->nurbs ->degree_v );
165
+ return ;
166
+ }
89
167
this ->range_knots_u = {
90
168
this ->nurbs ->knots_u [this ->nurbs ->degree_u ],
91
169
this ->nurbs ->knots_u [this ->nurbs ->knots_u .size () - this ->nurbs ->degree_u - 1 ]
@@ -94,14 +172,21 @@ namespace webifc::geometry{
94
172
this ->nurbs ->knots_v [this ->nurbs ->degree_v ],
95
173
this ->nurbs ->knots_v [this ->nurbs ->knots_v .size () - this ->nurbs ->degree_v - 1 ]
96
174
};
175
+
176
+ // Compute sample surface points.
97
177
this ->ptc = tinynurbs::surfacePoint (*this ->nurbs , 0.0 , 0.0 );
98
178
this ->pth = tinynurbs::surfacePoint (*this ->nurbs , 1.0 , 0.0 );
99
179
this ->ptv = tinynurbs::surfacePoint (*this ->nurbs , 0.0 , 1.0 );
180
+
181
+ // Compute distances for further use.
100
182
this ->dh = glm::distance (ptc, pth);
101
183
this ->dv = glm::distance (ptc, ptv);
102
184
this ->pr = (dh + 1 ) / (dv + 1 );
185
+
186
+ // Scale error tolerances.
103
187
this ->minError /= this ->scaling ;
104
188
this ->maxError /= this ->scaling ;
189
+ _initialized = true ;
105
190
}
106
191
std::vector<double > Nurbs::get_weights () const {
107
192
std::vector<double > result (this ->num_u * this ->num_v );
0 commit comments