Monday, August 23, 2021

Trying out Cadhub.xyz

Trying out Cadhub.xyz

cadhub.xyz/u/TLC123/unionRoundMask-scad


 

ComplementryRGBColor

ComplementryRGBColor calculates the opposite point of the 
color wheel to resolve the complementary color


for(i=[0:360/20:180]){ c=rands(0,1,3,i); rotate(i,[0,.1,1]) { color(c)render()translate([5,5])square(10); color(complementryRGBColor(c))render()translate([13,13])square(10); } echo(c,complementryRGBColor(c)); } function complementryRGBColor(c) = let (r = c[0], g = c[1], b = c[2]) (max(r, g, b) == min(r, g, b)) ? [1 - r, 1 - g, 1 - b] : let (mx = max(r, g, b), mn = min(r, g, b), h = (mx + mn) / 2, s = (mx + mn) / 2, l = (mx + mn) / 2, d = mx - mn) let (s = l > 0.5 ? d / (2 - mx - mn) : d / (mx + mn), h = mx == r ? (g - b) / d + (g < b ? 6 : 0) : mx == g ? (b - r) / d + 2 : /*mx== b?*/ (r - g) / d + 4) let (h = round((h * 60) + 180) % 360) let (h = h / 360) let (hue2rgb = function(p, q, t) let (t = t - floor(t)) (t < 1 / 6) ? p + (q - p) * 6 * t : (t < 1 / 2) ? q : (t < 2 / 3) ? p + (q - p) * (2 / 3 - t) * 6 : p) let (q = l < 0.5 ? l * (1 + s) : l + s - l * s) let (p = 2 * l - q) let (r = hue2rgb(p, q, h + 1 / 3)) let (g = hue2rgb(p, q, h)) let (b = hue2rgb(p, q, h - 1 / 3))[r, g, b];

Saturday, August 14, 2021

OpenSCAD unionRound() Module

One of the most common request is boolean operations with fillet/chamfer/rounding/radius/smoothing . Most option so far has been unsatisfactory or glacially slow.

Updated version at Github
  
Enabled by fast convex + convex minkowski sum. Thanks whoever implemented that.

Unions of simple operands has a general FAST solution in all cases where the joint area is convex

For non convex operands, a simple masking system enable us to isolate out only local convex areas to process.
Masks are in practice a common volume that both operands are first intersected by.

Though not a complete solution a good part of common cases can be filleted. (se limitations.)

