Rounded Polygon

classic Classic list List threaded Threaded
172 messages Options
1 ... 3456789
Reply | Threaded
Open this post in threaded view
|

Re: Rounded Polygon

Ronaldo
Em sex, 29 de mar de 2019 às 17:44, adrianv <[hidden email]> escreveu:
It's not clear to me what the constraints are for controlling the derivative
matching for the triangular patch, but yes, it appears I have with order 4
not even matched the first derivative.   

The C1 continuity (first derivative) between two adjacent triangular patches involves the co-planarity of some triangle pairs adjacent to the common border (see fig. 1). It is in some sense an extension of the condition that holds for curves. The C2 continuity (second order) requires the coindicence of some points extending from some triangles in a second row away from the common border (see fig. 2). The figures were taken from Farin's paper found at http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.413.7346&rep=rep1&type=pdf. Although this is the main reference on the subject, its nomenclature is hard to follow. I have tried without success, to express by triangular patches the cylindrical surface of an edge rounded with the degree 4 curve. That would help me to try meeting the necessary C2 continuity.

So this raises the questions:  Is the code correct?  Is it possible to match
derivatives as desired (with a patch of sufficient order)? 

This depends on what you mean by correct. I haven't seen nothing wrong with your functions.
I still believe we could achieve the necessary C2 conditions with triangular patches with even degree. If the 4x4 rectangular patch I built really matches the conditions (and I am still unsure about it), then at least a degree 8=4+4 triangular patch will do it.
 
Should the edges of the patch match the 4th order 1d bezier curve with the
same control points? 

Yes, possibly with a higher degree representation.

// given p, the Bezier CP of an arc of degree len(p), 
// find the control points of the same arc expressed as a curve of degree len(p)+n
function BzDegreeElevation(p, n) =
  n==0 ? p :
  let(q = [ p[0],
            for(i=[1:len(p)-1], u = i/len(p)) 
               u*p[i-1] + (1-u)*p[i] ,
            p[len(p)-1] ] ) 
   BzDegreeElevation  (q, n-1);


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

