@jscad/web 2.5.10 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +1 -1
  3. package/dist/jscad-web.min.js +959 -2030
  4. package/examples/CHANGELOG.md +30 -0
  5. package/examples/README.md +1 -5
  6. package/examples/package.json +1 -1
  7. package/examples/parameters/gear.js +1 -1
  8. package/locales/README.md +23 -0
  9. package/locales/de.json +1 -0
  10. package/locales/en.json +2 -1
  11. package/locales/fr.json +1 -0
  12. package/locales/hr.json +1 -0
  13. package/locales/ja.json +1 -0
  14. package/locales/zh.json +62 -0
  15. package/package.json +7 -7
  16. package/postInstall.js +0 -1
  17. package/src/index.js +2 -1
  18. package/src/sideEffects/i18n/index.js +2 -1
  19. package/src/sideEffects/worker/index.js +7 -8
  20. package/src/ui/flow/design.js +10 -305
  21. package/src/ui/flow/reducers.js +304 -0
  22. package/examples/old/benchmark-cag.jscad +0 -27
  23. package/examples/old/benchmark-csg.jscad +0 -29
  24. package/examples/old/benchmark.jscad +0 -25
  25. package/examples/old/bunch-cubes.jscad +0 -17
  26. package/examples/old/complex/example001.jscad +0 -31
  27. package/examples/old/complex/example002.jscad +0 -25
  28. package/examples/old/complex/example003.jscad +0 -25
  29. package/examples/old/complex/example004.jscad +0 -16
  30. package/examples/old/complex/example005.jscad +0 -27
  31. package/examples/old/complex/globe.js +0 -235
  32. package/examples/old/complex/iphone4-case.js +0 -213
  33. package/examples/old/complex/umbilical_torus.js +0 -43
  34. package/examples/old/complex/umbilical_torus.scad +0 -37
  35. package/examples/old/core/cncCutout.js +0 -16
  36. package/examples/old/core/connectors/servo.js +0 -185
  37. package/examples/old/core/extrusions/extrudeLinear.js +0 -24
  38. package/examples/old/core/extrusions/extrudeRectangular.js +0 -21
  39. package/examples/old/core/extrusions/extrudeRotate.js +0 -43
  40. package/examples/old/core/extrusions/slices/four2three-round.js +0 -62
  41. package/examples/old/core/extrusions/slices/four2three.js +0 -53
  42. package/examples/old/core/extrusions/slices/jar-barrel.js +0 -60
  43. package/examples/old/core/extrusions/slices/jar.js +0 -69
  44. package/examples/old/core/extrusions/slices/non-aff.js +0 -72
  45. package/examples/old/core/extrusions/slices/rose.js +0 -52
  46. package/examples/old/core/extrusions/slices/screw.js +0 -34
  47. package/examples/old/core/extrusions/slices/screwDouble.js +0 -34
  48. package/examples/old/core/extrusions/slices/slices.js +0 -43
  49. package/examples/old/core/extrusions/slices/spring.js +0 -41
  50. package/examples/old/core/extrusions/slices/three2four.js +0 -42
  51. package/examples/old/core/extrusions/slices/tor.js +0 -30
  52. package/examples/old/core/hulls/hullChain.js +0 -58
  53. package/examples/old/core/lookup.js +0 -19
  54. package/examples/old/core/platonics/main.jscad +0 -42
  55. package/examples/old/core/platonics/maths_geodesic.jscad +0 -192
  56. package/examples/old/core/platonics/origv07/dualdodeca_difference.stl +0 -1962
  57. package/examples/old/core/platonics/origv07/dualdodeca_intersection.stl +0 -1374
  58. package/examples/old/core/platonics/origv07/dualdodeca_union.stl +0 -1822
  59. package/examples/old/core/platonics/origv07/maths_geodesic.scad +0 -162
  60. package/examples/old/core/platonics/origv07/platonic.scad +0 -483
  61. package/examples/old/core/platonics/origv07/test_platonic.scad +0 -616
  62. package/examples/old/core/platonics/platonic.jscad +0 -528
  63. package/examples/old/core/text/textSimplex.js +0 -625
  64. package/examples/old/core/transforms/transformations.js +0 -29
  65. package/examples/old/echo.jscad +0 -7
  66. package/examples/old/formats/scad/example001.scad +0 -26
  67. package/examples/old/formats/scad/example002.scad +0 -23
  68. package/examples/old/formats/scad/example003.scad +0 -20
  69. package/examples/old/formats/scad/example004.scad +0 -11
  70. package/examples/old/formats/scad/example005.scad +0 -20
  71. package/examples/old/json_logo.json +0 -1
  72. package/examples/old/parameters/axis-coupler.js +0 -149
  73. package/examples/old/parameters/celtic-knot-ring.js +0 -300
  74. package/examples/old/parameters/grille.js +0 -257
  75. package/examples/old/parameters/lamp-shade.js +0 -369
  76. package/examples/old/parameters/name-plate.js +0 -46
  77. package/examples/old/parameters/s-hook.js +0 -131
  78. package/examples/old/parameters/stepper-motor.js +0 -127
  79. package/examples/old/various/logo.js +0 -32
  80. package/examples/old/voxel.json +0 -1
