discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

NURBS length review and comments

JD
John David
Thu, Feb 6, 2025 9:42 PM

I REALLY want to play with BOSL2's the new NURBS library, but my use case
leans heavily on calculating the length.  Since one has not been provided,
I wrote one that I think is generic enough to be generally useful.  Please
critique the following code, so that I can nail it down before going way
down a rabbit hole...

Basically, I recursively evaluate a general nurbs_curve call, and double
the splinesteps at each step.  The termination condition comes when the
percent of the previous length and the current eval length exceeds some
small epsilon. (code below). For this rendition I chose to evaluate a
percentage of the overall length instead of a raw difference -- because I
will be dealing with very large numbers, and very small numbers, and a
percent works well for me ATM.

I used one of the example curves from the NURBS library, and it takes a
splinesteps=64 to give the results "... diff:", 0.0170575, " for
splinesteps:", 64, " percent:", 0.0000677391 with a length of 251.811. We
could also specify the termination condition by difference, or whatever
people want.

Also, I know there is a single line trick using a for statement to evaluate
a 2d and 3d points, but I cannot remember the trick. Let me know if you can
suggest a rewrite of the _dist function to take 2d and 3d points.

Thanks and best regards,

EBo --

include <BOSL2/std.scad>
include <BOSL2/nurbs.scad>

control =
[[5,0,0],[0,20,0],[33,43,0],[37,88,0],[60,62,0],[44,22,0],[77,44,0],[79,22,0],[44,3,0],[22,7,0]];
nurb_len = nurbs_len(control,2,splinesteps=4);
echo("*** nurb_len:",nurb_len);

// _dist: a helper function to calculate the distance between two NURB
//  point evaluations.
function _dist(p1, p2) =
sqrt((p1.x-p2.x)^2 + (p1.y-p2.y)^2 + (p1.z-p2.z)^2);

// _lsum: a recursive helper function to calculate the length of
//  multiple NURB evaluatited points. Uses tail recursion to
//  terminate.
function _lsum(v, i=1, r=0) =
i<len(v)  ? _lsum(v, i+1, r+_dist(v[i-1],v[i])) : r;

// nurbs_len: evaluate the length of a NURBS curve.  This is a
//  recursive evaluation which evaluates the twice the splinesteps at
//  each recursions.  It also sets and passes dpen the variable
//  _priorlen to save recalculating prior length calculations again.
//
// variables:
//  control,degree,u,mult,weights,type="clamped",knots : are all
//      passed through to the nurbs_curve evaluation function.
//  splinesteps: also passed on to nurbs_curve evaluation function,
//      but set as a default to 4.
//
// returns: the estimated spline length whose nurb_curve splinesteps
//  and splinesteps2 by less than eps percent.
function nurbs_len(control,degree,splinesteps=4,
u, mult, weights, type="clamped", knots,
eps=0.0001, _priorlen=0) =
let (
pts = nurbs_curve(control,degree, splinesteps,
u, mult, weights, type, knots),
slen = _lsum(pts),
dif = abs(_priorlen-slen)
) echo("... diff:",dif, "  for splinesteps:", splinesteps, "  percent:",
1-_priorlen/slen)
_priorlen/slen <= 1.0-eps ?
nurbs_len(control,degree,splinesteps
2,
u, mult, weights, type, knots,
eps, _priorlen=slen)
: slen;

