How to make a shape from a set of 2d points

9 views
Skip to first unread message

Wink Saville

unread,
Jun 13, 2020, 5:45:19 PM6/13/20
to Curv
I'm interested in making a hand launched (or R/C) airplane with my 3D printer. One of the things I need to do is to create a wing from airfoil data. For example, here is a site where you can select an airfoil and it generates the code from the data which will create the wing using OpenSCAD.

I've played around with OpenSCAD and do not like it's language, so I searched for alternatives and ended up here. Doug has been super helpful as I've gone though my first few days of newbie experiences. So now I want to see if Curv can help me in my goal to make a simple airplane.

So the first question, as the subject line says:

How to make a shape from a set of 2D points?

Doug Moen

unread,
Jun 13, 2020, 8:36:29 PM6/13/20
to Curv
The 2nd link describes an airfoil as an OpenSCAD 'polygon'.
There is no general polygon primitive in the standard Curv library, only regular polygons.
However, it's possible to define one.
I just grabbed the following definition from shadertoy.com and translated it to Curv.

// Copyright © 2019 Inigo Quilez (The MIT Licence)
let
polygon v = make_shape {
  dist p =
    do
      local p = p[[X,Y]];
      local num = count v;
      local d = dot[p-v[0],p-v[0]];
      local s = 1;
      local j = num-1;
      for (i in 0..<num) (
        // distance d
        local e = v[j] - v[i];
        local w = p - v[i];
        local b = w - e*clamp[dot[w,e]/dot[e,e], 0, 1];
        d := min[d, dot[b,b]];
        // winding number from http://geomalgorithms.com/a03-_inclusion.html
        local cond = [p[Y]>=v[i,Y], p[Y]<v[j,Y], e[X]*w[Y]>e[Y]*w[X]];
        if (and cond || and(not cond)) s := -s;
        j := i;
      );
    in s * sqrt d;
  bbox = [[...min v,0], [...max v,0]];
  is_2d = true;
};
in polygon [
    [0,0],
    [0,1],
    [1,0]
]

Editorial note: There are a large number of useful SDF algorithms on shadertoy.com. The Curv language began life as "OpenSCAD2", but I've tweaked it over the years to make it easy to transliterate shadertoy code into Curv with only minor syntactic changes. Also, this is an example of a distance function that contains a loop and conditionals. This topic came up in the libfive thread. I'm sure it's possible to implement polygon in libfive, but without mutable variables, loops and conditionals, you would do a whole lot more work to adapt Inigo Quilez's code.

So now, here's the OpenSCAD airfoil code.

e396_points = [[1000,0],[996.63,1.07],[987.09,4.36],[972.38,9.57],[952.91,15.94],[928.59,23.13],[899.64,31.24],[866.62,40.2],[830.07,49.83],[790.57,59.86],[748.6799,70],[704.94,79.92],[659.9,89.26],[614.04,97.61],[567.68,104.53],[521.02,109.83],[474.34,113.41],[428.01,115.25],[382.36,115.32],[337.74,113.65],[294.5,110.29],[252.9699,105.38],[213.51,99.07],[176.5,91.54],[142.31,82.93],[111.24,73.42],[83.59,63.18],[59.58,52.44],[39.41,41.41],[23.25,30.4],[11.22,19.72],[3.44,9.8],[1.61,6.31],[0.65,3.75],[0.24,2.15],[0.03,0.65],[0,-0.06],[0.04,-0.74],[0.1499,-1.37],[0.35,-1.98],[0.65,-2.6],[1.02,-3.2201],[1.95,-4.48],[3.12,-5.75],[5.27,-7.67],[11.1,-11.52],[24.52,-17.19],[42.79,-21.9],[65.8099,-25.44],[93.4799,-27.69],[125.66,-28.63],[162.15,-28.26],[202.73,-26.65],[247.11,-23.92],[294.95,-20.29],[345.8,-16],[399.11,-11.33],[454.25,-6.53],[510.54,-1.84],[567.26,2.52],[623.65,6.33],[678.94,9.4299],[732.3101,11.66],[782.94,12.93],[830.02,13.2],[872.76,12.49],[910.4,10.88],[942.25,8.52],[967.56,5.6299],[985.68,2.8],[996.44,0.75]];

linear_extrude(height=20)
scale([15, 15])
translate([0,0])
scale (0.001)
polygon(points=e396_points);

Let's translate it into Curv.

let
points = [[1000,0],[996.63,1.07],[987.09,4.36],[972.38,9.57],[952.91,15.94],[928.59,23.13],[899.64,31.24],[866.62,40.2],[830.07,49.83],[790.57,59.86],[748.6799,70],[704.94,79.92],[659.9,89.26],[614.04,97.61],[567.68,104.53],[521.02,109.83],[474.34,113.41],[428.01,115.25],[382.36,115.32],[337.74,113.65],[294.5,110.29],[252.9699,105.38],[213.51,99.07],[176.5,91.54],[142.31,82.93],[111.24,73.42],[83.59,63.18],[59.58,52.44],[39.41,41.41],[23.25,30.4],[11.22,19.72],[3.44,9.8],[1.61,6.31],[0.65,3.75],[0.24,2.15],[0.03,0.65],[0,-0.06],[0.04,-0.74],[0.1499,-1.37],[0.35,-1.98],[0.65,-2.6],[1.02,-3.2201],[1.95,-4.48],[3.12,-5.75],[5.27,-7.67],[11.1,-11.52],[24.52,-17.19],[42.79,-21.9],[65.8099,-25.44],[93.4799,-27.69],[125.66,-28.63],[162.15,-28.26],[202.73,-26.65],[247.11,-23.92],[294.95,-20.29],[345.8,-16],[399.11,-11.33],[454.25,-6.53],[510.54,-1.84],[567.26,2.52],[623.65,6.33],[678.94,9.4299],[732.3101,11.66],[782.94,12.93],[830.02,13.2],[872.76,12.49],[910.4,10.88],[942.25,8.52],[967.56,5.6299],[985.68,2.8],[996.44,0.75]];

polygon v = make_shape {
  dist p =
    do
      local p = p[[X,Y]];
      local num = count v;
      local d = dot[p-v[0],p-v[0]];
      local s = 1;
      local j = num-1;
      for (i in 0..<num) (
        // distance d
        local e = v[j] - v[i];
        local w = p - v[i];
        local b = w - e*clamp[dot[w,e]/dot[e,e], 0, 1];
        d := min[d, dot[b,b]];
        // winding number from http://geomalgorithms.com/a03-_inclusion.html
        local cond = [p[Y]>=v[i,Y], p[Y]<v[j,Y], e[X]*w[Y]>e[Y]*w[X]];
        if (and cond || and(not cond)) s := -s;
        j := i;
      );
    in s * sqrt d;
  bbox = [[...min v,0], [...max v,0]];
  is_2d = true;
};

in
polygon points

Wink Saville

unread,
Jun 13, 2020, 9:15:17 PM6/13/20
to Doug Moen, Curv
THANKS!! I need to learn and understand SDF, fun times ahead :)

--
You received this message because you are subscribed to the Google Groups "Curv" group.
To unsubscribe from this group and stop receiving emails from it, send an email to curv+uns...@googlegroups.com.
To view this discussion on the web, visit https://groups.google.com/d/msgid/curv/96b41053-11b1-41fd-a915-dd12114d8b03%40www.fastmail.com.

Doug Moen

unread,
Jun 14, 2020, 8:52:22 AM6/14/20
to Curv
The "polygon" primitive has been added to the standard library and the documentation. Issue closed.
Reply all
Reply to author
Forward
0 new messages