C1continuity.PNG (30K) Download Attachment
C2continuity.PNG (40K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Rounded Polygon

adrianv
Ronaldo wrote
> Em sex, 29 de mar de 2019 às 17:44, adrianv &lt;

> avm4@

> &gt; escreveu:
>
>> It's not clear to me what the constraints are for controlling the
>> derivative
>> matching for the triangular patch, but yes, it appears I have with order
>> 4
>> not even matched the first derivative.
>>
>
> The C1 continuity (first derivative) between two adjacent triangular
> patches involves the co-planarity of some triangle pairs adjacent to the
> common border (see fig. 1). It is in some sense an extension of the
> condition that holds for curves. The C2 continuity (second order) requires
> the coindicence of some points extending from some triangles in a second
> row away from the common border (see fig. 2). The figures were taken from
> Farin's paper found at
> http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.413.7346&rep=rep1&type=pdf.
> Although this is the main reference on the subject, its nomenclature is
> hard to follow. I have tried without success, to express by triangular
> patches the cylindrical surface of an edge rounded with the degree 4
> curve.
> That would help me to try meeting the necessary C2 continuity.

My patch is failing C1 even though it appears to me that I meet the
coplanarity condition for the triangles adjacent to the edge.  What is
wrong?  

I have not been successful thus far at deciphering the C2 condition from the
paper.  

I did confirm that my patch edges matches the shape of the 1d curve I
previously produced with the order 4 bezier.  



--
Sent from: http://forum.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: Rounded Polygon

adrianv
I remain baffled by the lack of C1 agreement for my triangular patch.  I ran
across another reference which I think is a little bit easier to follow:

https://pdfs.semanticscholar.org/3854/c6e3ea6367eb7ad8b340f944ee4f1502ac10.pdf

But at least for C1, I don't see anything new---my control points are
coplanar and yet my patch lacks C1 continuity at the edge.   I tried
implementing a non-recursive calculation of the patch and it matched my
previous calculation.  




--
Sent from: http://forum.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: Rounded Polygon

Ronaldo
adrianv <[hidden email]> wrote:
I remain baffled by the lack of C1 agreement for my triangular patch.  I ran
across another reference which I think is a little bit easier to follow:

Thank you for that reference: a very useful procedure.

I am also surprised that the coplanarity condition is not enough to a C1 joint. I guess I missed something from the references and that something else is needed. I was not successful in my attempts to model a C2 or even a C1 corner with degree 6 tripatches. However I got a tripatch model for the cylindrical shape of the edges.

It is clear that the coplanarity condition is not preserved when we promote a degree elevation of your degree 4 model. When we apply the degree elevation of 1 degree to your model, the middle triangle of the border is no longer orthogonal to the edge curve plane. 

DegreeElevationTo5.PNG

To get the degree elevation I use the following function:

// find the representation of a degree n tripatch p as a degree n+m tripatch
function triPatchDegreeElevation(p, m) =
  m==0? p:
  let( n = len(p),
       q = [ p[0],
             for(i=[1:n-1], u = 1-i/n )
               [ u*p[i][0] + (1-u)*p[i-1][0],
                 for(j=[1:1:i-1], v = j/i )
                    (1-u)*v*p[i-1][j-1] +  (1-u)*(1-v)*p[i-1][j] + u*p[i][j],
                 u*p[i][i] + (1-u)*p[i-1][i-1]
               ],
             [ p[n-1][0], 
               for(j=[1:1:n-1], v = j/n ) v*p[n-1][j-1] + (1-v)*p[n-1][j],
               p[n-1][n-1] 
             ]
           ] )
  triPatchDegreeElevation(q, m-1);

Note that this function supposes the input tripatch p is a triangular matrix bellow the diagonal and not above as you defined in your codes.

The cylindrical shape of a rounded edge (a sweep of the degree 4 border curve) may be modeled by:

function cylindricalPatchCP(p0, p1, p2, d, r0) =
  let(  cv = curveG2CP([p0,p1,p2],r0),
        bs = BzSubdiv(cv,1/2) )
  [ [bs[4]+d],
    [ bs[3]+3*d/4, bs[5]+3*d/4 ],
    [ bs[2]+d/2, 2*(bs[4]+d/2)-(bs[2]+bs[6]+d)/2 , bs[6]+d/2 ],
    [ bs[1]+d/4, (cv[1]+cv[2])/2+d/4, (cv[2]+cv[3])/2+d/4, bs[7]+d/4 ],
    cv
  ];

// our well known degree 4 curve
function curveG2CP(p,r0=0.5) =
  [ p[0], p[0]+r0*(p[1]-p[0]), p[1], p[2]+r0*(p[1]-p[2]), p[2] ];

// Bezier subdivision of CP p
function BzSubdiv(p,u) =
  len(p) == 2 ? [p[0], (1-u)*p[0]+u*p[1], p[1]] :
  [ p[0],
    each BzSubdiv([for(i=[0:len(p)-2]) (1-u)*p[i]+u*p[i+1]],u),
    p[len(p)-1] ];
 
That patch makes a clear C1 joint with its mirror image along axis x. This two patches satisfy the planarity condition at the common border even with a degree elevation.

Taking all this in consideration, my next attempt will be to find a model such that both itself and its 1 degree elevation satisfy the condition of orthogonality of the border triangles and the plane of border curve.

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

Re: Rounded Polygon

Ronaldo
I forgot to mention: the parameter d in cylindricalPatchCP() should be [0,0,0] to get the cylindrical shape. Parameter d deforms the shape without changing its border derivatives.

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

Re: Rounded Polygon

Ronaldo
Wrong explanation!

In this version of cylindricalPatchCP(), p0, p1 and p2 are the three points defining the degree 4 border of the patch. The parameter d is the tip of the tripatch opposed to that border. A typical call would be:

cylCP  = cylindricalPatchCP([10,0,10], [10,0,0], [10,10,0], [30,0,0], r0);


Em sex, 5 de abr de 2019 às 16:36, Ronaldo Persiano <[hidden email]> escreveu:
I forgot to mention: the parameter d in cylindricalPatchCP() should be [0,0,0] to get the cylindrical shape. Parameter d deforms the shape without changing its border derivatives.

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

Re: Rounded Polygon

Ronaldo
In reply to this post by Ronaldo


I am also surprised that the coplanarity condition is not enough to a C1 joint. I guess I missed something from the references and that something else is needed.

I understand now what was my misunderstanding of the coplanarity condition for C1 joints. The condition is valid for the graph of real-valued polynomials and not for muiti-valued polynomials as the tripatches. Both references we got are concerned with interpolation problems of real-valued data. In this case, the first two coordinates of the graph have very specific position depending just on the triangle domain and the polynomial degree. Although the graph may be regarded as a surface patch, the specific positions of the projection of the CP on the xy plane does mater.

To get a C1 condition valid for three-variate polynomials we will need to verify the coplanarity condition for each coordinate polynomial. Taking adrian model degree 4 patch P as an example, I graphed the three coordinates of it:

graph(revert(P), [0,0,0], [10,0,0], [0,10,0],[0,2,0], 0.05);
mirror([0,1,0]) graph(revert(P), [0,0,0], [10,0,0], [0,10,0],[0,2,0], 0.05);
translate([7,7,0]) scale([1,1,0.01]) text("X", size=1);

translate([10,0,0]){
graph(revert(P), [0,0,0], [10,0,0], [0,10,0],[2,0,0], 0.05);
mirror([0,1,0]) graph(revert(P), [0,0,0], [10,0,0], [0,10,0],[2,0,0], 0.05);
translate([7,7,0]) scale([1,1,0.01]) text("Y", size=1);
}

translate([20,0,0]){
graph(revert(P), [0,0,0], [10,0,0], [0,10,0],[0,0,2], 0.05);
mirror([0,1,0]) graph(revert(P), [0,0,0], [10,0,0], [0,10,0],[0,0,2], 0.05);
translate([7,7,0]) scale([1,1,0.01]) text("Z", size=1);
}

module graph(p, P0, P1, P2, d=[1,0,0], w) {
  n = len(p);
  base = [ [P0],  for(i=[1:n-1]) [for(j=[0:i]) (1-i/n)*P0 + i/n*( (1-j/i)*P1 + j/i*P2) ]  ];
  tri_grid(base,w);
  graph = [for(i=[0:n-1]) [for(j=[0:i]) [base[i][j][0], base[i][j][1], p[i][j]*d ] ] ];
  translate([0,0,1])  color("red") tri_grid(graph,w);

module tri_grid(p, w=0.05) {
    n = len(p);
    for(i=[0:n-2]) for(j=[1:n-i-1]) line([p[n-i-1][j], p[n-i-1][j-1]], w=w);
    for(j=[0:n-2]) for(i=[0:n-j-2]) line([p[n-i-1][j], p[n-i-2][j]],   w=w);
    for(k=[0:n-2]) for(j=[1:n-k-1]) line([p[j+k][j],   p[j+k-1][j-1]], w=w);
}

function revert(p) = [for(i=[len(p)-1:-1:0]) p[i]];

The revert is needed due to the order adrian defined his patches.

The image outcome of this code is:

graphs.PNG
where the grids in blue represent the specific arranges the down projection of the graph CP should have and the grids in red show the graph of each coordinate of adrian surface. Besides, I mirror the graphs in order to check the C1 conditions. It is clear from the image that just the coordinate z has a C1 joint with it mirror image. Both coordinates X and Y fails to have C1 continuity at those joints.

Based on that considerations we could try to build a patch that meets the C1 condition (and perhaps the C2 condition) at the joints. However, what we really need is G1 and G2 continuity, that is a geometric differentiabilty and not a parametric one. Hard stuff!


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

Re: Rounded Polygon

Ronaldo
Based on that considerations we could try to build a patch that meets the C1 condition (and perhaps the C2 condition) at the joints. However, what we really need is G1 and G2 continuity, that is a geometric differentiability and not a parametric one. Hard stuff!

Well, I have a good news and a definitely bad one. I have found in Farin's book ("Curves and Surfaces for CAGD") the full condition for a C1 joint between to tripatches. Besides the co-planarity condition it is required that any pair of CP grid triangle adjacent to the meeting border of the two patches is an affine image of the other pairs. This affine transform should not include any reflection, just translations, rotations and positive scales. The following image shows the C1 joint of a degree 2 patch with its mirror image:

C1joint.PNG

The grid in red is a mirror image of the grid in blue. The transparent pairs of triangles satisfy the conditions of being co-planar and each one is an affine transform of the other pair without any reflection. The joint is C1. For patches of degree n the number of pairs to be considered will be n.  Note that the condition excludes reflections as a possible affine transform and the following image shows what happens when the affine transform between pairs does not meet that requirement:

NonC1joint.PNG
In this example the adjacent pairs of triangles although co-planar does not meet the affine condition restriction. The joint is clearly not C1.

I did try to apply this condition to model a rounded corner with a tripatch and that is the bad news: it seems impossible to get, even the C1 condition, with a tripatch of any degree with all the border constraints of a rounded corner we need. To understand my point, consider the following image that schematically represents a tripatch of undefined degree intended to round a corner:

SchematicCorner.PNG
The blue lines are the patch border and some of the grid triangles near the patch corner are represented. Besides I added the grid triangles of the mirrored patch near patch corner B. To meet our constraints, the grid triangles in the patch corner should be a rectangle triangle whose hypotenuse is towards the patch center. Then, along the border AB, we need to have the grid triangles as illustrated and no affine transform will bring a triangle pair near A to a triangle pair near B except with some negative scale factor (which is a reflection). So, the conditions to have a rounded corner with curvature continuity does not allow to meet the condition of of a C1 joint with tripatch of any degree.

We could try to model the corner with a set of tripatches like the Clough-Tocher scheme that uses three patches, or Power-Sabin scheme with 6 tripatches. However, to get a C2 conditions between two patches of the scheme seems to require higher degree polynomials. 

The great advantage of the use of tripatch over the rectangular patch would be the 3 symmetries that lacks in the later. It is possible to get a 3 symmetry based on the rectangular patch solution by taking the media of sampling the three surface patches each one collapsing a row to one corner vertex. That would be time consuming (three evaluations of a degree 8 polynomial for each sample point). 

The asymmetry of the rectangular patch does not seems great enough to justify that onus. Besides, I have confirmed that the collapsed rectangular patch that rounds a corner is indeed curvature continuous as we had supposed.

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

Re: Rounded Polygon

adrianv
It is great to have a resolution to the questions about the triangular
patches.  

Can you elaborate a bit on the condition?  In the first example, it appears
the two top triangles are not coplanar.  Is that just a rendering issue?  In
your second example (with the obvious C1 failure) it appears that the
bordering triangles can be mapped onto each other by a rotation.   I assume
the affine transformation is confined to the plane that contains the
triangles.  

In musing a bit about symmetry it has occurred to me that most applications
for this would be shapes that lacked 3 axis symmetry anyway.   Most likely
an object would be rounded in a symmetric way in the x-y plane but then in a
different way in the z direction because the object might be much thinner in
the z direction, for example.  It seems like it makes sense to simply align
the odd axis along the collapsed line of the  square in the patch.

It does raise the question about potential advantages of the extrusion
approach.  



--
Sent from: http://forum.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: Rounded Polygon

Ronaldo



Can you elaborate a bit on the condition?  In the first example, it appears
the two top triangles are not coplanar.  Is that just a rendering issue? 

The condition for a C1 joint between two tripatches I have found in Farin's book was just that small reference:

C1Farin.PNG
It is clear that if the pair is an affine map of the domain then each pair is an affine map the other pairs. Although the text does not say it, I have found in my experiments that the affine map in that condition cannot include any reflection but just translations, rotations and positive scales. The second example of my previous message corroborates that. I have not checked whether shears are allowed.

In my examples, the pairs of triangles meeting at the border are all coplanars. The view angle I used to generate the images might not have being the best. You may experiment and check my conclusions playing with the code I have used to produce the images:

// The C1 case CP
P = [ [[0,-3,0]],
      [[0,-2,1.5],[-2,-2,0]],
      [[2,0,0],[0,0,1.5],[-2,0,0]]
     ];

// The non-C1 case CP
Q = [ [[0,-3,0]],
      [[2,-2,0],[-2,-2,0]],
      [[2,0,0],[0,0,2],[-2,0,0]]
     ];


// The C1 case
translate(){
color("red")
tri_grid(P,w);
showTriPatch(P);
%showTriPatch([[P[2][0]], [P[2][1], P[1][0]]]);
%showTriPatch([[P[2][1]], [P[2][2], P[1][1]]]);
}
// Its mirror image
mirror([0,1,0]) {
color("blue")
tri_grid(P,w);
showTriPatch(P);
%showTriPatch([[P[2][0]], [P[2][1], P[1][0]]]);
%showTriPatch([[P[2][1]], [P[2][2], P[1][1]]]);
}

// The non-C1 case
translate([0,7,0]){
color("red")
tri_grid(Q,w);
showTriPatch(Q);
scale([1,1.5,1])
mirror([0,1,0]){
showTriPatch(Q);
color("blue")
tri_grid(Q,w);
}
}

// sample a tripatch with CP cp in a triangular array
function triPatchSample(cp,n) = 
  [for(i=[0:n-1]) [for(j=[0:i]) BtriPatchPoint(cp, (n-1-i)/(n-1), j/(n-1)) ] ];

// generates the image of the surface of a tripatch p
module showTriPatch(p,n=10) {
  pdat = trimesh2polyhedron(triPatchSample(p,n));
  polyhedron(pdat[0],pdat[1]);
}

// computes the point in a tripatch mapped by the parameters (u,v)
function BtriPatchPoint(p,u,v) =
  len(p) == 1 ? p[0][0] :
  let( n  = len(p),
       pu = [for(i=[0:n-2]) p[i] ],
       pv = [for(i=[1:n-1]) [for(j=[0:i-1]) p[i][j] ] ],
       pw = [for(i=[1:n-1]) [for(j=[1:  i]) p[i][j] ] ] )
  BtriPatchPoint(u*pu + v*pv + (1-u-v)*pw, u, v);

// generates the mesh of a triangular array of 3D points in a polyhedron data format [verts, faces]
function trimesh2polyhedron(p,inv=false) =
    let( n = len(p),
         vertices = inv ?   [ for(i=[0:n-1], j=[0:i]) p[i][i-j] ]:
                            [ for(pt=p, q=pt) q ] ,
         tris = concat(
                    [for(i=[1:n-1], j=[1:i]) 
                        [ j+(i+1)*(i)/2, j-1+(i-1)*(i)/2, j-1+(i+1)*(i)/2 ] ],
                    n <= 2 ? [] : 
                    [for(i=[1:n-2], j=[1:i]) 
                        [ j+(i+1)*(i+2)/2, j+(i+1)*(i)/2, j-1+(i+1)*(i)/2 ] ]) )
    [ vertices, tris ];       

module line(p,closed=false,dots=false,w=0.1) 
  if (dots) 
    for(i=[0:len(p)-1]) 
      translate(p[i]) sphere(4*w);
  else
    for(i=[0:len(p)-(closed? 1:2)])
      hull(){ translate(p[i])   sphere(w); 
              translate(p[(i+1)%len(p)]) sphere(w);
            } 
            
// draw the mesh of a triangular array of points
module tri_grid(p, w=0.05) {
    n = len(p);
    for(i=[0:n-2]) for(j=[1:n-i-1]) line([p[n-i-1][j], p[n-i-1][j-1]], w=w);
    for(j=[0:n-2]) for(i=[0:n-j-2]) line([p[n-i-1][j], p[n-i-2][j]],   w=w);
    for(k=[0:n-2]) for(j=[1:n-k-1]) line([p[j+k][j],   p[j+k-1][j-1]], w=w);
}

In your second example (with the obvious C1 failure) it appears that the
bordering triangles can be mapped onto each other by a rotation.   I assume
the affine transformation is confined to the plane that contains the
triangles.  

Yes, they can but mapping the triangle of a patch in the triangle of the other patch. In the code above, I changed one of the patches in order to make this clearer. The two patches now are not the mirror image of each other.  

In musing a bit about symmetry it has occurred to me that most applications
for this would be shapes that lacked 3 axis symmetry anyway.   Most likely
an object would be rounded in a symmetric way in the x-y plane but then in a
different way in the z direction because the object might be much thinner in
the z direction, for example.  It seems like it makes sense to simply align
the odd axis along the collapsed line of the  square in the patch.

I am not sure this makes sense. In the method of rounding a cube by hulling spheres, would you consider a smashed sphere to have that asymmetry? Anyway, the asymmetry of the rectangular patch with a collapsed row is very very mild and should not have any significant effect.

It does raise the question about potential advantages of the extrusion approach. 

I agree.

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

Re: Rounded Polygon

TLC123
In reply to this post by irevdev
Trigger warning: Rant ahead!

So this rounded business talk goes round and round.

First its rounded polygons.
Then rounded 3d primitives.
Then it turns into rounded 3d boolean operations.

Some suggest the operations need to be built ins.
Some counter it can all be done in user-space with polyhedrons.

Followed by a long exchange that in essence asks how to replicate well
established B-rep operations like those in Parasolid/Opencascade etc based
systems, but now in open-scad, in user-space. Great fun project and all but
completely insane as a task.

Some suggest various nested Minkowski operations as a side note, always with
some huge buts.

Rinse and repeat every few months.

The argument that time consuming builtin operations breaks fast preview
completely falls apart when the suggested alternative is hundred times
slower user-space polyhedron operations. Implemented with only lists of
list, no mutable data or linked structures and some good old float point
errors as a throwback to the very core issue why precision math CGAL was
chosen for Openscad in the first place.

Addressing every other feature request with "solve it yourself in
user-space" cannot be a sane way forward when those ideas already been
ruminated exhaustively in ever repeating waves.

Maybe a more honest answer is that it is hard, very hard, close to
impossible, to implement rounded modelling in this kind of  preview/render
hybrid system. A system that unfortunately painted itself into a bit of a
corner from the beginning. But then again it is infinitely harder to do all
that in the so called user-space.

If a willing few has them magic skills to solve this in pure openscad then
surely they are the kind that could expand CGAL with similar functions for
far lesser effort.

end rant.

My question to the community is: What level of features is sane to be solved
by users and what
belongs in the developer world?









--
Sent from: http://forum.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: Rounded Polygon

sysrpl
I am the OP of the recent reddit post on this subject:


Being just a beginner I had no idea how to use the hull() function. A day later I now I know how to use hull() I can say it definitely solves the problem of generated rounded solid a non issue. The hull() function also is very fast and is almost instant when used in render(). So in short, rounded shapes is easy if you just use the hull() function.

A rounded cube with hull():

module roundCube(w, d, h, radius)
{
    hull()
    {
        translate([w / 2, d / 2, 0]) sphere(radius);
        translate([w / 2, d / -2, 0]) sphere(radius);
        translate([-w / 2, d / 2, 0]) sphere(radius);
        translate([-w / 2, d / -2, 0]) sphere(radius);
        translate([w / 2, d / 2, h]) sphere(radius);
        translate([w / 2, d / -2, h]) sphere(radius);
        translate([-w / 2, d / 2, h]) sphere(radius);
        translate([-w / 2, d / -2, h]) sphere(radius);
    }
}

Easy peezee and done.


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

Re: Rounded Polygon

acwest
Hull only works for convex shapes, though. Minkowsky works for non-convex, but is much slower

On Thu, 25 Apr 2019, 16:16 Anthony Walter, <[hidden email]> wrote:
I am the OP of the recent reddit post on this subject:


Being just a beginner I had no idea how to use the hull() function. A day later I now I know how to use hull() I can say it definitely solves the problem of generated rounded solid a non issue. The hull() function also is very fast and is almost instant when used in render(). So in short, rounded shapes is easy if you just use the hull() function.

A rounded cube with hull():

module roundCube(w, d, h, radius)
{
    hull()
    {
        translate([w / 2, d / 2, 0]) sphere(radius);
        translate([w / 2, d / -2, 0]) sphere(radius);
        translate([-w / 2, d / 2, 0]) sphere(radius);
        translate([-w / 2, d / -2, 0]) sphere(radius);
        translate([w / 2, d / 2, h]) sphere(radius);
        translate([w / 2, d / -2, h]) sphere(radius);
        translate([-w / 2, d / 2, h]) sphere(radius);
        translate([-w / 2, d / -2, h]) sphere(radius);
    }
}

Easy peezee and done.

_______________________________________________
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
tp3
Reply | Threaded
Open this post in threaded view
|

Re: Rounded Polygon

tp3
In reply to this post by TLC123
On 25.04.19 21:44, TLC123 wrote:
> My question to the community is: What level of features is sane
> to be solved by users and what belongs in the developer world?

This is a very good question. Burying it in this topic after the
rant seems a bit strange though...

Also, I suspect there's no easy and single answer. Maybe that
discussion could be had, but separately. So I won't start now.

ciao,
   Torsten.

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

Re: Rounded Polygon

JordanBrown
In reply to this post by acwest
I don't claim to really understand the math, but a Minkowski sum basically involves moving an object A along the entire perimeter of another object B, and the result is the entire area swept.  Right?

Is there another operation (Minkowski difference, maybe?) that moves B around the *inside* of A, and that doesn't include anything that B can't reach?  (Do I need to draw a picture to describe what I mean?)

This latter operation would seem like a powerful way to take a shape and round all of its edges, while preserving its major dimensions.

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

Re: Rounded Polygon

JordanBrown
On 4/25/2019 4:25 PM, Jordan Brown wrote:
I don't claim to really understand the math, but a Minkowski sum basically involves moving an object A along the entire perimeter of another object B, and the result is the entire area swept.  Right?

Is there another operation (Minkowski difference, maybe?) that moves B around the *inside* of A, and that doesn't include anything that B can't reach?  (Do I need to draw a picture to describe what I mean?)

This latter operation would seem like a powerful way to take a shape and round all of its edges, while preserving its major dimensions.

And is often the case, a few searches and clicks later:  https://en.wikipedia.org/wiki/Opening_(morphology)


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

Re: Rounded Polygon

nophead
See   https://github.com/openscad/openscad/issues/1678

Minkwoski difference can be done with Minkowski sum and difference but it is very slow and uses an enormous amount of memory for values of $fn that make things smooth. 

 

On Fri, 26 Apr 2019 at 06:25, Jordan Brown <[hidden email]> wrote:
On 4/25/2019 4:25 PM, Jordan Brown wrote:
I don't claim to really understand the math, but a Minkowski sum basically involves moving an object A along the entire perimeter of another object B, and the result is the entire area swept.  Right?

Is there another operation (Minkowski difference, maybe?) that moves B around the *inside* of A, and that doesn't include anything that B can't reach?  (Do I need to draw a picture to describe what I mean?)

This latter operation would seem like a powerful way to take a shape and round all of its edges, while preserving its major dimensions.

And is often the case, a few searches and clicks later:  https://en.wikipedia.org/wiki/Opening_(morphology)

_______________________________________________
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: Rounded Polygon

adrianv
In reply to this post by acwest
Even for convex shapes hull has limitations.  Anthony, if you think rounding
is "easy peezee" then first I suggest fixing the module so the rounded cube
is the right size rather than 2*r oversized.  Then I ask how you would make
a rounded pyramid with an arbitrary base polygon and apex that is a
designated size and not oversized.  Next, how would you use the hull method
to make a cylinder with rounded ends?  What if the cylinder's ends are not
normal to its axis?  If that's too easy then suppose I construct a parabola
and extrude it.  How would you round that?

data = [for(x=[-2:.05:2])[x,x*x]];
linear_extrude(height=4)polygon(data);

I'm not saying these things can't be done.  For making a rounded polyhedron
you need to put the spheres in the right place, which is not "easy peezee"
in my opinion when the polyhedron is not a cube.  (Oh, and don't forget that
spheres are actually polyhedra, and undersized.)  And the methods that leap
to mind for the cylinder seem little complex.  For the case of the parabolic
shape I don't see a way of using hull that is easier than just generating
the whole shape directly.  

The other problem with using hull is that it assumes that it makes sense to
build up your convex object from a union of convex objects.  What if you
create your convex object through difference() operations?  Then you cannot
round the final object using hull() operations.   If everything has to be
constructed with hull() it limits your options for how you can model stuff.  

As acwest notes, non-convex shapes cannot be rounded with hull.   In my
experience, nothing I design ends up being convex.  I've been pondering the
task of making a box where the inside joint between the walls and base is
rounded and the top edge is rounded.  To do this for a general box (with an
arbitrary shaped base) appears to be very difficult.  

Regarding run time, hull() can be slow.  In fact, for polyhedra with large
numbers of faces it seems that minkowski() is faster than hull().   I just
did a timing test and the hull of 50 spheres with $fn=32 took 38 seconds to
preview.  I understand that technically what's slow for hull() is not the
hull operation but the unavoidable yet unnecessary union operation between
all the spheres.  

It is possible to make a general minkowski rounding function with 3 calls to
minkowski.  But is has the limitation that the shape cannot have any areas
thinner than the roundover radius.  Also there is the question of speed.
Reportedly rounding the union of a cylinder and cube (that don't meet at
right angles) takes 12 hours.  And of course it enforces the same rounding
radius globally on the model, which may not be what you need.  


acwest wrote
> Hull only works for convex shapes, though. Minkowsky works for non-convex,
> but is much slower
>
> On Thu, 25 Apr 2019, 16:16 Anthony Walter, &lt;

> sysrpl@

> &gt; wrote:
>
>> I am the OP of the recent reddit post on this subject:
>>
>> https://www.reddit.com/r/openscad/comments/bfx897/openscad_rounded_boxes/
>>
>> Being just a beginner I had no idea how to use the hull() function. A day
>> later I now I know how to use hull() I can say it definitely solves the
>> problem of generated rounded solid a non issue. The hull() function also
>> is
>> very fast and is almost instant when used in render(). So in short,
>> rounded
>> shapes is easy if you just use the hull() function.
>>
>> A rounded cube with hull():
>>
>> module roundCube(w, d, h, radius)
>> {
>>     hull()
>>     {
>>         translate([w / 2, d / 2, 0]) sphere(radius);
>>         translate([w / 2, d / -2, 0]) sphere(radius);
>>         translate([-w / 2, d / 2, 0]) sphere(radius);
>>         translate([-w / 2, d / -2, 0]) sphere(radius);
>>         translate([w / 2, d / 2, h]) sphere(radius);
>>         translate([w / 2, d / -2, h]) sphere(radius);
>>         translate([-w / 2, d / 2, h]) sphere(radius);
>>         translate([-w / 2, d / -2, h]) sphere(radius);
>>     }
>> }
>>
>> Easy peezee and done.





--
Sent from: http://forum.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: Rounded Polygon

nophead
Hull is only slow if it has an implicit union inside it. For example if you place spheres with a for loop or a common translation or rotation then they get unioned first and that is very slow with CGAL. If you place each sphere individually, like the example above, then hull is very fast,

Spheres can be made exact by rotate extruding a semi circle with $fn a multiple of 4. I redefine sphere myself to be that.

//
// Replicate OpenSCAD logic to calculate number of sides from radius
//
function r2sides(r) = $fn ? $fn : ceil(max(min(360/ $fa, r * 2 * PI / $fs), 5));
//
// Round up number of sides to multiple of 4 to ensure points on all axes
//
function r2sides4n(r) = floor((r2sides(r) + 3) / 4) * 4;
//
// Circle with multiple of 4 vertices
//
module Circle(r, d = undef) {
    R = is_undef(d) ? r : d / 2;
    circle(R, $fn = r2sides4n(R));
}
//
// Semi circle
//
module semi_circle(r)
    intersection() {
        Circle(r);

        sq = r + 1;
        translate([-sq, 0])
            square([2 * sq, sq]);
    }
//
// Sphere that has vertices on all three axes. Has the advantage of giving correct dimensions when hulled
//
module sphere(r = 1, d = undef) {
    R = is_undef(d) ? r : d / 2;
    rotate_extrude($fn = r2sides4n(R))
        rotate(-90)
            semi_circle(R);
}

spheres.png

I manage to make everything I need with these techniques but a version of 3D Minkowski that would run before the heat death of the universe and consume less than an infinite amount of memory would be nice.

On Fri, 26 Apr 2019 at 12:16, adrianv <[hidden email]> wrote:
Even for convex shapes hull has limitations.  Anthony, if you think rounding
is "easy peezee" then first I suggest fixing the module so the rounded cube
is the right size rather than 2*r oversized.  Then I ask how you would make
a rounded pyramid with an arbitrary base polygon and apex that is a
designated size and not oversized.  Next, how would you use the hull method
to make a cylinder with rounded ends?  What if the cylinder's ends are not
normal to its axis?  If that's too easy then suppose I construct a parabola
and extrude it.  How would you round that?

data = [for(x=[-2:.05:2])[x,x*x]];
linear_extrude(height=4)polygon(data);

I'm not saying these things can't be done.  For making a rounded polyhedron
you need to put the spheres in the right place, which is not "easy peezee"
in my opinion when the polyhedron is not a cube.  (Oh, and don't forget that
spheres are actually polyhedra, and undersized.)  And the methods that leap
to mind for the cylinder seem little complex.  For the case of the parabolic
shape I don't see a way of using hull that is easier than just generating
the whole shape directly. 

The other problem with using hull is that it assumes that it makes sense to
build up your convex object from a union of convex objects.  What if you
create your convex object through difference() operations?  Then you cannot
round the final object using hull() operations.   If everything has to be
constructed with hull() it limits your options for how you can model stuff. 

As acwest notes, non-convex shapes cannot be rounded with hull.   In my
experience, nothing I design ends up being convex.  I've been pondering the
task of making a box where the inside joint between the walls and base is
rounded and the top edge is rounded.  To do this for a general box (with an
arbitrary shaped base) appears to be very difficult. 

Regarding run time, hull() can be slow.  In fact, for polyhedra with large
numbers of faces it seems that minkowski() is faster than hull().   I just
did a timing test and the hull of 50 spheres with $fn=32 took 38 seconds to
preview.  I understand that technically what's slow for hull() is not the
hull operation but the unavoidable yet unnecessary union operation between
all the spheres. 

It is possible to make a general minkowski rounding function with 3 calls to
minkowski.  But is has the limitation that the shape cannot have any areas
thinner than the roundover radius.  Also there is the question of speed.
Reportedly rounding the union of a cylinder and cube (that don't meet at
right angles) takes 12 hours.  And of course it enforces the same rounding
radius globally on the model, which may not be what you need. 


acwest wrote
> Hull only works for convex shapes, though. Minkowsky works for non-convex,
> but is much slower
>
> On Thu, 25 Apr 2019, 16:16 Anthony Walter, &lt;

> sysrpl@

> &gt; wrote:
>
>> I am the OP of the recent reddit post on this subject:
>>
>> https://www.reddit.com/r/openscad/comments/bfx897/openscad_rounded_boxes/
>>
>> Being just a beginner I had no idea how to use the hull() function. A day
>> later I now I know how to use hull() I can say it definitely solves the
>> problem of generated rounded solid a non issue. The hull() function also
>> is
>> very fast and is almost instant when used in render(). So in short,
>> rounded
>> shapes is easy if you just use the hull() function.
>>
>> A rounded cube with hull():
>>
>> module roundCube(w, d, h, radius)
>> {
>>     hull()
>>     {
>>         translate([w / 2, d / 2, 0]) sphere(radius);
>>         translate([w / 2, d / -2, 0]) sphere(radius);
>>         translate([-w / 2, d / 2, 0]) sphere(radius);
>>         translate([-w / 2, d / -2, 0]) sphere(radius);
>>         translate([w / 2, d / 2, h]) sphere(radius);
>>         translate([w / 2, d / -2, h]) sphere(radius);
>>         translate([-w / 2, d / 2, h]) sphere(radius);
>>         translate([-w / 2, d / -2, h]) sphere(radius);
>>     }
>> }
>>
>> Easy peezee and done.





--
Sent from: http://forum.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: Rounded Polygon

adrianv
nophead wrote
> Hull is only slow if it has an implicit union inside it. For example if
> you
> place spheres with a for loop or a common translation or rotation then
> they
> get unioned first and that is very slow with CGAL. If you place each
> sphere
> individually, like the example above, then hull is very fast,

I had forgotten about that.  It's not a very attractive coding method if you
have a lot of stuff to hull, though.   Also note that I had an error in my
code.  It actually takes 3.5 minutes to compute the hull of the 50 spheres.  

> Spheres can be made exact by rotate extruding a semi circle with $fn a
> multiple of 4. I redefine sphere myself to be that.

That's a nice idea.  

Note, however, that it only makes hulls exact for faces parallel to the
coordinate planes.  In my example problem of the pyramid it's going to be
very difficult to figure out the effective radius of the "sphere" in the
direction of each face so that you can position them exactly right to get a
hull that actually has the exact dimensions desired.    




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

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