I REALLY want to play with BOSL2's the new NURBS library, but my use case leans heavily on calculating the length. Since one has not been provided, I wrote one that I think is generic enough to be generally useful. Please critique the following code, so that I can nail it down before going way down a rabbit hole... Basically, I recursively evaluate a general nurbs_curve call, and double the splinesteps at each step. The termination condition comes when the percent of the previous length and the current eval length exceeds some small epsilon. (code below). For this rendition I chose to evaluate a percentage of the overall length instead of a raw difference -- because I will be dealing with very large numbers, and very small numbers, and a percent works well for me ATM. I used one of the example curves from the NURBS library, and it takes a splinesteps=64 to give the results "... diff:", 0.0170575, " for splinesteps:", 64, " percent:", 0.0000677391 with a length of 251.811. We could also specify the termination condition by difference, or whatever people want. Also, I know there is a single line trick using a for statement to evaluate a 2d and 3d points, but I cannot remember the trick. Let me know if you can suggest a rewrite of the _dist function to take 2d and 3d points. Thanks and best regards, EBo -- include <BOSL2/std.scad> include <BOSL2/nurbs.scad> control = [[5,0,0],[0,20,0],[33,43,0],[37,88,0],[60,62,0],[44,22,0],[77,44,0],[79,22,0],[44,3,0],[22,7,0]]; nurb_len = nurbs_len(control,2,splinesteps=4); echo("*** nurb_len:",nurb_len); // _dist: a helper function to calculate the distance between two NURB // point evaluations. function _dist(p1, p2) = sqrt((p1.x-p2.x)^2 + (p1.y-p2.y)^2 + (p1.z-p2.z)^2); // _lsum: a recursive helper function to calculate the length of // multiple NURB evaluatited points. Uses tail recursion to // terminate. function _lsum(v, i=1, r=0) = i<len(v) ? _lsum(v, i+1, r+_dist(v[i-1],v[i])) : r; // nurbs_len: evaluate the length of a NURBS curve. This is a // recursive evaluation which evaluates the twice the splinesteps at // each recursions. It also sets and passes dpen the variable // _priorlen to save recalculating prior length calculations again. // // variables: // control,degree,u,mult,weights,type="clamped",knots : are all // passed through to the nurbs_curve evaluation function. // splinesteps: also passed on to nurbs_curve evaluation function, // but set as a default to 4. // // returns: the estimated spline length whose nurb_curve splinesteps // and splinesteps*2 by less than eps percent. function nurbs_len(control,degree,splinesteps=4, u, mult, weights, type="clamped", knots, eps=0.0001, _priorlen=0) = let ( pts = nurbs_curve(control,degree, splinesteps, u, mult, weights, type, knots), slen = _lsum(pts), dif = abs(_priorlen-slen) ) echo("... diff:",dif, " for splinesteps:", splinesteps, " percent:", 1-_priorlen/slen) _priorlen/slen <= 1.0-eps ? nurbs_len(control,degree,splinesteps*2, u, mult, weights, type, knots, eps, _priorlen=slen) : slen;
CM
Curt McDowell
Thu, Feb 6, 2025 11:01 PM

That strategy looks pretty reasonable since there is no closed form for
the arc length. The only thing I'd suggest is to get rid of _dist(p1,
p2) and use norm(p1 - p2). That expression works for both 2D and 3D, and
by extension, so would _lsum().

Regards,
Curt

On 2/6/2025 1:42 PM, John David via Discuss wrote:

I REALLY want to play with BOSL2's the new NURBS library, but my use
case leans heavily on calculating the length. Since one has not been
provided, I wrote one that I think is generic enough to be generally
useful.  Please critique the following code, so that I can nail it
down before going way down a rabbit hole...

That strategy looks pretty reasonable since there is no closed form for the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2) and use norm(p1 - p2). That expression works for both 2D and 3D, and by extension, so would _lsum(). Regards, Curt On 2/6/2025 1:42 PM, John David via Discuss wrote: > I REALLY want to play with BOSL2's the new NURBS library, but my use > case leans heavily on calculating the length. Since one has not been > provided, I wrote one that I think is generic enough to be generally > useful.  Please critique the following code, so that I can nail it > down before going way down a rabbit hole...
JD
John David
Thu, Feb 6, 2025 11:35 PM

Thank you Curt.  That change has been made and tested.

On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss <
discuss@lists.openscad.org> wrote:

That strategy looks pretty reasonable since there is no closed form for
the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2)
and use norm(p1 - p2). That expression works for both 2D and 3D, and by
extension, so would _lsum().

Regards,
Curt
On 2/6/2025 1:42 PM, John David via Discuss wrote:

I REALLY want to play with BOSL2's the new NURBS library, but my use case
leans heavily on calculating the length.  Since one has not been provided,
I wrote one that I think is generic enough to be generally useful.  Please
critique the following code, so that I can nail it down before going way
down a rabbit hole...


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Thank you Curt. That change has been made and tested. On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss < discuss@lists.openscad.org> wrote: > That strategy looks pretty reasonable since there is no closed form for > the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2) > and use norm(p1 - p2). That expression works for both 2D and 3D, and by > extension, so would _lsum(). > > Regards, > Curt > On 2/6/2025 1:42 PM, John David via Discuss wrote: > > I REALLY want to play with BOSL2's the new NURBS library, but my use case > leans heavily on calculating the length. Since one has not been provided, > I wrote one that I think is generic enough to be generally useful. Please > critique the following code, so that I can nail it down before going way > down a rabbit hole... > > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
AM
Adrian Mariano
Fri, Feb 7, 2025 12:15 AM

