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;
169 calc_length(PN_stdfloat from, PN_stdfloat to)
const {
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)) {
256 adjust_point(PN_stdfloat, PN_stdfloat, PN_stdfloat, PN_stdfloat) {
265 adjust_tangent(PN_stdfloat, PN_stdfloat, PN_stdfloat, PN_stdfloat) {
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);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
A class to retrieve the individual data elements previously stored in a Datagram.
int8_t get_int8()
Extracts a signed 8-bit integer.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void add_int8(int8_t value)
Adds a signed 8-bit integer to the datagram.
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.
A parametric curve defined by a sequence of control vertices, each with an in and out tangent.
int append_cv(int type, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Adds a new CV to the end of the curve.
bool set_cv_out(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Changes the given CV's out tangent.
bool set_cv_tstart(int n, PN_stdfloat tstart)
Changes the given CV's parametric starting time.
const LVecBase3 & get_cv_out(int n) const
Returns the out tangent of the given CV.
int get_num_cvs() const
Returns the number of CV's in the curve.
bool set_cv_in(int n, PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Changes the given CV's in tangent.
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...
void remove_all_cvs()
Removes all CV's from the curve.
bool set_cv_type(int n, int type)
Changes the given CV's continuity type.
const LVecBase3 & get_cv_in(int n) const
Returns the in tangent of the given CV.
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
This abstract class defines the interface only for a Nurbs-style curve, with knots and coordinates in...
A basic node of the scene graph or data graph.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
A virtual base class for parametric curves.
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...
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.
int get_num_dimensions() const
Returns the number of significant dimensions in the curve's vertices, as set by a previous call to se...
virtual bool convert_to_nurbs(ParametricCurve *nc) const
Stores in the indicated NurbsCurve a NURBS representation of an equivalent 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...
virtual bool get_bezier_seg(BezierSeg &) const
Fills the BezierSeg structure with a description of the curve segment as a Bezier,...
virtual bool get_bezier_segs(BezierSegs &) const
Fills up the indicated vector with a list of BezierSeg structs that describe the curve.
ParametricCurve()
This is a virtual base class.
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.
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of PandaNode by calling the xf...
virtual bool is_valid() const
Returns true if the curve is defined.
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 set_num_dimensions(int num)
Specifies the number of significant dimensions in the curve's vertices.
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.
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of PandaNode by duplicating ...
void unregister_drawer(ParametricCurveDrawer *drawer)
Removes a previously registered drawer from the list of automatically- refreshed drawers.
virtual bool convert_to_hermite(HermiteCurve *hc) const
Stores an equivalent curve representation in the indicated Hermite curve, if possible.
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...
TypeHandle is the identifier used to differentiate C++ class types.
This is our own Panda specialization on the default STL vector.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.