25 static const PN_stdfloat tolerance_divisor = 100000.0f;
35 _curve_type = PCT_NONE;
48 nassertv(_drawers.empty());
107 switch (_curve_type) {
141 _num_dimensions = num;
152 return _num_dimensions;
174 PN_stdfloat to_minus_from = to - from;
176 if (to_minus_from < 0.0f) {
177 PN_stdfloat temp = to;
180 to_minus_from=-to_minus_from;
184 int num_segs = (int)(to_minus_from) + 1;
187 PN_stdfloat net = 0.0f;
189 for (
int i = 1; i <= num_segs; i++) {
193 t2 = (to - from) * (PN_stdfloat)i / (PN_stdfloat)num_segs + from;
196 net += r_calc_length(t1, t2, p1, p2, (p1 - p2).length());
212 find_length(PN_stdfloat start_t, PN_stdfloat length_offset)
const {
213 nassertr(length_offset >= 0.0f, start_t);
214 nassertr(start_t >= 0.0f && start_t <=
get_max_t(), start_t);
221 int num_segs = (int)cfloor(max_t - start_t + 1);
224 PN_stdfloat net = 0.0f;
226 for (
int i = 1; i <= num_segs; i++) {
227 assert(net <= length_offset);
232 t2 = start_t + (((max_t - start_t) * (PN_stdfloat)i) / (PN_stdfloat)num_segs);
235 PN_stdfloat seglength = (p1 - p2).length();
238 if (r_find_length(length_offset - net, result,
239 t1, t2, p1, p2, seglength)) {
274 adjust_pt(PN_stdfloat, PN_stdfloat, PN_stdfloat, PN_stdfloat, PN_stdfloat, PN_stdfloat, PN_stdfloat) {
296 parametrics_cat.error()
297 << get_type() <<
" does not support stitching.\n";
312 parametrics_cat.error()
313 <<
"Unable to write to " << filename <<
"\n";
325 std::string curve_type;
344 if (!curve_type.empty()) {
352 if (cs == CS_default) {
353 cs = get_default_coordinate_system();
356 if (cs != CS_invalid) {
357 out <<
"<CoordinateSystem> { ";
382 if (!format_egg(out, get_name(), curve_type, 0)) {
442 if (!bz_segs.empty()) {
443 PN_stdfloat scale_in = 0.0f;
444 PN_stdfloat scale_out = bz_segs[0]._t;
445 n = hc->
append_cv(HC_SMOOTH, bz_segs[0]._v[0]);
446 hc->
set_cv_out(n, 3.0f * (bz_segs[0]._v[1] - bz_segs[0]._v[0]) / scale_out);
448 for (i = 0; i < (int)bz_segs.size()-1; i++) {
449 scale_in = scale_out;
450 scale_out = bz_segs[i+1]._t - bz_segs[i]._t;
452 if (!bz_segs[i]._v[3].almost_equal(bz_segs[i+1]._v[0], 0.0001f)) {
457 n = hc->
append_cv(HC_FREE, bz_segs[i+1]._v[0]);
458 hc->
set_cv_in(n, 3.0f * (bz_segs[i]._v[3] - bz_segs[i]._v[2]) / scale_in);
461 hc->
set_cv_out(n, 3.0f * (bz_segs[i+1]._v[1] - bz_segs[i+1]._v[0]) / scale_out);
465 scale_in = scale_out;
466 i = bz_segs.size()-1;
467 n = hc->
append_cv(HC_SMOOTH, bz_segs[i]._v[3]);
468 hc->
set_cv_in(n, 3.0f * (bz_segs[i]._v[3] - bz_segs[i]._v[2]) / scale_in);
474 for (n = 1; n < num_cvs-1; n++) {
479 if (in.almost_equal(out, 0.0001f)) {
484 if (in.almost_equal(out, 0.0001f)) {
500 nassertr(nurbs !=
nullptr,
false);
509 nurbs->remove_all_cvs();
511 if (!bz_segs.empty()) {
513 for (i = 0; i < (int)bz_segs.size(); i++) {
514 nurbs->append_cv(bz_segs[i]._v[0]);
515 nurbs->append_cv(bz_segs[i]._v[1]);
516 nurbs->append_cv(bz_segs[i]._v[2]);
517 if (i == (
int)bz_segs.size()-1 ||
518 !bz_segs[i]._v[3].almost_equal(bz_segs[i+1]._v[0], 0.0001f)) {
519 nurbs->append_cv(bz_segs[i]._v[3]);
525 nurbs->set_knot(0, 0.0f);
526 nurbs->set_knot(1, 0.0f);
527 nurbs->set_knot(2, 0.0f);
528 nurbs->set_knot(3, 0.0f);
530 for (i = 0; i < (int)bz_segs.size(); i++) {
533 nurbs->set_knot(ki, t);
534 nurbs->set_knot(ki+1, t);
535 nurbs->set_knot(ki+2, t);
537 if (i == ((
int)bz_segs.size())-1 ||
538 !bz_segs[i]._v[3].almost_equal(bz_segs[i+1]._v[0], 0.0001f)) {
539 nurbs->set_knot(ki, t);
559 _drawers.push_back(drawer);
569 _drawers.remove(drawer);
579 void ParametricCurve::
580 invalidate(PN_stdfloat, PN_stdfloat) {
588 void ParametricCurve::
604 bool ParametricCurve::
605 format_egg(std::ostream &,
const std::string &,
const std::string &,
int)
const {
616 PN_stdfloat ParametricCurve::
617 r_calc_length(PN_stdfloat t1, PN_stdfloat t2,
const LPoint3 &p1,
const LPoint3 &p2,
618 PN_stdfloat seglength)
const {
619 static const PN_stdfloat length_tolerance = 0.0000001f;
620 static const PN_stdfloat t_tolerance = 0.000001f;
622 if (t2 - t1 < t_tolerance) {
630 PN_stdfloat left, right;
634 get_point(tmid, pmid);
637 left = (p1 - pmid).length();
638 right = (pmid - p2).length();
640 if ((left + right) - seglength < length_tolerance) {
645 return r_calc_length(t1, tmid, p1, pmid, left) +
646 r_calc_length(tmid, t2, pmid, p2, right);
658 bool ParametricCurve::
659 r_find_length(PN_stdfloat target_length, PN_stdfloat &found_t,
660 PN_stdfloat t1, PN_stdfloat t2,
661 const LPoint3 &p1,
const LPoint3 &p2,
662 PN_stdfloat &seglength)
const {
663 static const PN_stdfloat length_tolerance = 0.0000001f;
664 static const PN_stdfloat t_tolerance = 0.000001f;
666 if (target_length < t_tolerance) {
676 PN_stdfloat left, right;
680 get_point(tmid, pmid);
683 left = (p1 - pmid).length();
684 right = (pmid - p2).length();
686 if ((left + right) - seglength < length_tolerance) {
688 return find_t_linear(target_length, found_t, t1, t2, p1, p2);
707 if (r_find_length(target_length, found_t, t1, tmid, p1, pmid, left)) {
712 if (r_find_length(target_length - left, found_t, tmid, t2, pmid, p2, right)) {
717 seglength = left + right;
731 bool ParametricCurve::
732 r_find_t(PN_stdfloat target_length, PN_stdfloat &found_t,
733 PN_stdfloat t1, PN_stdfloat t2,
734 const LPoint3 &p1,
const LPoint3 &p2)
const {
735 static const PN_stdfloat length_tolerance = 0.0001f;
736 static const PN_stdfloat t_tolerance = 0.0001f;
738 if (parametrics_cat.is_spam()) {
739 parametrics_cat.spam()
740 <<
"target_length " << target_length <<
" t1 " << t1 <<
" t2 " << t2 <<
"\n";
744 if (target_length < length_tolerance) {
750 PN_stdfloat point_dist;
751 point_dist = (p2 - p1).length();
754 if (point_dist < target_length) {
759 if ( (point_dist - target_length ) < length_tolerance ) {
765 if ((t2 - t1) < t_tolerance) {
777 get_point(tmid, pmid);
780 if (r_find_t(target_length, found_t, t1, tmid, p1, pmid)) {
784 left = (p1 - pmid).length();
785 if (r_find_t(target_length - left, found_t, tmid, t2, pmid, p2)) {
797 bool ParametricCurve::
798 find_t_linear(PN_stdfloat target_length, PN_stdfloat &found_t,
799 PN_stdfloat t1, PN_stdfloat t2,
800 const LPoint3 &p1,
const LPoint3 &p2)
const {
801 const PN_stdfloat length_tolerance = (p1-p2).length()/tolerance_divisor;
802 const PN_stdfloat t_tolerance = (t1+t2)/tolerance_divisor;
804 if (parametrics_cat.is_spam()) {
805 parametrics_cat.spam()
806 <<
"target_length " << target_length <<
" t1 " << t1 <<
" t2 " << t2 <<
"\n";
811 if (target_length > (p1 - p2).length()) {
816 PN_stdfloat tleft = t1;
817 PN_stdfloat tright = t2;
823 tmid = (tleft + tright) * 0.5f;
824 get_point(tmid, pmid);
825 len = (pmid - p1).length();
836 if (fabs(len - target_length) < length_tolerance) {
849 if ((tright - tleft) < t_tolerance) {
856 if (len > target_length) {
871 void ParametricCurve::
884 void ParametricCurve::
886 PandaNode::fillin(scan, manager);
bool open_write(std::ofstream &stream, bool truncate=true) const
Opens the indicated ifstream for writing the file, if possible.
A basic node of the scene graph or data graph.
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 void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
A virtual base class for parametric curves.
int get_cv_type(int n) const
Returns the given CV's continuity type, HC_CUT, HC_FREE, HC_G1, or HC_SMOOTH, or 0 if there is no suc...
int get_num_dimensions() const
Returns the number of significant dimensions in the curve's vertices, as set by a previous call to se...
bool set_cv_out(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Changes the given CV's out tangent.
virtual bool recompute()
Recalculates the curve, if necessary.
ParametricCurve()
This is a virtual base class.
void register_drawer(ParametricCurveDrawer *drawer)
Registers a Drawer with this curve that will automatically be updated whenever the curve is modified,...
int append_cv(int type, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Adds a new CV to the end of the curve.
std::string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
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...
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual bool convert_to_hermite(HermiteCurve *hc) const
Stores an equivalent curve representation in the indicated Hermite curve, if possible.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of PandaNode by calling the xf...
void set_num_dimensions(int num)
Specifies the number of significant dimensions in the curve's vertices.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
This abstract class defines the interface only for a Nurbs-style curve, with knots and coordinates in...
int get_num_cvs() const
Returns the number of CV's in the curve.
virtual NurbsCurveInterface * get_nurbs_interface()
Returns a pointer to the object as a NurbsCurveInterface object if it happens to be a NURBS-style cur...
A parametric curve defined by a sequence of control vertices, each with an in and out tangent.
virtual bool stitch(const ParametricCurve *a, const ParametricCurve *b)
Regenerates this curve as one long curve: the first curve connected end-to- end with the second one.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL vector.
virtual bool is_valid() const
Returns true if the curve is defined.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_int8(int8_t value)
Adds a signed 8-bit integer to the datagram.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void remove_all_cvs()
Removes all CV's from the curve.
The name of a file, such as a texture file or an Egg file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const LVecBase3 & get_cv_in(int n) const
Returns the in tangent of the given CV.
virtual PN_stdfloat get_max_t() const
Returns the upper bound of t for the entire curve.
virtual bool get_bezier_segs(BezierSegs &) const
Fills up the indicated vector with a list of BezierSeg structs that describe the curve.
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of PandaNode by duplicating ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool set_cv_type(int n, int type)
Changes the given CV's continuity type.
virtual bool adjust_pt(PN_stdfloat t, PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat tx, PN_stdfloat ty, PN_stdfloat tz)
Recomputes the curve such that it passes through the point (px, py, pz) with the tangent (tx,...
virtual bool adjust_tangent(PN_stdfloat t, PN_stdfloat tx, PN_stdfloat ty, PN_stdfloat tz)
Recomputes the curve such that it has the tangent (tx, ty, tz) at time t, but keeps the same position...
void set_curve_type(int type)
Sets the flag indicating the use to which the curve is intended to be put.
bool set_cv_tstart(int n, PN_stdfloat tstart)
Changes the given CV's parametric starting time.
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.
A class to retrieve the individual data elements previously stored in a Datagram.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
int8_t get_int8()
Extracts a signed 8-bit integer.
TypeHandle is the identifier used to differentiate C++ class types.
virtual bool convert_to_nurbs(ParametricCurve *nc) const
Stores in the indicated NurbsCurve a NURBS representation of an equivalent curve.
bool set_cv_in(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Changes the given CV's in tangent.
virtual bool get_bezier_seg(BezierSeg &) const
Fills the BezierSeg structure with a description of the curve segment as a Bezier,...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
const LVecBase3 & get_cv_out(int n) const
Returns the out tangent of the given CV.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_curve_type() const
Returns the flag indicating the use to which the curve is intended to be put.