15 #include "parametricCurveCollection.h" 16 #include "config_parametrics.h" 17 #include "curveFitter.h" 18 #include "nurbsCurve.h" 21 #include "compose_matrix.h" 22 #include "string_utils.h" 30 ParametricCurveCollection::
31 ParametricCurveCollection() {
41 prepare_add_curve(curve);
42 _curves.push_back(curve);
54 prepare_add_curve(curve);
55 index = max(min(index, (
int)_curves.size()), 0);
56 _curves.insert(_curves.begin() + index, curve);
88 for (
int i = 0; curve_index == -1 && i < (int)_curves.size(); i++) {
89 if (_curves[i] == curve) {
94 if (curve_index == -1) {
112 nassertv(index >= 0 && index < (
int)_curves.size());
114 prepare_remove_curve(curve);
115 _curves.erase(_curves.begin() + index);
127 ParametricCurves::const_iterator ci;
128 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
129 if (curve == (*ci)) {
143 ParametricCurves::iterator ci;
144 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
146 prepare_remove_curve(curve);
163 ParametricCurves::iterator ci;
164 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
172 prepare_remove_curve(curve);
180 prepare_remove_curve(curve);
185 prepare_remove_curve(curve);
190 _curves.push_back(xyz_curve);
193 _curves.push_back(hpr_curve);
207 ParametricCurves::const_iterator ci;
208 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
225 ParametricCurves::const_iterator ci;
226 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
250 ParametricCurves::const_iterator ci;
251 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
270 ParametricCurves::const_iterator ci;
271 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
288 ParametricCurves::const_iterator ci;
289 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
320 make_even(PN_stdfloat max_t, PN_stdfloat segments_per_unit) {
323 parametrics_cat.error()
324 <<
"No XYZ curve for make_even().\n";
334 int num_segments = max(1, (
int)cfloor(segments_per_unit * xyz_curve->
get_max_t() + 0.5f));
336 if (parametrics_cat.is_debug()) {
337 parametrics_cat.debug()
338 <<
"Calculating length of curve.\n";
342 PN_stdfloat segment_length = net_length / (PN_stdfloat)num_segments;
344 if (parametrics_cat.is_debug()) {
345 parametrics_cat.debug()
346 <<
"Curve has total length " << net_length <<
"; dividing into " 347 << num_segments <<
" segments of " << segment_length <<
" units each.\n";
350 PN_stdfloat last_t = 0.0f;
352 PN_stdfloat val_inc= max_t/num_segments;
353 PN_stdfloat val=val_inc;
355 for (
int i = 0; i < num_segments; i++,val+=val_inc) {
356 PN_stdfloat next_t = xyz_curve->
find_length(last_t, segment_length);
360 if (parametrics_cat.is_spam()) {
361 parametrics_cat.spam()
362 <<
"Point " << i <<
" is at " << next_t <<
"\n";
368 if (parametrics_cat.is_debug()) {
369 parametrics_cat.debug()
370 <<
"Done computing segments.\n";
393 parametrics_cat.error()
394 <<
"No XYZ curve for face_forward().\n";
401 ParametricCurves::const_iterator ci;
404 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
407 prepare_remove_curve(curve);
410 xyz_index = (ci - _curves.begin());
412 new_curves.push_back(curve);
415 _curves.swap(new_curves);
422 int num_segments = (int)cfloor(segments_per_unit * max_t + 0.5);
429 determine_hpr(0.001, xyz_curve, hpr);
432 for (
int i = 0; i < num_segments; i++) {
433 PN_stdfloat t = (PN_stdfloat)(i + 1) / num_segments * max_t;
434 determine_hpr(t, xyz_curve, hpr);
459 nurbs->set_curve_type(PCT_T);
461 nurbs->append_cv(
LVecBase3(0.0f, 0.0f, 0.0f));
463 nurbs->set_knot(0, 0.0f);
464 nurbs->set_knot(1, 0.0f);
465 nurbs->set_knot(2, max_t);
466 nurbs->set_knot(3, max_t);
496 ParametricCurves::const_reverse_iterator ci;
497 for (ci = _curves.rbegin(); ci != _curves.rend(); ++ci) {
510 default_curve = curve;
514 if (!curve->get_point(t0, point)) {
522 xyz_curve = default_curve;
527 if (!xyz_curve->get_point(t0, xyz)) {
533 if (!hpr_curve->get_point(t0, hpr)) {
566 compose_matrix(result,
586 ParametricCurves::const_iterator ci;
587 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
591 if (!curve->get_point(t0, point)) {
617 if (t0 >= 0.0f && t < xyz_curve->
get_max_t()) {
618 return xyz_curve->
adjust_point(t, xyz[0], xyz[1], xyz[2]);
639 if (t0 >= 0.0f && t < hpr_curve->
get_max_t()) {
640 return hpr_curve->
adjust_point(t, hpr[0], hpr[1], hpr[2]);
656 ParametricCurves::iterator ci;
657 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
690 if (!new_xyz->stitch(a_xyz, b_xyz)) {
699 if (!new_hpr->stitch(a_hpr, b_hpr)) {
718 out <<
"1 ParametricCurve";
731 write(ostream &out,
int indent_level)
const {
732 ParametricCurves::const_iterator ci;
733 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
735 indent(out, indent_level) << *curve <<
"\n";
752 parametrics_cat.error()
753 <<
"Unable to write to " << filename <<
"\n";
768 if (cs == CS_default) {
769 cs = get_default_coordinate_system();
772 if (cs != CS_invalid) {
773 out <<
"<CoordinateSystem> { ";
801 ParametricCurves::iterator ci;
802 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
813 name += format_string(xyz_count);
821 name += format_string(hpr_count);
829 name += format_string(t_count);
835 curve->set_name(name);
838 if (!curve->
write_egg(out, filename, CS_invalid)) {
855 if (node->
is_of_type(ParametricCurve::get_class_type())) {
857 prepare_add_curve(curve);
858 _curves.push_back(curve);
863 for (
int i = 0; i < num_children; i++) {
885 _drawers.push_back(drawer);
887 ParametricCurves::iterator ci;
888 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
903 _drawers.remove(drawer);
905 ParametricCurves::iterator ci;
906 for (ci = _curves.begin(); ci != _curves.end(); ++ci) {
920 bool ParametricCurveCollection::
925 if (!xyz_curve->get_tangent(t0, tangent)) {
934 look_at(mat, tangent);
937 return decompose_matrix(mat, scale, shear, hpr);
947 void ParametricCurveCollection::
949 DrawerList::iterator di;
950 for (di = _drawers.begin(); di != _drawers.end(); ++di) {
951 ParametricCurveDrawer *drawer = (*di);
963 void ParametricCurveCollection::
965 DrawerList::iterator di;
966 for (di = _drawers.begin(); di != _drawers.end(); ++di) {
967 ParametricCurveDrawer *drawer = (*di);
978 void ParametricCurveCollection::
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.
float length_squared() const
Returns the square of the vector's length, cheap and easy.
A basic node of the scene graph or data graph.
void register_drawer(ParametricCurveDrawer *drawer)
Registers a Drawer with this curve collection that will automatically be updated whenever the collect...
This is the base class for all three-component vectors and points.
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, but keeps the same tangent value at that point.
bool open_write(ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
int r_add_curves(PandaNode *node)
The recursive implementation of add_curves().
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...
A virtual base class for parametric curves.
ParametricCurve * get_timewarp_curve(int n) const
Returns the nth timewarp curve in the collection.
int get_num_children(Thread *current_thread=Thread::get_current_thread()) const
Returns the number of child nodes this node has.
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...
virtual bool recompute()
Recalculates the curve, if necessary.
void register_drawer(ParametricCurveDrawer *drawer)
Registers a Drawer with this curve that will automatically be updated whenever the curve is modified...
bool has_curve(ParametricCurve *curve) const
Returns true if the indicated ParametricCurve appears in this collection, false otherwise.
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...
PandaNode * get_child(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the nth child node of this node.
void set_text()
Indicates that the filename represents a text file.
bool write_egg(Filename filename, CoordinateSystem cs=CS_default)
Writes an egg description of the nurbs curve to the specified output file.
ParametricCurve * get_hpr_curve() const
Returns the first HPR curve in the collection, if any, or NULL if there are none. ...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
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 unregister_drawer(ParametricCurveDrawer *drawer)
Removes a previously registered drawer from the list of automatically-refreshed drawers.
int get_num_timewarps() const
Returns the number of timewarp curves in the collection.
void clear_timewarps()
Removes all the timewarp curves from the collection.
PN_stdfloat get_max_t() const
Returns the maximum T value associated with the last* curve in the collection.
void compute_tangents(PN_stdfloat scale)
Once a set of points has been built, and prior to calling MakeHermite() or MakeNurbs(), ComputeTangents() must be called to set up the tangents correctly (unless the tangents were defined as the points were added).
This is a set of zero or more ParametricCurves, which may or may not be related.
The name of a file, such as a texture file or an Egg file.
int add_curves(PandaNode *node)
Adds all the curves found in the scene graph rooted at the given node.
This is a 4-by-4 transform matrix.
void wrap_hpr()
Resets each HPR data point so that the maximum delta between any two consecutive points is 180 degree...
ParametricCurve * get_xyz_curve() const
Returns the first XYZ curve in the collection, if any, or NULL if there are none. ...
A Nonuniform Rational B-Spline.
void clear()
Removes all ParametricCurves from the collection.
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.
virtual PN_stdfloat get_max_t() const
Returns the upper bound of t for the entire curve.
bool recompute()
Ensures all the curves are freshly computed and up-to-date.
void add_hpr(PN_stdfloat t, const LVecBase3 &hpr)
Adds a single sample hpr.
string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
void output(ostream &out) const
Writes a brief one-line description of the ParametricCurveCollection to the indicated output stream...
void add_xyz(PN_stdfloat t, const LVecBase3 &xyz)
Adds a single sample xyz.
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...
void set_curve_type(int type)
Sets the flag indicating the use to which the curve is intended to be put.
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...
void write(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.
PN_stdfloat calc_length() const
Approximates the length of the entire curve to within a few decimal places.
void unregister_drawer(ParametricCurveDrawer *drawer)
Removes a previously registered drawer from the list of automatically-refreshed drawers.
int get_num_curves() const
Returns the number of ParametricCurves in the collection.
bool remove_curve(ParametricCurve *curve)
Removes the indicated ParametricCurve from the collection.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
This is a 3-by-3 transform matrix.
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...
ParametricCurve * get_default_curve() const
If there is an XYZ curve in the collection, returns it; otherwise, returns the first curve whose type...
int get_curve_type() const
Returns the flag indicating the use to which the curve is intended to be put.
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...