mirror of
https://github.com/Irev-Dev/Round-Anything.git
synced 2025-09-03 20:32:37 +02:00
Compare commits
33 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
061fef7c42 | ||
|
2f47c7631c | ||
|
57c7889ff0 | ||
|
0161f336e0 | ||
|
980948b31c | ||
|
d4a001ce09 | ||
|
116c961393 | ||
|
5711ff827c | ||
|
dd7d7121c0 | ||
|
ea20000c74 | ||
|
df71daa0cb | ||
|
23a4204593 | ||
|
ba1e80058c | ||
|
0fbca7c2d5 | ||
|
dd05f2e441 | ||
|
f35262f955 | ||
|
1b7623e17b | ||
|
c56190a81b | ||
|
e9faa0785d | ||
|
e9d3d805ab | ||
|
df50ac47ce | ||
|
9c2e9b929b | ||
|
cfd739d79d | ||
|
f69ddaa05b | ||
|
bce6705d4c | ||
|
28814a34a0 | ||
|
8ead00a2bf | ||
|
66f30bed93 | ||
|
f9928e36e1 | ||
|
26fb282626 | ||
|
c04a81f25c | ||
|
e6d91c352b | ||
|
297a7ce5dc |
16
README.md
16
README.md
@@ -6,11 +6,18 @@ Round-Anything is primarily a set of OpenSCAD utilities that help with rounding
|
||||
|
||||
## The Why
|
||||
|
||||
The truth is radii, internal radii in particular can be a real pain to add in openscad. and the more you move away from shapes with 90 degree angles the more difficult it becomes, effectively puting a complexity ceiling on parts you can produce in OpenScad. Because of how important radii in both making a apealing and strong part, reducing stress concentration etc, A library that focuses on radii as a core principle makes for a solid foundation for your parts. Furthermore the heart of the library revolves around the polygon, this is because we're leveraging the battle tested paradigm of extruding from 2d sketches of most CAD packages. I can't imagine making an OpenScad part without Round-Anything.
|
||||
The truth is radii, internal radii in particular can be a real pain to add in openscad. and the more you move away from shapes with 90 degree angles the more difficult it becomes, effectively putting a complexity ceiling on parts you can produce in OpenScad. Because of how important radii in both making an appealing and strong part, reducing stress concentration etc, A library that focuses on radii as a core principle makes for a solid foundation for your parts. Furthermore the heart of the library revolves around the polygon, this is because we're leveraging the battle tested paradigm of extruding from 2d sketches of most CAD packages. I can't imagine making an OpenScad part without Round-Anything.
|
||||
|
||||
### Quick side-notes
|
||||
|
||||
I'm currently working on a community website for "Code-CAD" (like OpenSCAD). A good way to think of it is codepen crossed with a thing repository. You can check it out at [cadhub.xyz](https://cadhub.xyz/) or it's [repo](https://github.com/Irev-Dev/cadhub).
|
||||
|
||||
Also please submit examples of what you build with the library in the [discussions](https://github.com/Irev-Dev/Round-Anything/discussions), I'd love to see them. I also recommend you "watch" the repo with notifications turned on for the discussions to stay up-to-date.
|
||||
|
||||
## Documentation
|
||||
|
||||
See an overview of the library in [video form](https://www.youtube.com/watch?v=laxv2wFKq8Q)
|
||||
|
||||
<a href="https://www.youtube.com/watch?v=laxv2wFKq8Q"><img src="https://i.ytimg.com/vi/laxv2wFKq8Q/sddefault.jpg" width="100%" align="left"></a>
|
||||
|
||||
|
||||
@@ -18,6 +25,8 @@ See an overview of the library in [video form](https://www.youtube.com/watch?v=l
|
||||
|
||||
[Full documentation of the API is here](https://kurthutten.com/blog/round-anything-api/).
|
||||
|
||||
[Installation instructions](https://github.com/Irev-Dev/Round-Anything/discussions/21)
|
||||
|
||||
## Extra
|
||||
|
||||
I [live streamed](https://www.youtube.com/watch?v=1Tegarwy69I&t=2s) the making of [this part](https://github.com/Irev-Dev/monitor-stand-turn-camera) using this library. I was able to make the bulk of this part quickly even with some complex radii involved thanks to the library.
|
||||
@@ -27,3 +36,8 @@ I [live streamed](https://www.youtube.com/watch?v=1Tegarwy69I&t=2s) the making o
|
||||
Below are some of the example parts that can be found in [roundAnythingExamples.scad](https://github.com/Irev-Dev/Round-Anything/blob/master/roundAnythingExamples.scad).
|
||||
|
||||
<img src="https://cdn.sanity.io/images/2hqqc7om/production/2dba6301d1f25b1c45a634058b280b52fa713b60-1920x1080.png?w=1920&h=1000&fit=crop" width="100%" align="left">
|
||||
|
||||
## Citation
|
||||
roundUnionMask Includes code based on examples from:
|
||||
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]
|
||||
|
3
examples/README.md
Normal file
3
examples/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Round-Anything examples
|
||||
|
||||
These examples are mostly to go with the [library Documentation](https://learn.cadhub.xyz/docs/round-anything/overview) and so are best viewed there.
|
34
examples/beamChain-1.scad
Normal file
34
examples/beamChain-1.scad
Normal file
@@ -0,0 +1,34 @@
|
||||
// beamChain example 1
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
function beamPoints(r1,r2,rStart=0,rEnd=0)=[
|
||||
[0, 0, rStart],
|
||||
[2, 8, 0 ],
|
||||
[5, 4, r1 ],
|
||||
[15, 10, r2 ],
|
||||
[17, 2, rEnd ]
|
||||
];
|
||||
|
||||
linear_extrude(1){
|
||||
|
||||
// chained lines by themselves
|
||||
translate(){
|
||||
radiiPoints=beamPoints(0,0);
|
||||
polygon(polyRound(beamChain(radiiPoints,offset1=0.02, offset2=-0.02),20));
|
||||
}
|
||||
|
||||
|
||||
// Add some radii to the line transitions
|
||||
translate([0,-7,0]){
|
||||
radiiPoints=beamPoints(2,1);
|
||||
polygon(polyRound(beamChain(radiiPoints,offset1=0.02, offset2=-0.02),20));
|
||||
}
|
||||
|
||||
// Give make the lines beams with some thickness
|
||||
translate([0,-7*2,0]){
|
||||
radiiPoints=beamPoints(2,1);
|
||||
polygon(polyRound(beamChain(radiiPoints,offset1=0.5, offset2=-0.5),20));
|
||||
}
|
||||
|
||||
}
|
27
examples/beamChain-2.scad
Normal file
27
examples/beamChain-2.scad
Normal file
@@ -0,0 +1,27 @@
|
||||
// beamChain example 2
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
function beamPoints(r1,r2,rStart=0,rEnd=0)=[
|
||||
[0, 0, rStart],
|
||||
[2, 8, 0 ],
|
||||
[5, 4, r1 ],
|
||||
[15, 10, r2 ],
|
||||
[17, 2, rEnd ]
|
||||
];
|
||||
|
||||
linear_extrude(1){
|
||||
|
||||
// Add an angle to the start of the beam
|
||||
translate([0,-7*3,0]){
|
||||
radiiPoints=beamPoints(2,1);
|
||||
polygon(polyRound(beamChain(radiiPoints,offset1=0.5, offset2=-0.5, startAngle=45),20));
|
||||
}
|
||||
|
||||
// Put a negative radius at the start for transationing to a flat surface
|
||||
translate([0,-7*4,0]){
|
||||
radiiPoints=beamPoints(2,1,rStart=-0.7);
|
||||
polygon(polyRound(beamChain(radiiPoints,offset1=0.5, offset2=-0.5, startAngle=45),20));
|
||||
}
|
||||
|
||||
}
|
50
examples/beamChain-3.scad
Normal file
50
examples/beamChain-3.scad
Normal file
@@ -0,0 +1,50 @@
|
||||
// beamChain example 3
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
function beamPoints(r1,r2,rStart=0,rEnd=0)=[
|
||||
[0, 0, rStart],
|
||||
[2, 8, 0 ],
|
||||
[5, 4, r1 ],
|
||||
[15, 10, r2 ],
|
||||
[17, 2, rEnd ]
|
||||
];
|
||||
|
||||
// Define more points for a polygon to be atteched to the end of the beam chain
|
||||
clipP=[
|
||||
[16, 1.2, 0 ],
|
||||
[16, 0, 0 ],
|
||||
[16.5, 0, 0 ],
|
||||
[16.5, 1, 0.2],
|
||||
[17.5, 1, 0.2],
|
||||
[17.5, 0, 0 ],
|
||||
[18, 0, 0 ],
|
||||
[18, 1.2, 0 ]
|
||||
];
|
||||
|
||||
linear_extrude(1){
|
||||
// end hook
|
||||
translate([-15,-7*5+3,0]){
|
||||
polygon(polyRound(clipP,20));
|
||||
}
|
||||
|
||||
// Attached to the end of the beam chain by dividing the beam paths in forward and return and
|
||||
// concat other polygon inbetween
|
||||
translate([0,-7*6,0]){
|
||||
radiiPoints=beamPoints(2,1);
|
||||
forwardPath=beamChain(radiiPoints,offset1=0.5,startAngle=-15,mode=2);
|
||||
returnPath=revList(beamChain(radiiPoints,offset1=-0.5,startAngle=-15,mode=2));
|
||||
entirePath=concat(forwardPath,clipP,returnPath);
|
||||
polygon(polyRound(entirePath,20));
|
||||
}
|
||||
|
||||
// Add transitioning radii into the end polygong
|
||||
translate([0,-7*7-2,0]){
|
||||
radiiPoints=beamPoints(2,1,rEnd=3);
|
||||
forwardPath=beamChain(radiiPoints,offset1=0.5,startAngle=-15,mode=2);
|
||||
returnPath=revList(beamChain(radiiPoints,offset1=-0.5,startAngle=-15,mode=2));
|
||||
entirePath=concat(forwardPath,clipP,returnPath);
|
||||
polygon(polyRound(entirePath,20));
|
||||
}
|
||||
|
||||
}
|
22
examples/beamChain-4.scad
Normal file
22
examples/beamChain-4.scad
Normal file
@@ -0,0 +1,22 @@
|
||||
// beamChain example 4
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
function beamPoints(r1,r2,rStart=0,rEnd=0)=[
|
||||
[0, 0, rStart],
|
||||
[2, 8, 0 ],
|
||||
[5, 4, r1 ],
|
||||
[15, 10, r2 ],
|
||||
[17, 2, rEnd ]
|
||||
];
|
||||
|
||||
linear_extrude(1){
|
||||
|
||||
translate([0,-7*9,0]){
|
||||
// Define multiple shells from the the one set of points
|
||||
for(i=[0:2]){
|
||||
polygon(polyRound(beamChain(beamPoints(2,1),offset1=-1+i*0.4, offset2=-1+i*0.4+0.25),20));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
13
examples/extrudeWithRadius.scad
Normal file
13
examples/extrudeWithRadius.scad
Normal file
@@ -0,0 +1,13 @@
|
||||
// extrudeWithRadius example
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
radiiPoints=[
|
||||
[-4, 0, 1 ],
|
||||
[5, 3, 1.5 ],
|
||||
[0, 7, 0.1 ],
|
||||
[8, 7, 10 ],
|
||||
[20, 20, 0.8 ],
|
||||
[10, 0, 10 ]
|
||||
];
|
||||
extrudeWithRadius(3,0.5,0.5,5)polygon(polyRound(radiiPoints,30));
|
10
examples/mirrorPoints.scad
Normal file
10
examples/mirrorPoints.scad
Normal file
@@ -0,0 +1,10 @@
|
||||
// mirrorPoints example
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
centerRadius=7;
|
||||
points=[[0,0,0],[2,8,0],[5,4,3],[15,10,0.5],[10,2,centerRadius]];
|
||||
mirroredPoints=mirrorPoints(points,0,[0,0]);
|
||||
linear_extrude(1)
|
||||
translate([0,-20,0])
|
||||
polygon(polyRound(mirroredPoints,20));
|
24
examples/negative-polyRoundExtrude.scad
Normal file
24
examples/negative-polyRoundExtrude.scad
Normal file
@@ -0,0 +1,24 @@
|
||||
// negative polyRoundExtrude example
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
extrudeRadius = 0.8;
|
||||
extrudeHeight = 2;
|
||||
tiny = 0.005; // tiny value is used to stop artifacts from planes lining up perfectly
|
||||
|
||||
radiiPoints=[
|
||||
[-7, -3, 0 ],
|
||||
[7, -3, 0 ],
|
||||
[0, 6, 1 ] // top of the triagle is rounded
|
||||
];
|
||||
negativeRadiiPoints=[
|
||||
[-3, -1, 0 ],
|
||||
[3, -1, 0 ],
|
||||
[0, 3, 1 ] // top of the triagle is rounded
|
||||
];
|
||||
|
||||
difference() {
|
||||
polyRoundExtrude(radiiPoints,extrudeHeight, extrudeRadius, extrudeRadius,fn=20);
|
||||
translate([0,0,-tiny])
|
||||
polyRoundExtrude(negativeRadiiPoints,extrudeHeight+2*tiny, -extrudeRadius, -extrudeRadius,fn=20);
|
||||
}
|
13
examples/polyRoundExtrude.scad
Normal file
13
examples/polyRoundExtrude.scad
Normal file
@@ -0,0 +1,13 @@
|
||||
// polyRoundExtrude example
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
radiiPoints=[
|
||||
[10, 0, 10 ],
|
||||
[20, 20, 1.1],
|
||||
[8, 7, 10 ],
|
||||
[0, 7, 0.3],
|
||||
[5, 3, 0.1],
|
||||
[-4, 0, 1 ]
|
||||
];
|
||||
polyRoundExtrude(radiiPoints,2,0.5,-0.8,fn=20);
|
13
examples/polyround.scad
Normal file
13
examples/polyround.scad
Normal file
@@ -0,0 +1,13 @@
|
||||
// polyRound example
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
radiiPoints=[
|
||||
[-4, 0, 1 ],
|
||||
[5, 3, 1.5 ],
|
||||
[0, 7, 0.1 ],
|
||||
[8, 7, 10 ],
|
||||
[20, 20, 0.8 ],
|
||||
[10, 0, 10 ]
|
||||
];
|
||||
linear_extrude(3)polygon(polyRound(radiiPoints,30));
|
25
examples/radii-conflict.scad
Normal file
25
examples/radii-conflict.scad
Normal file
@@ -0,0 +1,25 @@
|
||||
// radii conflict example
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
//example of radii conflict handling and debuging feature
|
||||
function makeRadiiPoints(r1, r2)=[
|
||||
[0, 0, 0 ],
|
||||
[0, 20, r1 ],
|
||||
[20, 20, r2 ],
|
||||
[20, 0, 0 ]
|
||||
];
|
||||
|
||||
linear_extrude(3){
|
||||
// the squre shape being 20 wide, two radii of 10 both fit into the shape (just)
|
||||
translate([-25,0,0])polygon(polyRound(makeRadiiPoints(10,10),50));
|
||||
|
||||
//radii are too large and are reduced to fit and will be reduce to 10 and 10
|
||||
translate([0,0,0])polygon(polyRound(makeRadiiPoints(30,30),50));
|
||||
|
||||
//radii are too large again and are reduced to fit, but keep their ratios r1 will go from 10 to 4 and r2 will go from 40 to 16
|
||||
translate([25,0,0])polygon(polyRound(makeRadiiPoints(10,40),50));
|
||||
|
||||
//mode 2 = no radii limiting
|
||||
translate([50,0,0])polygon(polyRound(makeRadiiPoints(15,20),50,mode=2));
|
||||
}
|
29
examples/shell2d.scad
Normal file
29
examples/shell2d.scad
Normal file
@@ -0,0 +1,29 @@
|
||||
// shell2d example
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
module gridpattern(memberW = 4, sqW = 12, iter = 5, r = 3){
|
||||
round2d(0, r)rotate([0, 0, 45])translate([-(iter * (sqW + memberW) + memberW) / 2, -(iter * (sqW + memberW) + memberW) / 2])difference(){
|
||||
square([(iter) * (sqW + memberW) + memberW, (iter) * (sqW + memberW) + memberW]);
|
||||
for (i = [0:iter - 1], j = [0:iter - 1]){
|
||||
translate([i * (sqW + memberW) + memberW, j * (sqW + memberW) + memberW])square([sqW, sqW]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
radiiPoints=[
|
||||
[-4, 0, 1 ],
|
||||
[5, 3, 1.5 ],
|
||||
[0, 7, 0.1 ],
|
||||
[8, 7, 10 ],
|
||||
[20, 20, 0.8 ],
|
||||
[10, 0, 10 ]
|
||||
];
|
||||
|
||||
linear_extrude(1){
|
||||
shell2d(-0.5)polygon(polyRound(radiiPoints,30));
|
||||
translate([0,-10,0])shell2d(-0.5){
|
||||
polygon(polyRound(radiiPoints,30));
|
||||
translate([8,8])gridpattern(memberW = 0.3, sqW = 1, iter = 17, r = 0.2);
|
||||
}
|
||||
}
|
30
examples/translateRadiiPoints.scad
Normal file
30
examples/translateRadiiPoints.scad
Normal file
@@ -0,0 +1,30 @@
|
||||
// translateRadiiPoints example
|
||||
|
||||
include <Round-Anything-1.0.4/polyround.scad>
|
||||
|
||||
nutW=5.5; nutH=3; boltR=1.6;
|
||||
minT=2; minR=0.8;
|
||||
function nutCapture(startAndEndRadius=0)=[
|
||||
[-boltR, 0, startAndEndRadius],
|
||||
[-boltR, minT, 0],
|
||||
[-nutW/2, minT, minR],
|
||||
[-nutW/2, minT+nutH, minR],
|
||||
[nutW/2, minT+nutH, minR],
|
||||
[nutW/2, minT, minR],
|
||||
[boltR, minT, 0],
|
||||
[boltR, 0, startAndEndRadius],
|
||||
];
|
||||
linear_extrude(3)translate([-5,0,0])polygon(polyRound(nutCapture(),20));
|
||||
|
||||
negativeNutCapture=translateRadiiPoints(nutCapture(),tran=[5,0]);
|
||||
rotatedNegativeNutCapture=translateRadiiPoints(nutCapture(1),tran=[20,5],rot=90);
|
||||
aSquare=concat(
|
||||
[[0,0,0]],
|
||||
negativeNutCapture,
|
||||
[[20,0,0]],
|
||||
rotatedNegativeNutCapture,
|
||||
[[20,10,0]],
|
||||
[[0,10,0]]
|
||||
);
|
||||
|
||||
linear_extrude(3)polygon(polyRound(aSquare,20));
|
File diff suppressed because it is too large
Load Diff
228020
nicefillets.stl
228020
nicefillets.stl
File diff suppressed because it is too large
Load Diff
@@ -90,7 +90,7 @@ let(
|
||||
)
|
||||
[polyhedronPoints, polyhedronFaces, layerLength];
|
||||
|
||||
function flatternRecursion(array, init=[], currentIndex)=
|
||||
function flatternRecursion(array, init=[], currentIndex=0)=
|
||||
// this is a private function, init and currentIndex are for the function's use
|
||||
// only for when it's calling itself, which is why there is a simplified version flatternArray that just calls this one
|
||||
// array= array to flattern by one level of nesting
|
||||
@@ -165,12 +165,15 @@ let(
|
||||
];
|
||||
|
||||
module polyRoundExtrude(radiiPoints,length=5,r1=1,r2=1,fn=10,convexity=10) {
|
||||
orderedRadiiPoints = CWorCCW(radiiPoints) == 1
|
||||
? reverseList(radiiPoints)
|
||||
: radiiPoints;
|
||||
assert(len(radiiPoints) > 2, str("There must be at least 3 radii points for polyRoundExtrude. ", radiiPoints, " is not long enough, you need ", 3 - len(radiiPoints), " more point/s. Example: polyRoundExtrude([[11,0,1],[20,20,1.1],[8,7,0.5]],2,0.5,-0.8,fn=8);"));
|
||||
if(len(radiiPoints) > 2) {
|
||||
orderedRadiiPoints = CWorCCW(radiiPoints) == 1
|
||||
? reverseList(radiiPoints)
|
||||
: radiiPoints;
|
||||
|
||||
polyhedronPointsNFaces=extrudePolygonWithRadius(orderedRadiiPoints,length,r1,r2,fn);
|
||||
polyhedron(points=polyhedronPointsNFaces[0], faces=polyhedronPointsNFaces[1], convexity=convexity);
|
||||
polyhedronPointsNFaces=extrudePolygonWithRadius(orderedRadiiPoints,length,r1,r2,fn);
|
||||
polyhedron(points=polyhedronPointsNFaces[0], faces=polyhedronPointsNFaces[1], convexity=convexity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -448,7 +451,7 @@ function CWorCCW(p)=
|
||||
(p[listWrap(i+0,Lp)].x-p[listWrap(i+1,Lp)].x)*(p[listWrap(i+0,Lp)].y+p[listWrap(i+1,Lp)].y)
|
||||
]
|
||||
)
|
||||
sign(sum(e));
|
||||
sign(polySum(e));
|
||||
|
||||
function CentreN2PointsArc(p1,p2,cen,mode=0,fn)=
|
||||
/* This function plots an arc from p1 to p2 with fn increments using the cen as the centre of the arc.
|
||||
@@ -682,8 +685,8 @@ function cosineRuleAngle(p1,p2,p3)=
|
||||
)
|
||||
acos((sq(p23)+sq(p12)-sq(p13))/(2*p23*p12));
|
||||
|
||||
function sum(list, idx = 0, result = 0) =
|
||||
idx >= len(list) ? result : sum(list, idx + 1, result + list[idx]);
|
||||
function polySum(list, idx = 0, result = 0) =
|
||||
idx >= len(list) ? result : polySum(list, idx + 1, result + list[idx]);
|
||||
|
||||
function sq(x)=x*x;
|
||||
function getGradient(p1,p2)=(p2.y-p1.y)/(p2.x-p1.x);
|
||||
|
91
unionRoundMask-Doc.md
Normal file
91
unionRoundMask-Doc.md
Normal file
@@ -0,0 +1,91 @@
|
||||
## unionRoundMask / unionRound
|
||||
---
|
||||
### Union with round fillet at selected places. Created for Round-Anything by TLC123 (2021).
|
||||
A shortcut for faster fillet union is enabled when the operation constrained to convex operands.
|
||||
For most cases unionRoundMask / unionRound replaces MinkowskiRound.
|
||||
Combined with a system of mask selectors, unionRound becomes even more versetile.
|
||||
|
||||

|
||||
|
||||
## unionRoundMask
|
||||
---
|
||||
Union with round fillet at selected places.
|
||||
### module unionRoundMask(r=1, detail = 5 , q=70, epsilon = 1e-6, showMask = true , includeOperands = true)
|
||||
|
||||
Masks are a method to perform unionRound on selected only areas,
|
||||
and circumvents the previous limitation to common convex work area.
|
||||
Mask are essentially just common primitives that is used to mark out areas by intersection.
|
||||
|
||||
r:
|
||||
* approximate radius for fillet. Exact radius is dependant on crease angle.
|
||||
* detail: numbers of fillet segments. 1 is essensially a chamfer/bevel.
|
||||
* Set low for faster preview. ( $preview?3:10 )
|
||||
|
||||
q:
|
||||
* determine how detailed clad operations are.
|
||||
* Set low for faster preview. ( $preview?30:70 )
|
||||
|
||||
epsilon:
|
||||
* For debugging, leave as is.
|
||||
|
||||
showMask:
|
||||
* For debugging, try it.
|
||||
|
||||
includeOperands:
|
||||
* For debugging, render only fillet when false.
|
||||
|
||||
### usage:
|
||||
````
|
||||
unionRoundMask( r = 1 , detail = $preview ? 3 : 10 , q = $preview ? 30 : 70 )
|
||||
{
|
||||
yourObject1();
|
||||
yourObject2();
|
||||
yourMask1();
|
||||
yourMask2();
|
||||
yourMask3();
|
||||
// ...
|
||||
// ...
|
||||
// ...
|
||||
}
|
||||
````
|
||||
|
||||
---
|
||||
## unionRound
|
||||
---
|
||||
### module unionRound(r=1, detail = 5 , q=70, epsilon = 1e-6 , includeOperands = true )
|
||||
|
||||
Module unionRound is the underlying work module of unionRoundMask.
|
||||
It can be used by it self, in some cases faster but more raw.
|
||||
|
||||
### usage:
|
||||
````
|
||||
unionRoundMask( r = 1 , detail = $preview ? 3 : 10 , q= $preview ? 30 : 70 )
|
||||
{
|
||||
yourObject1();
|
||||
yourObject2();
|
||||
}
|
||||
````
|
||||
|
||||
---
|
||||
## intersectionRound
|
||||
---
|
||||
module intersectionRound(r, q=70, epsilon = 1e-6,showOperands = true)
|
||||
prototype module
|
||||
Undocumented for now.
|
||||
|
||||
---
|
||||
## helpers
|
||||
---
|
||||
````
|
||||
module clad(r,q=70) // speed is limited to convex operand.
|
||||
module shell(r,q=70) // not in use.
|
||||
module inset(r,q=20) // speed is limited to convex operand.
|
||||
````
|
||||
---
|
||||
## Citation
|
||||
---
|
||||
### roundUnionMask Includes code based on examples from:
|
||||
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]
|
179
unionRoundMask.scad
Normal file
179
unionRoundMask.scad
Normal file
@@ -0,0 +1,179 @@
|
||||
////////////////////////////////////////////////////////
|
||||
/*
|
||||
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 = false, includeOperands = true) {
|
||||
//automask if none
|
||||
if($children <=2){
|
||||
unionRoundMask(r,detail,q,epsilon,showMask, includeOperands)
|
||||
{
|
||||
children(0);
|
||||
children(1);
|
||||
clad(max(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;
|
||||
rx=is_list(r)?r[1]:r;
|
||||
ry=is_list(r)?r[0]:r;
|
||||
union()for (i = [0: detail-1]) {
|
||||
{
|
||||
x = rx - sin(i * step ) * rx;
|
||||
y = ry - cos(i * step ) * ry;
|
||||
xi = rx - sin((i * step + step) ) * rx;
|
||||
yi = ry - cos((i * step + step) ) * ry;
|
||||
// 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]]);
|
||||
}
|
Reference in New Issue
Block a user