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 <stdexcept>
00039 #include <pcl/surface/on_nurbs/fitting_surface_tdm.h>
00040
00041 using namespace pcl;
00042 using namespace on_nurbs;
00043 using namespace Eigen;
00044
00045 FittingSurfaceTDM::FittingSurfaceTDM (NurbsDataSurface *data, const ON_NurbsSurface &ns) :
00046 FittingSurface (data, ns)
00047 {
00048 }
00049 FittingSurfaceTDM::FittingSurfaceTDM (int order, NurbsDataSurface *data, Eigen::Vector3d z) :
00050 FittingSurface (order, data, z)
00051 {
00052 }
00053
00054 void
00055 FittingSurfaceTDM::assemble (ParameterTDM param)
00056 {
00057 int nBnd = static_cast<int> (m_data->boundary.size ());
00058 int nInt = static_cast<int> (m_data->interior.size ());
00059 int nCurInt = param.regularisation_resU * param.regularisation_resV;
00060 int nCurBnd = 2 * param.regularisation_resU + 2 * param.regularisation_resV;
00061 int nCageReg = (m_nurbs.CVCount (0) - 2) * (m_nurbs.CVCount (1) - 2);
00062 int nCageRegBnd = 2 * (m_nurbs.CVCount (0) - 1) + 2 * (m_nurbs.CVCount (1) - 1);
00063
00064 if (param.boundary_weight <= 0.0)
00065 nBnd = 0;
00066 if (param.interior_weight <= 0.0)
00067 nInt = 0;
00068 if (param.boundary_regularisation <= 0.0)
00069 nCurBnd = 0;
00070 if (param.interior_regularisation <= 0.0)
00071 nCurInt = 0;
00072 if (param.interior_smoothness <= 0.0)
00073 nCageReg = 0;
00074 if (param.boundary_smoothness <= 0.0)
00075 nCageRegBnd = 0;
00076
00077 int ncp = m_nurbs.CVCount (0) * m_nurbs.CVCount (1);
00078 int nrows = nBnd + nInt + nCurInt + nCurBnd + nCageReg + nCageRegBnd;
00079
00080 m_solver.assign (3 * nrows, 3 * ncp, 1);
00081
00082 unsigned row = 0;
00083
00084
00085 if (nBnd > 0)
00086 assembleBoundary (param.boundary_weight, param.boundary_tangent_weight, row);
00087
00088
00089 if (nInt > 0)
00090 assembleInterior (param.interior_weight, param.interior_tangent_weight, row);
00091
00092
00093 if (nCageReg > 0)
00094 addCageInteriorRegularisation (param.interior_smoothness, row);
00095
00096 if (nCageRegBnd > 0)
00097 {
00098 addCageBoundaryRegularisation (param.boundary_smoothness, NORTH, row);
00099 addCageBoundaryRegularisation (param.boundary_smoothness, SOUTH, row);
00100 addCageBoundaryRegularisation (param.boundary_smoothness, WEST, row);
00101 addCageBoundaryRegularisation (param.boundary_smoothness, EAST, row);
00102 addCageCornerRegularisation (param.boundary_smoothness * 2.0, row);
00103 }
00104 }
00105
00106 void
00107 FittingSurfaceTDM::solve (double damp)
00108 {
00109 if (m_solver.solve ())
00110 updateSurf (damp);
00111 }
00112
00113 void
00114 FittingSurfaceTDM::updateSurf (double damp)
00115 {
00116 int ncp = m_nurbs.CVCount (0) * m_nurbs.CVCount (1);
00117
00118 for (int A = 0; A < ncp; A++)
00119 {
00120
00121 int I = gl2gr (A);
00122 int J = gl2gc (A);
00123
00124 ON_3dPoint cp_prev;
00125 m_nurbs.GetCV (I, J, cp_prev);
00126
00127 ON_3dPoint cp;
00128 cp.x = cp_prev.x + damp * (m_solver.x (3 * A + 0, 0) - cp_prev.x);
00129 cp.y = cp_prev.y + damp * (m_solver.x (3 * A + 1, 0) - cp_prev.y);
00130 cp.z = cp_prev.z + damp * (m_solver.x (3 * A + 2, 0) - cp_prev.z);
00131
00132 m_nurbs.SetCV (I, J, cp);
00133
00134 }
00135
00136 }
00137
00138 void
00139 FittingSurfaceTDM::assembleInterior (double wInt, double wTangent, unsigned &row)
00140 {
00141 m_data->interior_line_start.clear ();
00142 m_data->interior_line_end.clear ();
00143 m_data->interior_error.clear ();
00144 m_data->interior_normals.clear ();
00145 unsigned nInt = static_cast<unsigned> (m_data->interior.size ());
00146 for (unsigned p = 0; p < nInt; p++)
00147 {
00148 Vector3d &pcp = m_data->interior[p];
00149
00150
00151 Vector2d params;
00152 Vector3d pt, tu, tv, n;
00153 double error;
00154 if (p < m_data->interior_param.size ())
00155 {
00156 params = inverseMapping (m_nurbs, pcp, m_data->interior_param[p], error, pt, tu, tv, in_max_steps, in_accuracy);
00157 m_data->interior_param[p] = params;
00158 }
00159 else
00160 {
00161 params = FittingSurface::findClosestElementMidPoint (m_nurbs, pcp);
00162 params = inverseMapping (m_nurbs, pcp, params, error, pt, tu, tv, in_max_steps, in_accuracy);
00163 m_data->interior_param.push_back (params);
00164 }
00165 m_data->interior_error.push_back (error);
00166
00167 tu.normalize ();
00168 tv.normalize ();
00169 n = tu.cross (tv);
00170
00171 m_data->interior_normals.push_back (n);
00172 m_data->interior_line_start.push_back (pcp);
00173 m_data->interior_line_end.push_back (pt);
00174
00175 double w (wInt);
00176 if (p < m_data->interior_weight.size ())
00177 w = m_data->interior_weight[p];
00178
00179 addPointConstraint (m_data->interior_param[p], m_data->interior[p], n, tu, tv, wTangent, w, row);
00180 }
00181 }
00182
00183 void
00184 FittingSurfaceTDM::assembleBoundary (double wBnd, double wTangent, unsigned &row)
00185 {
00186 m_data->boundary_line_start.clear ();
00187 m_data->boundary_line_end.clear ();
00188 m_data->boundary_error.clear ();
00189 m_data->boundary_normals.clear ();
00190 unsigned nBnd = static_cast<unsigned> (m_data->boundary.size ());
00191 for (unsigned p = 0; p < nBnd; p++)
00192 {
00193 Vector3d &pcp = m_data->boundary[p];
00194
00195 double error;
00196 Vector3d pt, tu, tv, n;
00197 Vector2d params = inverseMappingBoundary (m_nurbs, pcp, error, pt, tu, tv, in_max_steps, in_accuracy);
00198 m_data->boundary_error.push_back (error);
00199
00200 if (p < m_data->boundary_param.size ())
00201 {
00202 m_data->boundary_param[p] = params;
00203 }
00204 else
00205 {
00206 m_data->boundary_param.push_back (params);
00207 }
00208
00209 tu.normalize ();
00210 tv.normalize ();
00211 n = tu.cross (tv);
00212
00213 m_data->boundary_normals.push_back (n);
00214 m_data->boundary_line_start.push_back (pcp);
00215 m_data->boundary_line_end.push_back (pt);
00216
00217 double w (wBnd);
00218 if (p < m_data->boundary_weight.size ())
00219 w = m_data->boundary_weight[p];
00220
00221 addPointConstraint (m_data->boundary_param[p], m_data->boundary[p], n, tu, tv, wTangent, w, row);
00222 }
00223 }
00224
00225 void
00226 FittingSurfaceTDM::addPointConstraint (const Eigen::Vector2d ¶ms, const Eigen::Vector3d &p,
00227 const Eigen::Vector3d &n, const Eigen::Vector3d &tu, const Eigen::Vector3d &tv,
00228 double tangent_weight, double weight, unsigned &row)
00229 {
00230 double *N0 = new double[m_nurbs.Order (0) * m_nurbs.Order (0)];
00231 double *N1 = new double[m_nurbs.Order (1) * m_nurbs.Order (1)];
00232
00233 int E = ON_NurbsSpanIndex (m_nurbs.Order(0), m_nurbs.CVCount (0), m_nurbs.m_knot[0], params (0), 0, 0);
00234 int F = ON_NurbsSpanIndex (m_nurbs.Order(1), m_nurbs.CVCount (1), m_nurbs.m_knot[1], params (1), 0, 0);
00235
00236 ON_EvaluateNurbsBasis (m_nurbs.Order (0), m_nurbs.m_knot[0] + E, params (0), N0);
00237 ON_EvaluateNurbsBasis (m_nurbs.Order (1), m_nurbs.m_knot[1] + F, params (1), N1);
00238
00239 double wt = tangent_weight;
00240 Eigen::Vector3d td = n + wt * tu + wt * tv;
00241
00242 m_solver.f (row + 0, 0, td (0) * p (0) * weight);
00243 m_solver.f (row + 1, 0, td (1) * p (1) * weight);
00244 m_solver.f (row + 2, 0, td (2) * p (2) * weight);
00245
00246 for (int i = 0; i < m_nurbs.Order (0); i++)
00247 {
00248 for (int j = 0; j < m_nurbs.Order (1); j++)
00249 {
00250
00251 double val = N0[i] * N1[j] * weight;
00252 unsigned ci = 3 * lrc2gl (E, F, i, j);
00253 m_solver.K (row + 0, ci + 0, td (0) * val);
00254 m_solver.K (row + 1, ci + 1, td (1) * val);
00255 m_solver.K (row + 2, ci + 2, td (2) * val);
00256
00257 }
00258 }
00259
00260 row += 3;
00261
00262 delete [] N1;
00263 delete [] N0;
00264 }
00265
00266 void
00267 FittingSurfaceTDM::addCageInteriorRegularisation (double weight, unsigned &row)
00268 {
00269 for (int i = 1; i < (m_nurbs.CVCount (0) - 1); i++)
00270 {
00271 for (int j = 1; j < (m_nurbs.CVCount (1) - 1); j++)
00272 {
00273
00274
00275
00276
00277
00278 m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 0) + 0, -4.0 * weight);
00279 m_solver.K (row + 0, 3 * grc2gl (i + 0, j - 1) + 0, 1.0 * weight);
00280 m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 1) + 0, 1.0 * weight);
00281 m_solver.K (row + 0, 3 * grc2gl (i - 1, j + 0) + 0, 1.0 * weight);
00282 m_solver.K (row + 0, 3 * grc2gl (i + 1, j + 0) + 0, 1.0 * weight);
00283
00284 m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 0) + 1, -4.0 * weight);
00285 m_solver.K (row + 1, 3 * grc2gl (i + 0, j - 1) + 1, 1.0 * weight);
00286 m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 1) + 1, 1.0 * weight);
00287 m_solver.K (row + 1, 3 * grc2gl (i - 1, j + 0) + 1, 1.0 * weight);
00288 m_solver.K (row + 1, 3 * grc2gl (i + 1, j + 0) + 1, 1.0 * weight);
00289
00290 m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 0) + 2, -4.0 * weight);
00291 m_solver.K (row + 2, 3 * grc2gl (i + 0, j - 1) + 2, 1.0 * weight);
00292 m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 1) + 2, 1.0 * weight);
00293 m_solver.K (row + 2, 3 * grc2gl (i - 1, j + 0) + 2, 1.0 * weight);
00294 m_solver.K (row + 2, 3 * grc2gl (i + 1, j + 0) + 2, 1.0 * weight);
00295
00296 row += 3;
00297 }
00298 }
00299 }
00300
00301 void
00302 FittingSurfaceTDM::addCageBoundaryRegularisation (double weight, int side, unsigned &row)
00303 {
00304 int i = 0;
00305 int j = 0;
00306
00307 switch (side)
00308 {
00309 case SOUTH:
00310 j = m_nurbs.CVCount (1) - 1;
00311 case NORTH:
00312 for (i = 1; i < (m_nurbs.CVCount (0) - 1); i++)
00313 {
00314
00315
00316
00317
00318
00319 m_solver.K (row + 0, 3 * grc2gl (i + 0, j) + 0, -2.0 * weight);
00320 m_solver.K (row + 0, 3 * grc2gl (i - 1, j) + 0, 1.0 * weight);
00321 m_solver.K (row + 0, 3 * grc2gl (i + 1, j) + 0, 1.0 * weight);
00322
00323 m_solver.K (row + 1, 3 * grc2gl (i + 0, j) + 1, -2.0 * weight);
00324 m_solver.K (row + 1, 3 * grc2gl (i - 1, j) + 1, 1.0 * weight);
00325 m_solver.K (row + 1, 3 * grc2gl (i + 1, j) + 1, 1.0 * weight);
00326
00327 m_solver.K (row + 2, 3 * grc2gl (i + 0, j) + 2, -2.0 * weight);
00328 m_solver.K (row + 2, 3 * grc2gl (i - 1, j) + 2, 1.0 * weight);
00329 m_solver.K (row + 2, 3 * grc2gl (i + 1, j) + 2, 1.0 * weight);
00330
00331 row += 3;
00332 }
00333 break;
00334
00335 case EAST:
00336 i = m_nurbs.CVCount (0) - 1;
00337 case WEST:
00338 for (j = 1; j < (m_nurbs.CVCount (1) - 1); j++)
00339 {
00340
00341
00342
00343
00344
00345 m_solver.K (row + 0, 3 * grc2gl (i, j + 0) + 0, -2.0 * weight);
00346 m_solver.K (row + 0, 3 * grc2gl (i, j - 1) + 0, 1.0 * weight);
00347 m_solver.K (row + 0, 3 * grc2gl (i, j + 1) + 0, 1.0 * weight);
00348
00349 m_solver.K (row + 1, 3 * grc2gl (i, j + 0) + 1, -2.0 * weight);
00350 m_solver.K (row + 1, 3 * grc2gl (i, j - 1) + 1, 1.0 * weight);
00351 m_solver.K (row + 1, 3 * grc2gl (i, j + 1) + 1, 1.0 * weight);
00352
00353 m_solver.K (row + 2, 3 * grc2gl (i, j + 0) + 2, -2.0 * weight);
00354 m_solver.K (row + 2, 3 * grc2gl (i, j - 1) + 2, 1.0 * weight);
00355 m_solver.K (row + 2, 3 * grc2gl (i, j + 1) + 2, 1.0 * weight);
00356
00357 row += 3;
00358 }
00359 break;
00360 }
00361 }
00362
00363 void
00364 FittingSurfaceTDM::addCageCornerRegularisation (double weight, unsigned &row)
00365 {
00366 {
00367 int i = 0;
00368 int j = 0;
00369
00370
00371
00372
00373
00374 m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 0) + 0, -2.0 * weight);
00375 m_solver.K (row + 0, 3 * grc2gl (i + 1, j + 0) + 0, 1.0 * weight);
00376 m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 1) + 0, 1.0 * weight);
00377
00378 m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 0) + 1, -2.0 * weight);
00379 m_solver.K (row + 1, 3 * grc2gl (i + 1, j + 0) + 1, 1.0 * weight);
00380 m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 1) + 1, 1.0 * weight);
00381
00382 m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 0) + 2, -2.0 * weight);
00383 m_solver.K (row + 2, 3 * grc2gl (i + 1, j + 0) + 2, 1.0 * weight);
00384 m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 1) + 2, 1.0 * weight);
00385
00386 row += 3;
00387
00388 }
00389
00390 {
00391 int i = m_nurbs.CVCount (0) - 1;
00392 int j = 0;
00393
00394
00395
00396
00397
00398 m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 0) + 0, -2.0 * weight);
00399 m_solver.K (row + 0, 3 * grc2gl (i - 1, j + 0) + 0, 1.0 * weight);
00400 m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 1) + 0, 1.0 * weight);
00401
00402 m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 0) + 1, -2.0 * weight);
00403 m_solver.K (row + 1, 3 * grc2gl (i - 1, j + 0) + 1, 1.0 * weight);
00404 m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 1) + 1, 1.0 * weight);
00405
00406 m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 0) + 2, -2.0 * weight);
00407 m_solver.K (row + 2, 3 * grc2gl (i - 1, j + 0) + 2, 1.0 * weight);
00408 m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 1) + 2, 1.0 * weight);
00409
00410 row += 3;
00411 }
00412
00413 {
00414 int i = m_nurbs.CVCount (0) - 1;
00415 int j = m_nurbs.CVCount (1) - 1;
00416
00417
00418
00419
00420
00421 m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 0) + 0, -2.0 * weight);
00422 m_solver.K (row + 0, 3 * grc2gl (i - 1, j + 0) + 0, 1.0 * weight);
00423 m_solver.K (row + 0, 3 * grc2gl (i + 0, j - 1) + 0, 1.0 * weight);
00424
00425 m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 0) + 1, -2.0 * weight);
00426 m_solver.K (row + 1, 3 * grc2gl (i - 1, j + 0) + 1, 1.0 * weight);
00427 m_solver.K (row + 1, 3 * grc2gl (i + 0, j - 1) + 1, 1.0 * weight);
00428
00429 m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 0) + 2, -2.0 * weight);
00430 m_solver.K (row + 2, 3 * grc2gl (i - 1, j + 0) + 2, 1.0 * weight);
00431 m_solver.K (row + 2, 3 * grc2gl (i + 0, j - 1) + 2, 1.0 * weight);
00432
00433 row += 3;
00434 }
00435
00436 {
00437 int i = 0;
00438 int j = m_nurbs.CVCount (1) - 1;
00439
00440
00441
00442
00443
00444 m_solver.K (row + 0, 3 * grc2gl (i + 0, j + 0) + 0, -2.0 * weight);
00445 m_solver.K (row + 0, 3 * grc2gl (i + 1, j + 0) + 0, 1.0 * weight);
00446 m_solver.K (row + 0, 3 * grc2gl (i + 0, j - 1) + 0, 1.0 * weight);
00447
00448 m_solver.K (row + 1, 3 * grc2gl (i + 0, j + 0) + 1, -2.0 * weight);
00449 m_solver.K (row + 1, 3 * grc2gl (i + 1, j + 0) + 1, 1.0 * weight);
00450 m_solver.K (row + 1, 3 * grc2gl (i + 0, j - 1) + 1, 1.0 * weight);
00451
00452 m_solver.K (row + 2, 3 * grc2gl (i + 0, j + 0) + 2, -2.0 * weight);
00453 m_solver.K (row + 2, 3 * grc2gl (i + 1, j + 0), 1.0 * weight);
00454 m_solver.K (row + 2, 3 * grc2gl (i + 0, j - 1) + 2 + 2, 1.0 * weight);
00455
00456 row += 3;
00457 }
00458
00459 }