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);