discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Rounded Polygon

A
adrianv
Wed, Mar 20, 2019 1:41 AM

I did a 3d printing test to assess how much of a difference these roundovers
make in the real world.    I printed four 50mm squares and rounded them
using my previous code with a "cut" setting.  I made one using circular arcs
with a cut of 5mm (and found a bug in my code---circles are definitely more
trouble) and I did the other three using the settings [5,.7], [5,.5], and
[5*.97,.3]  where I reduced the last one so the roundover would fit on the
square.

In comparing the printed objects, I note first of all that the circular
rounded model shows a clear line visible in reflected light as I shift it
around, so the transition between the flat part of the model and the curved
part is visible.  No such transition line is visible in any of the
continuous curvature 3 cases.  In comparing the 0.3 case to the 0.7 case I
am able to see the flat section light up in reflected light all at once, but
it does so without the sharp edges of the circular case.  The 0.3 case has
no flat section so it never has a section that lights up.

If I feel the models the circular model has what feels like a perceptible
lump at the transition.  The transition is tactile.  The other three cases
are indistinguishable and all feel smooth, with no perceptible transition.

My conclusion is that for models where appearance and/or feel are important,
it's better to choose the continuous curvature roundover.  And really,
there's no reason not to use it for 2d scenarios since the code is now
available in cases like this (or, if you prefer to write yourself...it's
easier to write than the circular case).

The other conclusion is that it doesn't seem to matter much if you pick the
curvature parameter anywhere in the range of [0.3,0.7], as they all feel the
same.  I think that the 0.3 looks slightly more elegant visually---the more
gradual curve is visually perceptible---but it does require a lot more room
to execute the curve.  I would suggest that if elegant appearance is
paramount, choose the smallest curvature parameter that fits with your
model.

I would post pictures but I don't think any of this stuff can be conveyed
photographically.  I asked a second person to examine the models without
explaining what was different, and presenting the models in a blind fashion,
and my observations were confirmed, so I think I didn't just dream it up.

Of course, I now wonder about the analogous 3d roundover problem.  Can we
make a continuous curvature rounded cube in a similar fashion?

--
Sent from: http://forum.openscad.org/