You could just use path_length() instead of a recursive sum.  (It's
possible path_length() will be faster since it's not recursive, and it is a
bit simpler to call that.)    You might possibly want to do
priolen/slen-1<epsilon because if epsilon is very small (like say around
machine epsilon), then 1-epsilon might equal 1.  A relative change seems
like the right termination condition.

As I previously mentioned, there is bezier_length() in BOSL2 for computing
the length of a bezier.  It might be interesting to drop nurbs into that
code---I'm not sure who wrote it (not me).  It does something completely
different involving straightness of the curve but it's also more local so
it doesn't refine everywhere.

On Thu, Feb 6, 2025 at 6:35 PM John David via Discuss <
discuss@lists.openscad.org> wrote:

Thank you Curt.  That change has been made and tested.

On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss <
discuss@lists.openscad.org> wrote:

That strategy looks pretty reasonable since there is no closed form for
the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2)
and use norm(p1 - p2). That expression works for both 2D and 3D, and by
extension, so would _lsum().

Regards,
Curt
On 2/6/2025 1:42 PM, John David via Discuss wrote:

I REALLY want to play with BOSL2's the new NURBS library, but my use case
leans heavily on calculating the length.  Since one has not been provided,
I wrote one that I think is generic enough to be generally useful.  Please
critique the following code, so that I can nail it down before going way
down a rabbit hole...


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

You could just use path_length() instead of a recursive sum. (It's possible path_length() will be faster since it's not recursive, and it is a bit simpler to call that.) You might possibly want to do priolen/slen-1<epsilon because if epsilon is very small (like say around machine epsilon), then 1-epsilon might equal 1. A relative change seems like the right termination condition. As I previously mentioned, there is bezier_length() in BOSL2 for computing the length of a bezier. It might be interesting to drop nurbs into that code---I'm not sure who wrote it (not me). It does something completely different involving straightness of the curve but it's also more local so it doesn't refine everywhere. On Thu, Feb 6, 2025 at 6:35 PM John David via Discuss < discuss@lists.openscad.org> wrote: > Thank you Curt. That change has been made and tested. > > On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss < > discuss@lists.openscad.org> wrote: > >> That strategy looks pretty reasonable since there is no closed form for >> the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2) >> and use norm(p1 - p2). That expression works for both 2D and 3D, and by >> extension, so would _lsum(). >> >> Regards, >> Curt >> On 2/6/2025 1:42 PM, John David via Discuss wrote: >> >> I REALLY want to play with BOSL2's the new NURBS library, but my use case >> leans heavily on calculating the length. Since one has not been provided, >> I wrote one that I think is generic enough to be generally useful. Please >> critique the following code, so that I can nail it down before going way >> down a rabbit hole... >> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
JD
John David
Fri, Feb 7, 2025 1:30 AM

Excellent.  path_length worked.  I did not know about that function :-/

re: priolen/slen-1<epsilon...

Nice catch.  I can see how anything near machine epsilon could be an
issue.  Thanks.

re: bezier_length()...

Depending on the weights and knot sequences of the NURBS, they cannot be
reduced to a Bezier, and my intent with the way I implemented it was to
support any generic NURBS.  It would be nice if there was a closed form
solution for NURBS, but that is either provably not possible, or someone
has not figure out how yet.

Thanks, Adrian, that is helping to tighten up my code.

EBo --

On Thu, Feb 6, 2025 at 7:16 PM Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:

You could just use path_length() instead of a recursive sum.  (It's
possible path_length() will be faster since it's not recursive, and it is a
bit simpler to call that.)    You might possibly want to do
priolen/slen-1<epsilon because if epsilon is very small (like say around
machine epsilon), then 1-epsilon might equal 1.  A relative change seems
like the right termination condition.