With an exploit of fast convex + convex minkowski and the Theorem: Given any collection of convex sets, their intersection is itself a convex set.
The following became possible:
   ////////////////////////////////////////////////////////
    /*
    unionRound() 1.0 Module by Torleif Ceder - TLC123 late summer 2021
     Pretty fast Union with radius, But limited to a subset of cases
    Usage 
     unionRound( radius , detail  )
        {
         YourObject1();
         YourObject2(); 
        } 
      unionRoundMask (r, detail , epsilon ,showMask )
        {
         YourObject1();
         YourObject2(); 
         YourMask();
         YourMask();   
         
         // ...
         // ...
         // ...
         
        } 
    limitations: 
     0. Only really fast when boolean operands are convex, 
            Minkowski is fast in that case. 
     1. Boolean operands may be concave but can only touch 
            in a single convex area
     2. Radius is of elliptic type and is only approximate r
            were operand intersect at perpendicular angle. 
    */
    //////////////////////////////////////////////////////// 
    // Demo code
    demo= false;
    if (demo)  
     unionRoundMask( r=1.5 , detail= 5 , q=70
    , includeOperands = true) {
     cube([10,10,2],true);
     rotate([20,-10,0])cylinder(5,1,1,$fn=12);   
     translate([0,0,1.5])cube([1.5,10,3],center=true); //mask
      rotate(90)
     translate([0,0,1.5])cube([3,10,3],center=true); //mask
    }
    
    // end of demo code
    //
    module unionRoundMask(r=1, detail = 5,q=70, epsilon = 1e-6
    , showMask = true, includeOperands = true) {
    //automask if none
    if($children <=2){
        unionRoundMask(r,detail,q,epsilon,showMask, includeOperands)
        {
            children(0);
            children(1);
            clad(r,q) intersection(){
                    children(0);
                    children(1);
                }
            }
            }
        else {
        union() {
          if(includeOperands){ 
                children(0);
                children(1);
               }
            if (showMask && $children > 2) %
                for (i = [2: max(2, $children - 1)]) children(i);

            if ($children > 2)
                for (i = [2: max(2, $children - 1)]) {
                    intersection() {
                        children(i);

                        unionRound(r, detail,q, epsilon
    ,includeOperands) {
                            intersection() {
                                children(0);
                                children(i); // mask
                            }
                            intersection() {
                                children(1);
                                children(i); // mask
                            }
                        }
                    }
                }
            }
         }
    }
    
    
    module unionRound(r=1, detail = 5,q=70,  epsilon = 1e-6
    , includeOperands=true) {
       if(includeOperands){ 
        children(0);
        children(1);
       }
        step = 90 / detail;
      union()for (i = [0:  detail-1]) {
            {
                x = r - sin(i * step ) * r;
                y = r - cos(i * step ) * r;
                xi = r - sin((i * step + step)  ) * r;
                yi = r - cos((i * step + step)  ) * r;
                color(rands(0, 1, 3, i))
                hull() {
                    intersection() {
                        // shell(epsilon) 
                        clad(x,q) children(0);
                        // shell(epsilon) 
                        clad(y,q) children(1);
                    }
                    intersection() {
                        // shell(epsilon) 
                        clad(xi,q) children(0);
                        // shell(epsilon) 
                        clad(yi,q) children(1);
                    }
                }
            }
        }
    }
    
    // prototype module slow maybe on concave feature
    module intersectionRound(r, q=70,  epsilon = 1e-6
,showOperands = true) {
        %if (showOperands){children(0);
        children(1);}
 
                    clad(r,q) inset(r,q)
                     hull()intersection() {
                           children(0);
                           children(1);
                    }
 
    }
    
    // unionRound helper expand by r
    module clad(r,q=70) {
        minkowski() {
            children();
            //        icosphere(r,2);
             isosphere(r,q); 
        }
    }
    // unionRound helper
    module shell(r,q=70) {
        difference() {
            clad(r,q) children();
            children();
        }
    }
    
    // inset 3d  "negative offset", optimally on convex hull
    // else jagged inner corners by q quality factor 
    module inset(r,q=20){
    a= generatepoints(q)*r;
    //#children();
    intersection_for(t=a){
      translate(t ) children();
    }
    }
    
    
    /*    
    // The following is a sphere with some equidistant properties.
    // Not strictly necessary

    Kogan, Jonathan (2017) 
    "A New Computationally Efficient Method for 
    Spacing n Points on a Sphere," 
    Rose-Hulman Undergraduate Mathematics Journal: 
    Vol. 18 : Iss. 2 , Article 5.
    Available at: 
    https://scholar.rose-hulman.edu/rhumj/vol18/iss2/5 */
    
    function sphericalcoordinate(x,y)=[cos(x)*cos(y),sin(x)*cos(y),sin(y)];
    function NX(n=70,x)= 
    let(toDeg=57.2958,PI=acos(-1)/toDeg,
    start=(-1.+1./(n-1.)),increment=(2.-2./(n-1.))/(n-1.) )
    [ for (j= [0:n-1])let (s=start+j*increment )
    sphericalcoordinate(s*x*toDeg,PI/2.*sign(s)*(1.-sqrt(1.-abs(s)))*toDeg)];
    function generatepoints(n=70)= NX(n,0.1+1.2*n);
    module isosphere(r,q=70){
    a= generatepoints(q);
    scale(r)hull()polyhedron(a,[[for(i=[0:len(a)-1])i]]);
    }



on Youtube

on GitHub

on Thingiverse

on OpenSCAD Snippet Pad

on r /OpenSCAD



Thursday, August 5, 2021

My OpenSCAD Feature wish list.

Language:
- Reference image import - based on surface()  just zero height and a texture.
        OpenCSG very much support this out of the box.



- Native Minkowski over 1D and 2D primitives.


- Native function import .scad file as pre render in [ points , faces ].
        this closes the loop a bit. At least save current mesh result as a 
         polyhedron([ points , faces ])   .dot scad file.

- Auto crop shape when:
ERROR: all points for rotate_extrude() must have the same X coordinate sign

- importMetrics catching information about imported files  similar to textmetrics()



Gui:

- Save/display depth map and normal map from render pipeline to png.
- Animation play- pause
- Ambient SSAO 



- Auto indent selection and general code beautifier
 Save current mesh result as a 
         polyhedron([ points , faces ])   .dot scad file.


T.B.C.