00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "piecewiseCurve.h"
00016 #include "cubicCurveseg.h"
00017 #include "config_parametrics.h"
00018
00019 #include "datagram.h"
00020 #include "datagramIterator.h"
00021 #include "bamWriter.h"
00022 #include "bamReader.h"
00023
00024 TypeHandle PiecewiseCurve::_type_handle;
00025
00026
00027
00028
00029
00030
00031 PiecewiseCurve::
00032 PiecewiseCurve() {
00033 _last_ti = 0;
00034 }
00035
00036
00037
00038
00039
00040
00041 PiecewiseCurve::
00042 ~PiecewiseCurve() {
00043 remove_all_curvesegs();
00044 }
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 bool PiecewiseCurve::
00055 is_valid() const {
00056 return !_segs.empty();
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066 PN_stdfloat PiecewiseCurve::
00067 get_max_t() const {
00068 return _segs.empty() ? 0.0f : _segs.back()._tend;
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 bool PiecewiseCurve::
00082 get_point(PN_stdfloat t, LVecBase3 &point) const {
00083 const ParametricCurve *curve;
00084 bool result = find_curve(curve, t);
00085 if (curve == NULL){
00086 return false;
00087 }
00088
00089 return result | curve->get_point(t, point);
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099 bool PiecewiseCurve::
00100 get_tangent(PN_stdfloat t, LVecBase3 &tangent) const {
00101 const ParametricCurve *curve;
00102 bool result = find_curve(curve, t);
00103
00104
00105 return result | curve->get_tangent(t, tangent);
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115 bool PiecewiseCurve::
00116 get_2ndtangent(PN_stdfloat t, LVecBase3 &tangent2) const {
00117 const ParametricCurve *curve;
00118 bool result = find_curve(curve, t);
00119
00120
00121 return result | curve->get_2ndtangent(t, tangent2);
00122 }
00123
00124
00125
00126
00127
00128
00129
00130
00131 bool PiecewiseCurve::
00132 adjust_point(PN_stdfloat t,
00133 PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz) {
00134 if (parametrics_cat.is_debug()) {
00135 parametrics_cat.debug()
00136 << "Adjusting point at " << t << " to " << px << " " << py << " "
00137 << pz << "\n";
00138 }
00139
00140 const ParametricCurve *curve;
00141 bool result = find_curve(curve, t);
00142
00143 if (!result) {
00144 cerr << "No curve segment at t = " << t << "\n";
00145 return false;
00146 }
00147
00148 rebuild_curveseg(RT_CV | RT_KEEP_ORIG, 0.0f, LVecBase4(),
00149 RT_POINT, t, LVecBase4(px, py, pz, 1.0f),
00150 RT_TANGENT | RT_KEEP_ORIG, t, LVecBase4(),
00151 RT_CV | RT_KEEP_ORIG, 0.0f, LVecBase4());
00152 return true;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162 bool PiecewiseCurve::
00163 adjust_tangent(PN_stdfloat t,
00164 PN_stdfloat tx, PN_stdfloat ty, PN_stdfloat tz) {
00165 const ParametricCurve *curve;
00166 bool result = find_curve(curve, t);
00167
00168 if (!result) {
00169 cerr << "No curve segment at t = " << t << "\n";
00170 return false;
00171 }
00172
00173 rebuild_curveseg(RT_CV | RT_KEEP_ORIG, 0.0f, LVecBase4(),
00174 RT_POINT | RT_KEEP_ORIG, t, LVecBase4(),
00175 RT_TANGENT, t, LVecBase4(tx, ty, tz, 0.0f),
00176 RT_CV | RT_KEEP_ORIG, 0.0f, LVecBase4());
00177 return true;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186 bool PiecewiseCurve::
00187 adjust_pt(PN_stdfloat t,
00188 PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz,
00189 PN_stdfloat tx, PN_stdfloat ty, PN_stdfloat tz) {
00190 const ParametricCurve *curve;
00191 bool result = find_curve(curve, t);
00192
00193 if (!result) {
00194 cerr << "No curve segment at t = " << t << "\n";
00195 return false;
00196 }
00197
00198 rebuild_curveseg(RT_CV | RT_KEEP_ORIG, 0.0f, LVecBase4(),
00199 RT_POINT, t, LVecBase4(px, py, pz, 1.0f),
00200 RT_TANGENT, t, LVecBase4(tx, ty, tz, 0.0f),
00201 RT_CV | RT_KEEP_ORIG, 0.0f, LVecBase4());
00202 return true;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212 bool PiecewiseCurve::
00213 get_pt(PN_stdfloat t, LVecBase3 &point, LVecBase3 &tangent) const {
00214 const ParametricCurve *curve;
00215 bool result = find_curve(curve, t);
00216
00217
00218 return result | curve->get_pt(t, point, tangent);
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228 int PiecewiseCurve::
00229 get_num_segs() const {
00230 return _segs.size();
00231 }
00232
00233
00234
00235
00236
00237
00238
00239 ParametricCurve *PiecewiseCurve::
00240 get_curveseg(int ti) {
00241 assert(ti >= 0 && ti < (int)_segs.size());
00242 return _segs[ti]._curve;
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 bool PiecewiseCurve::
00260 insert_curveseg(int ti, ParametricCurve *seg, PN_stdfloat tlength) {
00261 if (ti < 0 || ti > (int)_segs.size()) {
00262 return false;
00263 }
00264
00265 if (ti == (int)_segs.size()) {
00266 _segs.push_back(Curveseg(seg, get_max_t() + tlength));
00267
00268 } else if (ti==0) {
00269 _segs.insert(_segs.begin(),
00270 Curveseg(seg, tlength));
00271
00272 } else {
00273 _segs.insert(_segs.begin() + ti,
00274 Curveseg(seg, _segs[ti-1]._tend + tlength));
00275 }
00276
00277 return true;
00278 }
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 bool PiecewiseCurve::
00289 remove_curveseg(int ti) {
00290 if (ti < 0 || ti >= (int)_segs.size()) {
00291 return false;
00292 }
00293
00294 PN_stdfloat tlength = get_tlength(ti);
00295 _segs.erase(_segs.begin() + ti);
00296
00297
00298
00299 while (ti < (int)_segs.size()) {
00300 _segs[ti]._tend -= tlength;
00301 ti++;
00302 }
00303
00304 _last_ti = 0;
00305 return true;
00306 }
00307
00308
00309
00310
00311
00312
00313 void PiecewiseCurve::
00314 remove_all_curvesegs() {
00315 _segs.erase(_segs.begin(), _segs.end());
00316 _last_ti = 0;
00317 }
00318
00319
00320
00321
00322
00323
00324
00325 PN_stdfloat PiecewiseCurve::
00326 get_tlength(int ti) const {
00327 assert(ti >= 0 && ti < (int)_segs.size());
00328 return (ti==0) ? _segs[ti]._tend : _segs[ti]._tend - _segs[ti-1]._tend;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337 PN_stdfloat PiecewiseCurve::
00338 get_tstart(int ti) const {
00339 assert(ti >= 0 && ti <= (int)_segs.size());
00340 return (ti==0) ? 0.0f : _segs[ti-1]._tend;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349 PN_stdfloat PiecewiseCurve::
00350 get_tend(int ti) const {
00351 assert(ti >= 0 && ti < (int)_segs.size());
00352 return _segs[ti]._tend;
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 bool PiecewiseCurve::
00365 set_tlength(int ti, PN_stdfloat tlength) {
00366 if (ti < 0 || ti >= (int)_segs.size()) {
00367 return false;
00368 }
00369
00370 _segs[ti]._tend += tlength - get_tlength(ti);
00371 return true;
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 void PiecewiseCurve::
00391 make_nurbs(int order, int num_cvs,
00392 const PN_stdfloat knots[], const LVecBase4 cvs[]) {
00393 remove_all_curvesegs();
00394
00395 for (int i=0; i<num_cvs - order + 1; i++) {
00396 if (knots[i+order] > knots[i+order-1]) {
00397 int ti = get_num_segs();
00398 bool result =
00399 insert_curveseg(ti, new CubicCurveseg(order, knots+i, cvs+i),
00400 knots[i+order] - knots[i+order-1]);
00401 assert(result);
00402 }
00403 }
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 bool PiecewiseCurve::
00417 get_bezier_segs(BezierSegs &bz_segs) const {
00418 bz_segs.erase(bz_segs.begin(), bz_segs.end());
00419 int i;
00420 BezierSeg seg;
00421 for (i = 0; i < (int)_segs.size(); i++) {
00422 if (!_segs[i]._curve->get_bezier_seg(seg)) {
00423 return false;
00424 }
00425 seg._t = _segs[i]._tend;
00426 bz_segs.push_back(seg);
00427 }
00428
00429 return true;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 bool PiecewiseCurve::
00442 rebuild_curveseg(int, PN_stdfloat, const LVecBase4 &,
00443 int, PN_stdfloat, const LVecBase4 &,
00444 int, PN_stdfloat, const LVecBase4 &,
00445 int, PN_stdfloat, const LVecBase4 &) {
00446 cerr << "rebuild_curveseg not implemented for this curve type.\n";
00447 return false;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 bool PiecewiseCurve::
00463 find_curve(const ParametricCurve *&curve, PN_stdfloat &t) const {
00464
00465
00466
00467
00468
00469 if (_last_ti>0 && _segs[_last_ti-1]._tend>=t) {
00470
00471
00472
00473
00474
00475
00476
00477
00478 ((PiecewiseCurve *)this)->_last_ti = 0;
00479 }
00480
00481 int ti;
00482 for (ti = _last_ti; ti < (int)_segs.size(); ti++) {
00483 if (_segs[ti]._tend+0.00001f > t) {
00484 break;
00485 }
00486 }
00487
00488 if (ti < (int)_segs.size()) {
00489
00490 if (ti > 0) {
00491 t = (t - _segs[ti-1]._tend) / (_segs[ti]._tend - _segs[ti-1]._tend);
00492 } else {
00493 t /= _segs[0]._tend;
00494 }
00495 }
00496
00497 if (t < 0) {
00498
00499 curve = _segs[0]._curve;
00500 t = 0.0f;
00501 return false;
00502 }
00503
00504 if (ti >= (int)_segs.size() || !_segs[ti]._curve->is_valid()) {
00505 assert(ti <= (int)_segs.size());
00506
00507
00508
00509
00510
00511 if (ti > 0 && t < _segs[ti-1]._tend+0.0001f) {
00512 ti--;
00513 t = 1.0f;
00514 }
00515
00516 if (ti >= (int)_segs.size()) {
00517 if (_segs.empty()) {
00518 curve = NULL;
00519 t = 0.0f;
00520 return false;
00521 } else {
00522 curve = _segs.back()._curve;
00523 t = 1.0f;
00524 return false;
00525 }
00526 } else if (!_segs[ti]._curve->is_valid()) {
00527 curve = _segs[ti]._curve;
00528 return false;
00529 }
00530 }
00531
00532
00533
00534 ((PiecewiseCurve *)this)->_last_ti = ti;
00535
00536
00537 t *= _segs[ti]._curve->get_max_t();
00538 curve = _segs[ti]._curve;
00539 return true;
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557 PN_stdfloat PiecewiseCurve::
00558 current_seg_range(PN_stdfloat t) const {
00559 int ti = _last_ti;
00560
00561 assert(ti < (int)_segs.size());
00562
00563
00564 if (ti > 0) {
00565 t = (t - _segs[ti-1]._tend) / (_segs[ti]._tend - _segs[ti-1]._tend);
00566 } else {
00567 t /= _segs[0]._tend;
00568 }
00569
00570 return t;
00571 }
00572
00573
00574
00575
00576
00577
00578
00579 void PiecewiseCurve::
00580 write_datagram(BamWriter *manager, Datagram &me) {
00581 ParametricCurve::write_datagram(manager, me);
00582
00583 me.add_uint32(_segs.size());
00584 size_t i;
00585 for (i = 0; i < _segs.size(); i++) {
00586 const Curveseg &seg = _segs[i];
00587 manager->write_pointer(me, seg._curve);
00588 me.add_float64(seg._tend);
00589 }
00590
00591 _last_ti = 0;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 void PiecewiseCurve::
00603 fillin(DatagramIterator &scan, BamReader *manager) {
00604 ParametricCurve::fillin(scan, manager);
00605
00606 size_t num_segs = scan.get_uint32();
00607 _segs.reserve(num_segs);
00608 size_t i;
00609 for (i = 0; i < num_segs; i++) {
00610 Curveseg seg;
00611 manager->read_pointer(scan);
00612 seg._curve = (ParametricCurve *)NULL;
00613 seg._tend = scan.get_float64();
00614 _segs.push_back(seg);
00615 }
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625 int PiecewiseCurve::
00626 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00627 int used = ParametricCurve::complete_pointers(p_list, manager);
00628
00629 size_t i;
00630 for (i = 0; i < _segs.size(); i++) {
00631 _segs[i]._curve = DCAST(ParametricCurve, p_list[used + i]);
00632 }
00633
00634 return used + _segs.size();
00635 }