smoothing 2D curves in BOSL2

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

smoothing 2D curves in BOSL2

jon_bondy
I need to smooth a curve that I created by hand (enter X/Y pairs
measured from a photo), and looked to BOSL2, because I feel that it is
the most full-featured library I know of.  Of course, "full featured"
also means "hard to search", because there are so many files and
functions and modules.  The curves in question contain dozens of points,
so a simple bezier is not an obvious fit [sic]. Also, I need this part
to fit [!] up against a matching physical part, so getting a pretty
curve is less important than staying close to my points and making the
curve smoother.

How would you (whoever you are?) go about searching for a curve
smoothing function in BOSL2 (or elsewhere)?  Is there a BOSL2 cheat sheet?

I will need to do some 3D smoothing at some point soon, too.

I'm not asking anyone to point me at the function or module.  I want to
know how to think about my quest so that I don't have to post another
question like this in the future

Thanks!

Jon


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: smoothing 2D curves in BOSL2

OpenSCAD mailing list-2
If you aren't too concentrated on OpenSCAD for the entire project, Inkscape can trace your curve and smooth it, then with the Path to OpenSCAD extension (<v1.x), generate a similar set of points. The extension is a bit unrefined (you have to add the .scad manually) and tends to reduce the size (change scale to 1 in the code) but it gets stuff done. It may even support thickness = 0, but I'm not sure what might happen.

On Thursday, March 4, 2021, 12:02:35 PM EST, jon <[hidden email]> wrote:


I need to smooth a curve that I created by hand (enter X/Y pairs
measured from a photo), and looked to BOSL2, because I feel that it is
the most full-featured library I know of.  Of course, "full featured"
also means "hard to search", because there are so many files and
functions and modules.  The curves in question contain dozens of points,
so a simple bezier is not an obvious fit [sic]. Also, I need this part
to fit [!] up against a matching physical part, so getting a pretty
curve is less important than staying close to my points and making the
curve smoother.

How would you (whoever you are?) go about searching for a curve
smoothing function in BOSL2 (or elsewhere)?  Is there a BOSL2 cheat sheet?

I will need to do some 3D smoothing at some point soon, too.

I'm not asking anyone to point me at the function or module.  I want to
know how to think about my quest so that I don't have to post another
question like this in the future

Thanks!

Jon


_______________________________________________
OpenSCAD mailing list

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: smoothing 2D curves in BOSL2

Ronaldo
In reply to this post by jon_bondy
Jon,

