-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathChamfer.scad
176 lines (164 loc) · 7.81 KB
/
Chamfer.scad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/**
* This code is published under a
* Creative Commons Attribution-NonCommercial-ShareAlike 3.0
* licence, please respect it.
*
* Chamfered primitives for OpenSCAD v1.2 - By TimeWaster
*/
/**
* chamferCube returns an cube with 45° chamfers on the edges of the
* cube. The chamfers are diectly printable on Fused deposition
* modelling (FDM) printers without support structures.
*
* @param size The size of the cube along the [x, y, z] axis,
* example: [1, 2, 3]
* @param chamfers Which chamfers to render along the [x, y, z] axis,
* example: [[0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]]
* X axis: 4 values in clockwise order starting from
* the zero point, as seen from "Left view" (Ctrl + 6)
* Y axis: 4 values in clockwise order starting from
* the zero point, as seen from "Front view" (Ctrl + 8)
* Z axis: 4 values in clockwise order starting from
* the zero point, as seen from "Bottom view" (Ctrl + 5)
* @param ch The "height" of the chamfers as seen from
* one of the dimensional planes (The real
* length is side c in a right angled triangle)
*/
module chamferCube(size, chamfers = [undef, undef, undef], ch = 1, ph1 = 1, ph2 = undef, ph3 = undef, ph4 = undef, sizeX = undef, sizeY = undef, sizeZ = undef, chamferHeight = undef, chamferX = undef, chamferY = undef, chamferZ = undef) {
if(size[0]) {
chamferCubeImpl(size[0], size[1], size[2], ch, chamfers[0], chamfers[1], chamfers[2]);
} else {
// keep backwards compatibility
size = (sizeX == undef) ? size : sizeX;
chamfers = (sizeY == undef) ? chamfers : sizeY;
ch = (sizeZ == undef) ? ch : sizeZ;
ph1 = (chamferHeight == undef) ? ph1 : chamferHeight;
ph2 = (chamferX == undef) ? ph2 : chamferX;
ph3 = (chamferY == undef) ? ph3 : chamferY;
ph4 = (chamferZ == undef) ? ph4 : chamferZ;
chamferCubeImpl(size, chamfers, ch, ph1, ph2, ph3, ph4);
}
}
module chamferCubeImpl(sizeX, sizeY, sizeZ, chamferHeight, chamferX, chamferY, chamferZ) {
chamferX = (chamferX == undef) ? [1, 1, 1, 1] : chamferX;
chamferY = (chamferY == undef) ? [1, 1, 1, 1] : chamferY;
chamferZ = (chamferZ == undef) ? [1, 1, 1, 1] : chamferZ;
chamferCLength = sqrt(chamferHeight * chamferHeight * 2);
difference() {
cube([sizeX, sizeY, sizeZ]);
for(x = [0 : 3]) {
chamferSide1 = min(x, 1) - floor(x / 3); // 0 1 1 0
chamferSide2 = floor(x / 2); // 0 0 1 1
if(chamferX[x]) {
translate([-0.1, chamferSide1 * sizeY, -chamferHeight + chamferSide2 * sizeZ])
rotate([45, 0, 0])
cube([sizeX + 0.2, chamferCLength, chamferCLength]);
}
if(chamferY[x]) {
translate([-chamferHeight + chamferSide2 * sizeX, -0.1, chamferSide1 * sizeZ])
rotate([0, 45, 0])
cube([chamferCLength, sizeY + 0.2, chamferCLength]);
}
if(chamferZ[x]) {
translate([chamferSide1 * sizeX, -chamferHeight + chamferSide2 * sizeY, -0.1])
rotate([0, 0, 45])
cube([chamferCLength, chamferCLength, sizeZ + 0.2]);
}
}
}
}
/**
* chamferCylinder returns an cylinder or cone with 45° chamfers on
* the edges of the cylinder. The chamfers are diectly printable on
* Fused deposition modelling (FDM) printers without support structures.
*
* @param h Height of the cylinder
* @param r Radius of the cylinder (At the bottom)
* @param r2 Radius of the cylinder (At the top)
* @param ch The "height" of the chamfer at radius 1 as
* seen from one of the dimensional planes (The
* real length is side c in a right angled triangle)
* @param ch2 The "height" of the chamfer at radius 2 as
* seen from one of the dimensional planes (The
* real length is side c in a right angled triangle)
* @param a The angle of the visible part of a wedge
* starting from the x axis counter-clockwise
* @param q A circle quality factor where 1.0 is a fairly
* good quality, range from 0.0 to 2.0
*/
module chamferCylinder(h, r, r2 = undef, ch = 1, ch2 = undef, a = 0, q = -1.0, height = undef, radius = undef, radius2 = undef, chamferHeight = undef, chamferHeight2 = undef, angle = undef, quality = undef) {
// keep backwards compatibility
h = (height == undef) ? h : height;
r = (radius == undef) ? r : radius;
r2 = (radius2 == undef) ? r2 : radius2;
ch = (chamferHeight == undef) ? ch : chamferHeight;
ch2 = (chamferHeight2 == undef) ? ch2 : chamferHeight2;
a = (angle == undef) ? a : angle;
q = (quality == undef) ? q : quality;
height = h;
radius = r;
radius2 = (r2 == undef) ? r : r2;
chamferHeight = ch;
chamferHeight2 = (ch2 == undef) ? ch : ch2;
angle = a;
quality = q;
module cc() {
upperOverLength = (chamferHeight2 >= 0) ? 0 : 0.01;
lowerOverLength = (chamferHeight >= 0) ? 0 : 0.01;
cSegs = circleSegments(max(radius, radius2), quality);
if(chamferHeight >= 0 || chamferHeight2 >= 0) {
hull() {
if(chamferHeight2 > 0) {
translate([0, 0, height - abs(chamferHeight2)]) cylinder(abs(chamferHeight2), r1 = radius2, r2 = radius2 - chamferHeight2, $fn = cSegs);
}
translate([0, 0, abs(chamferHeight)]) cylinder(height - abs(chamferHeight2) - abs(chamferHeight), r1 = radius, r2 = radius2, $fn = cSegs);
if(chamferHeight > 0) {
cylinder(abs(chamferHeight), r1 = radius - chamferHeight, r2 = radius, $fn = cSegs);
}
}
}
if(chamferHeight < 0 || chamferHeight2 < 0) {
if(chamferHeight2 < 0) {
translate([0, 0, height - abs(chamferHeight2)]) cylinder(abs(chamferHeight2), r1 = radius2, r2 = radius2 - chamferHeight2, $fn = cSegs);
}
translate([0, 0, abs(chamferHeight) - lowerOverLength]) cylinder(height - abs(chamferHeight2) - abs(chamferHeight) + lowerOverLength + upperOverLength, r1 = radius, r2 = radius2, $fn = cSegs);
if(chamferHeight < 0) {
cylinder(abs(chamferHeight), r1 = radius - chamferHeight, r2 = radius, $fn = cSegs);
}
}
}
module box(brim = abs(min(chamferHeight2, 0)) + 1) {
translate([-radius - brim, 0, -brim]) cube([radius * 2 + brim * 2, radius + brim, height + brim * 2]);
}
module hcc() {
intersection() {
cc();
box();
}
}
if(angle <= 0 || angle >= 360) cc();
else {
if(angle > 180) hcc();
difference() {
if(angle <= 180) hcc();
else rotate([0, 0, 180]) hcc();
rotate([0, 0, angle]) box(abs(min(chamferHeight2, 0)) + radius);
}
}
}
/**
* circleSegments calculates the number of segments needed to maintain
* a constant circle quality.
* If a globalSegementsQuality variable exist it will overwrite the
* standard quality setting (1.0). Order of usage is:
* Standard (1.0) <- globalCircleQuality <- Quality parameter
*
* @param r Radius of the circle
* @param q A quality factor, where 1.0 is a fairly good
* quality, range from 0.0 to 2.0
*
* @return The number of segments for the circle
*/
function circleSegments(r, q = -1.0) = (q >= 3 ? q : ((r * PI * 4 + 40) * ((q >= 0.0) ? q : globalCircleQuality)));
// set global quality to 1.0, can be overridden by user
globalCircleQuality = 1.0;