As I previously mentioned, there is bezier_length() in BOSL2 for computing
the length of a bezier.  It might be interesting to drop nurbs into that
code---I'm not sure who wrote it (not me).  It does something completely
different involving straightness of the curve but it's also more local so
it doesn't refine everywhere.

On Thu, Feb 6, 2025 at 6:35 PM John David via Discuss <
discuss@lists.openscad.org> wrote:

Thank you Curt.  That change has been made and tested.

On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss <
discuss@lists.openscad.org> wrote:

That strategy looks pretty reasonable since there is no closed form for
the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2)
and use norm(p1 - p2). That expression works for both 2D and 3D, and by
extension, so would _lsum().

Regards,
Curt
On 2/6/2025 1:42 PM, John David via Discuss wrote:

I REALLY want to play with BOSL2's the new NURBS library, but my use
case leans heavily on calculating the length.  Since one has not been
provided, I wrote one that I think is generic enough to be generally
useful.  Please critique the following code, so that I can nail it down
before going way down a rabbit hole...


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Excellent. path_length worked. I did not know about that function :-/ re: priolen/slen-1<epsilon... Nice catch. I can see how anything near machine epsilon could be an issue. Thanks. re: bezier_length()... Depending on the weights and knot sequences of the NURBS, they cannot be reduced to a Bezier, and my intent with the way I implemented it was to support any generic NURBS. It would be nice if there was a closed form solution for NURBS, but that is either provably not possible, or someone has not figure out how yet. Thanks, Adrian, that is helping to tighten up my code. EBo -- On Thu, Feb 6, 2025 at 7:16 PM Adrian Mariano via Discuss < discuss@lists.openscad.org> wrote: > You could just use path_length() instead of a recursive sum. (It's > possible path_length() will be faster since it's not recursive, and it is a > bit simpler to call that.) You might possibly want to do > priolen/slen-1<epsilon because if epsilon is very small (like say around > machine epsilon), then 1-epsilon might equal 1. A relative change seems > like the right termination condition. > > As I previously mentioned, there is bezier_length() in BOSL2 for computing > the length of a bezier. It might be interesting to drop nurbs into that > code---I'm not sure who wrote it (not me). It does something completely > different involving straightness of the curve but it's also more local so > it doesn't refine everywhere. > > On Thu, Feb 6, 2025 at 6:35 PM John David via Discuss < > discuss@lists.openscad.org> wrote: > >> Thank you Curt. That change has been made and tested. >> >> On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> That strategy looks pretty reasonable since there is no closed form for >>> the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2) >>> and use norm(p1 - p2). That expression works for both 2D and 3D, and by >>> extension, so would _lsum(). >>> >>> Regards, >>> Curt >>> On 2/6/2025 1:42 PM, John David via Discuss wrote: >>> >>> I REALLY want to play with BOSL2's the new NURBS library, but my use >>> case leans heavily on calculating the length. Since one has not been >>> provided, I wrote one that I think is generic enough to be generally >>> useful. Please critique the following code, so that I can nail it down >>> before going way down a rabbit hole... >>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
AM
Adrian Mariano
Fri, Feb 7, 2025 2:24 AM

You know that I wrote the nurbs code you're using, right?  My suggestion
regarding bezier length is to replace every invocation of bezier_points
with nurbs_curve (passing all necessary paramters) to produce a new
nurbs_length function, not to try to reduce the nurbs to a bezier somehow
and use the existing function.

On Thu, Feb 6, 2025 at 8:30 PM John David ebo.2112@gmail.com wrote:

Excellent.  path_length worked.  I did not know about that function :-/

re: priolen/slen-1<epsilon...

Nice catch.  I can see how anything near machine epsilon could be an
issue.  Thanks.

re: bezier_length()...

Depending on the weights and knot sequences of the NURBS, they cannot be
reduced to a Bezier, and my intent with the way I implemented it was to
support any generic NURBS.  It would be nice if there was a closed form
solution for NURBS, but that is either provably not possible, or someone
has not figure out how yet.

Thanks, Adrian, that is helping to tighten up my code.

EBo --

On Thu, Feb 6, 2025 at 7:16 PM Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:

You could just use path_length() instead of a recursive sum.  (It's
possible path_length() will be faster since it's not recursive, and it is a
bit simpler to call that.)    You might possibly want to do
priolen/slen-1<epsilon because if epsilon is very small (like say around
machine epsilon), then 1-epsilon might equal 1.  A relative change seems
like the right termination condition.

