| 2283 | } |
| 2284 | |
| 2285 | bool LNLib::NurbsSurface::GlobalApproximation( |
| 2286 | const std::vector<std::vector<XYZ>>& throughPoints, |
| 2287 | int degreeU, |
| 2288 | int degreeV, |
| 2289 | int controlPointsRows, |
| 2290 | int controlPointsColumns, |
| 2291 | LN_NurbsSurface& surface) |
| 2292 | { |
| 2293 | VALIDATE_ARGUMENT(throughPoints.size() > 0, "throughPoints", "ThroughPoints row size must be greater than zero."); |
| 2294 | VALIDATE_ARGUMENT(throughPoints[0].size() > 0, "throughPoints", "ThroughPoints column size must be greater than zero."); |
| 2295 | VALIDATE_ARGUMENT(degreeU > 0 && degreeU <= Constants::NURBSMaxDegree, "degreeU", "Invalid degreeU."); |
| 2296 | VALIDATE_ARGUMENT(degreeV > 0 && degreeV <= Constants::NURBSMaxDegree, "degreeV", "Invalid degreeV."); |
| 2297 | VALIDATE_ARGUMENT(controlPointsRows > degreeV, "controlPointsRows", "Control points rows must be > degreeV."); |
| 2298 | VALIDATE_ARGUMENT(controlPointsColumns > degreeU, "controlPointsColumns", "Control points columns must be > degreeU."); |
| 2299 | |
| 2300 | int dataRows = static_cast<int>(throughPoints.size()); |
| 2301 | int dataCols = static_cast<int>(throughPoints[0].size()); |
| 2302 | |
| 2303 | std::vector<std::vector<XYZ>> tempControlPoints; |
| 2304 | std::vector<double> knotVectorU; |
| 2305 | |
| 2306 | for (int i = 0; i < dataRows; ++i) { |
| 2307 | LN_NurbsCurve curve; |
| 2308 | bool success = NurbsCurve::LeastSquaresApproximation(degreeU, throughPoints[i], controlPointsColumns, curve); |
| 2309 | if (!success) return false; |
| 2310 | |
| 2311 | auto xyzPoints = ControlPointsUtils::ToXYZ(curve.ControlPoints); |
| 2312 | tempControlPoints.push_back(xyzPoints); |
| 2313 | |
| 2314 | if (i == 0) { |
| 2315 | knotVectorU = curve.KnotVector; |
| 2316 | } |
| 2317 | } |
| 2318 | |
| 2319 | std::vector<std::vector<XYZ>> transposed; |
| 2320 | MathUtils::Transpose(tempControlPoints, transposed); |
| 2321 | |
| 2322 | std::vector<std::vector<XYZ>> finalControlPoints; |
| 2323 | std::vector<double> knotVectorV; |
| 2324 | |
| 2325 | for (int j = 0; j < static_cast<int>(transposed.size()); ++j) { |
| 2326 | LN_NurbsCurve curve; |
| 2327 | bool success = NurbsCurve::LeastSquaresApproximation(degreeV, transposed[j], controlPointsRows, curve); |
| 2328 | if (!success) return false; |
| 2329 | |
| 2330 | auto xyzPoints = ControlPointsUtils::ToXYZ(curve.ControlPoints); |
| 2331 | finalControlPoints.push_back(xyzPoints); |
| 2332 | |
| 2333 | if (j == 0) { |
| 2334 | knotVectorV = curve.KnotVector; |
| 2335 | } |
| 2336 | } |
| 2337 | |
| 2338 | std::vector<std::vector<XYZ>> surfaceControlPoints; |
| 2339 | MathUtils::Transpose(finalControlPoints, surfaceControlPoints); |
| 2340 | |
| 2341 | surface.DegreeU = degreeU; |
| 2342 | surface.DegreeV = degreeV; |