00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pandabase.h"
00020 #include "pointerTo.h"
00021
00022 #include "curveFitter.h"
00023 #include "config_parametrics.h"
00024 #include "parametricCurve.h"
00025 #include "classicNurbsCurve.h"
00026 #include "hermiteCurve.h"
00027 #include <algorithm>
00028
00029 TypeHandle CurveFitter::_type_handle;
00030
00031
00032
00033
00034
00035
00036 CurveFitter::
00037 CurveFitter() {
00038 _got_xyz = false;
00039 _got_hpr = false;
00040 }
00041
00042
00043
00044
00045
00046
00047 CurveFitter::
00048 ~CurveFitter() {
00049 }
00050
00051
00052
00053
00054
00055
00056
00057 void CurveFitter::
00058 reset() {
00059 _data.erase(_data.begin(), _data.end());
00060 }
00061
00062
00063
00064
00065
00066
00067 void CurveFitter::
00068 add_xyz(float t, const LVecBase3f &xyz) {
00069 DataPoint dp;
00070 dp._t = t;
00071 dp._xyz = xyz;
00072 _data.push_back(dp);
00073 _got_xyz = true;
00074 }
00075
00076
00077
00078
00079
00080
00081 void CurveFitter::
00082 add_hpr(float t, const LVecBase3f &hpr) {
00083 DataPoint dp;
00084 dp._t = t;
00085 dp._hpr = hpr;
00086 _data.push_back(dp);
00087 _got_hpr = true;
00088 }
00089
00090
00091
00092
00093
00094
00095 void CurveFitter::
00096 add_xyz_hpr(float t, const LVecBase3f &xyz, const LVecBase3f &hpr) {
00097 DataPoint dp;
00098 dp._t = t;
00099 dp._xyz = xyz;
00100 dp._hpr = hpr;
00101 _data.push_back(dp);
00102 _got_xyz = true;
00103 _got_hpr = true;
00104 }
00105
00106
00107
00108
00109
00110
00111
00112 int CurveFitter::
00113 get_num_samples() const {
00114 return _data.size();
00115 }
00116
00117
00118
00119
00120
00121
00122 float CurveFitter::
00123 get_sample_t(int n) const {
00124 nassertr(n >= 0 && n < (int)_data.size(), 0.0f);
00125 return _data[n]._t;
00126 }
00127
00128
00129
00130
00131
00132
00133 LVecBase3f CurveFitter::
00134 get_sample_xyz(int n) const {
00135 nassertr(n >= 0 && n < (int)_data.size(), LVecBase3f::zero());
00136 return _data[n]._xyz;
00137 }
00138
00139
00140
00141
00142
00143
00144 LVecBase3f CurveFitter::
00145 get_sample_hpr(int n) const {
00146 nassertr(n >= 0 && n < (int)_data.size(), LVecBase3f::zero());
00147 return _data[n]._hpr;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157 LVecBase3f CurveFitter::
00158 get_sample_tangent(int n) const {
00159 nassertr(n >= 0 && n < (int)_data.size(), LVecBase3f::zero());
00160 return _data[n]._tangent;
00161 }
00162
00163
00164
00165
00166
00167
00168
00169 void CurveFitter::
00170 remove_samples(int begin, int end) {
00171 begin = max(0, min((int)_data.size(), begin));
00172 end = max(0, min((int)_data.size(), end));
00173
00174 nassertv(begin <= end);
00175
00176 _data.erase(_data.begin() + begin, _data.begin() + end);
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 void CurveFitter::
00188 sample(ParametricCurveCollection *curves, int count) {
00189 nassertv(curves != (ParametricCurveCollection *)NULL);
00190 float max_t = curves->get_max_t();
00191 float t, last_t, d;
00192 DataPoint dp;
00193
00194 last_t = 0.0f;
00195 d = 0.0f;
00196 int i;
00197 for (i = 0; i < count; i++) {
00198 t = max_t * (float)i / (float)(count-1);
00199 if (curves->evaluate(t, dp._xyz, dp._hpr)) {
00200 dp._t = t;
00201 _data.push_back(dp);
00202 }
00203 }
00204
00205 if (curves->get_xyz_curve() != (ParametricCurve *)NULL) {
00206 _got_xyz = true;
00207 }
00208 if (curves->get_hpr_curve() != (ParametricCurve *)NULL) {
00209 _got_hpr = true;
00210 }
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void CurveFitter::
00223 wrap_hpr() {
00224 Data::iterator di;
00225 LVecBase3f last(0.0f, 0.0f, 0.0f);
00226 LVecBase3f net(0.0f, 0.0f, 0.0f);
00227
00228 for (di = _data.begin(); di != _data.end(); ++di) {
00229 int i;
00230 for (i = 0; i < 3; i++) {
00231 (*di)._hpr[i] += net[i];
00232
00233 while (((*di)._hpr[i] - last[i]) > 180.0f) {
00234 (*di)._hpr[i] -= 360.0f;
00235 net[i] -= 360.0f;
00236 }
00237
00238 while (((*di)._hpr[i] - last[i]) < -180.0f) {
00239 (*di)._hpr[i] += 360.0f;
00240 net[i] += 360.0f;
00241 }
00242
00243 last[i] = (*di)._hpr[i];
00244 }
00245 }
00246 }
00247
00248
00249
00250
00251
00252
00253
00254 void CurveFitter::
00255 sort_points() {
00256 sort(_data.begin(), _data.end());
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 void CurveFitter::
00268 desample(float factor) {
00269 int in, out;
00270 float count = factor;
00271
00272 out = 0;
00273 for (in = 0; in < (int)_data.size()-1; in++) {
00274 if (count >= factor) {
00275 _data[out] = _data[in];
00276 out++;
00277 count -= factor;
00278 }
00279 count += 1.0f;
00280 }
00281
00282 _data[out] = _data.back();
00283 out++;
00284
00285 _data.erase(_data.begin() + out, _data.end());
00286 }
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 void CurveFitter::
00298 compute_tangents(float scale) {
00299
00300 bool closed = false;
00301
00302 if (_got_xyz) {
00303 closed =
00304 (_data.front()._xyz.almost_equal(_data.back()._xyz, 0.001f));
00305
00306 } else if (_got_hpr) {
00307 closed =
00308 (_data.front()._hpr.almost_equal(_data.back()._hpr, 0.001f));
00309 }
00310
00311 int i;
00312 int len = _data.size();
00313
00314
00315
00316
00317 if (_got_xyz) {
00318 for (i = 1; i < len-1; i++) {
00319 _data[i]._tangent =
00320 (_data[i+1]._xyz - _data[i-1]._xyz) * scale /
00321 (_data[i+1]._t - _data[i-1]._t);
00322 }
00323 }
00324 if (_got_hpr) {
00325 for (i = 1; i < len-1; i++) {
00326 _data[i]._hpr_tangent =
00327 (_data[i+1]._hpr - _data[i-1]._hpr) * scale /
00328 (_data[i+1]._t - _data[i-1]._t);
00329 }
00330 }
00331
00332
00333 if (closed) {
00334 if (_got_xyz) {
00335 _data[0]._tangent = _data[len-1]._tangent =
00336 (_data[1]._xyz - _data[len-2]._xyz) * scale /
00337 ((_data[1]._t - _data[0]._t) + (_data[len-1]._t - _data[len-2]._t));
00338 }
00339 if (_got_hpr) {
00340 _data[0]._tangent = _data[len-1]._tangent =
00341 (_data[1]._hpr - _data[len-2]._hpr) * scale /
00342 ((_data[1]._t - _data[0]._t) + (_data[len-1]._t - _data[len-2]._t));
00343 }
00344
00345 } else {
00346 if (_got_xyz) {
00347 _data[0]._tangent =
00348 (_data[1]._xyz - _data[0]._xyz) * scale /
00349 ((_data[1]._t - _data[0]._t) * 2.0f);
00350 _data[len-1]._tangent =
00351 (_data[len-1]._xyz - _data[len-2]._xyz) * scale /
00352 ((_data[len-1]._t - _data[len-2]._t) * 2.0f);
00353 }
00354 if (_got_hpr) {
00355 _data[0]._tangent =
00356 (_data[1]._hpr - _data[0]._hpr) * scale /
00357 ((_data[1]._t - _data[0]._t) * 2.0f);
00358 _data[len-1]._tangent =
00359 (_data[len-1]._hpr - _data[len-2]._hpr) * scale /
00360 ((_data[len-1]._t - _data[len-2]._t) * 2.0f);
00361 }
00362 }
00363 }
00364
00365
00366
00367
00368
00369
00370
00371 PT(ParametricCurveCollection) CurveFitter::
00372 make_hermite() const {
00373 PT(ParametricCurveCollection) result = new ParametricCurveCollection;
00374
00375 if (_got_xyz) {
00376 HermiteCurve *hc = new HermiteCurve;
00377 result->add_curve(hc);
00378 hc->set_curve_type(PCT_XYZ);
00379
00380 Data::const_iterator di;
00381 for (di = _data.begin(); di != _data.end(); ++di) {
00382 int n = hc->insert_cv((*di)._t);
00383 hc->set_cv_type(n, HC_SMOOTH);
00384 hc->set_cv_point(n, (*di)._xyz);
00385 hc->set_cv_in(n, (*di)._tangent);
00386 hc->set_cv_out(n, (*di)._tangent);
00387 }
00388 }
00389
00390 if (_got_hpr) {
00391 HermiteCurve *hc = new HermiteCurve;
00392 result->add_curve(hc);
00393 hc->set_curve_type(PCT_HPR);
00394
00395 Data::const_iterator di;
00396 for (di = _data.begin(); di != _data.end(); ++di) {
00397 int n = hc->insert_cv((*di)._t);
00398 hc->set_cv_type(n, HC_SMOOTH);
00399 hc->set_cv_point(n, (*di)._hpr);
00400 hc->set_cv_in(n, (*di)._hpr_tangent);
00401 hc->set_cv_out(n, (*di)._hpr_tangent);
00402 }
00403 }
00404
00405 return result;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415 PT(ParametricCurveCollection) CurveFitter::
00416 make_nurbs() const {
00417
00418
00419 PT(ParametricCurveCollection) hermites = make_hermite();
00420 PT(ParametricCurveCollection) result = new ParametricCurveCollection;
00421
00422 int num_curves = hermites->get_num_curves();
00423 for (int c = 0; c < num_curves; c++) {
00424 ClassicNurbsCurve *nc = new ClassicNurbsCurve(*hermites->get_curve(c));
00425 result->add_curve(nc);
00426
00427
00428
00429
00430 int num_knots = nc->get_num_knots();
00431
00432
00433
00434 assert(nc->get_order() == 4);
00435 assert(num_knots > 0);
00436
00437
00438
00439
00440
00441
00442
00443
00444 int i;
00445 float k1, k2 = nc->get_knot(num_knots-1);
00446 const float one_third = 1.0f/3.0f;
00447 for (i = 3; i < num_knots - 4; i += 3) {
00448 k1 = nc->get_knot(i-1);
00449 k2 = nc->get_knot(i+2);
00450 nc->set_knot(i, (k1 + k1 + k2) * one_third);
00451 nc->set_knot(i+1, (k1 + k2 + k2) * one_third);
00452 }
00453
00454
00455 nc->set_knot(num_knots-4, k2);
00456
00457
00458 nc->recompute();
00459 }
00460
00461 return result;
00462 }
00463
00464
00465
00466
00467
00468
00469 void CurveFitter::
00470 output(ostream &out) const {
00471 out << "CurveFitter, " << _data.size() << " samples.\n";
00472 }
00473
00474
00475
00476
00477
00478
00479 void CurveFitter::
00480 write(ostream &out) const {
00481 out << "CurveFitter, " << _data.size() << " samples:\n";
00482 Data::const_iterator di;
00483 for (di = _data.begin(); di != _data.end(); ++di) {
00484 out << " " << (*di) << "\n";
00485 }
00486 }
00487