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.
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]]);
}
No comments:
Post a Comment