@@ -1,257 +0,0 @@
1
- // title : Grille
2
- // author : Joost Nieuwenhuijse
3
- // license : MIT License
4
- // description: a grille for...
5
- // file : grille.jscad
6
-
7
- // Here we define the user editable parameters:
8
- function getParameterDefinitions () {
9
- return [
10
- {name: 'outerwidth', caption: 'Outer width of grille:', type: 'float', initial: 190},
11
- {name: 'outerheight', caption: 'Outer height of grille:', type: 'float', initial: 120},
12
- {name: 'outerdepth', caption: 'Outer depth of grille:', type: 'float', initial: 12},
13
- {name: 'thickness', caption: 'Wall thickness:', type: 'float', initial: 2.5},
14
- {name: 'innerdistance', caption: 'Inner standoff distance:', type: 'float', initial: 2},
15
- {name: 'bladescale', caption: 'Relative size of blades (1.0 is default):', type: 'float', initial: 1},
16
- {name: 'numdividers', caption: 'Number of vertical dividers:', type: 'int', initial: 2},
17
- {
18
- name: 'addlooseners',
19
- type: 'choice',
20
- caption: 'Add loops (for easy removal):',
21
- values: [0, 1],
22
- captions: ['No', 'Yes'],
23
- initial: 1
24
- },
25
- {
26
- name: 'show',
27
- type: 'choice',
28
- caption: 'Show:',
29
- values: ['all', 'grille', 'holders'],
30
- captions: ['All', 'Grille (for printing)', 'Holders (for printing)'],
31
- initial: 'all'
32
- },
33
- {
34
- name: 'mouseears',
35
- type: 'choice',
36
- caption: 'Add mouse ears:',
37
- values: [0, 1],
38
- captions: ['No', 'Yes'],
39
- initial: 1
40
- },
41
- {
42
- name: 'quality',
43
- type: 'choice',
44
- caption: 'Quality:',
45
- values: [0, 1],
46
- captions: ['Draft', 'Final'],
47
- initial: 0
48
- }
49
- ];
50
- }
51
-
52
- function main (params) {
53
- var outerwidth = params.outerwidth;
54
- var outerheight = params.outerheight;
55
- var thickness = params.thickness;
56
- var outerdepth = params.outerdepth;
57
- var innerdistance = params.innerdistance;
58
- var bladescale = params.bladescale;
59
-
60
- var draft = params.quality !== 1;
61
-
62
- var marginleftright = 21;
63
- var margintopbottom = 15;
64
- var bladedistance = 12 * bladescale;
65
- var frontroundradius = 5;
66
- frontroundradius = Math.max(frontroundradius, thickness + 0.2);
67
- var outerroundradius = 3;
68
- outerroundradius = Math.max(outerroundradius, thickness + 0.2);
69
- outerdepth = Math.max(outerdepth, outerroundradius);
70
- outerdepth = Math.max(outerdepth, innerdistance + thickness);
71
- var frontextend = innerdistance + bladescale * 12 + thickness - outerdepth;
72
- frontextend = Math.max(frontextend, 1.5);
73
- var bladewidth = outerwidth - 2 * marginleftright;
74
- var bladesheight = outerheight - 2 * margintopbottom;
75
- var numblades = Math.ceil(bladesheight / bladedistance) + 1;
76
- var topnotchsize = new CSG.Vector3D([20, 8, 3]);
77
- var topnotchpos = new CSG.Vector3D([outerwidth / 2 - thickness - topnotchsize.x / 2, outerheight / 2 - thickness - topnotchsize.y / 2, topnotchsize.z / 2]);
78
- var bottomnotchsize = new CSG.Vector3D([12, 4, topnotchsize.z]);
79
- var bottomnotchpos = new CSG.Vector3D([outerwidth / 2 - thickness - 4 - bottomnotchsize.x / 2, -outerheight / 2 + thickness + bottomnotchsize.y / 2, bottomnotchsize.z / 2]);
80
-
81
- var roundresolution = draft ? 4 : 16;
82
-
83
- var result = new CSG();
84
- if (params.show !== 'holders') {
85
- // build the shell:
86
- var z0plane = CSG.Plane.fromNormalAndPoint([0, 0, -1], [0, 0, 0]);
87
- var outershell = CSG.roundedCube({center: [0, 0, 0], radius: [outerwidth / 2, outerheight / 2, outerdepth], roundradius: outerroundradius, resolution: roundresolution});
88
- outershell = outershell.cutByPlane(z0plane);
89
- var innershell = CSG.roundedCube({center: [0, 0, 0], radius: [outerwidth / 2 - thickness, outerheight / 2 - thickness, outerdepth - thickness], roundradius: outerroundradius - thickness, resolution: roundresolution});
90
- innershell = innershell.cutByPlane(z0plane);
91
- var shell = outershell.subtract(innershell);
92
- var frontextendoutershell = CSG.roundedCube({center: [0, 0, 0], radius: [bladewidth / 2 + thickness, bladesheight / 2 + thickness, outerdepth + frontextend + frontroundradius + thickness], roundradius: frontroundradius, resolution: roundresolution});
93
- var frontextendinnershell = CSG.roundedCube({center: [0, 0, 0], radius: [bladewidth / 2, bladesheight / 2, outerdepth + frontextend + frontroundradius + thickness + 100], roundradius: frontroundradius - thickness, resolution: roundresolution});
94
- frontextendinnershell = frontextendinnershell.cutByPlane(z0plane);
95
- var plane3 = CSG.Plane.fromNormalAndPoint([0, 0, 1], [0, 0, outerdepth + frontextend + 100]);
96
- frontextendinnershell = frontextendinnershell.cutByPlane(plane3);
97
- var plane1 = CSG.Plane.fromNormalAndPoint([0, 0, 1], [0, 0, outerdepth + frontextend]);
98
- frontextendoutershell = frontextendoutershell.cutByPlane(plane1);
99
- var plane2 = CSG.Plane.fromNormalAndPoint([0, 0, -1], [0, 0, innerdistance]);
100
- frontextendoutershell = frontextendoutershell.cutByPlane(plane2);
101
- shell = shell.subtract(frontextendinnershell);
102
- var frontextendshell = frontextendoutershell.subtract(frontextendinnershell);
103
- shell = shell.union(frontextendshell);
104
-
105
- // build a blade:
106
- var curvedpath = CSG.Path2D.arc({
107
- center: [0, 0, 0],
108
- radius: 15 * bladescale,
109
- startangle: 20,
110
- endangle: 80,
111
- resolution: draft ? 8 : 32
112
- });
113
- var blade = curvedpath.rectangularExtrude(thickness, bladewidth, draft ? 4 : 16, true);
114
- var bladecenter = blade.getBounds()[0].plus(blade.getBounds()[1]).times(0.5);
115
- blade = blade.translate(bladecenter.negated());
116
- blade = blade.rotateY(-90);
117
- blade = blade.translate([0, 0, -blade.getBounds()[0].z + innerdistance]);
118
- var bladesize = blade.getBounds()[1].minus(blade.getBounds()[0]);
119
-
120
- // add the blades to the shell:
121
- var blades = new CSG();
122
- for (var i = 0; i < numblades; i++) {
123
- var topy = bladesheight / 2 + thickness - i * bladedistance;
124
- var translatedblade = blade.translate([0, topy - bladesize.y / 2, 0]);
125
- blades = blades.union(translatedblade);
126
- }
127
- blades = blades.intersect(frontextendinnershell);
128
- var grille = shell;
129
- grille = shell.union(blades);
130
-
131
- // add the dividers:
132
- var dividers = new CSG();
133
- if (params.numdividers > 0) {
134
- var w1 = (bladewidth - params.numdividers * thickness) / (params.numdividers + 1);
135
- for (var j = 0; j < params.numdividers; j++) {
136
- var x = -(params.numdividers - 1) * (w1 + thickness) / 2 + j * (w1 + thickness);
137
- var z1 = outerdepth + frontextend;
138
- var divider = CSG.cube({center: [x, 0, (z1 + innerdistance) / 2], radius: [thickness / 2, bladesheight / 2, (z1 - innerdistance) / 2]});
139
- dividers = dividers.union(divider);
140
- }
141
- }
142
- grille = grille.union(dividers);
143
-
144
- // create the notches:
145
- var notches = new CSG();
146
- var topnotch1 = CSG.cube({center: topnotchpos, radius: topnotchsize.times(0.5)});
147
- notches = notches.union(topnotch1);
148
- var topnotch2 = CSG.cube({center: [-topnotchpos.x, topnotchpos.y, topnotchpos.z], radius: topnotchsize.times(0.5)});
149
- notches = notches.union(topnotch2);
150
- var bottomnotch1 = CSG.cube({center: bottomnotchpos, radius: bottomnotchsize.times(0.5)});
151
- notches = notches.union(bottomnotch1);
152
- var bottomnotch2 = CSG.cube({center: [-bottomnotchpos.x, bottomnotchpos.y, bottomnotchpos.z], radius: bottomnotchsize.times(0.5)});
153
- notches = notches.union(bottomnotch2);
154
- notches = notches.intersect(outershell);
155
- grille = grille.union(notches);
156
- result = result.union(grille);
157
-
158
- // create the looseners:
159
- if (params.addlooseners === 1) {
160
- var loosenerinnerwidth = 5;
161
- var loosenerinnerheight = 2;
162
- var loosenerdepth = 4;
163
- var loosener = CSG.cube({center: [0, -outerheight / 2 - loosenerinnerheight / 2, loosenerdepth / 2],
164
- radius: [loosenerinnerwidth / 2 + thickness, loosenerinnerheight / 2 + thickness, loosenerdepth / 2]});
165
- loosener = loosener.subtract(CSG.cube({center: [0, -outerheight / 2 - loosenerinnerheight / 2, loosenerdepth / 2],
166
- radius: [loosenerinnerwidth / 2, loosenerinnerheight / 2, loosenerdepth / 2]}));
167
- var loosenerx = -outerwidth / 2 + loosenerinnerwidth / 2 + 5 + thickness;
168
-
169
- var looseners = loosener.translate([loosenerx, 0, 0]);
170
- looseners = looseners.union(loosener.translate([-loosenerx, 0, 0]));
171
- result = result.union(looseners);
172
- }
173
-
174
- if (params.mouseears === 1) {
175
- for (var k = 0; k < 4; k++) {
176
- var xpos = outerwidth / 2 - 10;
177
- var ypos = outerheight / 2;
178
- if (k & 1) xpos = -xpos;
179
- if (k & 2) ypos = -ypos;
180
- var cylinder = CSG.cylinder({start: [xpos, ypos, 0], end: [xpos, ypos, 0.5], radius: 15});
181
- result = result.union(cylinder);
182
- }
183
- for (var m = 0; m < 4; m++) {
184
- var xpos2 = bladewidth / 2 + thickness / 2;
185
- var ypos2 = bladesheight / 2 + thickness / 2;
186
- if (m & 1) xpos2 = -xpos2;
187
- if (m & 2) ypos2 = -ypos2;
188
- var cyl1 = CSG.cylinder({start: [xpos2, ypos2, 0], end: [xpos2, ypos2, 0.5], radius: 15});
189
- var cyl2 = CSG.cylinder({start: [xpos2, ypos2, 0], end: [xpos2, ypos2, innerdistance], radius: 5});
190
- result = result.union(cyl1.union(cyl2));
191
- }
192
- }
193
- }
194
-
195
- if (params.show !== 'grille') {
196
- // create the holders:
197
- var holderyoffset = 0.5;
198
- var holderzoffset = 1;
199
- var holderwidth = 10;
200
- var holderthickness = 3;
201
- var holdertopclipheight = 4;
202
- var holderbottomclipheight = 2;
203
- var holderscrewholeradius = 2;
204
- var holderscrewholedistance = 6;
205
-
206
- var holderx;
207
- if (params.show === 'holders') {
208
- // just the holders:
209
- holderx = holderwidth / 2 + 2;
210
- } else {
211
- holderx = bottomnotchpos.x + bottomnotchsize.x / 2 - holderwidth / 2;
212
- }
213
- var holdery1 = topnotchpos.y - topnotchsize.y / 2 - holderyoffset;
214
- var holdery2 = bottomnotchpos.y + bottomnotchsize.y / 2 + holderyoffset;
215
-
216
- var holdery0 = holdery1 + holdertopclipheight;
217
- var holdery3 = holdery2 - holderbottomclipheight;
218
- var holder = CSG.cube({center: [0, (holdery1 + holdery2) / 2, holderthickness / 2],
219
- radius: [holderwidth / 2, (holdery1 - holdery2) / 2, holderthickness / 2]});
220
- var d1 = 7;
221
- var holdery1a = holdery1 - d1;
222
- var holdery2a = holdery2 + d1;
223
- var holderz1 = topnotchsize.z + holderzoffset;
224
- var holderz2 = holderz1 + holderthickness;
225
- holder = holder.union(CSG.cube({
226
- center: [0, (holdery1a + holdery1) / 2, holderz2 / 2],
227
- radius: [holderwidth / 2, (holdery1 - holdery1a) / 2, holderz2 / 2]
228
- }));
229
- holder = holder.union(CSG.cube({
230
- center: [0, (holdery2a + holdery2) / 2, holderz2 / 2],
231
- radius: [holderwidth / 2, (holdery2a - holdery2) / 2, holderz2 / 2]
232
- }));
233
- holder = holder.union(CSG.cube({
234
- center: [0, (holdery0 + holdery1a) / 2, (holderz2 + holderz1) / 2],
235
- radius: [holderwidth / 2, (holdery0 - holdery1a) / 2, (holderz2 - holderz1) / 2]
236
- }));
237
- holder = holder.union(CSG.cube({
238
- center: [0, (holdery2a + holdery3) / 2, (holderz2 + holderz1) / 2],
239
- radius: [holderwidth / 2, (holdery2a - holdery3) / 2, (holderz2 - holderz1) / 2]
240
- }));
241
- var screwhole = CSG.cylinder({start: [0, 0, 0], end: [0, 0, holderthickness], radius: holderscrewholeradius, resolution: 16});
242
- holder = holder.subtract(screwhole.translate([0, holdery1a - holderscrewholedistance, 0]));
243
- holder = holder.subtract(screwhole.translate([0, holdery2a + holderscrewholedistance, 0]));
244
-
245
- holder = holder.setColor(0, 1, 0);
246
-
247
- var holders = holder.translate([holderx, 0, 0]);
248
- holders = holders.union(holder.translate([-holderx, 0, 0]));
249
- if (params.show === 'holders') {
250
- holders = holders.rotateZ(90);
251
- }
252
-
253
- result = result.union(holders);
254
- }
255
- result = result.rotateZ(90);
256
- return result;
257
- }
@@ -1,369 +0,0 @@
1
- // title : Lamp Shade
2
- // author : Joost Nieuwenhuijse
3
- // license : MIT License
4
- // description: a lamp shade
5
- // file : lamp-shade.jscad
6
-
7
- function main (params) {
8
- CSG.defaultResolution2D = (params.quality === 'DRAFT') ? 8 : 32;
9
-
10
- var bottomradius = params.bottomdiameter / 2;
11
- var topradius = params.topdiameter / 2;
12
- var height = params.height;
13
- var numfaces = params.numfaces;
14
- var thickness = params.thickness;
15
- var topholeradius = params.topholediameter / 2;
16
- var cutterRadius = params.cutterdiameter / 2;
17
-
18
- var solid = CSG.cube({radius: [1000, 1000, height / 2]});
19
-
20
- var plane = CSG.Plane.fromPoints([bottomradius, 0, -height / 2], [bottomradius, 10, -height / 2], [topradius, 0, height / 2]);
21
- for (var i = 0; i < numfaces; i++) {
22
- solid = solid.cutByPlane(plane.rotateZ(i * 360 / numfaces));
23
- }
24
-
25
- var plates = solidToOuterShellPlates(solid, thickness);
26
- plates = removePlateWithNormal(plates, [0, 0, -1]);
27
- plates = removePlateWithNormal(plates, [0, 0, 1]);
28
-
29
- for (var j = 1; j < numfaces; j++) {
30
- plates[j] = plates[0].rotateZ(j * 360 / numfaces);
31
- }
32
-
33
- var topplate = getStockPlate(1000, 1000, thickness)
34
- .subtract(CSG.cylinder({start: [0, 0, -thickness], end: [0, 0, thickness], radius: topholeradius}))
35
- .translate([0, 0, height / 2 - thickness / 2 - 10]);
36
- topplate = topplate.intersect(solid);
37
- topplate = fixPlate(topplate, thickness);
38
-
39
- var fingerjointoptions = {
40
- margin: 0, cutterRadius: cutterRadius, fingerWidth: 25
41
- };
42
- plates = fingerJoint(plates, fingerjointoptions);
43
- plates = fingerJointAdd(plates, topplate, fingerjointoptions);
44
-
45
- if (params.type === 'TOPPLATE') {
46
- return plateCSGToCAG(plates[numfaces]);
47
- } else {
48
- var plate2d = plateCSGToCAG(plates[0]);
49
- plate2d = addRandomHoles(plate2d);
50
- if (params.type === 'SIDEPLATE') {
51
- return plate2d;
52
- } else {
53
- for (var k = 0; k < numfaces; k++) {
54
- var plate3d = plateCAGToCSG(plate2d, plates[k].properties.platebasis, thickness);
55
- plates[k] = plate3d;
56
- }
57
- var result = new CSG().union(plates);
58
- result = result.rotateX(90);
59
- return result;
60
- }
61
- }
62
- }
63
-
64
- function addRandomHoles (plate) {
65
- var distancefromedge = 8;
66
- var distancebetweenholes = 10;
67
- var mindiameter = 10;
68
- var maxdiameter = 25;
69
- // maskarea: the 'forbidden' area for holes:
70
- var maskarea = plate.contract(distancefromedge, 4);
71
- var bounds = maskarea.getBounds();
72
- maskarea = maskarea.flipped();
73
- var holes = [];
74
- var existingholecenters = [];
75
- var existingholeradii = [];
76
- for (var i = 0; i < 10; i++) {
77
- for (var tryindex = 0; tryindex < 10; tryindex++) {
78
- var holeradius = (mindiameter + Math.random() * (maxdiameter - mindiameter)) / 2;
79
- var x = bounds[0].x + holeradius + (bounds[1].x - bounds[0].x - holeradius * 2) * Math.random();
80
- var y = bounds[0].y + holeradius + (bounds[1].y - bounds[0].y - holeradius * 2) * Math.random();
81
- var holecenter = new CSG.Vector2D(x, y);
82
- var valid = true;
83
- // check if the hole is too close to one of the existing holes:
84
- var numexistingholes = existingholecenters.length;
85
- for (var i2 = 0; i2 < numexistingholes; i2++) {
86
- var d = holecenter.minus(existingholecenters[i2]).length();
87
- if (d < holeradius + existingholeradii[i2] + distancebetweenholes) {
88
- valid = false;
89
- break;
90
- }
91
- }
92
- if (valid) {
93
- // check if the hole is not too close to the edges:
94
- var hole = CAG.circle({radius: holeradius, center: holecenter});
95
- var testarea = maskarea.intersect(hole);
96
- if (testarea.sides.length !== 0) valid = false;
97
- if (valid) {
98
- existingholeradii.push(holeradius);
99
- existingholecenters.push(holecenter);
100
- holes.push(hole);
101
- break;
102
- }
103
- }
104
- }
105
- }
106
- return plate.subtract(holes);
107
- }
108
-
109
- function plateCSGToCAG (plate) {
110
- if (!('platebasis' in plate.properties)) {
111
- throw new Error('Plates should be created using getStockPlate()');
112
- }
113
- var plate2d = plate.projectToOrthoNormalBasis(plate.properties.platebasis);
114
- return plate2d;
115
- }
116
-
117
- function plateCAGToCSG (plate2d, platebasis, thickness) {
118
- var basisinversematrix = platebasis.getInverseProjectionMatrix();
119
- var plateReprojected = plate2d.extrude({offset: [0, 0, thickness]}).translate([0, 0, -thickness / 2]);
120
- plateReprojected = plateReprojected.transform(basisinversematrix);
121
- plateReprojected.properties.platebasis = platebasis;
122
- return plateReprojected;
123
- }
124
-
125
- function fixPlate (plate, thickness) {
126
- return plateCAGToCSG(plateCSGToCAG(plate), plate.properties.platebasis, thickness);
127
- }
128
-
129
- function removePlateWithNormal (plates, normalvector) {
130
- normalvector = new CSG.Vector3D(normalvector);
131
- var result = [];
132
- plates.map(function (plate) {
133
- if (!('platebasis' in plate.properties)) {
134
- throw new Error('Plates should be created using getStockPlate()');
135
- }
136
- if (plate.properties.platebasis.plane.normal.dot(normalvector) < 0.9999) {
137
- result.push(plate);
138
- }
139
- });
140
- return result;
141
- }
142
-
143
- function getStockPlate (width, height, thickness) {
144
- var result = CSG.cube({radius: [width / 2, height / 2, thickness / 2]});
145
- result.properties.platebasis = CSG.OrthoNormalBasis.Z0Plane();
146
- return result;
147
- }
148
-
149
- function fingerJointAdd (plates, newplate, options) {
150
- var result = plates.slice(0);
151
- var numplates = plates.length;
152
- for (var plateindex1 = 0; plateindex1 < numplates; plateindex1++) {
153
- var joined = fingerJointTwo(result[plateindex1], newplate, options);
154
- result[plateindex1] = joined[0];
155
- newplate = joined[1];
156
- }
157
- result.push(newplate);
158
- return result;
159
- }
160
-
161
- // Finger joint between multiple plates:
162
- function fingerJoint (plates, options) {
163
- var result = plates.slice(0);
164
- var numplates = plates.length;
165
- var maxdelta = Math.floor(numplates / 2);
166
- for (var delta = 1; delta <= maxdelta; delta++) {
167
- for (var plateindex1 = 0; plateindex1 < numplates; plateindex1++) {
168
- var plateindex2 = plateindex1 + delta;
169
- if (plateindex2 >= numplates) plateindex2 -= numplates;
170
-
171
- var joined = fingerJointTwo(result[plateindex1], result[plateindex2], options);
172
- result[plateindex1] = joined[0];
173
- result[plateindex2] = joined[1];
174
- if (delta * 2 >= numplates) {
175
- // numplates is even
176
- if (plateindex1 * 2 >= numplates) {
177
- // and we've done the first half: we're done
178
- break;
179
- }
180
- }
181
- }
182
- }
183
- return result;
184
- }
185
-
186
- function fingerJointTwo (plate1, plate2, options) {
187
- if (!options) options = {};
188
- if (!('platebasis' in plate1.properties)) {
189
- throw new Error('Plates should be created using getStockPlate()');
190
- }
191
- if (!('platebasis' in plate2.properties)) {
192
- throw new Error('Plates should be created using getStockPlate()');
193
- }
194
- // get the intersection solid of the 2 plates:
195
- var intersection = plate1.intersect(plate2);
196
- if (intersection.polygons.length === 0) {
197
- // plates do not intersect. Return unmodified:
198
- return [plate1, plate2];
199
- } else {
200
- var plane1 = plate1.properties.platebasis.plane;
201
- var plane2 = plate2.properties.platebasis.plane;
202
- // get the intersection line of the 2 center planes:
203
- var jointline = plane1.intersectWithPlane(plane2);
204
- // Now we need to find the two endpoints on jointline (the points at the edges of intersection):
205
- // construct a plane perpendicular to jointline:
206
- plane1 = CSG.Plane.fromNormalAndPoint(jointline.direction, jointline.point);
207
- // make the plane into an orthonormal basis:
208
- var basis1 = new CSG.OrthoNormalBasis(plane1);
209
- // get the projection matrix for the orthobasis:
210
- var matrix = basis1.getProjectionMatrix();
211
- // now transform the intersection solid:
212
- var intersectionTransformed = intersection.transform(matrix);
213
- var bounds = intersectionTransformed.getBounds();
214
- // now we know the two edge points. The joint line runs from jointlineOrigin, in the
215
- // direction jointlineDirection and has a length jointlineLength (jointlineLength >= 0)
216
- var jointlineOrigin = jointline.point.plus(jointline.direction.times(bounds[0].z));
217
- var jointlineDirection = jointline.direction;
218
- var jointlineLength = bounds[1].z - bounds[0].z;
219
-
220
- var fingerwidth = options.fingerWidth || (jointlineLength / 4);
221
- var numfingers = Math.round(jointlineLength / fingerwidth);
222
- if (numfingers < 2) numfingers = 2;
223
- fingerwidth = jointlineLength / numfingers;
224
-
225
- var margin = options.margin || 0;
226
- var cutterRadius = options.cutterRadius || 0;
227
- var results = [];
228
- for (var plateindex = 0; plateindex < 2; plateindex++) {
229
- var thisplate = (plateindex === 1) ? plate2 : plate1;
230
- // var otherplate = (plateindex === 1) ? plate1 : plate2;
231
- // create a new orthonormal basis for this plate, such that the joint line runs in the positive x direction:
232
- var platebasis = new CSG.OrthoNormalBasis(thisplate.properties.platebasis.plane, jointlineDirection);
233
- // get the 2d shape of our plate:
234
- var plate2d = thisplate.projectToOrthoNormalBasis(platebasis);
235
- var jointlineOrigin2d = platebasis.to2D(jointlineOrigin);
236
- matrix = platebasis.getProjectionMatrix();
237
- intersectionTransformed = intersection.transform(matrix);
238
- bounds = intersectionTransformed.getBounds();
239
- var maxz = bounds[1].z;
240
- var minz = bounds[0].z;
241
- var maxy = bounds[1].y + margin / 2;
242
- var miny = bounds[0].y - margin / 2;
243
-
244
- var cutouts2d = [];
245
- for (var fingerindex = 0; fingerindex < numfingers; fingerindex++) {
246
- if ((plateindex === 0) && ((fingerindex & 1) === 0)) continue;
247
- if ((plateindex === 1) && ((fingerindex & 1) !== 0)) continue;
248
- var minx = jointlineOrigin2d.x + fingerindex * fingerwidth - margin / 2;
249
- var maxx = minx + fingerwidth + margin;
250
- var cutout = createRectCutoutWithCutterRadius(minx, miny, maxx, maxy, cutterRadius, plate2d);
251
- cutouts2d.push(cutout);
252
- }
253
- var cutout2d = new CAG().union(cutouts2d);
254
- var cutout3d = cutout2d.extrude({offset: [0, 0, maxz - minz]}).translate([0, 0, minz]);
255
- cutout3d = cutout3d.transform(platebasis.getInverseProjectionMatrix());
256
- var thisplateModified = thisplate.subtract(cutout3d);
257
- results[plateindex] = thisplateModified;
258
- }
259
- return results;
260
- }
261
- }
262
-
263
- // Create a rectangular cutout in 2D
264
- // minx, miny, maxx, maxy: boundaries of the rectangle
265
- // cutterRadius: if > 0, add extra cutting margin at the corners of the rectangle
266
- // plate2d is the 2d shape from which the cutout will be subtracted
267
- // it is tested at the corners of the cutout rectangle, to see if do need to add the extra margin at that corner
268
-
269
- function createRectCutoutWithCutterRadius (minx, miny, maxx, maxy, cutterRadius, plate2d) {
270
- var deltax = maxx - minx;
271
- var deltay = maxy - miny;
272
- var cutout = CAG.rectangle({radius: [(maxx - minx) / 2, (maxy - miny) / 2], center: [(maxx + minx) / 2, (maxy + miny) / 2]});
273
- var cornercutouts = [];
274
- if (cutterRadius > 0) {
275
- var extracutout = cutterRadius * 0.2;
276
- var hypcutterradius = cutterRadius / Math.sqrt(2.0);
277
- var halfcutterradius = 0.5 * cutterRadius;
278
- var dcx, dcy;
279
- if (deltax > 3 * deltay) {
280
- dcx = cutterRadius + extracutout / 2;
281
- dcy = extracutout / 2;
282
- } else if (deltay > 3 * deltax) {
283
- dcx = extracutout / 2;
284
- dcy = cutterRadius + extracutout / 2;
285
- } else {
286
- dcx = hypcutterradius - extracutout / 2;
287
- dcy = hypcutterradius - extracutout / 2;
288
- }
289
- for (var corner = 0; corner < 4; corner++) {
290
- var cutoutcenterx = (corner & 2) ? (maxx - dcx) : (minx + dcx);
291
- var cutoutcentery = (corner & 1) ? (maxy - dcy) : (miny + dcy);
292
- var cornercutout = CAG.rectangle({radius: [cutterRadius + extracutout / 2, cutterRadius + extracutout / 2], center: [cutoutcenterx, cutoutcentery]});
293
- var testrectacenterx = (corner & 2) ? (maxx - halfcutterradius) : (minx + halfcutterradius);
294
- var testrectbcenterx = (corner & 2) ? (maxx + halfcutterradius) : (minx - halfcutterradius);
295
- var testrectacentery = (corner & 1) ? (maxy + halfcutterradius) : (miny - halfcutterradius);
296
- var testrectbcentery = (corner & 1) ? (maxy - halfcutterradius) : (miny + halfcutterradius);
297
- var testrecta = CAG.rectangle({radius: [halfcutterradius, halfcutterradius], center: [testrectacenterx, testrectacentery]});
298
- var testrectb = CAG.rectangle({radius: [halfcutterradius, halfcutterradius], center: [testrectbcenterx, testrectbcentery]});
299
- if ((plate2d.intersect(testrecta).sides.length > 0) && (plate2d.intersect(testrectb).sides.length > 0)) {
300
- cornercutouts.push(cornercutout);
301
- }
302
- }
303
- }
304
- if (cornercutouts.length > 0) {
305
- cutout = cutout.union(cornercutouts);
306
- }
307
- return cutout;
308
- }
309
-
310
- function solidToOuterShellPlates (csg, thickness) {
311
- csg = csg.canonicalized();
312
- var bounds = csg.getBounds();
313
- var csgcenter = bounds[1].plus(bounds[0]).times(0.5);
314
- var csgradius = bounds[1].minus(bounds[0]).length();
315
- var plane2polygons = {};
316
- csg.polygons.map(function (polygon) {
317
- var planetag = polygon.plane.getTag();
318
- if (!(planetag in plane2polygons)) {
319
- plane2polygons[planetag] = [];
320
- }
321
- plane2polygons[planetag].push(polygon);
322
- });
323
- var plates = [];
324
- for (var planetag in plane2polygons) {
325
- var polygons = plane2polygons[planetag];
326
- var plane = polygons[0].plane;
327
- var shellcenterplane = new CSG.Plane(plane.normal, plane.w - thickness / 2);
328
- var basis = new CSG.OrthoNormalBasis(shellcenterplane);
329
- var inversebasisprojection = basis.getInverseProjectionMatrix();
330
- var csgcenterProjected = basis.to2D(csgcenter);
331
- var plate = getStockPlate(csgradius, csgradius, thickness).translate([csgcenterProjected.x, csgcenterProjected.y, 0]);
332
- plate = plate.transform(inversebasisprojection);
333
- plate = plate.intersect(csg);
334
- plates.push(plate);
335
- }
336
- return plates;
337
- }
338
-
339
- function getParameterDefinitions () {
340
- return [
341
- {name: 'topdiameter', type: 'float', initial: 160, caption: 'Top diameter:'},
342
- {name: 'bottomdiameter', type: 'float', initial: 300, caption: 'Bottom diameter:'},
343
- {name: 'height', type: 'float', initial: 170, caption: 'Height:'},
344
- {name: 'numfaces', type: 'int', initial: 5, caption: 'Number of faces:'},
345
- {name: 'thickness', type: 'float', initial: 4, caption: 'Thickness of stock material:'},
346
- {name: 'topholediameter', type: 'float', initial: 42, caption: 'Diameter of top hole:'},
347
- {name: 'cutterdiameter', type: 'float', initial: 3.2, step: 0.1, caption: 'Diameter of CNC cutter / laser beam:'},
348
- {
349
- name: 'type',
350
- type: 'choice',
351
- values: ['ASSEMBLED', 'TOPPLATE', 'SIDEPLATE'], // these are the values that will be supplied to your script
352
- captions: ['Assembled', 'Top plate (DXF output)', 'Side plate (DXF output)'], // optional, these values are shown in the listbox
353
- // if omitted, the items in the 'values' array are used
354
- caption: 'Show:', // optional, displayed left of the input field
355
- initial: 'ASSEMBLED' // optional, default selected value
356
- // if omitted, the first item is selected by default
357
- },
358
- {
359
- name: 'quality',
360
- type: 'choice',
361
- values: ['DRAFT', 'HIGH'], // these are the values that will be supplied to your script
362
- captions: ['Draft', 'High'], // optional, these values are shown in the listbox
363
- // if omitted, the items in the 'values' array are used
364
- caption: 'Quality:', // optional, displayed left of the input field
365
- initial: 'DRAFT' // optional, default selected value
366
- // if omitted, the first item is selected by default
367
- }
368
- ];
369
- }
@@ -1,46 +0,0 @@
1
- // title : Name Plate
2
- // author : Rene K. Mueller
3
- // license : MIT License
4
- // description: create your own name plate
5
- // date : 2013/04/24
6
- // file : name_plate.jscad
7
-
8
- const getParameterDefinitions = () => {
9
- return [
10
- { name: 'name', initial: 'Joe Example', type: 'text', caption: 'Your name', size: 30 },
11
- { name: 'title', initial: '3D Printer Developer', type: 'text', caption: 'Your title', size: 30 },
12
- { name: 'thickness', initial: 3, type: 'float', caption: 'Thickness' }
13
- ]
14
- }
15
-
16
- const main = (params) => {
17
- var o = [] // our stack of objects
18
- var l = [] // our stack of line segments (when rendering vector text)
19
- var p = [] // our stack of extruded line segments
20
-
21
- // -- render name & extrude
22
- l = vectorText(0, 0, params.name)
23
- l.forEach(function (s) {
24
- p.push(extrudeRectangular(s, { w: params.thickness, h: params.thickness }))
25
- })
26
- o.push(union(p).setColor([1, 1, 0]).scale([1 / 3, 1 / 3, 1 / 3]).center([true, true, false]).translate([0, 0, params.thickness]))
27
-
28
- if (params.title.length) {
29
- // -- render title & extrude
30
- l = vectorText(0, 0, params.title)
31
- p = []
32
- l.forEach(function (s) {
33
- p.push(extrudeRectangular(s, { w: params.thickness, h: params.thickness }))
34
- })
35
- o.push(union(p).setColor([1, 1, 0]).scale([1 / 8, 1 / 8, 1 / 3]).center([true, true, false]).translate([0, -8, params.thickness]))
36
- }
37
- o = [union(o)] // neat: we combine name + title, and make it first entry of an array
38
-
39
- var b = o[0].getBounds()
40
- var m = 2
41
- var w = b[1].x - b[0].x + m * 2
42
- var h = b[1].y - b[0].y + m * 2
43
- o.push(cube({ size: [w, h, params.thickness], round: true, radius: 0.5 }).translate([b[0].x - m, b[0].y - m, 0]))
44
-
45
- return union(o)
46
- }