15 #include "parametricCurve.h" 16 #include "config_parametrics.h" 17 #include "hermiteCurve.h" 18 #include "nurbsCurve.h" 21 #include "datagramIterator.h" 22 #include "bamWriter.h" 23 #include "bamReader.h" 24 #include "omniBoundingVolume.h" 26 static const PN_stdfloat tolerance_divisor = 100000.0f;
39 _curve_type = PCT_NONE;
54 nassertv(_drawers.empty());
130 switch (_curve_type) {
169 _num_dimensions = num;
183 return _num_dimensions;
211 PN_stdfloat to_minus_from = to - from;
213 if (to_minus_from < 0.0f) {
214 PN_stdfloat temp = to;
217 to_minus_from=-to_minus_from;
221 int num_segs = (int)(to_minus_from) + 1;
224 PN_stdfloat net = 0.0f;
226 for (
int i = 1; i <= num_segs; i++) {
230 t2 = (to - from) * (PN_stdfloat)i / (PN_stdfloat)num_segs + from;
233 net += r_calc_length(t1, t2, p1, p2, (p1 - p2).length());
253 find_length(PN_stdfloat start_t, PN_stdfloat length_offset)
const {
254 nassertr(length_offset >= 0.0f, start_t);
255 nassertr(start_t >= 0.0f && start_t <=
get_max_t(), start_t);
262 int num_segs = (int)cfloor(max_t - start_t + 1);
265 PN_stdfloat net = 0.0f;
267 for (
int i = 1; i <= num_segs; i++) {
268 assert(net <= length_offset);
273 t2 = start_t + (((max_t - start_t) * (PN_stdfloat)i) / (PN_stdfloat)num_segs);
276 PN_stdfloat seglength = (p1 - p2).length();
279 if (r_find_length(length_offset - net, result,
280 t1, t2, p1, p2, seglength)) {
323 adjust_pt(PN_stdfloat, PN_stdfloat, PN_stdfloat, PN_stdfloat, PN_stdfloat, PN_stdfloat, PN_stdfloat) {
351 parametrics_cat.error()
352 << get_type() <<
" does not support stitching.\n";
370 parametrics_cat.error()
371 <<
"Unable to write to " << filename <<
"\n";
405 if (!curve_type.empty()) {
413 if (cs == CS_default) {
414 cs = get_default_coordinate_system();
417 if (cs != CS_invalid) {
418 out <<
"<CoordinateSystem> { ";
443 if (!format_egg(out, get_name(), curve_type, 0)) {
517 if (!bz_segs.empty()) {
518 PN_stdfloat scale_in = 0.0f;
519 PN_stdfloat scale_out = bz_segs[0]._t;
520 n = hc->
append_cv(HC_SMOOTH, bz_segs[0]._v[0]);
521 hc->
set_cv_out(n, 3.0f * (bz_segs[0]._v[1] - bz_segs[0]._v[0]) / scale_out);
523 for (i = 0; i < (int)bz_segs.size()-1; i++) {
524 scale_in = scale_out;
525 scale_out = bz_segs[i+1]._t - bz_segs[i]._t;
527 if (!bz_segs[i]._v[3].almost_equal(bz_segs[i+1]._v[0], 0.0001f)) {
532 n = hc->
append_cv(HC_FREE, bz_segs[i+1]._v[0]);
533 hc->
set_cv_in(n, 3.0f * (bz_segs[i]._v[3] - bz_segs[i]._v[2]) / scale_in);
536 hc->
set_cv_out(n, 3.0f * (bz_segs[i+1]._v[1] - bz_segs[i+1]._v[0]) / scale_out);
540 scale_in = scale_out;
541 i = bz_segs.size()-1;
542 n = hc->
append_cv(HC_SMOOTH, bz_segs[i]._v[3]);
543 hc->
set_cv_in(n, 3.0f * (bz_segs[i]._v[3] - bz_segs[i]._v[2]) / scale_in);
549 for (n = 1; n < num_cvs-1; n++) {
587 nurbs->remove_all_cvs();
589 if (!bz_segs.empty()) {
591 for (i = 0; i < (int)bz_segs.size(); i++) {
592 nurbs->append_cv(bz_segs[i]._v[0]);
593 nurbs->append_cv(bz_segs[i]._v[1]);
594 nurbs->append_cv(bz_segs[i]._v[2]);
595 if (i == (
int)bz_segs.size()-1 ||
596 !bz_segs[i]._v[3].almost_equal(bz_segs[i+1]._v[0], 0.0001f)) {
597 nurbs->append_cv(bz_segs[i]._v[3]);
603 nurbs->set_knot(0, 0.0f);
604 nurbs->set_knot(1, 0.0f);
605 nurbs->set_knot(2, 0.0f);
606 nurbs->set_knot(3, 0.0f);
608 for (i = 0; i < (int)bz_segs.size(); i++) {
611 nurbs->set_knot(ki, t);
612 nurbs->set_knot(ki+1, t);
613 nurbs->set_knot(ki+2, t);
615 if (i == ((
int)bz_segs.size())-1 ||
616 !bz_segs[i]._v[3].almost_equal(bz_segs[i+1]._v[0], 0.0001f)) {
617 nurbs->set_knot(ki, t);
641 _drawers.push_back(drawer);
653 _drawers.remove(drawer);
666 void ParametricCurve::
667 invalidate(PN_stdfloat, PN_stdfloat) {
678 void ParametricCurve::
697 bool ParametricCurve::
698 format_egg(ostream &,
const string &,
const string &,
int)
const {
712 PN_stdfloat ParametricCurve::
713 r_calc_length(PN_stdfloat t1, PN_stdfloat t2,
const LPoint3 &p1,
const LPoint3 &p2,
714 PN_stdfloat seglength)
const {
715 static const PN_stdfloat length_tolerance = 0.0000001f;
716 static const PN_stdfloat t_tolerance = 0.000001f;
718 if (t2 - t1 < t_tolerance) {
726 PN_stdfloat left, right;
731 get_point(tmid, pmid);
734 left = (p1 - pmid).length();
735 right = (pmid - p2).length();
737 if ((left + right) - seglength < length_tolerance) {
742 return r_calc_length(t1, tmid, p1, pmid, left) +
743 r_calc_length(tmid, t2, pmid, p2, right);
759 bool ParametricCurve::
760 r_find_length(PN_stdfloat target_length, PN_stdfloat &found_t,
761 PN_stdfloat t1, PN_stdfloat t2,
763 PN_stdfloat &seglength)
const {
764 static const PN_stdfloat length_tolerance = 0.0000001f;
765 static const PN_stdfloat t_tolerance = 0.000001f;
767 if (target_length < t_tolerance) {
777 PN_stdfloat left, right;
782 get_point(tmid, pmid);
785 left = (p1 - pmid).length();
786 right = (pmid - p2).length();
788 if ((left + right) - seglength < length_tolerance) {
790 return find_t_linear(target_length, found_t, t1, t2, p1, p2);
809 if (r_find_length(target_length, found_t, t1, tmid, p1, pmid, left)) {
814 if (r_find_length(target_length - left, found_t, tmid, t2, pmid, p2, right)) {
819 seglength = left + right;
837 bool ParametricCurve::
838 r_find_t(PN_stdfloat target_length, PN_stdfloat &found_t,
839 PN_stdfloat t1, PN_stdfloat t2,
841 static const PN_stdfloat length_tolerance = 0.0001f;
842 static const PN_stdfloat t_tolerance = 0.0001f;
844 if (parametrics_cat.is_spam()) {
845 parametrics_cat.spam()
846 <<
"target_length " << target_length <<
" t1 " << t1 <<
" t2 " << t2 <<
"\n";
850 if (target_length < length_tolerance) {
856 PN_stdfloat point_dist;
857 point_dist = (p2 - p1).length();
860 if (point_dist < target_length) {
865 if ( (point_dist - target_length ) < length_tolerance ) {
871 if ((t2 - t1) < t_tolerance) {
884 get_point(tmid, pmid);
887 if (r_find_t(target_length, found_t, t1, tmid, p1, pmid)) {
891 left = (p1 - pmid).length();
892 if (r_find_t(target_length - left, found_t, tmid, t2, pmid, p2)) {
906 bool ParametricCurve::
907 find_t_linear(PN_stdfloat target_length, PN_stdfloat &found_t,
908 PN_stdfloat t1, PN_stdfloat t2,
910 const PN_stdfloat length_tolerance = (p1-p2).length()/tolerance_divisor;
911 const PN_stdfloat t_tolerance = (t1+t2)/tolerance_divisor;
913 if (parametrics_cat.is_spam()) {
914 parametrics_cat.spam()
915 <<
"target_length " << target_length <<
" t1 " << t1 <<
" t2 " << t2 <<
"\n";
920 if (target_length > (p1 - p2).length()) {
925 PN_stdfloat tleft = t1;
926 PN_stdfloat tright = t2;
932 tmid = (tleft + tright) * 0.5f;
933 get_point(tmid, pmid);
934 len = (pmid - p1).length();
945 if (fabs(len - target_length) < length_tolerance) {
958 if ((tright - tleft) < t_tolerance) {
965 if (len > target_length) {
982 void ParametricCurve::
998 void ParametricCurve::
1000 PandaNode::fillin(scan, manager);
PN_int8 get_int8()
Extracts a signed 8-bit integer.
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, 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.
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.
void add_int8(PN_int8 value)
Adds a signed 8-bit integer to the datagram.
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.
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.
virtual bool convert_to_hermite(HermiteCurve *hc) const
Stores an equivalent curve representation in the indicated Hermite curve, if possible.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
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 a three-component point in space (as opposed to a three-component vector, which represents a ...
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...
bool almost_equal(const LVecBase3f &other, float threshold) const
Returns true if two vectors are memberwise equal within a specified tolerance.
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...
This is our own Panda specialization on the default STL vector.
virtual bool is_valid() const
Returns true if the curve is defined.
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.
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 ...
string get_basename_wo_extension() const
Returns the basename part of the filename, without the file extension.
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.
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, if possible, but does not change the _t member of the structure.
bool normalize()
Normalizes the vector in place.
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.
int get_curve_type() const
Returns the flag indicating the use to which the curve is intended to be put.