00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <pcl/surface/on_nurbs/global_optimization_tdm.h>
00039 #include <pcl/surface/on_nurbs/closing_boundary.h>
00040 #include <stdexcept>
00041
00042 using namespace pcl;
00043 using namespace on_nurbs;
00044 using namespace Eigen;
00045
00046 GlobalOptimizationTDM::GlobalOptimizationTDM (const std::vector<NurbsDataSurface*> &data,
00047 const std::vector<ON_NurbsSurface*> &nurbs) :
00048 GlobalOptimization (data, nurbs)
00049 {
00050 }
00051
00052 void
00053 GlobalOptimizationTDM::assemble (Parameter params)
00054 {
00055
00056 m_ncols = 0;
00057 unsigned nnurbs = static_cast<unsigned> (m_nurbs.size ());
00058 unsigned nInt (0), nBnd (0), nCageRegInt (0), nCageRegBnd (0), nCommonBnd (0);
00059 for (unsigned i = 0; i < nnurbs; i++)
00060 {
00061 nInt += static_cast<unsigned> (m_data[i]->interior.size ());
00062 nBnd += static_cast<unsigned> (m_data[i]->boundary.size ());
00063 nCommonBnd += static_cast<unsigned> (m_data[i]->common_boundary_point.size ());
00064 nCageRegInt += (m_nurbs[i]->m_cv_count[0] - 2) * (m_nurbs[i]->m_cv_count[1] - 2);
00065 nCageRegBnd += 2 * (m_nurbs[i]->m_cv_count[0] - 1) + 2 * (m_nurbs[i]->m_cv_count[1] - 1);
00066 m_ncols += m_nurbs[i]->CVCount ();
00067 }
00068
00069 m_nrows = 0;
00070 if (params.interior_weight > 0.0)
00071 m_nrows += nInt;
00072 if (params.boundary_weight > 0.0)
00073 m_nrows += nBnd;
00074 if (params.interior_smoothness > 0.0)
00075 m_nrows += nCageRegInt;
00076 if (params.boundary_smoothness > 0.0)
00077 m_nrows += nCageRegBnd;
00078 if (params.closing_weight > 0.0)
00079 {
00080 if (params.closing_samples > 0)
00081 m_nrows += (4 * params.closing_samples);
00082 else
00083 m_nrows += nBnd;
00084 }
00085 if (params.common_weight > 0.0)
00086 m_nrows += nCommonBnd;
00087
00088 m_nrows *= 3;
00089 m_ncols *= 3;
00090
00091 m_solver.assign (m_nrows, m_ncols, 1);
00092
00093 for (unsigned i = 0; i < m_data.size (); i++)
00094 m_data[i]->common_boundary_param.clear ();
00095
00096
00097 unsigned row (0);
00098 int ncps (0);
00099
00100 for (unsigned id = 0; id < nnurbs; id++)
00101 {
00102
00103
00104 assembleInteriorPoints (id, ncps, params.interior_weight, row);
00105
00106
00107 assembleBoundaryPoints (id, ncps, params.boundary_weight, row);
00108
00109
00110 assembleRegularisation (id, ncps, params.interior_smoothness, params.boundary_smoothness, row);
00111
00112
00113 assembleClosingBoundaries (id, params.closing_samples, params.closing_sigma, params.closing_weight, row);
00114
00115
00116 assembleCommonBoundaries (id, params.common_weight, row);
00117
00118 ncps += m_nurbs[id]->CVCount ();
00119 }
00120 }
00121
00122 void
00123 GlobalOptimizationTDM::assemble (ParameterTDM params)
00124 {
00125
00126 m_ncols = 0;
00127 unsigned nnurbs = static_cast<unsigned> (m_nurbs.size ());
00128 unsigned nInt (0), nBnd (0), nCageRegInt (0), nCageRegBnd (0), nCommonBnd (0), nCommonPar (0);
00129 for (unsigned i = 0; i < nnurbs; i++)
00130 {
00131 nInt += static_cast<unsigned> (m_data[i]->interior.size ());
00132 nBnd += static_cast<unsigned> (m_data[i]->boundary.size ());
00133 nCommonBnd += static_cast<unsigned> (m_data[i]->common_boundary_point.size ());
00134 nCommonPar += static_cast<unsigned> (m_data[i]->common_idx.size ());
00135 nCageRegInt += (m_nurbs[i]->m_cv_count[0] - 2) * (m_nurbs[i]->m_cv_count[1] - 2);
00136 nCageRegBnd += 2 * (m_nurbs[i]->m_cv_count[0] - 1) + 2 * (m_nurbs[i]->m_cv_count[1] - 1);
00137 m_ncols += m_nurbs[i]->CVCount ();
00138 }
00139
00140 m_nrows = 0;
00141 if (params.interior_weight > 0.0)
00142 m_nrows += nInt;
00143 if (params.boundary_weight > 0.0)
00144 m_nrows += nBnd;
00145 if (params.interior_smoothness > 0.0)
00146 m_nrows += nCageRegInt;
00147 if (params.boundary_smoothness > 0.0)
00148 m_nrows += nCageRegBnd;
00149 if (params.closing_weight > 0.0)
00150 {
00151 if (params.closing_samples > 0)
00152 m_nrows += (4 * params.closing_samples) * nnurbs * (nnurbs - 1);
00153 else
00154 m_nrows += nBnd;
00155 }
00156 if (params.common_weight > 0.0)
00157 {
00158 m_nrows += nCommonBnd;
00159 m_nrows += nCommonPar;
00160 }
00161
00162 m_nrows *= 3;
00163 m_ncols *= 3;
00164
00165 m_solver.assign (m_nrows, m_ncols, 1);
00166
00167
00168
00169
00170
00171 unsigned row (0);
00172 int ncps (0);
00173
00174 for (unsigned id = 0; id < nnurbs; id++)
00175 {
00176
00177
00178 assembleInteriorPointsTD (id, ncps, params.interior_tangent_weight, params.interior_weight, row);
00179
00180
00181 assembleBoundaryPoints (id, ncps, params.boundary_weight, row);
00182
00183
00184 assembleRegularisation (id, ncps, params.interior_smoothness, params.boundary_smoothness, row);
00185
00186
00187 assembleClosingBoundariesTD (id, params.closing_samples, params.closing_sigma, params.closing_tangent_weight,
00188 params.closing_weight, row);
00189
00190
00191
00192
00193 assembleCommonParams (id, params.common_weight, row);
00194
00195 ncps += m_nurbs[id]->CVCount ();
00196 }
00197 }
00198
00199 void
00200 GlobalOptimizationTDM::solve (double damp)
00201 {
00202 if (m_solver.solve ())
00203 updateSurf (damp);
00204 }
00205
00206 void
00207 GlobalOptimizationTDM::updateSurf (double damp)
00208 {
00209 int ncps (0);
00210
00211 for (unsigned i = 0; i < m_nurbs.size (); i++)
00212 {
00213 ON_NurbsSurface* nurbs = m_nurbs[i];
00214
00215 int ncp = nurbs->CVCount ();
00216
00217 for (int A = 0; A < ncp; A++)
00218 {
00219
00220 int I = gl2gr (*nurbs, A);
00221 int J = gl2gc (*nurbs, A);
00222
00223 ON_3dPoint cp_prev;
00224 nurbs->GetCV (I, J, cp_prev);
00225
00226 ON_3dPoint cp;
00227 cp.x = cp_prev.x + damp * (m_solver.x (3 * (ncps + A) + 0, 0) - cp_prev.x);
00228 cp.y = cp_prev.y + damp * (m_solver.x (3 * (ncps + A) + 1, 0) - cp_prev.y);
00229 cp.z = cp_prev.z + damp * (m_solver.x (3 * (ncps + A) + 2, 0) - cp_prev.z);
00230
00231 nurbs->SetCV (I, J, cp);
00232 }
00233
00234 ncps += ncp;
00235 }
00236 }
00237
00238 void
00239 GlobalOptimizationTDM::assembleCommonParams (unsigned id1, double weight, unsigned &row)
00240 {
00241 if (weight <= 0.0)
00242 return;
00243
00244 NurbsDataSurface *data = m_data[id1];
00245
00246
00247 for (size_t i = 0; i < data->common_idx.size (); i++)
00248 {
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 addParamConstraint (Eigen::Vector2i (id1, data->common_idx[i]), data->common_param1[i], data->common_param2[i],
00259 weight, row);
00260 }
00261 }
00262
00263 void
00264 GlobalOptimizationTDM::assembleCommonBoundaries (unsigned id1, double weight, unsigned &row)
00265 {
00266 if (weight <= 0.0)
00267 return;
00268
00269
00270 Eigen::Vector3d p1, tu1, tv1, p2, tu2, tv2, t1, t2;
00271 Eigen::Vector2d params1, params2;
00272 double error1, error2;
00273 NurbsDataSurface *data1 = m_data[id1];
00274 ON_NurbsSurface* nurbs1 = m_nurbs[id1];
00275
00276 if (nurbs1->m_order[0] != nurbs1->m_order[1])
00277 printf ("[GlobalOptimizationTDM::assembleCommonBoundaries] Warning, order in u and v direction differ (nurbs1).\n");
00278
00279 for (unsigned i = 0; i < data1->common_boundary_point.size (); i++)
00280 {
00281 Eigen::Vector3d p0 = data1->common_boundary_point[i];
00282 Eigen::Vector2i id (id1, data1->common_boundary_idx[i]);
00283
00284 if (id (1) < 0 || id (1) >= static_cast<int> (m_nurbs.size ()))
00285 throw std::runtime_error (
00286 "[GlobalOptimizationTDM::assembleCommonBoundaries] Error, common boundary index out of bounds.\n");
00287
00288 ON_NurbsSurface* nurbs2 = m_nurbs[id (1)];
00289 double w (1.0);
00290
00291 if (nurbs2->m_order[0] != nurbs2->m_order[1])
00292 printf (
00293 "[GlobalOptimizationTDM::assembleCommonBoundaries] Warning, order in u and v direction differ (nurbs2).\n");
00294
00295 if (nurbs1->m_order[0] == nurbs2->m_order[0])
00296 {
00297 params1 = FittingSurface::inverseMappingBoundary (*m_nurbs[id (0)], p0, error1, p1, tu1, tv1, im_max_steps,
00298 im_accuracy, true);
00299 params2 = FittingSurface::inverseMappingBoundary (*m_nurbs[id (1)], p0, error2, p2, tu2, tv2, im_max_steps,
00300 im_accuracy, true);
00301
00302 if (params1 (0) == 0.0 || params1 (0) == 1.0)
00303 t1 = tv1;
00304 if (params1 (1) == 0.0 || params1 (1) == 1.0)
00305 t1 = tu1;
00306 if (params2 (0) == 0.0 || params2 (0) == 1.0)
00307 t2 = tv2;
00308 if (params2 (1) == 0.0 || params2 (1) == 1.0)
00309 t2 = tu2;
00310
00311 t1.normalize ();
00312 t2.normalize ();
00313
00314
00315 w = t1.dot (t2);
00316 if (w < 0.0)
00317 w = -w;
00318 }
00319 else
00320 {
00321
00322 if (nurbs1->m_order[0] < nurbs2->m_order[0])
00323 {
00324 params1 = FittingSurface::findClosestElementMidPoint (*m_nurbs[id (0)], p0);
00325 params1 = FittingSurface::inverseMapping (*m_nurbs[id (0)], p0, params1, error1, p1, tu1, tv1, im_max_steps,
00326 im_accuracy, true);
00327 params2 = FittingSurface::inverseMappingBoundary (*m_nurbs[id (1)], p0, error2, p2, tu2, tv2, im_max_steps,
00328 im_accuracy, true);
00329 }
00330 else
00331 {
00332 params1 = FittingSurface::inverseMappingBoundary (*m_nurbs[id (0)], p0, error1, p1, tu1, tv1, im_max_steps,
00333 im_accuracy, true);
00334 params2 = FittingSurface::findClosestElementMidPoint (*m_nurbs[id (1)], p0);
00335 params2 = FittingSurface::inverseMapping (*m_nurbs[id (1)], p0, params2, error2, p2, tu2, tv2, im_max_steps,
00336 im_accuracy);
00337 }
00338
00339 }
00340
00341
00342
00343
00344 m_data[id (0)]->common_boundary_param.push_back (params1);
00345 m_data[id (1)]->common_boundary_param.push_back (params2);
00346
00347
00348
00349 addParamConstraint (id, params1, params2, weight * w, row);
00350
00351 }
00352 }
00353
00354 void
00355 GlobalOptimizationTDM::assembleClosingBoundaries (unsigned id, unsigned samples, double sigma, double weight,
00356 unsigned &row)
00357 {
00358 if (weight <= 0.0 || samples <= 0 || sigma < 0.0)
00359 return;
00360
00361 double ds = 1.0 / (2.0 * sigma * sigma);
00362
00363 ON_NurbsSurface *nurbs1 = m_nurbs[id];
00364
00365
00366 vector_vec3d boundary1, boundary2;
00367 vector_vec2d params1, params2;
00368 ClosingBoundary::sampleFromBoundary (nurbs1, boundary1, params1, samples);
00369
00370
00371 for (unsigned n2 = (id + 1); n2 < m_nurbs.size (); n2++)
00372 {
00373 ON_NurbsSurface *nurbs2 = m_nurbs[n2];
00374
00375
00376 for (unsigned i = 0; i < boundary1.size (); i++)
00377 {
00378 double error;
00379 Eigen::Vector3d p, tu, tv;
00380 Eigen::Vector2d params;
00381 Eigen::Vector3d p0 = boundary1[i];
00382
00383 params = FittingSurface::inverseMappingBoundary (*nurbs2, p0, error, p, tu, tv, im_max_steps, im_accuracy, true);
00384
00385
00386
00387
00388
00389
00390 double w = weight * exp (-(error * error) * ds);
00391 addParamConstraint (Eigen::Vector2i (id, n2), params1[i], params, w, row);
00392
00393 }
00394 }
00395 }
00396
00397 void
00398 GlobalOptimizationTDM::assembleClosingBoundariesTD (unsigned id, unsigned samples, double sigma, double wTangent,
00399 double weight, unsigned &row)
00400 {
00401 if (weight <= 0.0 || samples <= 0 || sigma < 0.0)
00402 return;
00403
00404 double ds = 1.0 / (2.0 * sigma * sigma);
00405
00406 ON_NurbsSurface *nurbs1 = m_nurbs[id];
00407
00408
00409 vector_vec3d boundary1, boundary2;
00410 vector_vec2d params1, params2;
00411 ClosingBoundary::sampleFromBoundary (nurbs1, boundary1, params1, samples);
00412
00413
00414
00415 for (unsigned n2 = 0; n2 < m_nurbs.size (); n2++)
00416 {
00417 if (id == n2)
00418 continue;
00419 ON_NurbsSurface *nurbs2 = m_nurbs[n2];
00420
00421
00422 for (unsigned i = 0; i < boundary1.size (); i++)
00423 {
00424 double error;
00425 Eigen::Vector3d p, n, tu, tv;
00426 Eigen::Vector2d params;
00427 Eigen::Vector3d p0 = boundary1[i];
00428
00429 params = FittingSurface::inverseMappingBoundary (*nurbs2, p0, error, p, tu, tv, im_max_steps, im_accuracy, true);
00430
00431 tu.normalize ();
00432 tv.normalize ();
00433 n = tu.cross (tv);
00434
00435
00436
00437
00438
00439
00440 double w = weight * exp (-(error * error) * ds);
00441 addParamConstraintTD (Eigen::Vector2i (id, n2), params1[i], params, n, tu, tv, wTangent, w, row);
00442
00443 }
00444 }
00445 }
00446
00447 void
00448 GlobalOptimizationTDM::assembleInteriorPoints (unsigned id, int ncps, double weight, unsigned &row)
00449 {
00450 if (weight <= 0.0)
00451 return;
00452
00453 ON_NurbsSurface *nurbs = m_nurbs[id];
00454 NurbsDataSurface *data = m_data[id];
00455 unsigned nInt = static_cast<unsigned> (m_data[id]->interior.size ());
00456
00457
00458 data->interior_line_start.clear ();
00459 data->interior_line_end.clear ();
00460 data->interior_error.clear ();
00461 data->interior_normals.clear ();
00462
00463
00464 for (unsigned p = 0; p < nInt; p++)
00465 {
00466 Vector3d pcp;
00467 pcp (0) = data->interior[p] (0);
00468 pcp (1) = data->interior[p] (1);
00469 pcp (2) = data->interior[p] (2);
00470
00471
00472 Vector2d params;
00473 Vector3d pt, tu, tv, n;
00474 double error;
00475 if (p < data->interior_param.size ())
00476 {
00477 params = FittingSurface::inverseMapping (*nurbs, pcp, data->interior_param[p], error, pt, tu, tv, im_max_steps,
00478 im_accuracy);
00479 data->interior_param[p] = params;
00480 }
00481 else
00482 {
00483 params = FittingSurface::findClosestElementMidPoint (*m_nurbs[id], pcp);
00484 params = FittingSurface::inverseMapping (*m_nurbs[id], pcp, params, error, pt, tu, tv, im_max_steps, im_accuracy);
00485 data->interior_param.push_back (params);
00486 }
00487 data->interior_error.push_back (error);
00488
00489 n = tu.cross (tv);
00490 n.normalize ();
00491
00492 data->interior_normals.push_back (n);
00493 data->interior_line_start.push_back (pcp);
00494 data->interior_line_end.push_back (pt);
00495
00496 addPointConstraint (id, ncps, params, pcp, weight, row);
00497 }
00498 }
00499
00500 void
00501 GlobalOptimizationTDM::assembleInteriorPointsTD (unsigned id, int ncps, double wTangent, double weight, unsigned &row)
00502 {
00503 if (weight <= 0.0)
00504 return;
00505
00506 ON_NurbsSurface *nurbs = m_nurbs[id];
00507 NurbsDataSurface *data = m_data[id];
00508 unsigned nInt = static_cast<unsigned> (m_data[id]->interior.size ());
00509
00510
00511 data->interior_line_start.clear ();
00512 data->interior_line_end.clear ();
00513 data->interior_error.clear ();
00514 data->interior_normals.clear ();
00515
00516
00517 for (unsigned p = 0; p < nInt; p++)
00518 {
00519 Vector3d pcp;
00520 pcp (0) = data->interior[p] (0);
00521 pcp (1) = data->interior[p] (1);
00522 pcp (2) = data->interior[p] (2);
00523
00524
00525 Vector2d params;
00526 Vector3d pt, tu, tv, n;
00527 double error;
00528 if (p < data->interior_param.size ())
00529 {
00530 params = FittingSurface::inverseMapping (*nurbs, pcp, data->interior_param[p], error, pt, tu, tv, im_max_steps,
00531 im_accuracy);
00532 data->interior_param[p] = params;
00533 }
00534 else
00535 {
00536 params = FittingSurface::findClosestElementMidPoint (*m_nurbs[id], pcp);
00537 params = FittingSurface::inverseMapping (*m_nurbs[id], pcp, params, error, pt, tu, tv, im_max_steps, im_accuracy);
00538 data->interior_param.push_back (params);
00539 }
00540 data->interior_error.push_back (error);
00541
00542 tu.normalize ();
00543 tv.normalize ();
00544 n = tu.cross (tv);
00545
00546 data->interior_normals.push_back (n);
00547 data->interior_line_start.push_back (pcp);
00548 data->interior_line_end.push_back (pt);
00549
00550 addPointConstraintTD (id, ncps, params, pcp, n, tu, tv, wTangent, weight, row);
00551 }
00552 }
00553
00554 void
00555 GlobalOptimizationTDM::assembleBoundaryPoints (unsigned id, int ncps, double weight, unsigned &row)
00556 {
00557 if (weight <= 0.0)
00558 return;
00559
00560 ON_NurbsSurface *nurbs = m_nurbs[id];
00561 NurbsDataSurface *data = m_data[id];
00562 unsigned nBnd = static_cast<unsigned> (m_data[id]->boundary.size ());
00563
00564
00565 data->boundary_line_start.clear ();
00566 data->boundary_line_end.clear ();
00567 data->boundary_error.clear ();
00568 data->boundary_normals.clear ();
00569 data->boundary_param.clear ();
00570
00571 for (unsigned p = 0; p < nBnd; p++)
00572 {
00573 Vector3d pcp;
00574 pcp (0) = data->boundary[p] (0);
00575 pcp (1) = data->boundary[p] (1);
00576 pcp (2) = data->boundary[p] (2);
00577
00578
00579 Vector3d pt, tu, tv, n;
00580 double error;
00581
00582 Vector2d params =
00583 FittingSurface::inverseMappingBoundary (*nurbs, pcp, error, pt, tu, tv, im_max_steps, im_accuracy);
00584 data->boundary_error.push_back (error);
00585
00586 if (p < data->boundary_param.size ())
00587 {
00588 data->boundary_param[p] = params;
00589 }
00590 else
00591 {
00592 data->boundary_param.push_back (params);
00593 }
00594
00595 n = tu.cross (tv);
00596 n.normalize ();
00597
00598 data->boundary_normals.push_back (n);
00599 data->boundary_line_start.push_back (pcp);
00600 data->boundary_line_end.push_back (pt);
00601
00602 addPointConstraint (id, ncps, params, pcp, weight, row);
00603 }
00604 }
00605
00606 void
00607 GlobalOptimizationTDM::assembleRegularisation (unsigned id, int ncps, double wCageRegInt, double wCageRegBnd,
00608 unsigned &row)
00609 {
00610 if (wCageRegBnd <= 0.0 || wCageRegInt <= 0.0)
00611 {
00612 printf ("[GlobalOptimizationTDM::assembleRegularisation] Warning, no regularisation may lead "
00613 "to under-determined equation system. Add cage regularisation (smoothing) to avoid.\n");
00614 }
00615
00616 if (wCageRegInt > 0.0)
00617 addCageInteriorRegularisation (id, ncps, wCageRegInt, row);
00618
00619 if (wCageRegBnd > 0.0)
00620 {
00621 addCageBoundaryRegularisation (id, ncps, wCageRegBnd, NORTH, row);
00622 addCageBoundaryRegularisation (id, ncps, wCageRegBnd, SOUTH, row);
00623 addCageBoundaryRegularisation (id, ncps, wCageRegBnd, WEST, row);
00624 addCageBoundaryRegularisation (id, ncps, wCageRegBnd, EAST, row);
00625 addCageCornerRegularisation (id, ncps, wCageRegBnd * 2.0, row);
00626 }
00627 }
00628
00629 void
00630 GlobalOptimizationTDM::addParamConstraint (const Eigen::Vector2i &id, const Eigen::Vector2d ¶ms1,
00631 const Eigen::Vector2d ¶ms2, double weight, unsigned &row)
00632 {
00633 vector_vec2d params;
00634 params.push_back (params1);
00635 params.push_back (params2);
00636
00637 for (unsigned n = 0; n < 2; n++)
00638 {
00639 ON_NurbsSurface* nurbs = m_nurbs[id (n)];
00640
00641 double *N0 = new double[nurbs->m_order[0] * nurbs->m_order[0]];
00642 double *N1 = new double[nurbs->m_order[1] * nurbs->m_order[1]];
00643
00644 int E = ON_NurbsSpanIndex (nurbs->m_order[0], nurbs->m_cv_count[0], nurbs->m_knot[0], params[n] (0), 0, 0);
00645 int F = ON_NurbsSpanIndex (nurbs->m_order[1], nurbs->m_cv_count[1], nurbs->m_knot[1], params[n] (1), 0, 0);
00646
00647
00648
00649
00650
00651 int ncps (0);
00652 for (int i = 0; i < id (n); i++)
00653 ncps += m_nurbs[i]->CVCount ();
00654
00655 ON_EvaluateNurbsBasis (nurbs->m_order[0], nurbs->m_knot[0] + E, params[n] (0), N0);
00656 ON_EvaluateNurbsBasis (nurbs->m_order[1], nurbs->m_knot[1] + F, params[n] (1), N1);
00657
00658 double s (1.0);
00659 n == 0 ? s = 1.0 : s = -1.0;
00660
00661 for (int i = 0; i < nurbs->m_order[0]; i++)
00662 {
00663 for (int j = 0; j < nurbs->m_order[1]; j++)
00664 {
00665
00666 double val = weight * N0[i] * N1[j] * s;
00667 unsigned ci = 3 * (ncps + lrc2gl (*nurbs, E, F, i, j));
00668
00669 m_solver.K (row + 0, ci + 0, val);
00670 m_solver.K (row + 1, ci + 1, val);
00671 m_solver.K (row + 2, ci + 2, val);
00672
00673 }
00674 }
00675
00676 delete [] N1;
00677 delete [] N0;
00678 }
00679
00680 row += 3;
00681
00682
00683
00684 }
00685
00686 void
00687 GlobalOptimizationTDM::addParamConstraintTD (const Eigen::Vector2i &id, const Eigen::Vector2d ¶ms1,
00688 const Eigen::Vector2d ¶ms2, const Eigen::Vector3d &n,
00689 const Eigen::Vector3d &tu, const Eigen::Vector3d &tv,
00690 double tangent_weight, double weight, unsigned &row)
00691 {
00692 vector_vec2d params;
00693 params.push_back (params1);
00694 params.push_back (params2);
00695
00696 Eigen::Vector3d td = n + tangent_weight * tu + tangent_weight * tv;
00697
00698 for (unsigned n = 0; n < 2; n++)
00699 {
00700 ON_NurbsSurface* nurbs = m_nurbs[id (n)];
00701
00702 double *N0 = new double[nurbs->m_order[0] * nurbs->m_order[0]];
00703 double *N1 = new double[nurbs->m_order[1] * nurbs->m_order[1]];
00704
00705 int E = ON_NurbsSpanIndex (nurbs->m_order[0], nurbs->m_cv_count[0], nurbs->m_knot[0], params[n] (0), 0, 0);
00706 int F = ON_NurbsSpanIndex (nurbs->m_order[1], nurbs->m_cv_count[1], nurbs->m_knot[1], params[n] (1), 0, 0);
00707
00708
00709
00710
00711
00712 int ncps (0);
00713 for (int i = 0; i < id (n); i++)
00714 ncps += m_nurbs[i]->CVCount ();
00715
00716 ON_EvaluateNurbsBasis (nurbs->m_order[0], nurbs->m_knot[0] + E, params[n] (0), N0);
00717 ON_EvaluateNurbsBasis (nurbs->m_order[1], nurbs->m_knot[1] + F, params[n] (1), N1);
00718
00719 double s (1.0);
00720 n == 0 ? s = 1.0 : s = -1.0;
00721
00722 for (int i = 0; i < nurbs->m_order[0]; i++)
00723 {
00724 for (int j = 0; j < nurbs->m_order[1]; j++)
00725 {
00726
00727 double val = weight * N0[i] * N1[j] * s;
00728 unsigned ci = 3 * (ncps + lrc2gl (*nurbs, E, F, i, j));
00729
00730 m_solver.K (row + 0, ci + 0, td (0) * val);
00731 m_solver.K (row + 1, ci + 1, td (1) * val);
00732 m_solver.K (row + 2, ci + 2, td (2) * val);
00733
00734 }
00735 }
00736
00737 delete [] N1;
00738 delete [] N0;
00739 }
00740
00741 row += 3;
00742
00743
00744
00745 }
00746
00747 void
00748 GlobalOptimizationTDM::addPointConstraint (unsigned id, int ncps, const Eigen::Vector2d ¶ms,
00749 const Eigen::Vector3d &point, double weight, unsigned &row)
00750 {
00751 ON_NurbsSurface *nurbs = m_nurbs[id];
00752
00753 double *N0 = new double[nurbs->m_order[0] * nurbs->m_order[0]];
00754 double *N1 = new double[nurbs->m_order[1] * nurbs->m_order[1]];
00755
00756 int E = ON_NurbsSpanIndex (nurbs->m_order[0], nurbs->m_cv_count[0], nurbs->m_knot[0], params (0), 0, 0);
00757 int F = ON_NurbsSpanIndex (nurbs->m_order[1], nurbs->m_cv_count[1], nurbs->m_knot[1], params (1), 0, 0);
00758
00759 ON_EvaluateNurbsBasis (nurbs->m_order[0], nurbs->m_knot[0] + E, params (0), N0);
00760 ON_EvaluateNurbsBasis (nurbs->m_order[1], nurbs->m_knot[1] + F, params (1), N1);
00761
00762 m_solver.f (row + 0, 0, point (0) * weight);
00763 m_solver.f (row + 1, 0, point (1) * weight);
00764 m_solver.f (row + 2, 0, point (2) * weight);
00765
00766 for (int i = 0; i < nurbs->m_order[0]; i++)
00767 {
00768
00769 for (int j = 0; j < nurbs->m_order[1]; j++)
00770 {
00771
00772 double val = weight * N0[i] * N1[j];
00773 unsigned ci = 3 * (ncps + lrc2gl (*nurbs, E, F, i, j));
00774
00775 m_solver.K (row + 0, ci + 0, val);
00776 m_solver.K (row + 1, ci + 1, val);
00777 m_solver.K (row + 2, ci + 2, val);
00778
00779 }
00780
00781 }
00782
00783 row += 3;
00784
00785
00786
00787
00788 delete [] N1;
00789 delete [] N0;
00790 }
00791
00792 void
00793 GlobalOptimizationTDM::addPointConstraintTD (unsigned id, int ncps, const Eigen::Vector2d ¶ms,
00794 const Eigen::Vector3d &p, const Eigen::Vector3d &n,
00795 const Eigen::Vector3d &tu, const Eigen::Vector3d &tv,
00796 double tangent_weight, double weight, unsigned &row)
00797 {
00798 ON_NurbsSurface *nurbs = m_nurbs[id];
00799
00800 double *N0 = new double[nurbs->m_order[0] * nurbs->m_order[0]];
00801 double *N1 = new double[nurbs->m_order[1] * nurbs->m_order[1]];
00802
00803 int E = ON_NurbsSpanIndex (nurbs->m_order[0], nurbs->m_cv_count[0], nurbs->m_knot[0], params (0), 0, 0);
00804 int F = ON_NurbsSpanIndex (nurbs->m_order[1], nurbs->m_cv_count[1], nurbs->m_knot[1], params (1), 0, 0);
00805
00806 ON_EvaluateNurbsBasis (nurbs->m_order[0], nurbs->m_knot[0] + E, params (0), N0);
00807 ON_EvaluateNurbsBasis (nurbs->m_order[1], nurbs->m_knot[1] + F, params (1), N1);
00808
00809 double wt = tangent_weight;
00810 Eigen::Vector3d td = n + wt * tu + wt * tv;
00811
00812 m_solver.f (row + 0, 0, td (0) * p (0) * weight);
00813 m_solver.f (row + 1, 0, td (1) * p (1) * weight);
00814 m_solver.f (row + 2, 0, td (2) * p (2) * weight);
00815
00816 for (int i = 0; i < nurbs->m_order[0]; i++)
00817 {
00818
00819 for (int j = 0; j < nurbs->m_order[1]; j++)
00820 {
00821
00822 double val = weight * N0[i] * N1[j];
00823 unsigned ci = 3 * (ncps + lrc2gl (*nurbs, E, F, i, j));
00824
00825 m_solver.K (row + 0, ci + 0, td (0) * val);
00826 m_solver.K (row + 1, ci + 1, td (1) * val);
00827 m_solver.K (row + 2, ci + 2, td (2) * val);
00828
00829 }
00830
00831 }
00832
00833 row += 3;
00834
00835
00836
00837
00838 delete [] N1;
00839 delete [] N0;
00840 }
00841
00842 void
00843 GlobalOptimizationTDM::addCageInteriorRegularisation (unsigned id, int ncps, double weight, unsigned &row)
00844 {
00845 ON_NurbsSurface *nurbs = m_nurbs[id];
00846
00847 for (int i = 1; i < (nurbs->CVCount (0) - 1); i++)
00848 {
00849 for (int j = 1; j < (nurbs->CVCount (1) - 1); j++)
00850 {
00851
00852
00853
00854
00855
00856 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 0, -4.0 * weight);
00857 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j - 1)) + 0, 1.0 * weight);
00858 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 1)) + 0, 1.0 * weight);
00859 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i - 1, j + 0)) + 0, 1.0 * weight);
00860 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 1, j + 0)) + 0, 1.0 * weight);
00861
00862 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 1, -4.0 * weight);
00863 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j - 1)) + 1, 1.0 * weight);
00864 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 1)) + 1, 1.0 * weight);
00865 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i - 1, j + 0)) + 1, 1.0 * weight);
00866 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 1, j + 0)) + 1, 1.0 * weight);
00867
00868 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 2, -4.0 * weight);
00869 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j - 1)) + 2, 1.0 * weight);
00870 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 1)) + 2, 1.0 * weight);
00871 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i - 1, j + 0)) + 2, 1.0 * weight);
00872 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 1, j + 0)) + 2, 1.0 * weight);
00873
00874 row += 3;
00875 }
00876 }
00877
00878
00879 }
00880
00881 void
00882 GlobalOptimizationTDM::addCageBoundaryRegularisation (unsigned id, int ncps, double weight, int side, unsigned &row)
00883 {
00884 ON_NurbsSurface *nurbs = m_nurbs[id];
00885
00886 int i = 0;
00887 int j = 0;
00888
00889 switch (side)
00890 {
00891 case SOUTH:
00892 j = nurbs->CVCount (1) - 1;
00893 case NORTH:
00894 for (i = 1; i < (nurbs->CVCount (0) - 1); i++)
00895 {
00896
00897
00898
00899
00900
00901 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j)) + 0, -2.0 * weight);
00902 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i - 1, j)) + 0, 1.0 * weight);
00903 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 1, j)) + 0, 1.0 * weight);
00904
00905 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j)) + 1, -2.0 * weight);
00906 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i - 1, j)) + 1, 1.0 * weight);
00907 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 1, j)) + 1, 1.0 * weight);
00908
00909 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j)) + 2, -2.0 * weight);
00910 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i - 1, j)) + 2, 1.0 * weight);
00911 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 1, j)) + 2, 1.0 * weight);
00912
00913 row += 3;
00914 }
00915 break;
00916
00917 case EAST:
00918 i = nurbs->CVCount (0) - 1;
00919 case WEST:
00920 for (j = 1; j < (nurbs->CVCount (1) - 1); j++)
00921 {
00922
00923
00924
00925
00926
00927 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i, j + 0)) + 0, -2.0 * weight);
00928 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i, j - 1)) + 0, 1.0 * weight);
00929 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i, j + 1)) + 0, 1.0 * weight);
00930
00931 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i, j + 0)) + 1, -2.0 * weight);
00932 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i, j - 1)) + 1, 1.0 * weight);
00933 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i, j + 1)) + 1, 1.0 * weight);
00934
00935 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i, j + 0)) + 2, -2.0 * weight);
00936 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i, j - 1)) + 2, 1.0 * weight);
00937 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i, j + 1)) + 2, 1.0 * weight);
00938
00939 row += 3;
00940 }
00941 break;
00942 }
00943
00944
00945 }
00946
00947 void
00948 GlobalOptimizationTDM::addCageCornerRegularisation (unsigned id, int ncps, double weight, unsigned &row)
00949 {
00950 ON_NurbsSurface *nurbs = m_nurbs[id];
00951
00952 {
00953 int i = 0;
00954 int j = 0;
00955
00956
00957
00958
00959
00960 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 0, -2.0 * weight);
00961 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 1, j + 0)) + 0, 1.0 * weight);
00962 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 1)) + 0, 1.0 * weight);
00963
00964 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 1, -2.0 * weight);
00965 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 1, j + 0)) + 1, 1.0 * weight);
00966 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 1)) + 1, 1.0 * weight);
00967
00968 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 2, -2.0 * weight);
00969 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 1, j + 0)) + 2, 1.0 * weight);
00970 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 1)) + 2, 1.0 * weight);
00971
00972 row += 3;
00973 }
00974
00975 {
00976 int i = nurbs->CVCount (0) - 1;
00977 int j = 0;
00978
00979
00980
00981
00982
00983 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 0, -2.0 * weight);
00984 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i - 1, j + 0)) + 0, 1.0 * weight);
00985 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 1)) + 0, 1.0 * weight);
00986
00987 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 1, -2.0 * weight);
00988 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i - 1, j + 0)) + 1, 1.0 * weight);
00989 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 1)) + 1, 1.0 * weight);
00990
00991 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 2, -2.0 * weight);
00992 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i - 1, j + 0)) + 2, 1.0 * weight);
00993 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 1)) + 2, 1.0 * weight);
00994
00995 row += 3;
00996 }
00997
00998 {
00999 int i = nurbs->CVCount (0) - 1;
01000 int j = nurbs->CVCount (1) - 1;
01001
01002
01003
01004
01005
01006 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 0, -2.0 * weight);
01007 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i - 1, j + 0)) + 0, 1.0 * weight);
01008 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j - 1)) + 0, 1.0 * weight);
01009
01010 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 1, -2.0 * weight);
01011 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i - 1, j + 0)) + 1, 1.0 * weight);
01012 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j - 1)) + 1, 1.0 * weight);
01013
01014 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 2, -2.0 * weight);
01015 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i - 1, j + 0)) + 2, 1.0 * weight);
01016 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j - 1)) + 2, 1.0 * weight);
01017
01018 row += 3;
01019 }
01020
01021 {
01022 int i = 0;
01023 int j = nurbs->CVCount (1) - 1;
01024
01025
01026
01027
01028
01029 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 0, -2.0 * weight);
01030 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 1, j + 0)) + 0, 1.0 * weight);
01031 m_solver.K (row + 0, 3 * (ncps + grc2gl (*nurbs, i + 0, j - 1)) + 0, 1.0 * weight);
01032
01033 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 1, -2.0 * weight);
01034 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 1, j + 0)) + 1, 1.0 * weight);
01035 m_solver.K (row + 1, 3 * (ncps + grc2gl (*nurbs, i + 0, j - 1)) + 1, 1.0 * weight);
01036
01037 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j + 0)) + 2, -2.0 * weight);
01038 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 1, j + 0)) + 2, 1.0 * weight);
01039 m_solver.K (row + 2, 3 * (ncps + grc2gl (*nurbs, i + 0, j - 1)) + 2, 1.0 * weight);
01040
01041 row += 3;
01042 }
01043
01044
01045
01046 }
01047