As I previously mentioned, there is bezier_length() in BOSL2 for
computing the length of a bezier.  It might be interesting to drop nurbs
into that code---I'm not sure who wrote it (not me).  It does something
completely different involving straightness of the curve but it's also more
local so it doesn't refine everywhere.

On Thu, Feb 6, 2025 at 6:35 PM John David via Discuss <
discuss@lists.openscad.org> wrote:

Thank you Curt.  That change has been made and tested.

On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss <
discuss@lists.openscad.org> wrote:

That strategy looks pretty reasonable since there is no closed form for
the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2)
and use norm(p1 - p2). That expression works for both 2D and 3D, and by
extension, so would _lsum().

Regards,
Curt
On 2/6/2025 1:42 PM, John David via Discuss wrote:

I REALLY want to play with BOSL2's the new NURBS library, but my use
case leans heavily on calculating the length.  Since one has not been
provided, I wrote one that I think is generic enough to be generally
useful.  Please critique the following code, so that I can nail it down
before going way down a rabbit hole...


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

You know that I wrote the nurbs code you're using, right? My suggestion regarding bezier length is to replace every invocation of bezier_points with nurbs_curve (passing all necessary paramters) to produce a new nurbs_length function, not to try to reduce the nurbs to a bezier somehow and use the existing function. On Thu, Feb 6, 2025 at 8:30 PM John David <ebo.2112@gmail.com> wrote: > Excellent. path_length worked. I did not know about that function :-/ > > re: priolen/slen-1<epsilon... > > Nice catch. I can see how anything near machine epsilon could be an > issue. Thanks. > > re: bezier_length()... > > Depending on the weights and knot sequences of the NURBS, they cannot be > reduced to a Bezier, and my intent with the way I implemented it was to > support any generic NURBS. It would be nice if there was a closed form > solution for NURBS, but that is either provably not possible, or someone > has not figure out how yet. > > Thanks, Adrian, that is helping to tighten up my code. > > EBo -- > > On Thu, Feb 6, 2025 at 7:16 PM Adrian Mariano via Discuss < > discuss@lists.openscad.org> wrote: > >> You could just use path_length() instead of a recursive sum. (It's >> possible path_length() will be faster since it's not recursive, and it is a >> bit simpler to call that.) You might possibly want to do >> priolen/slen-1<epsilon because if epsilon is very small (like say around >> machine epsilon), then 1-epsilon might equal 1. A relative change seems >> like the right termination condition. >> >> As I previously mentioned, there is bezier_length() in BOSL2 for >> computing the length of a bezier. It might be interesting to drop nurbs >> into that code---I'm not sure who wrote it (not me). It does something >> completely different involving straightness of the curve but it's also more >> local so it doesn't refine everywhere. >> >> On Thu, Feb 6, 2025 at 6:35 PM John David via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> Thank you Curt. That change has been made and tested. >>> >>> On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>>> That strategy looks pretty reasonable since there is no closed form for >>>> the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2) >>>> and use norm(p1 - p2). That expression works for both 2D and 3D, and by >>>> extension, so would _lsum(). >>>> >>>> Regards, >>>> Curt >>>> On 2/6/2025 1:42 PM, John David via Discuss wrote: >>>> >>>> I REALLY want to play with BOSL2's the new NURBS library, but my use >>>> case leans heavily on calculating the length. Since one has not been >>>> provided, I wrote one that I think is generic enough to be generally >>>> useful. Please critique the following code, so that I can nail it down >>>> before going way down a rabbit hole... >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> >
SP
Sanjeev Prabhakar
Fri, Feb 7, 2025 2:25 AM

Application of bspline curves :)

[image: Screenshot 2025-02-07 at 7.53.37 AM.png]

On Fri, 7 Feb 2025 at 07:00, John David via Discuss <
discuss@lists.openscad.org> wrote:

Excellent.  path_length worked.  I did not know about that function :-/

re: priolen/slen-1<epsilon...

Nice catch.  I can see how anything near machine epsilon could be an
issue.  Thanks.

re: bezier_length()...

Depending on the weights and knot sequences of the NURBS, they cannot be
reduced to a Bezier, and my intent with the way I implemented it was to
support any generic NURBS.  It would be nice if there was a closed form
solution for NURBS, but that is either provably not possible, or someone
has not figure out how yet.