I did a 3d printing test to assess how much of a difference these roundovers make in the real world. I printed four 50mm squares and rounded them using my previous code with a "cut" setting. I made one using circular arcs with a cut of 5mm (and found a bug in my code---circles are definitely more trouble) and I did the other three using the settings [5,.7], [5,.5], and [5*.97,.3] where I reduced the last one so the roundover would fit on the square. In comparing the printed objects, I note first of all that the circular rounded model shows a clear line visible in reflected light as I shift it around, so the transition between the flat part of the model and the curved part is visible. No such transition line is visible in any of the continuous curvature 3 cases. In comparing the 0.3 case to the 0.7 case I am able to see the flat section light up in reflected light all at once, but it does so without the sharp edges of the circular case. The 0.3 case has no flat section so it never has a section that lights up. If I feel the models the circular model has what feels like a perceptible lump at the transition. The transition is tactile. The other three cases are indistinguishable and all feel smooth, with no perceptible transition. My conclusion is that for models where appearance and/or feel are important, it's better to choose the continuous curvature roundover. And really, there's no reason not to use it for 2d scenarios since the code is now available in cases like this (or, if you prefer to write yourself...it's easier to write than the circular case). The other conclusion is that it doesn't seem to matter much if you pick the curvature parameter anywhere in the range of [0.3,0.7], as they all feel the same. I think that the 0.3 looks slightly more elegant visually---the more gradual curve is visually perceptible---but it does require a lot more room to execute the curve. I would suggest that if elegant appearance is paramount, choose the smallest curvature parameter that fits with your model. I would post pictures but I don't think any of this stuff can be conveyed photographically. I asked a second person to examine the models without explaining what was different, and presenting the models in a blind fashion, and my observations were confirmed, so I think I didn't just dream it up. Of course, I now wonder about the analogous 3d roundover problem. Can we make a continuous curvature rounded cube in a similar fashion? -- Sent from: http://forum.openscad.org/
P
Parkinbot
Wed, Mar 20, 2019 2:24 PM

adrianv wrote

Of course, I now wonder about the analogous 3d roundover problem.  Can we
make a continuous curvature rounded cube in a similar fashion?

It shouldn't be too difficult to rotate_extrude such an arc rounding a 90°
corner and to translate/rotate 8 instances to the corners of a cube and to
hull them. Have a try.

--
Sent from: http://forum.openscad.org/

adrianv wrote > Of course, I now wonder about the analogous 3d roundover problem. Can we > make a continuous curvature rounded cube in a similar fashion? It shouldn't be too difficult to rotate_extrude such an arc rounding a 90° corner and to translate/rotate 8 instances to the corners of a cube and to hull them. Have a try. -- Sent from: http://forum.openscad.org/
A
adrianv
Wed, Mar 20, 2019 3:43 PM

Parkinbot wrote

adrianv wrote

Of course, I now wonder about the analogous 3d roundover problem.  Can we
make a continuous curvature rounded cube in a similar fashion?

It shouldn't be too difficult to rotate_extrude such an arc rounding a 90°
corner and to translate/rotate 8 instances to the corners of a cube and to
hull them. Have a try.

Wouldn't rotate extruding give a shape with discontinuous curvature in the
direction of rotation?  It's the equivalent of the circular roundover, so
where it meets the linear section (the rounded edge) the curvature of the
edge will be zero and the curvature of the extruded corner will be nonzero.
It seems like some 3d bezier approach is necessary to construct the shape in
the corner.  And curvature on a surface now is a vector of two values, so
maybe matching curvature is more difficult?

If I wanted a cylinder with a rounded end the rotate extrude method should
work.

Perhaps if I did a sweep of the shape I have already constructed along a
path defined by the same shape?  Would that work?

--
Sent from: http://forum.openscad.org/

Parkinbot wrote > adrianv wrote >> Of course, I now wonder about the analogous 3d roundover problem. Can we >> make a continuous curvature rounded cube in a similar fashion? > > It shouldn't be too difficult to rotate_extrude such an arc rounding a 90° > corner and to translate/rotate 8 instances to the corners of a cube and to > hull them. Have a try. Wouldn't rotate extruding give a shape with discontinuous curvature in the direction of rotation? It's the equivalent of the circular roundover, so where it meets the linear section (the rounded edge) the curvature of the edge will be zero and the curvature of the extruded corner will be nonzero. It seems like some 3d bezier approach is necessary to construct the shape in the corner. And curvature on a surface now is a vector of two values, so maybe matching curvature is more difficult? If I wanted a cylinder with a rounded end the rotate extrude method should work. Perhaps if I did a sweep of the shape I have already constructed along a path defined by the same shape? Would that work? -- Sent from: http://forum.openscad.org/
P
Parkinbot
Wed, Mar 20, 2019 5:24 PM

adrianv wrote

Wouldn't rotate extruding give a shape with discontinuous curvature in the
direction of rotation?  It's the equivalent of the circular roundover, so

this is correct. But it is a start.

Looking at a poor man's cube with rounded edges:

r0 = 5;
r = 10;
hull() for(i=[-r, r], j=[-r, r],k=[-r, r]) translate([i,j,k]) sphere(r0,
$fn=40);

http://forum.openscad.org/file/t887/roundedcube.png

shows that you have to produce appropriate corner pieces that will have
proper transitions of the three corners. If you know where you have to go,
you can try to define a sweep path for it. For this you need to find a
proper parametrization of your path along the z-axis, that will transit from
a rect to the rounded path.

--
Sent from: http://forum.openscad.org/

adrianv wrote > Wouldn't rotate extruding give a shape with discontinuous curvature in the > direction of rotation? It's the equivalent of the circular roundover, so this is correct. But it is a start. Looking at a poor man's cube with rounded edges: r0 = 5; r = 10; hull() for(i=[-r, r], j=[-r, r],k=[-r, r]) translate([i,j,k]) sphere(r0, $fn=40); <http://forum.openscad.org/file/t887/roundedcube.png> shows that you have to produce appropriate corner pieces that will have proper transitions of the three corners. If you know where you have to go, you can try to define a sweep path for it. For this you need to find a proper parametrization of your path along the z-axis, that will transit from a rect to the rounded path. -- Sent from: http://forum.openscad.org/
A
adrianv
Wed, Mar 20, 2019 5:47 PM

Maybe my idea wasn't clear.  Suppose I start with square =
[[0,0],[1,0],[1,1],[0,1]], and then apply my roundcorners function, so
roundsquare = roundedcorners(square,...).  Now roundsquare is a path that
traces out a square with continuously rounded corners.  If I use roundsquare
as a shape and sweep it along the path (elevated to 3d) of 5*roundsquare
that should give me a sort of rectangular torus with smooth edges.  So I
union in some filler cube in the center and the result should hopefully be a
rounded cube with continuous curvature.

It seems like the alternative approach would be to actually figure out how
bezier curves work in 3d and directly implement the required corner patch

--
Sent from: http://forum.openscad.org/

Maybe my idea wasn't clear. Suppose I start with square = [[0,0],[1,0],[1,1],[0,1]], and then apply my roundcorners function, so roundsquare = roundedcorners(square,...). Now roundsquare is a path that traces out a square with continuously rounded corners. If I use roundsquare as a shape and sweep it along the path (elevated to 3d) of 5*roundsquare that should give me a sort of rectangular torus with smooth edges. So I union in some filler cube in the center and the result should hopefully be a rounded cube with continuous curvature. It seems like the alternative approach would be to actually figure out how bezier curves work in 3d and directly implement the required corner patch -- Sent from: http://forum.openscad.org/
P
Parkinbot
Wed, Mar 20, 2019 6:29 PM

adrianv wrote

Maybe my idea wasn't clear.  Suppose I start with square =
[[0,0],[1,0],[1,1],[0,1]], and then apply my roundcorners function, so
roundsquare = roundedcorners(square,...).  Now roundsquare is a path that
traces out a square with continuously rounded corners.

I understand this and that you want to go the hard way (for which
rotate_extrude will not do).
In order to do a sweep you need to create a sequence of polygons that can be
coated. Thus you have to define this sequence so that the polygons also will
grow in the desired way (as given by roundsquare) and find the
z-coordinate sequence that will also reflect the roundsquare path and the
roundedcorners rules.
With reference to my last image: You will have to define and arrange the
extrusion polygons in the way it is shown there as layers.
As I understand your approach you currently can gradually refine a given
corner in xy-space, but you don't have the means (parameters) to produce a
sequence arranged in the same sense as these layers are: so that the middle
point will follow the roundsquare path in z direction, as well as in any
other direction.

--
Sent from: http://forum.openscad.org/

adrianv wrote > Maybe my idea wasn't clear. Suppose I start with square = > [[0,0],[1,0],[1,1],[0,1]], and then apply my roundcorners function, so > roundsquare = roundedcorners(square,...). Now roundsquare is a path that > traces out a square with continuously rounded corners. I understand this and that you want to go the hard way (for which rotate_extrude will not do). In order to do a sweep you need to create a sequence of polygons that can be coated. Thus you have to define this sequence so that the polygons also will *grow* in the desired way (as given by roundsquare) and find the z-coordinate sequence that will also reflect the roundsquare path and the roundedcorners rules. With reference to my last image: You will have to define and arrange the extrusion polygons in the way it is shown there as layers. As I understand your approach you currently can gradually refine a given corner in xy-space, but you don't have the means (parameters) to produce a sequence arranged in the same sense as these layers are: so that the middle point will follow the roundsquare path in z direction, as well as in any other direction. -- Sent from: http://forum.openscad.org/
P
Parkinbot
Wed, Mar 20, 2019 10:38 PM

Here some code for my initial approach using rotate_extrude to make a corner
and hull it. I used Ronaldos Bezier implementation. The horizontal edge
roundings are Bezier roundings, and the vertical ones are quarter circles,
due to the rotate_extrude call.
Now, look at the corner and study how you would sweep the rounding (xy) with
a Bezier instead of a quarter circle.

http://forum.openscad.org/file/t887/BezierCube.png

BezierCube(30, 200);
// #cube(200, center = true);  // sizetest

module BezierCube(r = 30, s = 100)
{
q = [[0,r], [r,r], [r,0]];
p = concat([[0,0]], BZeroCurvature(q[0],q[1],q[2],n=20,r0=2/3,r1=1/2)); //
the polygon
hull() // construct the cube by hulling the corners
for(i=[0:3], j=[1,-1]) scale(j)rotate(i*90) translate([s/2-r,s/2-r,
s/2-r]) corner(p);
}
module corner(p)  rotate_extrude(angle = 90, $fa=1) polygon(p);

function BezierPoint(p, u) =
(len(p) == 2)?
u*p[1] + (1-u)p[0] :
u
BezierPoint([for(i=[1:len(p)-1]) p[i] ], u)
+ (1-u)*BezierPoint([for(i=[0:len(p)-2]) p[i] ], u);

function BezierCurve(p, n=10) = [for(i=[0:n-1]) BezierPoint(p, i/(n-1)) ];

function BZeroCurvature(p0,p1,p2,n=20,r0=2/3,r1=1/2) =
assert(r0>0 && r0<1 && r1>0 && r1<1, "improper value of r0 or r1")
let( p = [ p0,
p0 + r0*(p1-p0)r1,
p0 + r0
(p1-p0),
p2 + r0*(p1-p2),
p2 + r0*(p1-p2)*r1,
p2 ] )
BezierCurve(p,n);

--
Sent from: http://forum.openscad.org/

Here some code for my initial approach using rotate_extrude to make a corner and hull it. I used Ronaldos Bezier implementation. The horizontal edge roundings are Bezier roundings, and the vertical ones are quarter circles, due to the rotate_extrude call. Now, look at the corner and study how you would sweep the rounding (xy) with a Bezier instead of a quarter circle. <http://forum.openscad.org/file/t887/BezierCube.png> BezierCube(30, 200); // #cube(200, center = true); // sizetest module BezierCube(r = 30, s = 100) { q = [[0,r], [r,r], [r,0]]; p = concat([[0,0]], BZeroCurvature(q[0],q[1],q[2],n=20,r0=2/3,r1=1/2)); // the polygon hull() // construct the cube by hulling the corners for(i=[0:3], j=[1,-1]) scale(j)rotate(i*90) translate([s/2-r,s/2-r, s/2-r]) corner(p); } module corner(p) rotate_extrude(angle = 90, $fa=1) polygon(p); function BezierPoint(p, u) = (len(p) == 2)? u*p[1] + (1-u)*p[0] : u*BezierPoint([for(i=[1:len(p)-1]) p[i] ], u) + (1-u)*BezierPoint([for(i=[0:len(p)-2]) p[i] ], u); function BezierCurve(p, n=10) = [for(i=[0:n-1]) BezierPoint(p, i/(n-1)) ]; function BZeroCurvature(p0,p1,p2,n=20,r0=2/3,r1=1/2) = assert(r0>0 && r0<1 && r1>0 && r1<1, "improper value of r0 or r1") let( p = [ p0, p0 + r0*(p1-p0)*r1, p0 + r0*(p1-p0), p2 + r0*(p1-p2), p2 + r0*(p1-p2)*r1, p2 ] ) BezierCurve(p,n); -- Sent from: http://forum.openscad.org/
P
Parkinbot
Wed, Mar 20, 2019 11:44 PM

OK, and here is some code that sweeps the corners in the desired way. It
scales each polygon in the sequence to get the desired extension for the xy
path before putting it into 3D (by z-rotating it (Rz)). By this you get a
bezier in all three directions.
Although it is another piece of work, it shouldn't be too difficult to
transfer this scheme into a single (and fast processing) sweep path to avoid
the unions.

http://forum.openscad.org/file/t887/BezierCube1.png

use <Naca_Sweep.scad>  // https://www.thingiverse.com/thing:1208001

BezierCube(30, 200);

module BezierCube(r = 30, s = 100)
{
q = [[0.001,r], [r,r], [r,0.001]];
b = BZeroCurvature(q[0],q[1],q[2],n=20,r0=4/5,r1=2/3);
hull() // construct the cube by hulling the corners
for(i=[0:3], j=[1,-1]) scale(j)rotate(i*90) translate([s/2-r,s/2-r,
s/2-r])
bcorner(b, r);
}

module bcorner(b, r)
{
sweep(gendata(b,r));
function gendata(b,r) =
[
let(step = 90/(len(b)-1))
for(x=[0:len(b)-1])
let(l = norm(b[x])/r)  // scale by bezier
Rz(x*step, Sx(l, Rx(90, vec3(b)))) // rotatex, scalex and rotatez
];
}

--
Sent from: http://forum.openscad.org/

OK, and here is some code that sweeps the corners in the desired way. It scales each polygon in the sequence to get the desired extension for the xy path before putting it into 3D (by z-rotating it (Rz)). By this you get a bezier in all three directions. Although it is another piece of work, it shouldn't be too difficult to transfer this scheme into a single (and fast processing) sweep path to avoid the unions. <http://forum.openscad.org/file/t887/BezierCube1.png> use <Naca_Sweep.scad> // https://www.thingiverse.com/thing:1208001 BezierCube(30, 200); module BezierCube(r = 30, s = 100) { q = [[0.001,r], [r,r], [r,0.001]]; b = BZeroCurvature(q[0],q[1],q[2],n=20,r0=4/5,r1=2/3); hull() // construct the cube by hulling the corners for(i=[0:3], j=[1,-1]) scale(j)rotate(i*90) translate([s/2-r,s/2-r, s/2-r]) bcorner(b, r); } module bcorner(b, r) { sweep(gendata(b,r)); function gendata(b,r) = [ let(step = 90/(len(b)-1)) for(x=[0:len(b)-1]) let(l = norm(b[x])/r) // scale by bezier Rz(x*step, Sx(l, Rx(90, vec3(b)))) // rotatex, scalex and rotatez ]; } -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Thu, Mar 21, 2019 1:34 AM

adrianv avm4@cornell.edu wrote:

It seems like the alternative approach would be to actually figure out how
bezier curves work in 3d and directly implement the required corner patch.

Yes, that is far better and easier than the sweep idea. I am travelling
without my notebook and have no way to develop it here in detail. But I
will give you some general ideas.

A rectangular Bézier surface patch is a parametric bivariate polynomial.
Its control points (CP) are usually represented by a bidimensional matrix
of points whose columns represent the control of one of the parameter and
the rows the control of the other parameter. For instance, the surface
patch of the roundover of a cube edge like you suggested has a CP matrix
with two columns with 5 points each. It is a degree 1 by degree 4 Bézier
surface.

For the corner, we will need at least a degree 4 by degree 4 Bézier patch
which has 25 control points in a matrix 5x5.

A point in a Bézier patch with a matrix of control points P corresponding
to a pair of parameters (u, v) can be easily computed by the following
simple code:

function BPatchPoint(P, u, v) =
transpose(BezierPoint(transpose(BezierPoint(P, u)), v));

where transpose() is the matrix transpose and BezierPoint() is the function
I defined before. A polyhedral approximation of the patch can be generated
by calling this function for a matrix of parameters (ui, vi).

Given two patches joined side by side, to have curvature continuity between
them all that is needed is to satisfy the curvature continuity condition by
the rows of CPs, row by row, as they were CPs of simple independent curves.

With that in mind, we could devise a patch to roundover a cube corner with
curvature continuity.

I will be back home soon and I hope to detail this stuff in two days. I
also have some comments about your curvature study and graphs but I have to
test my ideas first.

adrianv <avm4@cornell.edu> wrote: > > It seems like the alternative approach would be to actually figure out how > bezier curves work in 3d and directly implement the required corner patch. > Yes, that is far better and easier than the sweep idea. I am travelling without my notebook and have no way to develop it here in detail. But I will give you some general ideas. A rectangular Bézier surface patch is a parametric bivariate polynomial. Its control points (CP) are usually represented by a bidimensional matrix of points whose columns represent the control of one of the parameter and the rows the control of the other parameter. For instance, the surface patch of the roundover of a cube edge like you suggested has a CP matrix with two columns with 5 points each. It is a degree 1 by degree 4 Bézier surface. For the corner, we will need at least a degree 4 by degree 4 Bézier patch which has 25 control points in a matrix 5x5. A point in a Bézier patch with a matrix of control points P corresponding to a pair of parameters (u, v) can be easily computed by the following simple code: function BPatchPoint(P, u, v) = transpose(BezierPoint(transpose(BezierPoint(P, u)), v)); where transpose() is the matrix transpose and BezierPoint() is the function I defined before. A polyhedral approximation of the patch can be generated by calling this function for a matrix of parameters (ui, vi). Given two patches joined side by side, to have curvature continuity between them all that is needed is to satisfy the curvature continuity condition by the rows of CPs, row by row, as they were CPs of simple independent curves. With that in mind, we could devise a patch to roundover a cube corner with curvature continuity. I will be back home soon and I hope to detail this stuff in two days. I also have some comments about your curvature study and graphs but I have to test my ideas first.
RP
Ronaldo Persiano
Thu, Mar 21, 2019 3:35 PM

A point in a Bézier patch with a matrix of control points P corresponding
to a pair of parameters (u, v) can be easily computed by the following
simple code:

function BPatchPoint(P, u, v) =
transpose(BezierPoint(transpose(BezierPoint(P, u)), v));

where transpose() is the matrix transpose and BezierPoint() is the
function I defined before.

There is an error in that code: transposition is not needed. The correct
code is even simpler:

function BPatchPoint(P, u, v) =
BezierPoint(BezierPoint(P, u), v);

As the shape of the corner roundover patch is triangular I am considering
to model it with triangular Bezier patches of degree 6.

> > A point in a Bézier patch with a matrix of control points P corresponding > to a pair of parameters (u, v) can be easily computed by the following > simple code: > > function BPatchPoint(P, u, v) = > transpose(BezierPoint(transpose(BezierPoint(P, u)), v)); > > where transpose() is the matrix transpose and BezierPoint() is the > function I defined before. > There is an error in that code: transposition is not needed. The correct code is even simpler: function BPatchPoint(P, u, v) = BezierPoint(BezierPoint(P, u), v); As the shape of the corner roundover patch is triangular I am considering to model it with triangular Bezier patches of degree 6.