I agree with you that it is hard to find the correct function/module in a library so big and comprehensive like BOSL2. I usually use the wiki (https://github.com/revarbat/BOSL2/wiki/) and recently found a general alphabetical index (https://github.com/revarbat/BOSL2/wiki/Index) and a cheat sheet (https://github.com/revarbat/BOSL2/wiki/CheatSheet). The cheat sheet is useful when you know in which file the function/module is defined and want to remember its argument names. The alphabetical index helps to locate a function/module by its name showing in what file it is defined. From the index and the sheet you have links to the function/module documentation in the wiki.

Those documentation resources become more useful as reference guides as you get acquainted with the library. At the beginning, it is hard. To find a function you suspect is defined in the library, you need at least to understand how it is organized in files so you can open a promising file in the wiki and look at the functions/modules defined there. The list of file names in the root of the wiki give some hints where the function you want might be. At the end of the right column of the wiki, you will find links to the alphabetical index and the cheat sheet,

A BOSL2 tutorial is being prepared.

I guess an interpolator defined in beziers.scad may help you to find the smooth curve you are looking for. Take a look at path_to_bezier() that, from a list of points, generates a bezier path (that is a sequence of connected Bezier arcs) connecting the points with tangent continuity. You will need bezier_curve() or bezier_polygon() to draw the curve or polygon from the bezier path or bezier_path() to sample points in the bezier path.



Em qui., 4 de mar. de 2021 às 17:02, jon <[hidden email]> escreveu:
I need to smooth a curve that I created by hand (enter X/Y pairs
measured from a photo), and looked to BOSL2, because I feel that it is
the most full-featured library I know of.  Of course, "full featured"
also means "hard to search", because there are so many files and
functions and modules.  The curves in question contain dozens of points,
so a simple bezier is not an obvious fit [sic]. Also, I need this part
to fit [!] up against a matching physical part, so getting a pretty
curve is less important than staying close to my points and making the
curve smoother.

How would you (whoever you are?) go about searching for a curve
smoothing function in BOSL2 (or elsewhere)?  Is there a BOSL2 cheat sheet?

I will need to do some 3D smoothing at some point soon, too.

I'm not asking anyone to point me at the function or module.  I want to
know how to think about my quest so that I don't have to post another
question like this in the future

Thanks!

Jon


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: smoothing 2D curves in BOSL2

adrianv
In reply to this post by jon_bondy
I would suggest in general as Ronaldo does that looking at the top level files shown on the wiki and considering whether they seem connected to your current problem.  This will get easier as you get more familiar with the library.  For the task you face, I would think that rounding.scad would be the obvious place to start.   However, I'm not sure you'll find a good automatic solution to your problem.  The methods I'm familiar with assume that you want to preserve either the sides (round_corners) or the vertices (smooth_path) of your input.  I'm not aware of anything that will find an approximate curve to a point list where you don't care about any exact matching, but want to minimize error.  That sounds like a least squares problem.  

jon_bondy wrote
I need to smooth a curve that I created by hand (enter X/Y pairs
measured from a photo), and looked to BOSL2, because I feel that it is
the most full-featured library I know of.  Of course, "full featured"
also means "hard to search", because there are so many files and
functions and modules.  The curves in question contain dozens of points,
so a simple bezier is not an obvious fit [sic]. Also, I need this part
to fit [!] up against a matching physical part, so getting a pretty
curve is less important than staying close to my points and making the
curve smoother.

How would you (whoever you are?) go about searching for a curve
smoothing function in BOSL2 (or elsewhere)?  Is there a BOSL2 cheat sheet?

I will need to do some 3D smoothing at some point soon, too.

I'm not asking anyone to point me at the function or module.  I want to
know how to think about my quest so that I don't have to post another
question like this in the future

Thanks!

Jon


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: smoothing 2D curves in BOSL2

RevarBat
In reply to this post by Ronaldo
At this point there’s four automatically generated indices for BOSL2:

There is also a manually created index that gives a brief description of each file at:
https://github.com/revarbat/BOSL2/wiki/Home

The TOC page is the Table of Contents, listing all the functions/modules/constants by file and section.

The Index page lists all functions/modules/constants alphabetically by name.

The Topics page lists all functions/modules/constants by topics. This is new and incomplete, and continually expanding as I trawl through and update the documentation. It may be thematically what you would want to use in this instance, though.

The CheatSheet page shows the names and typical argument variations for all functions/modules/constants, organized by file and section. This is mostly complete, but it is missing some things.

I’m currently going through all the docs, adding Usage, Topics, and See Also tags that will fill out the indices.

- Revar



On Mar 4, 2021, at 10:35 AM, Ronaldo Persiano <[hidden email]> wrote:

Jon,

I agree with you that it is hard to find the correct function/module in a library so big and comprehensive like BOSL2. I usually use the wiki (https://github.com/revarbat/BOSL2/wiki/) and recently found a general alphabetical index (https://github.com/revarbat/BOSL2/wiki/Index) and a cheat sheet (https://github.com/revarbat/BOSL2/wiki/CheatSheet). The cheat sheet is useful when you know in which file the function/module is defined and want to remember its argument names. The alphabetical index helps to locate a function/module by its name showing in what file it is defined. From the index and the sheet you have links to the function/module documentation in the wiki.

Those documentation resources become more useful as reference guides as you get acquainted with the library. At the beginning, it is hard. To find a function you suspect is defined in the library, you need at least to understand how it is organized in files so you can open a promising file in the wiki and look at the functions/modules defined there. The list of file names in the root of the wiki give some hints where the function you want might be. At the end of the right column of the wiki, you will find links to the alphabetical index and the cheat sheet,

A BOSL2 tutorial is being prepared.

I guess an interpolator defined in beziers.scad may help you to find the smooth curve you are looking for. Take a look at path_to_bezier() that, from a list of points, generates a bezier path (that is a sequence of connected Bezier arcs) connecting the points with tangent continuity. You will need bezier_curve() or bezier_polygon() to draw the curve or polygon from the bezier path or bezier_path() to sample points in the bezier path.



Em qui., 4 de mar. de 2021 às 17:02, jon <[hidden email]> escreveu:
I need to smooth a curve that I created by hand (enter X/Y pairs
measured from a photo), and looked to BOSL2, because I feel that it is
the most full-featured library I know of.  Of course, "full featured"
also means "hard to search", because there are so many files and
functions and modules.  The curves in question contain dozens of points,
so a simple bezier is not an obvious fit [sic]. Also, I need this part
to fit [!] up against a matching physical part, so getting a pretty
curve is less important than staying close to my points and making the
curve smoother.

How would you (whoever you are?) go about searching for a curve
smoothing function in BOSL2 (or elsewhere)?  Is there a BOSL2 cheat sheet?

I will need to do some 3D smoothing at some point soon, too.

I'm not asking anyone to point me at the function or module.  I want to
know how to think about my quest so that I don't have to post another
question like this in the future

Thanks!

Jon


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: smoothing 2D curves in BOSL2

Ronaldo
In reply to this post by adrianv
Em qui., 4 de mar. de 2021 às 22:53, adrianv <[hidden email]> escreveu:
 For the task you face, I would think that rounding.scad would be the obvious place to start.   However, I'm not sure you'll find a good automatic solution to your problem.  The methods I'm familiar with assume that you want to preserve either the sides (round_corners) or the vertices (smooth_path) of your input.  I'm not aware of anything that will find an approximate curve to a point list where you don't care about any exact matching, but want to minimize error.  That sounds like a least squares problem.  

I don't think that rounding functions would help Jon. Some of them find approximations to a polygonal but their intention is just to smooth corners and not to get a smooth approximation curve. bezier_path() on the other hand may find an interpolation of the points using Bezier arcs.

For smooth (meaning curvature continuous) approximation I would suggest B-splines, which are not covered by the BOSL2 library as far as I know. B-splines are like Bezier in some sense: given a list of (control) points a polynomial-based curve is produced. The curve is polynomial by parts so you may have a lot of points but keeping the polynomial degree low. Similarly to Bezier,  B-splines usually interpolates only the two extremes of the input polygonal. The B-spline curve will approximate to the other points to some degree however.

There are many ways to define and compute B-splines. I have had success with a subdivision-based method. Such a method takes a sequence of points and refines it generating a longer list of points at each iteration. By repeated reiteration, it produces a sequence of points that converges to a B-spline curve. Typically, each iteration doubles the number of points.

The following code is my current implementation of the subdivision-based method for B-spline for both closed and open input polygonal. BOSL2 is not needed to run the main function BSpline_curve() , it is used here just to draw the results. There are a bunch of polygonal examples in the code. You will observe that the first one is very badly approximated because it is a zigzag, a very crude curve. The same happens with the points in a circle: the lower the number of points, the worse the approximation is. The number of points computed by BSpline_curve() depends on the value of $fn but it may be a lot more than the $fn value because the number of points duplicates at each iteration. 

 I hope it helps.

include<BOSL2/std.scad>

//p = [ [0,30,0], [0,30,0], [0,30,0], [0,30,0], [15,25,0], [20,0,0], [30,40,0], [40,10,0],
//      [50,100,0], [60,95,0], [70,90,0], [70,90,0], [70,90,0], [70,90,0] ]; closed=false;
//p = circle(25,$fn=4); closed=true;
//p = circle(25,$fn=12); closed=true;
p = [for(a=[0:20:359]) 25*[a/180,sin(a)]]; closed=false;

pts0 = BSpline_curve(p,closed,$fn=0);
pts1 = BSpline_curve(p,closed,$fn=40);
pts2 = BSpline_curve(p,closed,$fn=80);
pts3 = BSpline_curve(p,closed,$fn=160);

color("black")   move_copies(pts3) circle(.4,$fn=12);
color("magenta") move_copies(pts2) circle(.3,$fn=12);
color("blue")    move_copies(pts1) circle(.2,$fn=12);
color("red")     move_copies(pts0) circle(.15,$fn=12);

//color("blue") translate([5,0,0]) stroke(pts3, width=.2);

function BSpline_curve(p,closed=false)=
    is_undef($_n_)
    ?   assert(len(p)>3, "The point list should have a length 3 at least.")
        assert(is_undef($fn) || is_finite($fn), "The iteration number /n/ should be greater or equal to 0.")
        let( n = is_undef($fn) || $fn<0 ? 3 : $fn==0 ? 0 : ceil(ln($fn/len(p))/ln(2)) )
        len(p)<=3 ? undef :
        let( p = closed? p : concat( [p[0]], p, [p[len(p)-1]] ) )
        BSpline_curve(p,closed,$_n_ = n)
    :   // recursively refine the input polygonal
        $_n_ == 0 ? p :
        let( // extremity mask
             e = [16,8, 0, 0,
                   0,8,12, 3,
                   0,0, 4,11,
                   0,0, 0, 2 ]/16,
             // intermediate mask
             m = [4,1,4,6,0,1]/8,
             n = len(p) )  
        closed
        ? // closed B-spline
          BSpline_curve([ for(i=[0:n-1],j=[0,1]) m[j]*p[i] + m[j+2]*p[(i+1)%n] + m[j+4]*p[(i+2)%n] ],
                          closed ,
                          $_n_=$_n_-1
                       )
        : // open B-spline
          BSpline_curve(
              [ for(i=[0:1:min(3,n-3)]) // extreme refinement
                     [e[i+0],e[i+4],e[i+8],e[i+12]] * [p[0],p[1],p[2],p[3]] ,
                for(i=[3:1:n-4], j=[0,1]) // intermediate refinement
                     [m[j], m[j+2], m[j+4] ] * [p[i-1], p[i], p[i+1] ] ,
                [m[0], m[2], m[4] ] * [p[n-4], p[n-3], p[n-2] ] ,
                for(i=[min(3,n-2):-1:0]) // extreme refinement
                     [e[i+0], e[i+4], e[i+8], e[i+12] ] * [p[n-1], p[n-2], p[n-3], p[n-4] ]
              ] ,
              closed ,
              $_n_=$_n_-1
                       );



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org