Thanks, Adrian, that is helping to tighten up my code.

EBo --

On Thu, Feb 6, 2025 at 7:16 PM Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:

You could just use path_length() instead of a recursive sum.  (It's
possible path_length() will be faster since it's not recursive, and it is a
bit simpler to call that.)    You might possibly want to do
priolen/slen-1<epsilon because if epsilon is very small (like say around
machine epsilon), then 1-epsilon might equal 1.  A relative change seems
like the right termination condition.

As I previously mentioned, there is bezier_length() in BOSL2 for
computing the length of a bezier.  It might be interesting to drop nurbs
into that code---I'm not sure who wrote it (not me).  It does something
completely different involving straightness of the curve but it's also more
local so it doesn't refine everywhere.

On Thu, Feb 6, 2025 at 6:35 PM John David via Discuss <
discuss@lists.openscad.org> wrote:

Thank you Curt.  That change has been made and tested.

On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss <
discuss@lists.openscad.org> wrote:

That strategy looks pretty reasonable since there is no closed form for
the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2)
and use norm(p1 - p2). That expression works for both 2D and 3D, and by
extension, so would _lsum().

Regards,
Curt
On 2/6/2025 1:42 PM, John David via Discuss wrote:

I REALLY want to play with BOSL2's the new NURBS library, but my use
case leans heavily on calculating the length.  Since one has not been
provided, I wrote one that I think is generic enough to be generally
useful.  Please critique the following code, so that I can nail it down
before going way down a rabbit hole...


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

Application of bspline curves :) [image: Screenshot 2025-02-07 at 7.53.37 AM.png] On Fri, 7 Feb 2025 at 07:00, John David via Discuss < discuss@lists.openscad.org> wrote: > Excellent. path_length worked. I did not know about that function :-/ > > re: priolen/slen-1<epsilon... > > Nice catch. I can see how anything near machine epsilon could be an > issue. Thanks. > > re: bezier_length()... > > Depending on the weights and knot sequences of the NURBS, they cannot be > reduced to a Bezier, and my intent with the way I implemented it was to > support any generic NURBS. It would be nice if there was a closed form > solution for NURBS, but that is either provably not possible, or someone > has not figure out how yet. > > Thanks, Adrian, that is helping to tighten up my code. > > EBo -- > > On Thu, Feb 6, 2025 at 7:16 PM Adrian Mariano via Discuss < > discuss@lists.openscad.org> wrote: > >> You could just use path_length() instead of a recursive sum. (It's >> possible path_length() will be faster since it's not recursive, and it is a >> bit simpler to call that.) You might possibly want to do >> priolen/slen-1<epsilon because if epsilon is very small (like say around >> machine epsilon), then 1-epsilon might equal 1. A relative change seems >> like the right termination condition. >> >> As I previously mentioned, there is bezier_length() in BOSL2 for >> computing the length of a bezier. It might be interesting to drop nurbs >> into that code---I'm not sure who wrote it (not me). It does something >> completely different involving straightness of the curve but it's also more >> local so it doesn't refine everywhere. >> >> On Thu, Feb 6, 2025 at 6:35 PM John David via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> Thank you Curt. That change has been made and tested. >>> >>> On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>>> That strategy looks pretty reasonable since there is no closed form for >>>> the arc length. The only thing I'd suggest is to get rid of _dist(p1, p2) >>>> and use norm(p1 - p2). That expression works for both 2D and 3D, and by >>>> extension, so would _lsum(). >>>> >>>> Regards, >>>> Curt >>>> On 2/6/2025 1:42 PM, John David via Discuss wrote: >>>> >>>> I REALLY want to play with BOSL2's the new NURBS library, but my use >>>> case leans heavily on calculating the length. Since one has not been >>>> provided, I wrote one that I think is generic enough to be generally >>>> useful. Please critique the following code, so that I can nail it down >>>> before going way down a rabbit hole... >>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org >> > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org >
JD
John David
Fri, Feb 7, 2025 3:27 PM

When I hit reply on the previous post, I sent it to Adrian only by
mistake.  Here it is again for the group.

re: You know that I wrote the nurbs code you're using, right?

no <sheepish grin>  Thank you for all this...

