27ParametricCurveCollection::
28ParametricCurveCollection() {
36 prepare_add_curve(curve);
37 _curves.push_back(curve);
46 prepare_add_curve(curve);
47 index = std::min(index, _curves.size());
48 _curves.insert(_curves.begin() + index, curve);
74 for (
int i = 0; curve_index == -1 && i < (int)_curves.size(); i++) {
75 if (_curves[i] == curve) {
80 if (curve_index == -1) {
97 nassertv(index < _curves.size());
99 prepare_remove_curve(curve);
100 _curves.erase(_curves.begin() + index);
111 nassertv(index < _curves.size());
112 prepare_remove_curve(_curves[index]);
113 prepare_add_curve(curve);
114 _curves[index] = curve;
124 ParametricCurves::const_iterator ci;
125 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
126 if (curve == (*ci)) {
138 ParametricCurves::iterator ci;
139 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
141 prepare_remove_curve(curve);
156 ParametricCurves::iterator ci;
157 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
162 if (xyz_curve ==
nullptr) {
165 prepare_remove_curve(curve);
170 if (hpr_curve ==
nullptr) {
173 prepare_remove_curve(curve);
178 prepare_remove_curve(curve);
183 _curves.push_back(xyz_curve);
185 if (hpr_curve !=
nullptr) {
186 _curves.push_back(hpr_curve);
198 ParametricCurves::const_iterator ci;
199 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
214 ParametricCurves::const_iterator ci;
215 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
232 if (xyz_curve !=
nullptr) {
236 ParametricCurves::const_iterator ci;
237 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
253 ParametricCurves::const_iterator ci;
254 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
269 ParametricCurves::const_iterator ci;
270 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
279 nassert_raise(
"index out of range");
296make_even(PN_stdfloat max_t, PN_stdfloat segments_per_unit) {
298 if (xyz_curve ==
nullptr) {
299 parametrics_cat.error()
300 <<
"No XYZ curve for make_even().\n";
310 int num_segments = std::max(1, (
int)cfloor(segments_per_unit * xyz_curve->
get_max_t() + 0.5f));
312 if (parametrics_cat.is_debug()) {
313 parametrics_cat.debug()
314 <<
"Calculating length of curve.\n";
318 PN_stdfloat segment_length = net_length / (PN_stdfloat)num_segments;
320 if (parametrics_cat.is_debug()) {
321 parametrics_cat.debug()
322 <<
"Curve has total length " << net_length <<
"; dividing into "
323 << num_segments <<
" segments of " << segment_length <<
" units each.\n";
326 PN_stdfloat last_t = 0.0f;
327 fitter.
add_xyz(0.0f, LVecBase3(last_t, 0.0f, 0.0f));
328 PN_stdfloat val_inc= max_t/num_segments;
329 PN_stdfloat val=val_inc;
331 for (
int i = 0; i < num_segments; i++,val+=val_inc) {
332 PN_stdfloat next_t = xyz_curve->
find_length(last_t, segment_length);
334 val, LVecBase3(next_t, 0.0f, 0.0f));
336 if (parametrics_cat.is_spam()) {
337 parametrics_cat.spam()
338 <<
"Point " << i <<
" is at " << next_t <<
"\n";
344 if (parametrics_cat.is_debug()) {
345 parametrics_cat.debug()
346 <<
"Done computing segments.\n";
352 nassertv(t_curve !=
nullptr);
365 if (xyz_curve ==
nullptr) {
366 parametrics_cat.error()
367 <<
"No XYZ curve for face_forward().\n";
374 ParametricCurves::const_iterator ci;
377 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
380 prepare_remove_curve(curve);
383 xyz_index = (ci - _curves.begin());
385 new_curves.push_back(curve);
388 _curves.swap(new_curves);
395 int num_segments = (int)cfloor(segments_per_unit * max_t + 0.5);
397 LVecBase3 hpr(0.0f, 0.0f, 0.0f);
402 determine_hpr(0.001, xyz_curve, hpr);
405 for (
int i = 0; i < num_segments; i++) {
406 PN_stdfloat t = (PN_stdfloat)(i + 1) / num_segments * max_t;
407 determine_hpr(t, xyz_curve, hpr);
415 nassertv(hpr_curve !=
nullptr);
429 nurbs->set_curve_type(PCT_T);
431 nurbs->append_cv(LVecBase3(0.0f, 0.0f, 0.0f));
432 nurbs->append_cv(LVecBase3(
get_max_t(), 0.0f, 0.0f));
433 nurbs->set_knot(0, 0.0f);
434 nurbs->set_knot(1, 0.0f);
435 nurbs->set_knot(2, max_t);
436 nurbs->set_knot(3, max_t);
452evaluate(PN_stdfloat t, LVecBase3 &xyz, LVecBase3 &hpr)
const {
462 ParametricCurves::const_reverse_iterator ci;
463 for (ci = _curves.rbegin(); ci != _curves.rend(); ++ci) {
476 default_curve = curve;
480 if (!curve->get_point(t0, point)) {
487 if (xyz_curve ==
nullptr) {
488 xyz_curve = default_curve;
492 if (xyz_curve !=
nullptr) {
493 if (!xyz_curve->get_point(t0, xyz)) {
498 if (hpr_curve !=
nullptr) {
499 if (!hpr_curve->get_point(t0, hpr)) {
519evaluate(PN_stdfloat t, LMatrix4 &result, CoordinateSystem cs)
const {
520 LVecBase3 xyz(0.0f, 0.0f, 0.0f);
521 LVecBase3 hpr(0.0f, 0.0f, 0.0f);
527 compose_matrix(result,
528 LVecBase3(1.0f, 1.0f, 1.0f),
529 LVecBase3(0.0f, 0.0f, 0.0f),
544 ParametricCurves::const_iterator ci;
545 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
549 if (!curve->get_point(t0, point)) {
565adjust_xyz(PN_stdfloat t,
const LVecBase3 &xyz) {
567 if (xyz_curve ==
nullptr) {
572 if (t0 >= 0.0f && t < xyz_curve->
get_max_t()) {
573 return xyz_curve->
adjust_point(t, xyz[0], xyz[1], xyz[2]);
584adjust_hpr(PN_stdfloat t,
const LVecBase3 &hpr) {
586 if (hpr_curve ==
nullptr) {
591 if (t0 >= 0.0f && t < hpr_curve->
get_max_t()) {
592 return hpr_curve->
adjust_point(t, hpr[0], hpr[1], hpr[2]);
605 ParametricCurves::iterator ci;
606 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
634 if (a_xyz !=
nullptr && b_xyz !=
nullptr) {
636 if (!new_xyz->stitch(a_xyz, b_xyz)) {
643 if (a_hpr !=
nullptr && b_hpr !=
nullptr) {
645 if (!new_hpr->stitch(a_hpr, b_hpr)) {
660output(std::ostream &out)
const {
662 out <<
"1 ParametricCurve";
673write(std::ostream &out,
int indent_level)
const {
674 ParametricCurves::const_iterator ci;
675 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
677 indent(out, indent_level) << *curve <<
"\n";
691 parametrics_cat.error()
692 <<
"Unable to write to " << filename <<
"\n";
704 if (cs == CS_default) {
705 cs = get_default_coordinate_system();
708 if (cs != CS_invalid) {
709 out <<
"<CoordinateSystem> { ";
737 ParametricCurves::iterator ci;
738 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
749 name += format_string(xyz_count);
757 name += format_string(hpr_count);
765 name += format_string(t_count);
771 curve->set_name(name);
774 if (!curve->
write_egg(out, filename, CS_invalid)) {
789 if (node->
is_of_type(ParametricCurve::get_class_type())) {
791 prepare_add_curve(curve);
792 _curves.push_back(curve);
797 for (
int i = 0; i < num_children; i++) {
815 _drawers.push_back(drawer);
817 ParametricCurves::iterator ci;
818 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
831 _drawers.remove(drawer);
833 ParametricCurves::iterator ci;
834 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
845bool ParametricCurveCollection::
846determine_hpr(PN_stdfloat t,
ParametricCurve *xyz_curve, LVecBase3 &hpr)
const {
850 if (!xyz_curve->get_tangent(t0, tangent)) {
854 if (tangent.length_squared() == 0.0f) {
859 look_at(mat, tangent);
861 LVecBase3 scale, shear;
862 return decompose_matrix(mat, scale, shear, hpr);
869void ParametricCurveCollection::
871 DrawerList::iterator di;
872 for (di = _drawers.begin(); di != _drawers.end(); ++di) {
873 ParametricCurveDrawer *drawer = (*di);
882void ParametricCurveCollection::
884 DrawerList::iterator di;
885 for (di = _drawers.begin(); di != _drawers.end(); ++di) {
886 ParametricCurveDrawer *drawer = (*di);
894void ParametricCurveCollection::
void add_xyz(PN_stdfloat t, const LVecBase3 &xyz)
Adds a single sample xyz.
void wrap_hpr()
Resets each HPR data point so that the maximum delta between any two consecutive points is 180 degree...
void compute_tangents(PN_stdfloat scale)
Once a set of points has been built, and prior to calling MakeHermite() or MakeNurbs(),...
void add_hpr(PN_stdfloat t, const LVecBase3 &hpr)
Adds a single sample hpr.
The name of a file, such as a texture file or an Egg file.
void set_text()
Indicates that the filename represents a text file.
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
std::string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
A Nonuniform Rational B-Spline.
A basic node of the scene graph or data graph.
get_child
Returns the nth child node of this node.
get_num_children
Returns the number of child nodes this node has.
This is a set of zero or more ParametricCurves, which may or may not be related.
bool recompute()
Ensures all the curves are freshly computed and up-to-date.
void clear_timewarps()
Removes all the timewarp curves from the collection.
get_default_curve
If there is an XYZ curve in the collection, returns it; otherwise, returns the first curve whose type...
int add_curves(PandaNode *node)
Adds all the curves found in the scene graph rooted at the given node.
void insert_curve(size_t index, ParametricCurve *curve)
Adds a new ParametricCurve to the collection at the indicated index.
void unregister_drawer(ParametricCurveDrawer *drawer)
Removes a previously registered drawer from the list of automatically- refreshed drawers.
bool adjust_xyz(PN_stdfloat t, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Adjust the XYZ curve at the indicated time to the new value.
bool has_curve(ParametricCurve *curve) const
Returns true if the indicated ParametricCurve appears in this collection, false otherwise.
void write(std::ostream &out, int indent_level=0) const
Writes a complete multi-line description of the ParametricCurveCollection to the indicated output str...
void add_curve(ParametricCurve *curve)
Adds a new ParametricCurve to the collection.
bool adjust_hpr(PN_stdfloat t, PN_stdfloat h, PN_stdfloat p, PN_stdfloat r)
Adjust the HPR curve at the indicated time to the new value.
void face_forward(PN_stdfloat segments_per_unit)
Discards the existing HPR curve and generates a new one that looks in the direction of travel along t...
bool stitch(const ParametricCurveCollection *a, const ParametricCurveCollection *b)
Regenerates this curve as one long curve: the first curve connected end-to- end with the second one.
get_xyz_curve
Returns the first XYZ curve in the collection, if any, or NULL if there are none.
get_timewarp_curve
Returns the nth timewarp curve in the collection.
get_num_curves
Returns the number of ParametricCurves in the collection.
int r_add_curves(PandaNode *node)
The recursive implementation of add_curves().
void register_drawer(ParametricCurveDrawer *drawer)
Registers a Drawer with this curve collection that will automatically be updated whenever the collect...
void make_even(PN_stdfloat max_t, PN_stdfloat segments_per_unit)
Discards all existing timewarp curves and recomputes a new timewarp curve that maps distance along th...
get_num_timewarps
Returns the number of timewarp curves in the collection.
PN_stdfloat evaluate_t(PN_stdfloat t) const
Determines the value of t that should be passed to the XYZ and HPR curves, after applying the given v...
bool write_egg(Filename filename, CoordinateSystem cs=CS_default)
Writes an egg description of all the nurbs curves in the collection to the specified output file.
remove_curve
Removes the indicated ParametricCurve from the collection.
void clear()
Removes all ParametricCurves from the collection.
set_curve
Replaces the indicated ParametricCurve from the collection, by its index number.
bool evaluate(PN_stdfloat t, LVecBase3 &xyz, LVecBase3 &hpr) const
Computes the position and rotation represented by the first XYZ and HPR curves in the collection at t...
void reset_max_t(PN_stdfloat max_t)
Adjusts the apparent length of the curve by applying a new timewarp that maps the range [0....
void output(std::ostream &out) const
Writes a brief one-line description of the ParametricCurveCollection to the indicated output stream.
get_hpr_curve
Returns the first HPR curve in the collection, if any, or NULL if there are none.
get_max_t
Returns the maximum T value associated with the *last* curve in the collection.
A virtual base class for parametric curves.
PN_stdfloat calc_length() const
Approximates the length of the entire curve to within a few decimal places.
int get_curve_type() const
Returns the flag indicating the use to which the curve is intended to be put.
virtual bool recompute()
Recalculates the curve, if necessary.
virtual bool adjust_point(PN_stdfloat t, PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz)
Recomputes the curve such that it passes through the point (px, py, pz) at time t,...
virtual PN_stdfloat get_max_t() const
Returns the upper bound of t for the entire curve.
void set_curve_type(int type)
Sets the flag indicating the use to which the curve is intended to be put.
void register_drawer(ParametricCurveDrawer *drawer)
Registers a Drawer with this curve that will automatically be updated whenever the curve is modified,...
bool write_egg(Filename filename, CoordinateSystem cs=CS_default)
Writes an egg description of the nurbs curve to the specified output file.
void unregister_drawer(ParametricCurveDrawer *drawer)
Removes a previously registered drawer from the list of automatically- refreshed drawers.
PN_stdfloat find_length(PN_stdfloat start_t, PN_stdfloat length_offset) const
Returns the parametric value corresponding to the indicated distance along the curve from the startin...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.