summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--delta.jscad29
1 files changed, 29 insertions, 0 deletions
diff --git a/delta.jscad b/delta.jscad
index 326d172..35a777c 100644
--- a/delta.jscad
+++ b/delta.jscad
@@ -1,533 +1,562 @@
1var PRINT = { 1var PRINT = {
2 layer_height: 0.2, 2 layer_height: 0.2,
3 extrusion_width: 0.4, 3 extrusion_width: 0.4,
4 4
5 fit_tolerance: .2, slide_tolerance: .4, play_tolerance: .6, screw_tolerance: .3 5 fit_tolerance: .2, slide_tolerance: .4, play_tolerance: .6, screw_tolerance: .3
6}; 6};
7 7
8var CONFIG = { 8var CONFIG = {
9 extrusion: { 9 extrusion: {
10 w: 20, slotdepth: 6 10 w: 20, slotdepth: 6
11 }, 11 },
12 base: { 12 base: {
13 el: 240, // side extrusion length 13 el: 240, // side extrusion length
14 sl: 240+2*70, // triangle side length 14 sl: 240+2*70, // triangle side length
15 gap: 9 // vertical gap between side extrusions 15 gap: 9 // vertical gap between side extrusions
16 }, 16 },
17 column: { 17 column: {
18 h: 600 // column height 18 h: 600 // column height
19 }, 19 },
20 heatbed: { 20 heatbed: {
21 r: 220/2, // heatbed radius 21 r: 220/2, // heatbed radius
22 sr: 220/2-4.5,// radius of the screwholes circle 22 sr: 220/2-4.5,// radius of the screwholes circle
23 h: 3+1.5 // thickness (including insulation) 23 h: 3+1.5 // thickness (including insulation)
24 }, 24 },
25 glass: { 25 glass: {
26 r: 195/2, // glass radius 26 r: 195/2, // glass radius
27 h: 3 // glass thickness 27 h: 3 // glass thickness
28 }, 28 },
29 duet: { 29 duet: {
30 pcb_size: { x: 124, y: 100, z: 1 }, 30 pcb_size: { x: 124, y: 100, z: 1 },
31 hole_spacing: { x: 115, y: 92 }, 31 hole_spacing: { x: 115, y: 92 },
32 h: 30 32 h: 30
33 }, 33 },
34 foot: { 34 foot: {
35 d: 20*Math.sqrt(2), h: 30, 35 d: 20*Math.sqrt(2), h: 30,
36 bolt: { d:5, l: 19, hd: 10 }, 36 bolt: { d:5, l: 19, hd: 10 },
37 margin: 2.5, 37 margin: 2.5,
38 nut: { d: 8.6 /* TODO: */, h: 3.5 }, 38 nut: { d: 8.6 /* TODO: */, h: 3.5 },
39 shell: 4, 39 shell: 4,
40 zscalefactor: 1.6, 40 zscalefactor: 1.6,
41 foot: { ho: 2.5, hi: 5 } 41 foot: { ho: 2.5, hi: 5 }
42 }, 42 },
43 duetholder: { 43 duetholder: {
44 bolt: { d: 3, l: 10, head: { d: 5.33, h: 3 } }, 44 bolt: { d: 3, l: 10, head: { d: 5.33, h: 3 } },
45 margin: 3, 45 margin: 3,
46 s: 2.5 46 s: 2.5
47 }, 47 },
48 bedholder: { 48 bedholder: {
49 h: 15, 49 h: 15,
50 margin: 3, 50 margin: 3,
51 nut: { w: 5.4, h: 2.5 }, 51 nut: { w: 5.4, h: 2.5 },
52 bolt: { d: 3, l: 10, head: { d: 5.33, h: 3 } } 52 bolt: { d: 3, l: 10, head: { d: 5.33, h: 3 } }
53 }, 53 },
54 hotend: { 54 hotend: {
55 h: 62.4, // full assembly height 55 h: 62.4, // full assembly height
56 groove: { d:12, h:6 }, // grove diameter and height 56 groove: { d:12, h:6 }, // grove diameter and height
57 ungroove: { d:16, above:3.7, below: 3+4 } 57 ungroove: { d:16, above:3.7, below: 3+4 }
58 }, 58 },
59 effector: { 59 effector: {
60 h: 6, 60 h: 6,
61 o: 20,// offset to the rod mounts line 61 o: 20,// offset to the rod mounts line
62 rods_apart: 40, 62 rods_apart: 40,
63 cone: { shell: 1, angle: Math.PI/6 }, 63 cone: { shell: 1, angle: Math.PI/6 },
64 rodend: { 64 rodend: {
65 joint_w: 7,// thickness of the joint 65 joint_w: 7,// thickness of the joint
66 screw_l: 20-1, // 20 with the head 66 screw_l: 20-1, // 20 with the head
67 screw_d: 3 67 screw_d: 3
68 }, 68 },
69 hotend: { margin: 2 }, 69 hotend: { margin: 2 },
70 hinge: { 70 hinge: {
71 d: 3, w: 5, margin: 2.5, 71 d: 3, w: 5, margin: 2.5,
72 h: 1+(6+3.7)/2, // elevation + grove + top 72 h: 1+(6+3.7)/2, // elevation + grove + top
73 e: 1 // elevation 73 e: 1 // elevation
74 }, 74 },
75 clamp: { 75 clamp: {
76 shell: 4.6, 76 shell: 4.6,
77 d: 3, 77 d: 3,
78 margin: 2.5, 78 margin: 2.5,
79 split: 0.6 79 split: 0.6
80 }, 80 },
81 mswitch: { 81 mswitch: {
82 size: [ 19.8, 6, 10 ], 82 size: [ 19.8, 6, 10 ],
83 screw: { 83 screw: {
84 d: 2, h: 10/2-2, 84 d: 2, h: 10/2-2,
85 s: 1.3, // screw shell 85 s: 1.3, // screw shell
86 o: [-9.5/2,9.5/2].map(function(x) { 86 o: [-9.5/2,9.5/2].map(function(x) {
87 return -19.8/2+x; 87 return -19.8/2+x;
88 }) 88 })
89 }, 89 },
90 switch_x: 2.5 90 switch_x: 2.5
91 }, 91 },
92 guide: { 92 guide: {
93 width: 3, height: 5+1, length: 6 93 width: 3, height: 5+1, length: 6
94 }, 94 },
95 fanholder: { 95 fanholder: {
96 r: 30, 96 r: 30,
97 screw: { d: 3, m: 2.5/*margin*/ }, 97 screw: { d: 3, m: 2.5/*margin*/ },
98 w: 3 98 w: 3
99 } 99 }
100 }, 100 },
101 nut: { h: 2.3, w: 5.5 }, 101 nut: { h: 2.3, w: 5.5 },
102 color: { 102 color: {
103 extrusion: [0.8, 0.8, 0.8, 0.8], 103 extrusion: [0.8, 0.8, 0.8, 0.8],
104 pcb: [ 0, 0.3, 0.2, 0.8 ], 104 pcb: [ 0, 0.3, 0.2, 0.8 ],
105 bulk: [ .9, .9, .9, .2 ], 105 bulk: [ .9, .9, .9, .2 ],
106 parts: [ 0, 0.8, 0, 0.9 ], 106 parts: [ 0, 0.8, 0, 0.9 ],
107 softparts: [ 0, 0, 0.8, 0.9 ], 107 softparts: [ 0, 0, 0.8, 0.9 ],
108 heatbed: [0.8, 0.8, 0.8, 0.8 ], 108 heatbed: [0.8, 0.8, 0.8, 0.8 ],
109 glass: [0.9, 0.9, 0.9, 0.7 ] 109 glass: [0.9, 0.9, 0.9, 0.7 ]
110 } 110 }
111}; 111};
112 112
113var CD = { 113var CD = {
114 base: (function(){ 114 base: (function(){
115 var rv = {}; 115 var rv = {};
116 rv.circumscription_r = 116 rv.circumscription_r =
117 CONFIG.base.sl/2/Math.cos(Math.PI/6); 117 CONFIG.base.sl/2/Math.cos(Math.PI/6);
118 rv.outer_inscription_r = 118 rv.outer_inscription_r =
119 Math.sqrt(Math.pow(rv.circumscription_r,2)- 119 Math.sqrt(Math.pow(rv.circumscription_r,2)-
120 Math.pow(CONFIG.base.sl/2,2)); 120 Math.pow(CONFIG.base.sl/2,2));
121 rv.mid_inscription_r = 121 rv.mid_inscription_r =
122 rv.outer_inscription_r-CONFIG.extrusion.w/2; 122 rv.outer_inscription_r-CONFIG.extrusion.w/2;
123 rv.inner_inscription_r = 123 rv.inner_inscription_r =
124 rv.outer_inscription_r-CONFIG.extrusion.w; 124 rv.outer_inscription_r-CONFIG.extrusion.w;
125 // TODO: properly calculate 125 // TODO: properly calculate
126 rv.column_r = rv.circumscription_r - 48.29; 126 rv.column_r = rv.circumscription_r - 48.29;
127 return rv; 127 return rv;
128 })(), 128 })(),
129 duetholder: (function() { 129 duetholder: (function() {
130 var rv = {}; 130 var rv = {};
131 var s = CONFIG.base.sl; 131 var s = CONFIG.base.sl;
132 var l = CONFIG.duet.hole_spacing.x; 132 var l = CONFIG.duet.hole_spacing.x;
133 var w = CONFIG.duet.hole_spacing.y; 133 var w = CONFIG.duet.hole_spacing.y;
134 var h = s*Math.cos(Math.PI/6); 134 var h = s*Math.cos(Math.PI/6);
135 var h1 = h*(1-l/s); 135 var h1 = h*(1-l/s);
136 rv.distance = (h1-w)/3; // hole to side 136 rv.distance = (h1-w)/3; // hole to side
137 return rv; 137 return rv;
138 })() 138 })()
139}; 139};
140console.log(CONFIG); console.log(CD); 140console.log(CONFIG); console.log(CD);
141 141
142var U = { 142var U = {
143 hypotenuse: function(a,b) { 143 hypotenuse: function(a,b) {
144 return Math.sqrt(Math.pow(a,2)+Math.pow(b,2)); 144 return Math.sqrt(Math.pow(a,2)+Math.pow(b,2));
145 }, 145 },
146 peek: function(x,m) { 146 peek: function(x,m) {
147 console.log(x,m); 147 console.log(x,m);
148 return x; 148 return x;
149 },
150 axes: function U_axes(o) {
151 if(!o) o = {};
152 var l = o.l||20, g = o.g||0.7;
153 return union([
154 CSG.roundedCylinder({start:[0,0,0],end:[l,0,0]}).setColor([1,0,0,g]),
155 CSG.roundedCylinder({start:[0,0,0],end:[0,l,0]}).setColor([0,1,0,g]),
156 CSG.roundedCylinder({start:[0,0,0],end:[0,0,l]}).setColor([0,0,1,g])
157 ]);
158 },
159 pextract: function U_pextract(a,pn) { // TODO: monkeypatch Array
160 return a.map(function(x){return x[pn]});
161 },
162 hole: function U_hole(o) {
163 var r = o.r||o.radius||(o.d/2)||(o.diameter/2);
164 var n = Math.max(Math.round(4*r),4);
165 return CSG.cylinder({
166 start: o.start, end: o.end,
167 radius: r/Math.cos(Math.PI/n),
168 resultion: n
169 });
170 },
171
172 upright: function U_upright() { return new CSG.Connector([0,0,0],[0,0,1],[1,0,0]) },
173 downright: function U_downright() { return new CSG.Connector([0,0,0],[0,0,-1],[1,0,0]) },
174 P: function U_P(x) {
175 if(!x.properties.P) return x;
176 return x.connectTo(x.properties.P,U.upright(),false,0);
149 } 177 }
178
150}; 179};
151 180
152/* {h:,w:} */ 181/* {h:,w:} */
153function nut(o) { 182function nut(o) {
154 var rv = CSG.cylinder({ 183 var rv = CSG.cylinder({
155 start:[0,0,0],end:[0,0,o.h], 184 start:[0,0,0],end:[0,0,o.h],
156 radius: o.w/2/Math.cos(Math.PI/6), 185 radius: o.w/2/Math.cos(Math.PI/6),
157 resolution: 6 186 resolution: 6
158 }); 187 });
159 rv.properties.axis_connector = new CSG.Connector([0,0,0],[0,0,1],[0,1,0]); 188 rv.properties.axis_connector = new CSG.Connector([0,0,0],[0,0,1],[0,1,0]);
160 return rv; 189 return rv;
161} 190}
162 191
163var E3DV6 = { 192var E3DV6 = {
164 dimensions: { 193 dimensions: {
165 big_d: 22.3, 194 big_d: 22.3,
166 195
167 }, 196 },
168 heatsink: function() { 197 heatsink: function() {
169 var fn = 16; 198 var fn = 16;
170 var z=0; 199 var z=0;
171 var unite = [ {d:16,h:3.7},{d:12,h:6},{d:16,h:3} ].map(function(x) { 200 var unite = [ {d:16,h:3.7},{d:12,h:6},{d:16,h:3} ].map(function(x) {
172 return CSG.cylinder({ 201 return CSG.cylinder({
173 start: [0,0,z], end: [0,0,z-=x.h], 202 start: [0,0,z], end: [0,0,z-=x.h],
174 radius: x.d/2, resolution: fn 203 radius: x.d/2, resolution: fn
175 }); 204 });
176 }); 205 });
177 unite.push(CSG.cylinder({ 206 unite.push(CSG.cylinder({
178 start:[0,0,z-=1.5], end:[0,0,z-=1], 207 start:[0,0,z-=1.5], end:[0,0,z-=1],
179 radius: 16/2, resolution: fn 208 radius: 16/2, resolution: fn
180 })); 209 }));
181 for(var i=0;i<11;++i) unite.push(CSG.cylinder({ 210 for(var i=0;i<11;++i) unite.push(CSG.cylinder({
182 start:[0,0,z-=1.5], end:[0,0,z-=1], 211 start:[0,0,z-=1.5], end:[0,0,z-=1],
183 radius: this.dimensions.big_d/2, resolution: fn 212 radius: this.dimensions.big_d/2, resolution: fn
184 })); 213 }));
185 unite.push(CSG.cylinder({ 214 unite.push(CSG.cylinder({
186 start:[0,0,z], end: [0,0,-12.7], 215 start:[0,0,z], end: [0,0,-12.7],
187 radiusStart: 10/2, radiusEnd: 8.5/2, /* pretty arbitrary */ 216 radiusStart: 10/2, radiusEnd: 8.5/2, /* pretty arbitrary */
188 resolution: fn 217 resolution: fn
189 })); 218 }));
190 var rv = union(unite); 219 var rv = union(unite);
191 rv = rv.subtract([CSG.cylinder({ 220 rv = rv.subtract([CSG.cylinder({
192 start:[0,0,1], end: [0,0,z-1], 221 start:[0,0,1], end: [0,0,z-1],
193 radius: 4.2/2, resolution: fn 222 radius: 4.2/2, resolution: fn
194 }),CSG.cylinder({ 223 }),CSG.cylinder({
195 start:[0,0,1], end: [0,0,-6.7/*somewhat arbitrary*/], 224 start:[0,0,1], end: [0,0,-6.7/*somewhat arbitrary*/],
196 radius: 8/2, resolution: fn 225 radius: 8/2, resolution: fn
197 }),CSG.cylinder({ 226 }),CSG.cylinder({
198 start:[0,0,z-1], end: [0,0,z+14.8], 227 start:[0,0,z-1], end: [0,0,z+14.8],
199 radius: 6/2 /*M7*/, resolution: fn 228 radius: 6/2 /*M7*/, resolution: fn
200 })]); 229 })]);
201 rv.properties.pushfit_connector = new CSG.Connector([0,0,0],[0,0,-1],[1,0,0]); 230 rv.properties.pushfit_connector = new CSG.Connector([0,0,0],[0,0,-1],[1,0,0]);
202 rv.properties.heatbreak_connector = new CSG.Connector([0,0,z+14.8],[0,0,-1],[1,0,0]); 231 rv.properties.heatbreak_connector = new CSG.Connector([0,0,z+14.8],[0,0,-1],[1,0,0]);
203 rv.properties.grove_connector = new CSG.Connector([0,0,-3.7-3],[0,0,1],[1,0,0]); 232 rv.properties.grove_connector = new CSG.Connector([0,0,-3.7-3],[0,0,1],[1,0,0]);
204 return rv.setColor([0.8,0.8,0.8,0.9]); 233 return rv.setColor([0.8,0.8,0.8,0.9]);
205 } 234 }
206}; 235};
207 236
208var EFFECTOR = { 237var EFFECTOR = {
209 /* {sd: screw diameter, l: cone length, s: screw shell, a: angle from axis} */ 238 /* {sd: screw diameter, l: cone length, s: screw shell, a: angle from axis} */
210 cone: function effector_cone(o) { 239 cone: function effector_cone(o) {
211 var re = o.sd/2+o.s, rs = re+o.l*Math.tan(o.a||(Math.PI/4)); 240 var re = o.sd/2+o.s, rs = re+o.l*Math.tan(o.a||(Math.PI/4));
212 var rv = CSG.cylinder({ 241 var rv = CSG.cylinder({
213 start: [0,0,0], end: [0,0,o.l], 242 start: [0,0,0], end: [0,0,o.l],
214 radiusStart: rs, radiusEnd: re, 243 radiusStart: rs, radiusEnd: re,
215 resolution: Math.floor(rs*2*2) 244 resolution: Math.floor(rs*2*2)
216 }).subtract(CSG.cylinder({ 245 }).subtract(CSG.cylinder({
217 start:[0,0,-1], end:[0,0,o.l+1], radius: o.sd, 246 start:[0,0,-1], end:[0,0,o.l+1], radius: o.sd,
218 //resolution: Math.floor(o.sd*2*2) 247 //resolution: Math.floor(o.sd*2*2)
219 })); 248 }));
220 rv.properties.top_connector = new CSG.Connector([0,0,o.l],[0,0,-1],[1,0,0]); 249 rv.properties.top_connector = new CSG.Connector([0,0,o.l],[0,0,-1],[1,0,0]);
221 rv.properties.bottom_connector = new CSG.Connector([0,0,0],[0,0,1],[1,0,0]); 250 rv.properties.bottom_connector = new CSG.Connector([0,0,0],[0,0,1],[1,0,0]);
222 var nuthole = nut(CONFIG.nut); 251 var nuthole = nut(CONFIG.nut);
223 rv = rv.subtract(nuthole.connectTo( 252 rv = rv.subtract(nuthole.connectTo(
224 nuthole.properties.axis_connector, rv.properties.bottom_connector, 253 nuthole.properties.axis_connector, rv.properties.bottom_connector,
225 false, 0 254 false, 0
226 )); 255 ));
227 return rv.intersect(CSG.cylinder({start:[0,0,0],end:[0,0,o.l],radius:6/*TODO:calculate*/})); 256 return rv.intersect(CSG.cylinder({start:[0,0,0],end:[0,0,o.l],radius:6/*TODO:calculate*/}));
228 }, 257 },
229 platform_bb: function platform_bb() { 258 platform_bb: function platform_bb() {
230 var e = CONFIG.effector; 259 var e = CONFIG.effector;
231 var r = U.hypotenuse(e.rods_apart/2,e.o+e.rodend.screw_d/2+e.cone.shell); 260 var r = U.hypotenuse(e.rods_apart/2,e.o+e.rodend.screw_d/2+e.cone.shell);
232 var rv = CSG.sphere({ 261 var rv = CSG.sphere({
233 center: [0,0,e.h/2], radius: r, 262 center: [0,0,e.h/2], radius: r,
234 resolution: r*2*2 263 resolution: r*2*2
235 }).intersect(CSG.cube({ 264 }).intersect(CSG.cube({
236 corner1: [-r,-r,0], corner2: [r,r,e.h] 265 corner1: [-r,-r,0], corner2: [r,r,e.h]
237 })); 266 }));
238 rv.properties.base_connector = new CSG.Connector([0,0,0],[0,0,1],[1,0,0]); 267 rv.properties.base_connector = new CSG.Connector([0,0,0],[0,0,1],[1,0,0]);
239 return rv; 268 return rv;
240 }, 269 },
241 effector: function effector_effector() { 270 effector: function effector_effector() {
242 var e = CONFIG.effector; 271 var e = CONFIG.effector;
243 var conel = e.rodend.screw_l-e.rodend.joint_w; 272 var conel = e.rodend.screw_l-e.rodend.joint_w;
244 var nutr = CONFIG.nut.w/2/Math.cos(Math.PI/6); 273 var nutr = CONFIG.nut.w/2/Math.cos(Math.PI/6);
245 var cone = this.cone({sd:e.rodend.screw_d/2,l:conel,s:e.cone.shell,a:e.cone.angle}); 274 var cone = this.cone({sd:e.rodend.screw_d/2,l:conel,s:e.cone.shell,a:e.cone.angle});
246 var rcorner = U.hypotenuse(e.o-e.rodend.screw_d/2-e.cone.shell,e.rods_apart/2)-3.85; //XXX:config/calc 275 var rcorner = U.hypotenuse(e.o-e.rodend.screw_d/2-e.cone.shell,e.rods_apart/2)-3.85; //XXX:config/calc
247 var ropen = E3DV6.dimensions.big_d/2+e.hotend.margin; 276 var ropen = E3DV6.dimensions.big_d/2+e.hotend.margin;
248 var rmount = this.rmount = (rcorner+ropen)/2; 277 var rmount = this.rmount = (rcorner+ropen)/2;
249 var rv = []; 278 var rv = [];
250 for(var a=0;a<360;a+=120) { 279 for(var a=0;a<360;a+=120) {
251 rv.push(union([-1,1].map(function(s) { 280 rv.push(union([-1,1].map(function(s) {
252 return cone.connectTo(cone.properties.top_connector, 281 return cone.connectTo(cone.properties.top_connector,
253 new CSG.Connector([s*e.rods_apart/2,e.o,e.h/2],[-s,0,0],[0,0,1]), 282 new CSG.Connector([s*e.rods_apart/2,e.o,e.h/2],[-s,0,0],[0,0,1]),
254 false, 0); 283 false, 0);
255 })).union(CSG.cube({ 284 })).union(CSG.cube({
256 corner1:[e.rods_apart/2-conel+.1,e.o-nutr,0], 285 corner1:[e.rods_apart/2-conel+.1,e.o-nutr,0],
257 corner2:[-e.rods_apart/2+conel-.1, 286 corner2:[-e.rods_apart/2+conel-.1,
258 -rcorner, 287 -rcorner,
259 e.h] 288 e.h]
260 })).rotateZ(a)); 289 })).rotateZ(a));
261 } 290 }
262 rv.push(CSG.cylinder({ 291 rv.push(CSG.cylinder({
263 start:[0,0,0], end:[0,0,e.h], 292 start:[0,0,0], end:[0,0,e.h],
264 radius: U.hypotenuse(e.o-nutr,e.rods_apart/2-conel) 293 radius: U.hypotenuse(e.o-nutr,e.rods_apart/2-conel)
265 })); 294 }));
266 rv = union(rv).intersect(this.platform_bb()).subtract(CSG.cylinder({ 295 rv = union(rv).intersect(this.platform_bb()).subtract(CSG.cylinder({
267 start:[0,0,-1], end:[0,0,e.h+1], 296 start:[0,0,-1], end:[0,0,e.h+1],
268 radius: ropen, resolution: ropen*4 297 radius: ropen, resolution: ropen*4
269 })).subtract([/*0, probe here*/120,240].map(function(x) { /* nut pockets */ 298 })).subtract([/*0, probe here*/120,240].map(function(x) { /* nut pockets */
270 return CSG.cube({ 299 return CSG.cube({
271 corner1:[-CONFIG.nut.w/2,0,(e.h-CONFIG.nut.h)/2], 300 corner1:[-CONFIG.nut.w/2,0,(e.h-CONFIG.nut.h)/2],
272 corner2:[CONFIG.nut.w/2,-rcorner-1,(e.h+CONFIG.nut.h)/2] 301 corner2:[CONFIG.nut.w/2,-rcorner-1,(e.h+CONFIG.nut.h)/2]
273 }).union(CSG.cylinder({ 302 }).union(CSG.cylinder({
274 start:[0,-rmount,-1], end:[0,-rmount,e.h+1], 303 start:[0,-rmount,-1], end:[0,-rmount,e.h+1],
275 radius: 3/2 // XXX: 304 radius: 3/2 // XXX:
276 })).subtract(CSG.cylinder({ 305 })).subtract(CSG.cylinder({
277 start:[0,-rmount,(e.h+CONFIG.nut.h)/2], 306 start:[0,-rmount,(e.h+CONFIG.nut.h)/2],
278 end:[0,-rmount,(e.h+CONFIG.nut.h)/2+PRINT.layer_height*3/2], 307 end:[0,-rmount,(e.h+CONFIG.nut.h)/2+PRINT.layer_height*3/2],
279 radius: 3/2+.1 308 radius: 3/2+.1
280 })).rotateZ(x); 309 })).rotateZ(x);
281 })).subtract( CSG.cylinder({ // pulldown screw 310 })).subtract( CSG.cylinder({ // pulldown screw
282 start: [0,-rcorner+e.mswitch.size[1]+PRINT.extrusion_width+3/2/*XXX:conf*/,-1], 311 start: [0,-rcorner+e.mswitch.size[1]+PRINT.extrusion_width+3/2/*XXX:conf*/,-1],
283 end: [0,-rcorner+e.mswitch.size[1]+PRINT.extrusion_width+3/2/*XXX:conf*/,e.h+1], 312 end: [0,-rcorner+e.mswitch.size[1]+PRINT.extrusion_width+3/2/*XXX:conf*/,e.h+1],
284 radius: 3/2+1 /*XXX: config */ 313 radius: 3/2+1 /*XXX: config */
285 })).subtract( CSG.cylinder({ /* switch-screw */ 314 })).subtract( CSG.cylinder({ /* switch-screw */
286 start: [e.mswitch.switch_x,-rcorner+e.mswitch.size[1]/2,-1], 315 start: [e.mswitch.switch_x,-rcorner+e.mswitch.size[1]/2,-1],
287 end: [e.mswitch.switch_x,-rcorner+e.mswitch.size[1]/2,e.h+1], 316 end: [e.mswitch.switch_x,-rcorner+e.mswitch.size[1]/2,e.h+1],
288 radius: e.mswitch.screw.d/2 317 radius: e.mswitch.screw.d/2
289 })); 318 }));
290 // add hinges 319 // add hinges
291 rv.properties.hinge_connector=new CSG.Properties(); 320 rv.properties.hinge_connector=new CSG.Properties();
292 var hinges_apart=e.rods_apart/2-conel; 321 var hinges_apart=e.rods_apart/2-conel;
293 rv = rv.union([-1,1].map(function hinge(s) { 322 rv = rv.union([-1,1].map(function hinge(s) {
294 rv.properties.hinge_connector[s]=new CSG.Connector([s*hinges_apart,e.o,e.h+e.hinge.h],[s,0,0],[0,0,1]); 323 rv.properties.hinge_connector[s]=new CSG.Connector([s*hinges_apart,e.o,e.h+e.hinge.h],[s,0,0],[0,0,1]);
295 return CSG.cube({ 324 return CSG.cube({
296 corner1: [s*hinges_apart,e.o-e.hinge.margin-e.hinge.d/2,e.h], 325 corner1: [s*hinges_apart,e.o-e.hinge.margin-e.hinge.d/2,e.h],
297 corner2: [s*(hinges_apart+e.hinge.w),e.o+e.hinge.margin+e.hinge.d/2,e.h+e.hinge.h] 326 corner2: [s*(hinges_apart+e.hinge.w),e.o+e.hinge.margin+e.hinge.d/2,e.h+e.hinge.h]
298 }).union(CSG.cylinder({ 327 }).union(CSG.cylinder({
299 start: [s*hinges_apart,e.o,e.h+e.hinge.h], 328 start: [s*hinges_apart,e.o,e.h+e.hinge.h],
300 end: [s*(hinges_apart+e.hinge.w),e.o,e.h+e.hinge.h], 329 end: [s*(hinges_apart+e.hinge.w),e.o,e.h+e.hinge.h],
301 radius: e.hinge.d/2+e.hinge.margin 330 radius: e.hinge.d/2+e.hinge.margin
302 })).subtract(CSG.cylinder({ 331 })).subtract(CSG.cylinder({
303 start: [s*(hinges_apart-1),e.o,e.h+e.hinge.h], 332 start: [s*(hinges_apart-1),e.o,e.h+e.hinge.h],
304 end: [s*(hinges_apart+e.hinge.w+1),e.o,e.h+e.hinge.h], 333 end: [s*(hinges_apart+e.hinge.w+1),e.o,e.h+e.hinge.h],
305 radius: e.hinge.d/2 334 radius: e.hinge.d/2
306 })); 335 }));
307 })); 336 }));
308 // add clamp guides 337 // add clamp guides
309 var cgrr = e.guide.width/3; 338 var cgrr = e.guide.width/3;
310 rv = rv.union([-1,1].map(function guide(s) { 339 rv = rv.union([-1,1].map(function guide(s) {
311 return CSG.roundedCube({ 340 return CSG.roundedCube({
312 center: [s*(e.mswitch.size[0]+PRINT.slide_tolerance+e.guide.width)/2,-rcorner+e.guide.length/2,e.h+e.guide.height/2-cgrr], 341 center: [s*(e.mswitch.size[0]+PRINT.slide_tolerance+e.guide.width)/2,-rcorner+e.guide.length/2,e.h+e.guide.height/2-cgrr],
313 radius: [e.guide.width/2,e.guide.length/2,e.guide.height/2+cgrr], 342 radius: [e.guide.width/2,e.guide.length/2,e.guide.height/2+cgrr],
314 roundradius: cgrr 343 roundradius: cgrr
315 }).intersect(CSG.cube({ 344 }).intersect(CSG.cube({
316 center: [s*(e.mswitch.size[0]+PRINT.slide_tolerance+e.guide.width)/2,-rcorner+e.guide.length/2,e.h+e.guide.height/2], 345 center: [s*(e.mswitch.size[0]+PRINT.slide_tolerance+e.guide.width)/2,-rcorner+e.guide.length/2,e.h+e.guide.height/2],
317 radius: [e.guide.width/2,e.guide.length/2,e.guide.height/2+.1], 346 radius: [e.guide.width/2,e.guide.length/2,e.guide.height/2+.1],
318 roundradius: cgrr 347 roundradius: cgrr
319 })); 348 }));
320 })); 349 }));
321 rv.properties.grove_connector = new CSG.Connector([0,0,e.h+e.hinge.e+6/2],[0,0,1],[1,0,0]); 350 rv.properties.grove_connector = new CSG.Connector([0,0,e.h+e.hinge.e+6/2],[0,0,1],[1,0,0]);
322 rv.properties.rcorner = rcorner; 351 rv.properties.rcorner = rcorner;
323 return rv.setColor([0.4,0.8,0.4,0.9]); 352 return rv.setColor([0.4,0.8,0.4,0.9]);
324 }, 353 },
325 hinged: function effector_hinged(o) { 354 hinged: function effector_hinged(o) {
326 var e = CONFIG.effector; 355 var e = CONFIG.effector;
327 var conel = e.rodend.screw_l-e.rodend.joint_w; 356 var conel = e.rodend.screw_l-e.rodend.joint_w;
328 var hinges_apart = e.rods_apart/2-conel; 357 var hinges_apart = e.rods_apart/2-conel;
329 var hhr = e.o-e.hinge.d/2-e.hinge.margin; // hotend holder radius 358 var hhr = e.o-e.hinge.d/2-e.hinge.margin; // hotend holder radius
330 var hhh = CONFIG.hotend.groove.h+CONFIG.hotend.ungroove.above; 359 var hhh = CONFIG.hotend.groove.h+CONFIG.hotend.ungroove.above;
331 var rv = CSG.cylinder({ /* hinge */ 360 var rv = CSG.cylinder({ /* hinge */
332 start: [-hinges_apart+PRINT.slide_tolerance,e.o,e.h+e.hinge.h], 361 start: [-hinges_apart+PRINT.slide_tolerance,e.o,e.h+e.hinge.h],
333 end: [hinges_apart-PRINT.slide_tolerance,e.o,e.h+e.hinge.h], 362 end: [hinges_apart-PRINT.slide_tolerance,e.o,e.h+e.hinge.h],
334 radius: e.hinge.d/2+e.hinge.margin 363 radius: e.hinge.d/2+e.hinge.margin
335 }).union( /* lower hotend holder */ 364 }).union( /* lower hotend holder */
336 CSG.cylinder({ 365 CSG.cylinder({
337 start: [0,0,e.h+e.hinge.e], end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h], 366 start: [0,0,e.h+e.hinge.e], end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h],
338 radius: hhr 367 radius: hhr
339 }).subtract(CSG.cylinder({ 368 }).subtract(CSG.cylinder({
340 start: [0,0,e.h+e.hinge.e-1], end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h+1], 369 start: [0,0,e.h+e.hinge.e-1], end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h+1],
341 radius: CONFIG.hotend.groove.d/2 +PRINT.fit_tolerance 370 radius: CONFIG.hotend.groove.d/2 +PRINT.fit_tolerance
342 })) 371 }))
343 ).union( /* upper hotend holder */ 372 ).union( /* upper hotend holder */
344 CSG.cylinder({ 373 CSG.cylinder({
345 start: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h], 374 start: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h],
346 end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h+CONFIG.hotend.ungroove.above], 375 end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h+CONFIG.hotend.ungroove.above],
347 radius: hhr 376 radius: hhr
348 }).subtract(CSG.cylinder({ 377 }).subtract(CSG.cylinder({
349 start: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h-1], 378 start: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h-1],
350 end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h+CONFIG.hotend.ungroove.above+1], 379 end: [0,0,e.h+e.hinge.e+CONFIG.hotend.groove.h+CONFIG.hotend.ungroove.above+1],
351 radius: CONFIG.hotend.ungroove.d/2 +PRINT.fit_tolerance 380 radius: CONFIG.hotend.ungroove.d/2 +PRINT.fit_tolerance
352 })) 381 }))
353 ).union( /* connect mount with hinge */ 382 ).union( /* connect mount with hinge */
354 CSG.cube({ 383 CSG.cube({
355 corner1: [-hinges_apart+PRINT.slide_tolerance,CONFIG.hotend.ungroove.d/2+PRINT.fit_tolerance,e.h+e.hinge.e], 384 corner1: [-hinges_apart+PRINT.slide_tolerance,CONFIG.hotend.ungroove.d/2+PRINT.fit_tolerance,e.h+e.hinge.e],
356 corner2: [hinges_apart-PRINT.slide_tolerance,e.o,e.h+e.hinge.h+e.hinge.d/2+e.hinge.margin] 385 corner2: [hinges_apart-PRINT.slide_tolerance,e.o,e.h+e.hinge.h+e.hinge.d/2+e.hinge.margin]
357 }) 386 })
358 ).subtract( /* hinge screwhole */ 387 ).subtract( /* hinge screwhole */
359 CSG.cylinder({ 388 CSG.cylinder({
360 start: [-hinges_apart-1,e.o,e.h+e.hinge.h], 389 start: [-hinges_apart-1,e.o,e.h+e.hinge.h],
361 end: [hinges_apart+1,e.o,e.h+e.hinge.h], 390 end: [hinges_apart+1,e.o,e.h+e.hinge.h],
362 radius: e.hinge.d/2 391 radius: e.hinge.d/2
363 }) 392 })
364 ).union( /* hold clamp together */ 393 ).union( /* hold clamp together */
365 [-1,1].map(function(s) { 394 [-1,1].map(function(s) {
366 return CSG.roundedCube({ 395 return CSG.roundedCube({
367 corner1: [s*(-hhr-e.clamp.margin*2-e.clamp.d),-e.clamp.shell,e.h+e.hinge.e], 396 corner1: [s*(-hhr-e.clamp.margin*2-e.clamp.d),-e.clamp.shell,e.h+e.hinge.e],
368 corner2: [s*(-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance),+e.clamp.shell,e.h+e.hinge.e+hhh], 397 corner2: [s*(-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance),+e.clamp.shell,e.h+e.hinge.e+hhh],
369 roundradius: 1.5 398 roundradius: 1.5
370 }); 399 });
371 }) 400 })
372 ).subtract( /* screws for holding clamp */ 401 ).subtract( /* screws for holding clamp */
373 [-1,1].map(function(s) { 402 [-1,1].map(function(s) {
374 var nuthole = nut(CONFIG.nut); 403 var nuthole = nut(CONFIG.nut);
375 var x = s*(-hhr-e.clamp.margin-e.clamp.d/2); 404 var x = s*(-hhr-e.clamp.margin-e.clamp.d/2);
376 return CSG.cylinder({ 405 return CSG.cylinder({
377 start: [x,-e.clamp.shell-1,e.h+e.hinge.e+hhh/2], 406 start: [x,-e.clamp.shell-1,e.h+e.hinge.e+hhh/2],
378 end: [x,e.clamp.shell+1,e.h+e.hinge.e+hhh/2], 407 end: [x,e.clamp.shell+1,e.h+e.hinge.e+hhh/2],
379 radius: e.clamp.d/2 408 radius: e.clamp.d/2
380 }).union(nuthole.connectTo( 409 }).union(nuthole.connectTo(
381 nuthole.properties.axis_connector, 410 nuthole.properties.axis_connector,
382 new CSG.Connector([x,e.clamp.shell,e.h+e.hinge.e+hhh/2],[0,-1,0],[0,0,1]), 411 new CSG.Connector([x,e.clamp.shell,e.h+e.hinge.e+hhh/2],[0,-1,0],[0,0,1]),
383 false, 0 412 false, 0
384 )).union(CSG.cylinder({ 413 )).union(CSG.cylinder({
385 start: [x,-e.clamp.shell-1,e.h+e.hinge.e+hhh/2], 414 start: [x,-e.clamp.shell-1,e.h+e.hinge.e+hhh/2],
386 end: [x,0,e.h+e.hinge.e+hhh/2], 415 end: [x,0,e.h+e.hinge.e+hhh/2],
387 radius: e.clamp.d/2+PRINT.slide_tolerance 416 radius: e.clamp.d/2+PRINT.slide_tolerance
388 })); 417 }));
389 }) 418 })
390 ); 419 );
391 var ms = o.microswitch; 420 var ms = o.microswitch;
392 var msedge = o.effector.properties.rcorner; 421 var msedge = o.effector.properties.rcorner;
393 var msh = 9.5; // microswitch holes apart 422 var msh = 9.5; // microswitch holes apart
394 var mshh = Math.abs(ms.properties.switch_connector.point.z-ms.properties.screw_connector[0].point.z); // microswitch holes height 423 var mshh = Math.abs(ms.properties.switch_connector.point.z-ms.properties.screw_connector[0].point.z); // microswitch holes height
395 rv = rv.union(CSG.cube({ // connect clamp with microswitch 424 rv = rv.union(CSG.cube({ // connect clamp with microswitch
396 corner1: [-ms.properties.microswitch.size.x/2,-msedge+.1,e.h+e.hinge.e], 425 corner1: [-ms.properties.microswitch.size.x/2,-msedge+.1,e.h+e.hinge.e],
397 corner2: [+ms.properties.microswitch.size.x/2,-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance,e.h+e.hinge.e+hhh] 426 corner2: [+ms.properties.microswitch.size.x/2,-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance,e.h+e.hinge.e+hhh]
398 })).union([-msh/2,msh/2].map(function(x) { // shell for microswitch screws 427 })).union([-msh/2,msh/2].map(function(x) { // shell for microswitch screws
399 return CSG.roundedCylinder({ 428 return CSG.roundedCylinder({
400 start: [x,-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance-(e.mswitch.screw.d/2+e.mswitch.screw.s),e.h+e.hinge.e+mshh], 429 start: [x,-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance-(e.mswitch.screw.d/2+e.mswitch.screw.s),e.h+e.hinge.e+mshh],
401 end: [x,-msedge+ms.properties.microswitch.size.y,e.h+e.hinge.e+mshh], 430 end: [x,-msedge+ms.properties.microswitch.size.y,e.h+e.hinge.e+mshh],
402 radius: e.mswitch.screw.d/2+e.mswitch.screw.s 431 radius: e.mswitch.screw.d/2+e.mswitch.screw.s
403 }); 432 });
404 })).subtract(CSG.cube({ // cut off excess if any 433 })).subtract(CSG.cube({ // cut off excess if any
405 corner1:[-hhr,-msedge+ms.properties.microswitch.size.y,e.h+e.hinge.e-1], 434 corner1:[-hhr,-msedge+ms.properties.microswitch.size.y,e.h+e.hinge.e-1],
406 corner2:[hhr,-msedge-1,e.h+e.hinge.e+hhh+e.mswitch.screw.d+e.mswitch.screw.s+1] 435 corner2:[hhr,-msedge-1,e.h+e.hinge.e+hhh+e.mswitch.screw.d+e.mswitch.screw.s+1]
407 })).subtract([-msh/2,msh/2].map(function(x) { return CSG.roundedCylinder({ // screwholes 436 })).subtract([-msh/2,msh/2].map(function(x) { return CSG.roundedCylinder({ // screwholes
408 start: [x,-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance-(e.mswitch.screw.d/2+e.mswitch.screw.s),e.h+e.hinge.e+mshh], 437 start: [x,-CONFIG.hotend.ungroove.d/2-PRINT.fit_tolerance-(e.mswitch.screw.d/2+e.mswitch.screw.s),e.h+e.hinge.e+mshh],
409 end: [x,-msedge+ms.properties.microswitch.size.y,e.h+e.hinge.e+mshh], 438 end: [x,-msedge+ms.properties.microswitch.size.y,e.h+e.hinge.e+mshh],
410 radius: e.mswitch.screw.d/2 439 radius: e.mswitch.screw.d/2
411 })})).subtract(CSG.cylinder({ // pulldown screw 440 })})).subtract(CSG.cylinder({ // pulldown screw
412 start:[0,-msedge+ms.properties.microswitch.size.y+3/2/*XXX:config*/+PRINT.extrusion_width,e.h+e.hinge.e-1], 441 start:[0,-msedge+ms.properties.microswitch.size.y+3/2/*XXX:config*/+PRINT.extrusion_width,e.h+e.hinge.e-1],
413 end:[0,-msedge+ms.properties.microswitch.size.y+3/2/*XXX:config*/+PRINT.extrusion_width,e.h+e.hinge.e+hhh+1], 442 end:[0,-msedge+ms.properties.microswitch.size.y+3/2/*XXX:config*/+PRINT.extrusion_width,e.h+e.hinge.e+hhh+1],
414 radius: 3/2/*XXX:config*/ 443 radius: 3/2/*XXX:config*/
415 })); 444 }));
416 rv.properties.microswitch_screw_connector = new CSG.Properties(); 445 rv.properties.microswitch_screw_connector = new CSG.Properties();
417 [-msh/2,msh/2].forEach(function(x,i) { 446 [-msh/2,msh/2].forEach(function(x,i) {
418 rv.properties.microswitch_screw_connector[i] = new CSG.Connector( 447 rv.properties.microswitch_screw_connector[i] = new CSG.Connector(
419 [x,-msedge,e.h+e.hinge.e+mshh], 448 [x,-msedge,e.h+e.hinge.e+mshh],
420 [0,1,0], [0,0,-1] 449 [0,1,0], [0,0,-1]
421 ); 450 );
422 }); 451 });
423 return rv.setColor([0.3,0.8,0.3,0.9]); 452 return rv.setColor([0.3,0.8,0.3,0.9]);
424 }, 453 },
425 split_hinged: function effector_split_hinged(hinged) { 454 split_hinged: function effector_split_hinged(hinged) {
426 var e = CONFIG.effector; 455 var e = CONFIG.effector;
427 var b = hinged.getBounds(); 456 var b = hinged.getBounds();
428 var ymax = Math.max(Math.abs(b[0].y),Math.abs(b[1].y)); 457 var ymax = Math.max(Math.abs(b[0].y),Math.abs(b[1].y));
429 var zmax = Math.max(b[0].z,b[1].z); 458 var zmax = Math.max(b[0].z,b[1].z);
430 return [-1,1].map(function(s) { 459 return [-1,1].map(function(s) {
431 return hinged.intersect(CSG.cube({ 460 return hinged.intersect(CSG.cube({
432 corner1: [Math.min(b[0].x,b[1].x)-1,s*e.clamp.split/2,-zmax-1], 461 corner1: [Math.min(b[0].x,b[1].x)-1,s*e.clamp.split/2,-zmax-1],
433 corner2: [Math.max(b[0].x,b[1].x)+1,s*(ymax+1),zmax+1] 462 corner2: [Math.max(b[0].x,b[1].x)+1,s*(ymax+1),zmax+1]
434 })); 463 }));
435 }); 464 });
436 }, 465 },
437 fanholder: function effector_fanholder() { 466 fanholder: function effector_fanholder() {
438 var fh = CONFIG.effector.fanholder; 467 var fh = CONFIG.effector.fanholder;
439 var od = fh.screw.d+2*fh.screw.m; 468 var od = fh.screw.d+2*fh.screw.m;
440 return linear_extrude({height:fh.w},hull( 469 return linear_extrude({height:fh.w},hull(
441 CAG.circle({center:[0,-this.rmount],radius:od/2}), 470 CAG.circle({center:[0,-this.rmount],radius:od/2}),
442 CAG.circle({center:[0,-fh.r+od/2+fh.w/2],radius:fh.w/2}) 471 CAG.circle({center:[0,-fh.r+od/2+fh.w/2],radius:fh.w/2})
443 )).translate([0,0,-fh.w]).union( 472 )).translate([0,0,-fh.w]).union(
444 linear_extrude({height:fh.w},hull( 473 linear_extrude({height:fh.w},hull(
445 CAG.circle({center:[fh.w/2,-this.rmount-od/2-fh.w/2],radius:fh.w/2}), 474 CAG.circle({center:[fh.w/2,-this.rmount-od/2-fh.w/2],radius:fh.w/2}),
446 CAG.circle({center:[od/2,-fh.r],radius:od/2}) 475 CAG.circle({center:[od/2,-fh.r],radius:od/2})
447 )).rotateY(90).translate([-fh.w/2,0,0]) 476 )).rotateY(90).translate([-fh.w/2,0,0])
448 ).subtract( CSG.cylinder({ 477 ).subtract( CSG.cylinder({
449 start: [-fh.w,-fh.r,-od/2], 478 start: [-fh.w,-fh.r,-od/2],
450 end: [fh.w,-fh.r,-od/2], 479 end: [fh.w,-fh.r,-od/2],
451 radius: fh.screw.d/2 480 radius: fh.screw.d/2
452 })).subtract( CSG.cylinder({ 481 })).subtract( CSG.cylinder({
453 start: [0,-this.rmount,1], 482 start: [0,-this.rmount,1],
454 end: [0,-this.rmount,-fh.w-1], 483 end: [0,-this.rmount,-fh.w-1],
455 radius: fh.screw.d/2 484 radius: fh.screw.d/2
456 })).setColor([0.3,0.8,0.3,0.9]).rotateZ(-120); 485 })).setColor([0.3,0.8,0.3,0.9]).rotateZ(-120);
457 } 486 }
458}; 487};
459 488
460function columns() { 489function columns() {
461 var rv = [0,1,2].map(function(x) { 490 var rv = [0,1,2].map(function(x) {
462 return union(vector_char(0,0,String.fromCharCode('A'.charCodeAt(0)+x)).segments.map(function(x) { 491 return union(vector_char(0,0,String.fromCharCode('A'.charCodeAt(0)+x)).segments.map(function(x) {
463 return rectangular_extrude(x,{w:2,h:1}); 492 return rectangular_extrude(x,{w:2,h:1});
464 })).center().rotateX(90).translate([0,50,0]).rotateZ(x*120+120); 493 })).center().rotateX(90).translate([0,50,0]).rotateZ(x*120+120);
465 }); 494 });
466 return union(rv); 495 return union(rv);
467} 496}
468 497
469function microswitch() { 498function microswitch() {
470 var screw_connector = new CSG.Properties(); 499 var screw_connector = new CSG.Properties();
471 var rv = CSG.cube({ center:[0,0,2.5],radius: [19.8/2,6/2,10/2] }).union( 500 var rv = CSG.cube({ center:[0,0,2.5],radius: [19.8/2,6/2,10/2] }).union(
472 CSG.cube({ center: [2.5,0.5,6], radius: [2/2,3.5/2,5/2] }) 501 CSG.cube({ center: [2.5,0.5,6], radius: [2/2,3.5/2,5/2] })
473 ).union( 502 ).union(
474 [-8,-1,8].map(function(x) { 503 [-8,-1,8].map(function(x) {
475 return CSG.cube({ center:[x,0,0], radius: [0.6/2,3.2/2,13/2] }) 504 return CSG.cube({ center:[x,0,0], radius: [0.6/2,3.2/2,13/2] })
476 }) 505 })
477 ).subtract( 506 ).subtract(
478 [-9.5/2,9.5/2].map(function(x,i) { 507 [-9.5/2,9.5/2].map(function(x,i) {
479 screw_connector[i] = new CSG.Connector([x,6/2,0],[0,-1,0],[0,0,1]); 508 screw_connector[i] = new CSG.Connector([x,6/2,0],[0,-1,0],[0,0,1]);
480 return CSG.cylinder({ 509 return CSG.cylinder({
481 start: [x,-4,0], end: [x,4,0], 510 start: [x,-4,0], end: [x,4,0],
482 radius: 2/2 511 radius: 2/2
483 }) 512 })
484 }) 513 })
485 ); 514 );
486 rv.properties.switch_connector = new CSG.Connector([2.5,0.5,6+5/2],[0,0,1],[0,-1,0]); 515 rv.properties.switch_connector = new CSG.Connector([2.5,0.5,6+5/2],[0,0,1],[0,-1,0]);
487 rv.properties.screw_connector = screw_connector; 516 rv.properties.screw_connector = screw_connector;
488 rv.properties.microswitch = new CSG.Properties(); 517 rv.properties.microswitch = new CSG.Properties();
489 rv.properties.microswitch.size = new CSG.Vector3D( 518 rv.properties.microswitch.size = new CSG.Vector3D(
490 19.8,6,10 519 19.8,6,10
491 ); 520 );
492 return rv; 521 return rv;
493} 522}
494 523
495var FOURWINDS = [0,90,180,270]; 524var FOURWINDS = [0,90,180,270];
496 525
497var E2020 = { 526var E2020 = {
498 outer: 20, thickness: 1.8, 527 outer: 20, thickness: 1.8,
499 roundius: 1, centerhole: 5, 528 roundius: 1, centerhole: 5,
500 slot_width: 6, 529 slot_width: 6,
501 T: { width: 10, thickness: 1.5, depth: 6.5 }, 530 T: { width: 10, thickness: 1.5, depth: 6.5 },
502 531
503 extrusion: function(o) { 532 extrusion: function(o) {
504 if(!o) o = {}; 533 if(!o) o = {};
505 var e = o.extrusion || this; 534 var e = o.extrusion || this;
506 var l = o.l||5; 535 var l = o.l||5;
507 var iy = e.outer/2-e.T.depth; 536 var iy = e.outer/2-e.T.depth;
508 var ix = e.T.width/2-(e.outer/2-iy-e.thickness-e.T.thickness); 537 var ix = e.T.width/2-(e.outer/2-iy-e.thickness-e.T.thickness);
509 var rv = CAG.roundedRectangle({ 538 var rv = CAG.roundedRectangle({
510 corner1: [-e.outer/2,-e.outer/2], corner2: [e.outer/2,e.outer/2], 539 corner1: [-e.outer/2,-e.outer/2], corner2: [e.outer/2,e.outer/2],
511 roundradius: e.roundius 540 roundradius: e.roundius
512 }).subtract( 541 }).subtract(
513 FOURWINDS.map(function(w) { 542 FOURWINDS.map(function(w) {
514 return CAG.fromPoints([ 543 return CAG.fromPoints([
515 [ e.slot_width/2,e.outer/2+1], 544 [ e.slot_width/2,e.outer/2+1],
516 [ e.slot_width/2,e.outer/2-e.thickness], 545 [ e.slot_width/2,e.outer/2-e.thickness],
517 [ e.T.width/2,e.outer/2-e.thickness], 546 [ e.T.width/2,e.outer/2-e.thickness],
518 [ e.T.width/2,e.outer/2-e.thickness-e.T.thickness], 547 [ e.T.width/2,e.outer/2-e.thickness-e.T.thickness],
519 [ ix, iy ], 548 [ ix, iy ],
520 [ -ix, iy ], 549 [ -ix, iy ],
521 [ -e.T.width/2,e.outer/2-e.thickness-e.T.thickness], 550 [ -e.T.width/2,e.outer/2-e.thickness-e.T.thickness],
522 [ -e.T.width/2,e.outer/2-e.thickness], 551 [ -e.T.width/2,e.outer/2-e.thickness],
523 [ -e.slot_width/2,e.outer/2-e.thickness], 552 [ -e.slot_width/2,e.outer/2-e.thickness],
524 [ -e.slot_width/2,e.outer/2+1], 553 [ -e.slot_width/2,e.outer/2+1],
525 ]).rotateZ(w); 554 ]).rotateZ(w);
526 }) 555 })
527 ).subtract(CAG.circle({ 556 ).subtract(CAG.circle({
528 center: [0,0], radius: e.centerhole/2 557 center: [0,0], radius: e.centerhole/2
529 })).extrude({offset:[0,0,l]}); 558 })).extrude({offset:[0,0,l]});
530 rv.properties.c_top=rv.properties.c_left 559 rv.properties.c_top=rv.properties.c_left
531 = new CSG.Connector([0,0,l],[0,0,-1],[1,0,0]); 560 = new CSG.Connector([0,0,l],[0,0,-1],[1,0,0]);
532 rv.properties.c_bottom=rv.properties.c_right 561 rv.properties.c_bottom=rv.properties.c_right
533 = new CSG.Connector([0,0,0],[0,0,1],[1,0,0]); 562 = new CSG.Connector([0,0,0],[0,0,1],[1,0,0]);