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/
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/
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/
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/
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/
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/
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] :
uBezierPoint([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/
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/
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.
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.