1
0
mirror of https://github.com/Irev-Dev/Round-Anything.git synced 2025-09-03 20:32:37 +02:00

33 Commits

Author SHA1 Message Date
Kurt Hutten
061fef7c42 Merge pull request #48 from nfedyashev/nfedyashev-patch-1
Rename sum function
2023-08-07 08:41:33 +10:00
Nikita Fedyashev
2f47c7631c Rename sum function
This name is rather generic and has a high chance of conflicting with other libraries(e.g. BOSL2) or used-defined functions.
2023-08-04 11:02:11 +03:00
Kurt Hutten
57c7889ff0 Merge pull request #42 from duskmushroom/patch-1
Update README.md
2022-07-23 14:46:20 +10:00
DMoosh
0161f336e0 Update README.md
Grammar/spelling
2022-07-19 21:43:37 +03:00
Kurt Hutten
980948b31c Merge pull request #39 from jamespbryan/patch-1
Update README.md
2022-02-20 17:13:33 +11:00
James P Bryan
d4a001ce09 Update README.md
grammar correction 'a' to 'an'
2022-02-05 16:44:54 -05:00
Kurt Hutten
116c961393 Merge pull request #34 from Irev-Dev/Irev-Dev-patch-1
Delete insideoutsiteround.stl
2021-08-31 17:37:39 +10:00
Kurt Hutten
5711ff827c Delete nicefillets.stl 2021-08-31 17:36:07 +10:00
Kurt Hutten
dd7d7121c0 Delete insideoutsiteround.stl 2021-08-31 17:35:20 +10:00
Kurt Hutten
ea20000c74 Merge pull request #33 from TLC123/master
unionRoundMask
2021-08-31 17:33:51 +10:00
TLC123
df71daa0cb removed rands color due to interference with seed 2021-08-26 18:04:18 +02:00
TLC123
23a4204593 r radius can now also be a pair of [r,r] for a biased curve effect 2021-08-24 19:19:15 +02:00
TLC123
ba1e80058c Update unionRoundMask-Doc.md
documentaion for includeOperands argument
2021-08-23 16:44:02 +02:00
TLC123
0fbca7c2d5 option to not _includeOperands_ and just render fillet 2021-08-23 16:38:30 +02:00
TLC123
dd05f2e441 doc file is .md not .scad 2021-08-23 16:21:50 +02:00
TLC123
f35262f955 Update unionRoundMask-Doc.md
doc clean up
2021-08-23 16:19:56 +02:00
TLC123
1b7623e17b Update unionRoundMask-Doc.md
cleanup headers
2021-08-23 15:52:21 +02:00
TLC123
c56190a81b doc file is .md not .scad 2021-08-23 15:07:59 +02:00
TLC123
e9faa0785d Update unionRoundMask-Doc.md.scad 2021-08-23 15:03:51 +02:00
TLC123
e9d3d805ab UnionRoundMask and -doc.md 2021-08-23 14:59:51 +02:00
Kurt Hutten
df50ac47ce Merge pull request #32 from Irev-Dev/kurt/individual-exampes-29
Beam chain example formatting
2021-06-07 17:26:56 +10:00
Kurt Hutten
9c2e9b929b Beam chain example formatting 2021-06-07 17:26:32 +10:00
Kurt Hutten
cfd739d79d Merge pull request #31 from Irev-Dev/kurt/individual-exampes-29
Fix beamChain example and add negative polyRoundExtrude example
2021-06-07 17:07:30 +10:00
Kurt Hutten
f69ddaa05b Fix beamChain example and add negative polyRoundExtrude example 2021-06-07 17:06:02 +10:00
Kurt Hutten
bce6705d4c Merge pull request #30 from Irev-Dev/kurt/individual-exampes-29
Add individual examples
2021-06-07 07:15:59 +10:00
Kurt Hutten
28814a34a0 Add individual examples
Having one example per file will make for a integration and there
live demo links with CadHub.
Resolves #29.
2021-06-07 07:15:06 +10:00
Kurt Hutten
8ead00a2bf Merge pull request #28 from Irev-Dev/kurt/polyRoundExtrude-unbounded-26
Add error message when there are not enough polyRoundExtrude points
2021-05-31 05:20:34 +10:00
Kurt Hutten
66f30bed93 Add error message when there are not enough polyRoundExtrude points
Resolves #26
2021-05-30 14:54:29 +10:00
Kurt Hutten
f9928e36e1 Merge pull request #23 from damienmg/patch-1
Correctly instanciate recursion index
2021-05-03 11:39:05 +10:00
Damien Martin-Guillerez
26fb282626 Correctly instanciate recursion index
Caller of the flatternRecursion method does not set necessarily the index value and OpenSCAD complain that this result in adding number to undefined.
2021-05-02 11:43:31 +02:00
Kurt Hutten
c04a81f25c Update README.md 2021-01-28 18:28:26 +11:00
Kurt Hutten
e6d91c352b Update README.md 2021-01-03 18:51:22 +11:00
Kurt Hutten
297a7ce5dc Merge pull request #17 from Irev-Dev/issue16-fix-90deg-bug-in-findPoint
Fix 90 degree bug in findPoint
2020-11-02 18:14:50 +11:00
19 changed files with 590 additions and 235704 deletions

View File

@@ -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
View 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
View 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
View 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
View 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
View 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));
}
}
}

View 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));

View 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));

View 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);
}

View 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
View 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));

View 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
View 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);
}
}

View 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

File diff suppressed because it is too large Load Diff

View File

@@ -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
View 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.
![unionround-doc-example](https://user-images.githubusercontent.com/10944617/130456818-c5fd43d1-e6df-4e88-8474-aed1a0c3ca31.png)
## 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
View 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]]);
}