From a previous comment, "there is bezier_length() in BOSL2 for computing
the length of a bezier":

I must have misunderstood the statement.  If I recall correctly, a bezier
curve cannot exactly represent a circle, but a nurbs can.  So, what help
would the bezier_length() give me here?  To be honest, it has been nearly
25 years since I took Farin's class in CAGD.  I have forgotten a lot, and
may be misremembering the details.  I'm very confused at this point.

Ahhh... after rereading your post several times you are suggesting that I
refactor bezier_length to nurbs_length and pass though the weights, knots,
etc.  I'll give that a try.

As a note, this was the last revision of my code:

function nurbs_len(control,degree,splinesteps=4,
u, mult, weights, type="clamped", knots,
eps=0.0001, _priorlen=0) =
let (
pts = nurbs_curve(control,degree, splinesteps,
u, mult, weights, type, knots),
slen = path_length(pts),
diff = abs(_priorlen-slen)
) //echo("***
diff:",diff,"term:",1-(_priorlen/slen),"splinesteps:",splinesteps)
1-(_priorlen/slen) > eps ?
nurbs_len(control,degree,splinesteps*2,
u, mult, weights, type, knots,
eps, _priorlen=slen)
: slen;

EBo --

On Thu, Feb 6, 2025 at 9:24 PM Adrian Mariano avm4@cornell.edu wrote:

You know that I wrote the nurbs code you're using, right?  My suggestion
regarding bezier length is to replace every invocation of bezier_points
with nurbs_curve (passing all necessary paramters) to produce a new
nurbs_length function, not to try to reduce the nurbs to a bezier somehow
and use the existing function.

On Thu, Feb 6, 2025 at 8:30 PM John David ebo.2112@gmail.com wrote:

Excellent.  path_length worked.  I did not know about that function :-/

re: priolen/slen-1<epsilon...

Nice catch.  I can see how anything near machine epsilon could be an
issue.  Thanks.

re: bezier_length()...

Depending on the weights and knot sequences of the NURBS, they cannot be
reduced to a Bezier, and my intent with the way I implemented it was to
support any generic NURBS.  It would be nice if there was a closed form
solution for NURBS, but that is either provably not possible, or someone
has not figure out how yet.

Thanks, Adrian, that is helping to tighten up my code.

EBo --

On Thu, Feb 6, 2025 at 7:16 PM Adrian Mariano via Discuss <
discuss@lists.openscad.org> wrote:

You could just use path_length() instead of a recursive sum.  (It's
possible path_length() will be faster since it's not recursive, and it is a
bit simpler to call that.)    You might possibly want to do
priolen/slen-1<epsilon because if epsilon is very small (like say around
machine epsilon), then 1-epsilon might equal 1.  A relative change seems
like the right termination condition.

As I previously mentioned, there is bezier_length() in BOSL2 for
computing the length of a bezier.  It might be interesting to drop nurbs
into that code---I'm not sure who wrote it (not me).  It does something
completely different involving straightness of the curve but it's also more
local so it doesn't refine everywhere.

On Thu, Feb 6, 2025 at 6:35 PM John David via Discuss <
discuss@lists.openscad.org> wrote:

Thank you Curt.  That change has been made and tested.

On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss <
discuss@lists.openscad.org> wrote:

That strategy looks pretty reasonable since there is no closed form
for the arc length. The only thing I'd suggest is to get rid of _dist(p1,
p2) and use norm(p1 - p2). That expression works for both 2D and 3D, and by
extension, so would _lsum().

Regards,
Curt
On 2/6/2025 1:42 PM, John David via Discuss wrote:

I REALLY want to play with BOSL2's the new NURBS library, but my use
case leans heavily on calculating the length.  Since one has not been
provided, I wrote one that I think is generic enough to be generally
useful.  Please critique the following code, so that I can nail it down
before going way down a rabbit hole...


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

