Panda3D
|
00001 // Filename: piecewiseCurve.cxx 00002 // Created by: drose (04Mar01) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 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 // Function: PiecewiseCurve::Constructor 00028 // Access: Public 00029 // Description: 00030 //////////////////////////////////////////////////////////////////// 00031 PiecewiseCurve:: 00032 PiecewiseCurve() { 00033 _last_ti = 0; 00034 } 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: PiecewiseCurve::Destructor 00038 // Access: Protected 00039 // Description: 00040 //////////////////////////////////////////////////////////////////// 00041 PiecewiseCurve:: 00042 ~PiecewiseCurve() { 00043 remove_all_curvesegs(); 00044 } 00045 00046 00047 //////////////////////////////////////////////////////////////////// 00048 // Function: PiecewiseCurve::is_valid 00049 // Access: Published, Virtual 00050 // Description: Returns true if the curve is defined. In the case of 00051 // a PiecewiseCurve, this means we have at least one 00052 // segment. 00053 //////////////////////////////////////////////////////////////////// 00054 bool PiecewiseCurve:: 00055 is_valid() const { 00056 return !_segs.empty(); 00057 } 00058 00059 //////////////////////////////////////////////////////////////////// 00060 // Function: PiecewiseCurve::get_max_t 00061 // Access: Published, Virtual 00062 // Description: Returns the upper bound of t for the entire curve. 00063 // The curve is defined in the range 0.0f <= t <= 00064 // get_max_t(). 00065 //////////////////////////////////////////////////////////////////// 00066 PN_stdfloat PiecewiseCurve:: 00067 get_max_t() const { 00068 return _segs.empty() ? 0.0f : _segs.back()._tend; 00069 } 00070 00071 00072 //////////////////////////////////////////////////////////////////// 00073 // Function: PiecewiseCurve::get_point 00074 // Access: Published, Virtual 00075 // Description: Returns the point of the curve at a given parametric 00076 // point t. Returns true if t is in the valid range 0.0f 00077 // <= t <= get_max_t(); if t is outside this range, sets 00078 // point to the value of the curve at the beginning or 00079 // end (whichever is nearer) and returns false. 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 // We use | instead of || so we won't short-circuit this calculation. 00089 return result | curve->get_point(t, point); 00090 } 00091 00092 00093 //////////////////////////////////////////////////////////////////// 00094 // Function: PiecewiseCurve::get_tangent 00095 // Access: Published, Virtual 00096 // Description: Returns the tangent of the curve at a given parametric 00097 // point t. 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 // We use | instead of || so we won't short-circuit this calculation. 00105 return result | curve->get_tangent(t, tangent); 00106 } 00107 00108 00109 //////////////////////////////////////////////////////////////////// 00110 // Function: PiecewiseCurve::get_2ndtangent 00111 // Access: Published, Virtual 00112 // Description: Returns the tangent of the first derivative of the 00113 // curve at the point t. 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 // We use | instead of || so we won't short-circuit this calculation. 00121 return result | curve->get_2ndtangent(t, tangent2); 00122 } 00123 00124 //////////////////////////////////////////////////////////////////// 00125 // Function: PiecewiseCurve::adjust_point 00126 // Access: Published, Virtual 00127 // Description: Recomputes the curve such that it passes through the 00128 // point (px, py, pz) at time t, but keeps the same 00129 // tangent value at that point. 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 // Function: PiecewiseCurve::adjust_tangent 00157 // Access: Published, Virtual 00158 // Description: Recomputes the curve such that it has the tangent 00159 // (tx, ty, tz) at time t, but keeps the same position 00160 // at the point. 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 // Function: PiecewiseCurve::adjust_pt 00182 // Access: Published, Virtual 00183 // Description: Recomputes the curve such that it passes through the 00184 // point (px, py, pz) with the tangent (tx, ty, tz). 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 // Function: PiecewiseCurve::get_pt 00208 // Access: Published, Virtual 00209 // Description: Simultaneously returns the point and tangent of the 00210 // curve at a given parametric point t. 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 // We use | instead of || so we won't short-circuit this calculation. 00218 return result | curve->get_pt(t, point, tangent); 00219 } 00220 00221 00222 //////////////////////////////////////////////////////////////////// 00223 // Function: PiecewiseCurve::get_num_segs 00224 // Access: Public 00225 // Description: Returns the number of curve segments that make up the 00226 // Piecewise curve. 00227 //////////////////////////////////////////////////////////////////// 00228 int PiecewiseCurve:: 00229 get_num_segs() const { 00230 return _segs.size(); 00231 } 00232 00233 //////////////////////////////////////////////////////////////////// 00234 // Function: PiecewiseCurve::get_curveseg 00235 // Access: Public 00236 // Description: Returns the curve segment corresponding to the given 00237 // index. 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 // Function: PiecewiseCurve::insert_curveseg 00248 // Access: Public 00249 // Description: Inserts a new curve segment at the indicated index. 00250 // The curve segment must have been allocated via 00251 // new; it will be freed using delete when it is removed 00252 // or the PiecewiseCurve destructs. 00253 // 00254 // If the curve segment is not inserted at the end, its 00255 // tlength is subtracted from that of the following 00256 // segment, so that the overall length of the curve is 00257 // not changed. 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 // Function: PiecewiseCurve::remove_curveseg 00283 // Access: Public 00284 // Description: Removes the given curve segment from the curve and 00285 // frees it. Returns true if the segment was defined, 00286 // false otherwise. 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 // Now update the _tend figures for everything after the one we 00298 // removed. 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 // Function: PiecewiseCurve::remove_all_curvesegs 00310 // Access: Public 00311 // Description: Removes all curve segments from the curve. 00312 //////////////////////////////////////////////////////////////////// 00313 void PiecewiseCurve:: 00314 remove_all_curvesegs() { 00315 _segs.erase(_segs.begin(), _segs.end()); 00316 _last_ti = 0; 00317 } 00318 00319 //////////////////////////////////////////////////////////////////// 00320 // Function: PiecewiseCurve::get_tlength 00321 // Access: Public 00322 // Description: Returns the parametric length of the given segment of 00323 // the curve. 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 // Function: PiecewiseCurve::get_tstart 00333 // Access: Public 00334 // Description: Returns the parametric start of the given segment of 00335 // the curve. 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 // Function: PiecewiseCurve::get_tend 00345 // Access: Public 00346 // Description: Returns the parametric end of the given segment of 00347 // the curve. 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 // Function: PiecewiseCurve::set_tlength 00358 // Access: Public 00359 // Description: Sets the parametric length of the given segment of 00360 // the curve. The length of the following segment is 00361 // lengthened by the corresponding amount to keep the 00362 // overall length of the curve the same. 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 // Function: PiecewiseCurve::make_nurbs 00378 // Access: Public 00379 // Description: Defines the curve as a general NURBS curve. The 00380 // order is the degree plus one and must be 1, 2, 3, or 00381 // 4; cvs is an array of num_cvs points each with a 00382 // homogeneous coordinate; knots is an array of 00383 // num_cvs+order knot values. 00384 // 00385 // This creates the individual curve segments and sets 00386 // up the basis matrices, but does not store the CV's or 00387 // knot values so the curve shape is not later 00388 // modifiable. 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 // Function: PiecewiseCurve::get_bezier_segs 00409 // Access: Public, Virtual 00410 // Description: Fills up the indicated vector with a list of 00411 // BezierSeg structs that describe the curve. This 00412 // assumes the curve is a PiecewiseCurve of 00413 // CubicCurvesegs. Returns true if successful, false 00414 // otherwise. 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 // Function: PiecewiseCurve::rebuild_curveseg 00434 // Access: Public, Virtual 00435 // Description: Rebuilds the current curve segment (as selected by 00436 // the most recent call to find_curve()) according to 00437 // the specified properties (see 00438 // CubicCurveseg::compute_seg). Returns true if 00439 // possible, false if something goes horribly wrong. 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 // Function: PiecewiseCurve::find_curve 00452 // Access: Protected 00453 // Description: Finds the curve corresponding to the given value of 00454 // t. If t is inside the curve's defined range, sets 00455 // curve to the appropriate segment, translates t to 00456 // [0,1] to index into the segment's coordinate system, 00457 // and returns true. If t is outside the curve's 00458 // defined range, sets curve to the nearest segment and 00459 // t to the nearest point on this segment, and returns 00460 // false. 00461 //////////////////////////////////////////////////////////////////// 00462 bool PiecewiseCurve:: 00463 find_curve(const ParametricCurve *&curve, PN_stdfloat &t) const { 00464 // Check the index computed by the last call to find_curve(). If 00465 // it's still a reasonable starting value, start searching from 00466 // there. This way, we take advantage of locality of reference: the 00467 // search is trivial it is the same segment as last time, or the 00468 // next segment after the last one. 00469 if (_last_ti>0 && _segs[_last_ti-1]._tend>=t) { 00470 // However, if the new t value precedes that of last time, we'll 00471 // have to start over. 00472 00473 // We do some messy casting so we can get away with assigning a 00474 // value to a member within a const function. This assignment 00475 // doesn't really count as a const violation since we're just 00476 // updating a cached value, not changing any real data of the 00477 // class. 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 // Adjust t to the range [0,1). 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 // Oops. 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 // If we're out of bounds, or the curve is undefined, we're probably 00508 // screwed. There's one exception: if we were right on a border between 00509 // curves, try the curve before. 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 // Again, some messy casting so we can get away with updating the 00533 // cached index value for next time. 00534 ((PiecewiseCurve *)this)->_last_ti = ti; 00535 00536 // Now scale t back into the curve's own valid range. 00537 t *= _segs[ti]._curve->get_max_t(); 00538 curve = _segs[ti]._curve; 00539 return true; 00540 } 00541 00542 00543 //////////////////////////////////////////////////////////////////// 00544 // Function: PiecewiseCurve::current_seg_range 00545 // Access: Protected 00546 // Description: Returns a number in the range [0,1], representing the 00547 // conversion of t into the current segment's coordinate 00548 // system (the segment last returned by find_curve). 00549 // This operation is already performed automatically on 00550 // the t passed into find_seg; this function is useful 00551 // only to adjust a different value into the same range. 00552 // 00553 // It is an error to call this function if find_curve() 00554 // has not yet been called, or if find_curve() returned 00555 // false from its previous call. 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 // Adjust t to the range [0,1). 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 // Function: PiecewiseCurve::write_datagram 00575 // Access: Protected, Virtual 00576 // Description: Function to write the important information in 00577 // the particular object to a Datagram 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 // Function: PiecewiseCurve::fillin 00596 // Access: Protected 00597 // Description: Function that reads out of the datagram (or asks 00598 // manager to read) all of the data that is needed to 00599 // re-create this object and stores it in the appropiate 00600 // place 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 // Function: PiecewiseCurve::complete_pointers 00620 // Access: Protected, Virtual 00621 // Description: Takes in a vector of pointes to TypedWritable 00622 // objects that correspond to all the requests for 00623 // pointers that this object made to BamReader. 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 }