Trying out Cadhub.xyz
cadhub.xyz/u/TLC123/unionRoundMask-scad
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];
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.
//////////////////////////////////////////////////////// /* 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]]);
}
Language:
- Reference image import - based on surface() just zero height and a texture.
OpenCSG very much support this out of the box.
- 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