When I hit reply on the previous post, I sent it to Adrian only by mistake. Here it is again for the group. re: You know that I wrote the nurbs code you're using, right? no <sheepish grin> Thank you for all this... From a previous comment, "there is bezier_length() in BOSL2 for computing the length of a bezier": I must have misunderstood the statement. If I recall correctly, a bezier curve cannot exactly represent a circle, but a nurbs can. So, what help would the bezier_length() give me here? To be honest, it has been nearly 25 years since I took Farin's class in CAGD. I have forgotten a lot, and may be misremembering the details. I'm very confused at this point. Ahhh... after rereading your post several times you are suggesting that I refactor bezier_length to nurbs_length and pass though the weights, knots, etc. I'll give that a try. As a note, this was the last revision of my code: function nurbs_len(control,degree,splinesteps=4, u, mult, weights, type="clamped", knots, eps=0.0001, _priorlen=0) = let ( pts = nurbs_curve(control,degree, splinesteps, u, mult, weights, type, knots), slen = path_length(pts), diff = abs(_priorlen-slen) ) //echo("*** diff:",diff,"term:",1-(_priorlen/slen),"splinesteps:",splinesteps) 1-(_priorlen/slen) > eps ? nurbs_len(control,degree,splinesteps*2, u, mult, weights, type, knots, eps, _priorlen=slen) : slen; EBo -- On Thu, Feb 6, 2025 at 9:24 PM Adrian Mariano <avm4@cornell.edu> wrote: > You know that I wrote the nurbs code you're using, right? My suggestion > regarding bezier length is to replace every invocation of bezier_points > with nurbs_curve (passing all necessary paramters) to produce a new > nurbs_length function, not to try to reduce the nurbs to a bezier somehow > and use the existing function. > > On Thu, Feb 6, 2025 at 8:30 PM John David <ebo.2112@gmail.com> wrote: > >> Excellent. path_length worked. I did not know about that function :-/ >> >> re: priolen/slen-1<epsilon... >> >> Nice catch. I can see how anything near machine epsilon could be an >> issue. Thanks. >> >> re: bezier_length()... >> >> Depending on the weights and knot sequences of the NURBS, they cannot be >> reduced to a Bezier, and my intent with the way I implemented it was to >> support any generic NURBS. It would be nice if there was a closed form >> solution for NURBS, but that is either provably not possible, or someone >> has not figure out how yet. >> >> Thanks, Adrian, that is helping to tighten up my code. >> >> EBo -- >> >> On Thu, Feb 6, 2025 at 7:16 PM Adrian Mariano via Discuss < >> discuss@lists.openscad.org> wrote: >> >>> You could just use path_length() instead of a recursive sum. (It's >>> possible path_length() will be faster since it's not recursive, and it is a >>> bit simpler to call that.) You might possibly want to do >>> priolen/slen-1<epsilon because if epsilon is very small (like say around >>> machine epsilon), then 1-epsilon might equal 1. A relative change seems >>> like the right termination condition. >>> >>> As I previously mentioned, there is bezier_length() in BOSL2 for >>> computing the length of a bezier. It might be interesting to drop nurbs >>> into that code---I'm not sure who wrote it (not me). It does something >>> completely different involving straightness of the curve but it's also more >>> local so it doesn't refine everywhere. >>> >>> On Thu, Feb 6, 2025 at 6:35 PM John David via Discuss < >>> discuss@lists.openscad.org> wrote: >>> >>>> Thank you Curt. That change has been made and tested. >>>> >>>> On Thu, Feb 6, 2025 at 6:02 PM Curt McDowell via Discuss < >>>> discuss@lists.openscad.org> wrote: >>>> >>>>> That strategy looks pretty reasonable since there is no closed form >>>>> for the arc length. The only thing I'd suggest is to get rid of _dist(p1, >>>>> p2) and use norm(p1 - p2). That expression works for both 2D and 3D, and by >>>>> extension, so would _lsum(). >>>>> >>>>> Regards, >>>>> Curt >>>>> On 2/6/2025 1:42 PM, John David via Discuss wrote: >>>>> >>>>> I REALLY want to play with BOSL2's the new NURBS library, but my use >>>>> case leans heavily on calculating the length. Since one has not been >>>>> provided, I wrote one that I think is generic enough to be generally >>>>> useful. Please critique the following code, so that I can nail it down >>>>> before going way down a rabbit hole... >>>>> >>>>> _______________________________________________ >>>>> OpenSCAD mailing list >>>>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>>>> >>>> _______________________________________________ >>>> OpenSCAD mailing list >>>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>>> >>> _______________________________________________ >>> OpenSCAD mailing list >>> To unsubscribe send an email to discuss-leave@lists.openscad.org >>> >>