rubyscad 1.0.6 → 1.0.7

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 (63) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -21
  3. data/Gemfile +4 -4
  4. data/LICENSE.txt +21 -21
  5. data/README.md +322 -322
  6. data/Rakefile +1 -1
  7. data/examples/BasicCube.rb +50 -50
  8. data/examples/ChamferCube.rb +96 -96
  9. data/examples/FilletCube.rb +317 -317
  10. data/examples/example001.rb +33 -33
  11. data/examples/example001.scad +11 -11
  12. data/examples/example002.rb +23 -23
  13. data/examples/example002.scad +18 -18
  14. data/examples/example003.rb +19 -19
  15. data/examples/example003.scad +15 -15
  16. data/examples/example004.rb +11 -11
  17. data/examples/example004.scad +6 -6
  18. data/examples/example005.rb +22 -22
  19. data/examples/example005.scad +31 -31
  20. data/examples/example006.rb +46 -46
  21. data/examples/example006.scad +221 -221
  22. data/examples/example007.dxf +2410 -2410
  23. data/examples/example007.rb +53 -53
  24. data/examples/example007.scad +30 -30
  25. data/examples/example008.dxf +3238 -3238
  26. data/examples/example008.rb +34 -34
  27. data/examples/example008.scad +26 -26
  28. data/examples/example009.dxf +3894 -3894
  29. data/examples/example009.rb +33 -33
  30. data/examples/example009.scad +15 -15
  31. data/examples/example010.dat +51 -51
  32. data/examples/example010.rb +12 -12
  33. data/examples/example010.scad +7 -7
  34. data/examples/example011.rb +22 -22
  35. data/examples/example011.scad +3 -3
  36. data/examples/example012.rb +16 -16
  37. data/examples/example012.scad +8 -8
  38. data/examples/example013.dxf +2276 -2276
  39. data/examples/example013.rb +16 -16
  40. data/examples/example013.scad +12 -12
  41. data/examples/example014.rb +14 -14
  42. data/examples/example014.scad +12 -12
  43. data/examples/example015.rb +33 -33
  44. data/examples/example015.scad +22 -22
  45. data/examples/example016.rb +43 -43
  46. data/examples/example016.scad +49 -49
  47. data/examples/example017.rb +170 -170
  48. data/examples/example017.scad +124 -124
  49. data/examples/example018.rb +29 -29
  50. data/examples/example018.scad +74 -74
  51. data/examples/example019.rb +22 -22
  52. data/examples/example019.scad +84 -84
  53. data/examples/example020.rb +92 -92
  54. data/examples/example020.scad +62 -62
  55. data/examples/example021.rb +42 -42
  56. data/examples/example021.scad +159 -159
  57. data/examples/example022.rb +44 -44
  58. data/examples/example022.scad +103 -103
  59. data/lib/rubyscad.rb +2 -2
  60. data/lib/rubyscad/RubyScad.rb +369 -361
  61. data/lib/rubyscad/version.rb +3 -3
  62. data/rubyscad.gemspec +20 -20
  63. metadata +7 -9
@@ -1,103 +1,103 @@
1
- //created with rubyscad 1.0
2
-
3
- translate(v = [-15, 0, 0]) {
4
- cube(size = [10.000, 30.000, 40.000], center = true);
5
- cube(size = [20.000, 20.000, 40.000], center = true);
6
- translate(v = [-5.000, -10.000])
7
- cylinder(r = 5.000, h = 40.000, center = true);
8
- translate(v = [-5.000, 10.000])
9
- cylinder(r = 5.000, h = 40.000, center = true);
10
- translate(v = [5.000, -10.000])
11
- cylinder(r = 5.000, h = 40.000, center = true);
12
- translate(v = [5.000, 10.000])
13
- cylinder(r = 5.000, h = 40.000, center = true);
14
- }
15
- translate(v = [15, 0, 0]) {
16
- cube(size = [20.000, 20.000, 30.000], center = true);
17
- cube(size = [10.000, 30.000, 30.000], center = true);
18
- cube(size = [10.000, 20.000, 40.000], center = true);
19
- rotate(a = [0, 0, 0])
20
- translate(v = [-5.000, -10.000, 0])
21
- cylinder(h = 30.000, r = 5, center = true);
22
- rotate(a = [0, 0, 0])
23
- translate(v = [-5.000, 10.000, 0])
24
- cylinder(h = 30.000, r = 5, center = true);
25
- rotate(a = [0, 0, 0])
26
- translate(v = [5.000, -10.000, 0])
27
- cylinder(h = 30.000, r = 5, center = true);
28
- rotate(a = [0, 0, 0])
29
- translate(v = [5.000, 10.000, 0])
30
- cylinder(h = 30.000, r = 5, center = true);
31
- translate(v = [-5.000, -10.000, -15.000])
32
- sphere(r = 5);
33
- translate(v = [-5.000, -10.000, 15.000])
34
- sphere(r = 5);
35
- translate(v = [-5.000, 10.000, -15.000])
36
- sphere(r = 5);
37
- translate(v = [-5.000, 10.000, 15.000])
38
- sphere(r = 5);
39
- translate(v = [5.000, -10.000, -15.000])
40
- sphere(r = 5);
41
- translate(v = [5.000, -10.000, 15.000])
42
- sphere(r = 5);
43
- translate(v = [5.000, 10.000, -15.000])
44
- sphere(r = 5);
45
- translate(v = [5.000, 10.000, 15.000])
46
- sphere(r = 5);
47
- rotate(a = [90, 0, 90])
48
- translate(v = [-10.000, -15.000, 0])
49
- cylinder(h = 10.000, r = 5, center = true);
50
- rotate(a = [90, 0, 90])
51
- translate(v = [-10.000, 15.000, 0])
52
- cylinder(h = 10.000, r = 5, center = true);
53
- rotate(a = [90, 0, 90])
54
- translate(v = [10.000, -15.000, 0])
55
- cylinder(h = 10.000, r = 5, center = true);
56
- rotate(a = [90, 0, 90])
57
- translate(v = [10.000, 15.000, 0])
58
- cylinder(h = 10.000, r = 5, center = true);
59
- translate(v = [-5.000, -10.000, -15.000])
60
- sphere(r = 5);
61
- translate(v = [-5.000, -10.000, 15.000])
62
- sphere(r = 5);
63
- translate(v = [-5.000, 10.000, -15.000])
64
- sphere(r = 5);
65
- translate(v = [-5.000, 10.000, 15.000])
66
- sphere(r = 5);
67
- translate(v = [5.000, -10.000, -15.000])
68
- sphere(r = 5);
69
- translate(v = [5.000, -10.000, 15.000])
70
- sphere(r = 5);
71
- translate(v = [5.000, 10.000, -15.000])
72
- sphere(r = 5);
73
- translate(v = [5.000, 10.000, 15.000])
74
- sphere(r = 5);
75
- rotate(a = [90, 90, 0])
76
- translate(v = [-15.000, -5.000, 0])
77
- cylinder(h = 20.000, r = 5, center = true);
78
- rotate(a = [90, 90, 0])
79
- translate(v = [-15.000, 5.000, 0])
80
- cylinder(h = 20.000, r = 5, center = true);
81
- rotate(a = [90, 90, 0])
82
- translate(v = [15.000, -5.000, 0])
83
- cylinder(h = 20.000, r = 5, center = true);
84
- rotate(a = [90, 90, 0])
85
- translate(v = [15.000, 5.000, 0])
86
- cylinder(h = 20.000, r = 5, center = true);
87
- translate(v = [-5.000, -10.000, -15.000])
88
- sphere(r = 5);
89
- translate(v = [-5.000, -10.000, 15.000])
90
- sphere(r = 5);
91
- translate(v = [-5.000, 10.000, -15.000])
92
- sphere(r = 5);
93
- translate(v = [-5.000, 10.000, 15.000])
94
- sphere(r = 5);
95
- translate(v = [5.000, -10.000, -15.000])
96
- sphere(r = 5);
97
- translate(v = [5.000, -10.000, 15.000])
98
- sphere(r = 5);
99
- translate(v = [5.000, 10.000, -15.000])
100
- sphere(r = 5);
101
- translate(v = [5.000, 10.000, 15.000])
102
- sphere(r = 5);
103
- }
1
+ //created with rubyscad 1.0
2
+
3
+ translate(v = [-15, 0, 0]) {
4
+ cube(size = [10.000, 30.000, 40.000], center = true);
5
+ cube(size = [20.000, 20.000, 40.000], center = true);
6
+ translate(v = [-5.000, -10.000])
7
+ cylinder(r = 5.000, h = 40.000, center = true);
8
+ translate(v = [-5.000, 10.000])
9
+ cylinder(r = 5.000, h = 40.000, center = true);
10
+ translate(v = [5.000, -10.000])
11
+ cylinder(r = 5.000, h = 40.000, center = true);
12
+ translate(v = [5.000, 10.000])
13
+ cylinder(r = 5.000, h = 40.000, center = true);
14
+ }
15
+ translate(v = [15, 0, 0]) {
16
+ cube(size = [20.000, 20.000, 30.000], center = true);
17
+ cube(size = [10.000, 30.000, 30.000], center = true);
18
+ cube(size = [10.000, 20.000, 40.000], center = true);
19
+ rotate(a = [0, 0, 0])
20
+ translate(v = [-5.000, -10.000, 0])
21
+ cylinder(h = 30.000, r = 5, center = true);
22
+ rotate(a = [0, 0, 0])
23
+ translate(v = [-5.000, 10.000, 0])
24
+ cylinder(h = 30.000, r = 5, center = true);
25
+ rotate(a = [0, 0, 0])
26
+ translate(v = [5.000, -10.000, 0])
27
+ cylinder(h = 30.000, r = 5, center = true);
28
+ rotate(a = [0, 0, 0])
29
+ translate(v = [5.000, 10.000, 0])
30
+ cylinder(h = 30.000, r = 5, center = true);
31
+ translate(v = [-5.000, -10.000, -15.000])
32
+ sphere(r = 5);
33
+ translate(v = [-5.000, -10.000, 15.000])
34
+ sphere(r = 5);
35
+ translate(v = [-5.000, 10.000, -15.000])
36
+ sphere(r = 5);
37
+ translate(v = [-5.000, 10.000, 15.000])
38
+ sphere(r = 5);
39
+ translate(v = [5.000, -10.000, -15.000])
40
+ sphere(r = 5);
41
+ translate(v = [5.000, -10.000, 15.000])
42
+ sphere(r = 5);
43
+ translate(v = [5.000, 10.000, -15.000])
44
+ sphere(r = 5);
45
+ translate(v = [5.000, 10.000, 15.000])
46
+ sphere(r = 5);
47
+ rotate(a = [90, 0, 90])
48
+ translate(v = [-10.000, -15.000, 0])
49
+ cylinder(h = 10.000, r = 5, center = true);
50
+ rotate(a = [90, 0, 90])
51
+ translate(v = [-10.000, 15.000, 0])
52
+ cylinder(h = 10.000, r = 5, center = true);
53
+ rotate(a = [90, 0, 90])
54
+ translate(v = [10.000, -15.000, 0])
55
+ cylinder(h = 10.000, r = 5, center = true);
56
+ rotate(a = [90, 0, 90])
57
+ translate(v = [10.000, 15.000, 0])
58
+ cylinder(h = 10.000, r = 5, center = true);
59
+ translate(v = [-5.000, -10.000, -15.000])
60
+ sphere(r = 5);
61
+ translate(v = [-5.000, -10.000, 15.000])
62
+ sphere(r = 5);
63
+ translate(v = [-5.000, 10.000, -15.000])
64
+ sphere(r = 5);
65
+ translate(v = [-5.000, 10.000, 15.000])
66
+ sphere(r = 5);
67
+ translate(v = [5.000, -10.000, -15.000])
68
+ sphere(r = 5);
69
+ translate(v = [5.000, -10.000, 15.000])
70
+ sphere(r = 5);
71
+ translate(v = [5.000, 10.000, -15.000])
72
+ sphere(r = 5);
73
+ translate(v = [5.000, 10.000, 15.000])
74
+ sphere(r = 5);
75
+ rotate(a = [90, 90, 0])
76
+ translate(v = [-15.000, -5.000, 0])
77
+ cylinder(h = 20.000, r = 5, center = true);
78
+ rotate(a = [90, 90, 0])
79
+ translate(v = [-15.000, 5.000, 0])
80
+ cylinder(h = 20.000, r = 5, center = true);
81
+ rotate(a = [90, 90, 0])
82
+ translate(v = [15.000, -5.000, 0])
83
+ cylinder(h = 20.000, r = 5, center = true);
84
+ rotate(a = [90, 90, 0])
85
+ translate(v = [15.000, 5.000, 0])
86
+ cylinder(h = 20.000, r = 5, center = true);
87
+ translate(v = [-5.000, -10.000, -15.000])
88
+ sphere(r = 5);
89
+ translate(v = [-5.000, -10.000, 15.000])
90
+ sphere(r = 5);
91
+ translate(v = [-5.000, 10.000, -15.000])
92
+ sphere(r = 5);
93
+ translate(v = [-5.000, 10.000, 15.000])
94
+ sphere(r = 5);
95
+ translate(v = [5.000, -10.000, -15.000])
96
+ sphere(r = 5);
97
+ translate(v = [5.000, -10.000, 15.000])
98
+ sphere(r = 5);
99
+ translate(v = [5.000, 10.000, -15.000])
100
+ sphere(r = 5);
101
+ translate(v = [5.000, 10.000, 15.000])
102
+ sphere(r = 5);
103
+ }
@@ -1,2 +1,2 @@
1
- require 'rubyscad/version'
2
- require 'rubyscad/RubyScad'
1
+ require 'rubyscad/version'
2
+ require 'rubyscad/RubyScad'
@@ -1,361 +1,369 @@
1
- require 'rubyscad/version'
2
- require 'matrix'
3
-
4
- class Numeric
5
- def radians
6
- self * Math::PI / 180
7
- end
8
- end
9
-
10
- class Float
11
- FP_P = 3
12
- def to_s
13
- "%.#{FP_P}f" % self.round(FP_P)
14
- end
15
- end
16
-
17
- module RubyScad
18
- START_BLOCK = "{"
19
- END_BLOCK = "}"
20
- TAB_SIZE = 3
21
- PAD = 0.01
22
-
23
- CUBE_STR = "cube(%<args>s);"
24
- SPHERE_STR = "sphere(%<args>s);"
25
- CYLINDER_STR = "cylinder(%<args>s);"
26
- POLYHEDRON_STR = "polyhedron(%<args>s);"
27
- SQUARE_STR = "square(%<args>s);"
28
- CIRCLE_STR = "circle(%<args>s);"
29
- POLYGON_STR = "polygon(%<args>s);"
30
- TRANSLATE_STR = "translate(%<args>s)"
31
- ROTATE_STR = "rotate(%<args>s)"
32
- SCALE_STR = "scale(%<args>s)"
33
- MIRROR_STR = "mirror(%<args>s)"
34
- MULTMATRIX_STR = "multmatrix(%<args>s)"
35
- COLOR_STR = "color(%<args>s)"
36
- UNION_STR = "union(%<args>s)"
37
- DIFFERENCE_STR = "difference(%<args>s)"
38
- INTERSECTION_STR = "intersection(%<args>s)"
39
- RENDER_STR = "render(%<args>s)"
40
- MINKOWSKI_STR = "minkowski(%<args>s)"
41
- HULL_STR = "hull(%<args>s)"
42
- BACKGROUND_STR = '%'
43
- DEBUG_STR = '#'
44
- ROOT_STR = '!'
45
- DISABLE_STR = '*'
46
- IMPORT_STR = "import(%<args>s);"
47
- SURFACE_STR = "surface(%<args>s);"
48
- LINEAR_EXTRUDE_STR = "linear_extrude(%<args>s)"
49
- ROTATE_EXTRUDE_STR = "rotate_extrude(%<args>s)"
50
- PROJECTION_STR = "projection(%<args>s)"
51
-
52
- INCLUDE_STR = "include <%<file>s>"
53
- USE_STR = "use <%<file>s>"
54
- ECHO_STR = "echo(%<string>s);"
55
- FA_STR = "$fa = %<value>s;"
56
- FS_STR = "$fs = %<value>s;"
57
- FN_STR = "$fn = %<value>s;"
58
-
59
- def fa(value)
60
- format_output FA_STR % {value: value}
61
- end
62
-
63
- def fs(value)
64
- format_output FS_STR % {value: value}
65
- end
66
-
67
- def fn(value)
68
- format_output FN_STR % {value: value}
69
- end
70
-
71
- def include_scad(file)
72
- format_output INCLUDE_STR % {file: file}
73
- end
74
-
75
- def use(file)
76
- format_output USE_STR % {file: file}
77
- end
78
-
79
- def echo(*args)
80
- format_output ECHO_STR % {string: args.join(', ')}
81
- end
82
-
83
- def projection(args={}, &block)
84
- format_command PROJECTION_STR, args, &block
85
- end
86
-
87
- def linear_extrude(args={}, &block)
88
- str_end = args.include?(:file) ? ";" : ""
89
- format_command LINEAR_EXTRUDE_STR.concat(str_end), args, &block
90
- end
91
-
92
- def rotate_extrude(args={}, &block)
93
- str_end = args.include?(:file) ? ";" : ""
94
- format_command ROTATE_EXTRUDE_STR.concat(str_end), args, &block
95
- end
96
-
97
- def import(args={})
98
- format_command IMPORT_STR, args
99
- end
100
-
101
- def difference(&block)
102
- format_command DIFFERENCE_STR, &block
103
- end
104
-
105
- def union(&block)
106
- format_command UNION_STR, &block
107
- end
108
-
109
- def intersection(&block)
110
- format_command INTERSECTION_STR, &block
111
- end
112
-
113
- def render(args={}, &block)
114
- format_command RENDER_STR, args, &block
115
- end
116
-
117
- def minkowski(&block)
118
- format_command MINKOWSKI_STR, &block
119
- end
120
-
121
- def hull(&block)
122
- format_command HULL_STR, &block
123
- end
124
-
125
- def background()
126
- format_output BACKGROUND_STR
127
- yield if block_given?
128
- end
129
-
130
- def debug()
131
- format_output DEBUG_STR
132
- yield if block_given?
133
- end
134
-
135
- def root()
136
- format_output ROOT_STR
137
- yield if block_given?
138
- end
139
-
140
- def disable()
141
- format_output DISABLE_STR
142
- yield if block_given?
143
- end
144
-
145
- def cube(args={})
146
- format_command CUBE_STR, args
147
- end
148
-
149
- def sphere(args={})
150
- if args.include?(:d)
151
- args[:r] = args[:d]/2.0
152
- args.delete(:d)
153
- end
154
- format_command SPHERE_STR, args
155
- end
156
-
157
- def polyhedron(args={})
158
- format_command POLYHEDRON_STR, args
159
- end
160
-
161
- def square(args={})
162
- format_command SQUARE_STR, args
163
- end
164
-
165
- def circle(args={})
166
- if args.include?(:d)
167
- args[:r] = args[:d]/2.0
168
- args.delete(:d)
169
- end
170
- format_command CIRCLE_STR, args
171
- end
172
-
173
- def polygon(args={})
174
- format_command POLYGON_STR, args
175
- end
176
-
177
- def surface(args={})
178
- format_command SURFACE_STR, args
179
- end
180
-
181
- def cylinder(args={})
182
- if args.include?(:d)
183
- args[:r] = args[:d]/2.0
184
- args.delete(:d)
185
- end
186
- if args.include?(:d1)
187
- args[:r1] = args[:d1]/2.0
188
- args.delete(:d1)
189
- end
190
- if args.include?(:d2)
191
- args[:r2] = args[:d2]/2.0
192
- args.delete(:d2)
193
- end
194
- format_command CYLINDER_STR, args
195
- end
196
-
197
- def rotate(args={}, &block)
198
- vector_input(args, :a)
199
- format_command ROTATE_STR, args, &block
200
- end
201
-
202
- def translate(args={}, &block)
203
- vector_input(args, :v)
204
- format_command TRANSLATE_STR, args, &block
205
- end
206
-
207
- def scale(args={}, &block)
208
- vector_input(args, :v)
209
- format_command SCALE_STR, args, &block
210
- end
211
-
212
- def mirror(args={}, &block)
213
- vector_input(args, :v)
214
- format_command MIRROR_STR, args, &block
215
- end
216
-
217
- def multmatrix(args={}, &block)
218
- format_command MULTMATRIX_STR, args, &block
219
- end
220
-
221
- def color(args={}, &block)
222
- args[:color] = [args.fetch(:r, 0), args.fetch(:g, 0), args.fetch(:b, 0), args.fetch(:a, 1)] unless args.include?(:color)
223
- delete_from(args, :r, :g, :b, :a)
224
- format_command COLOR_STR, args, &block
225
- end
226
-
227
- def format_command(cmd_str, args={}, &block)
228
- arg_str = args.collect { |k, v| "#{format_key(k)} = #{format_value(v)}" }.join(', ')
229
- format_block cmd_str % {args: arg_str}, &block
230
- end
231
-
232
- def format_key(key)
233
- key = key.to_s
234
- key.prepend('$') if key.match("^f[asn]$")
235
- key
236
- end
237
-
238
- def format_value(var)
239
- if var.is_a?(Vector) or var.is_a?(Matrix)
240
- return var.to_a.to_s
241
- elsif var.is_a? String
242
- return '"' + var + '"'
243
- else
244
- return var.to_s
245
- end
246
- end
247
-
248
- def delete_from(hash, *keys)
249
- keys.each { |k| hash.delete(k) }
250
- end
251
-
252
- def vector_input(args, element)
253
- unless args.include?(element)
254
- args[element] = [args.fetch(:x, 0), args.fetch(:y, 0)]
255
- args[element].push(args[:z]) if args.include?(:z)
256
- delete_from(args, :x, :y, :z)
257
- end
258
- end
259
-
260
- def format_block(output_str)
261
- format_output output_str.concat(' ')
262
- if block_given?
263
- start_block
264
- yield
265
- end_block
266
- else
267
- new_line unless output_str.include?(';')
268
- end
269
- end
270
-
271
- def new_line
272
- format_output "\n"
273
- end
274
-
275
- def start_block()
276
- format_output START_BLOCK
277
- end
278
-
279
- def end_block()
280
- format_output END_BLOCK
281
- end
282
-
283
- def end_all_blocks()
284
- end_block while @@tab_level > 0
285
- end
286
-
287
- def space_string(str, tab_level)
288
- ((' '*TAB_SIZE)*tab_level) + str
289
- end
290
-
291
- def raw_output(str)
292
- if @@output_file
293
- File.open(@@output_file, 'a') { |f| f.print(str) }
294
- else
295
- print str
296
- end
297
- end
298
-
299
- def format_output(str)
300
- @@prev_output ||= ""
301
- @@tab_level ||= 0
302
- str.lines do |l|
303
- l.concat("\n") if l.match('[;\}\{>]')
304
- @@tab_level-=1 if(l.include?('}')) && @@tab_level > 0
305
- l = space_string(l, @@tab_level) if @@prev_output.include?("\n")
306
- raw_output(l)
307
- @@tab_level+=1 if(l.include?('{'))
308
- @@prev_output = l
309
- end
310
- end
311
-
312
- def self.start_output
313
- @@output_file ||= nil
314
- if ARGV[0] && ARGV[0].include?(".scad")
315
- @@output_file = ARGV[0]
316
- ARGV.shift
317
- end
318
- if @@output_file
319
- File.open(@@output_file, 'w') do |f|
320
- f.puts "//created with rubyscad #{VERSION}\n\n"
321
- end
322
- end
323
- end
324
-
325
- def self.extended(mod)
326
- start_output
327
- end
328
-
329
- def self.included(mod)
330
- start_output
331
- end
332
-
333
- start_output if __FILE__== $0
334
-
335
- def lookup(x, points)
336
- xmin, xmax = [0.0, 0.0]
337
- points.keys.sort.reverse_each do |k|
338
- if k <= x
339
- xmin = k
340
- break
341
- end
342
- end
343
- points.keys.sort.each do |k|
344
- if k >= x
345
- xmax = k
346
- break
347
- end
348
- end
349
- return points[xmax] if x == xmax
350
- return points[xmin] if x == xmin
351
- return points[xmin] + (((x - xmin) * (points[xmax] - points[xmin])) / (xmax - xmin))
352
- end
353
-
354
- def dxf_cross(args={})
355
- return 0.0
356
- end
357
-
358
- def dxf_dim(args={})
359
- return 0.0
360
- end
361
- end
1
+ require 'rubyscad/version'
2
+ require 'matrix'
3
+
4
+ class Numeric
5
+ def radians
6
+ self * Math::PI / 180
7
+ end
8
+ end
9
+
10
+ class Float
11
+ FP_P = 3
12
+ def to_s
13
+ "%.#{FP_P}f" % self.round(FP_P)
14
+ end
15
+ end
16
+
17
+ module RubyScad
18
+ START_BLOCK = "{"
19
+ END_BLOCK = "}"
20
+ TAB_SIZE = 3
21
+ PAD = 0.01
22
+
23
+ CUBE_STR = "cube(%<args>s);"
24
+ SPHERE_STR = "sphere(%<args>s);"
25
+ CYLINDER_STR = "cylinder(%<args>s);"
26
+ POLYHEDRON_STR = "polyhedron(%<args>s);"
27
+ SQUARE_STR = "square(%<args>s);"
28
+ CIRCLE_STR = "circle(%<args>s);"
29
+ POLYGON_STR = "polygon(%<args>s);"
30
+ TRANSLATE_STR = "translate(%<args>s)"
31
+ ROTATE_STR = "rotate(%<args>s)"
32
+ SCALE_STR = "scale(%<args>s)"
33
+ MIRROR_STR = "mirror(%<args>s)"
34
+ MULTMATRIX_STR = "multmatrix(%<args>s)"
35
+ COLOR_STR = "color(%<args>s)"
36
+ UNION_STR = "union(%<args>s)"
37
+ DIFFERENCE_STR = "difference(%<args>s)"
38
+ INTERSECTION_STR = "intersection(%<args>s)"
39
+ RENDER_STR = "render(%<args>s)"
40
+ MINKOWSKI_STR = "minkowski(%<args>s)"
41
+ HULL_STR = "hull(%<args>s)"
42
+ BACKGROUND_STR = '%'
43
+ DEBUG_STR = '#'
44
+ ROOT_STR = '!'
45
+ DISABLE_STR = '*'
46
+ IMPORT_STR = "import(%<args>s);"
47
+ SURFACE_STR = "surface(%<args>s);"
48
+ LINEAR_EXTRUDE_STR = "linear_extrude(%<args>s)"
49
+ ROTATE_EXTRUDE_STR = "rotate_extrude(%<args>s)"
50
+ PROJECTION_STR = "projection(%<args>s)"
51
+
52
+ INCLUDE_STR = "include <%<file>s>"
53
+ USE_STR = "use <%<file>s>"
54
+ ECHO_STR = "echo(%<string>s);"
55
+ FA_STR = "$fa = %<value>s;"
56
+ FS_STR = "$fs = %<value>s;"
57
+ FN_STR = "$fn = %<value>s;"
58
+
59
+ def fa(value)
60
+ format_output FA_STR % {value: value}
61
+ end
62
+
63
+ def fs(value)
64
+ format_output FS_STR % {value: value}
65
+ end
66
+
67
+ def fn(value)
68
+ format_output FN_STR % {value: value}
69
+ end
70
+
71
+ def include_scad(file)
72
+ format_output INCLUDE_STR % {file: file}
73
+ end
74
+
75
+ def use(file)
76
+ format_output USE_STR % {file: file}
77
+ end
78
+
79
+ def echo(*args)
80
+ format_output ECHO_STR % {string: args.join(', ')}
81
+ end
82
+
83
+ def projection(args={}, &block)
84
+ format_command PROJECTION_STR, args, &block
85
+ end
86
+
87
+ def linear_extrude(args={}, &block)
88
+ str_end = args.include?(:file) ? ";" : ""
89
+ format_command LINEAR_EXTRUDE_STR.concat(str_end), args, &block
90
+ end
91
+
92
+ def rotate_extrude(args={}, &block)
93
+ str_end = args.include?(:file) ? ";" : ""
94
+ format_command ROTATE_EXTRUDE_STR.concat(str_end), args, &block
95
+ end
96
+
97
+ def import(args={})
98
+ format_command IMPORT_STR, args
99
+ end
100
+
101
+ def difference(&block)
102
+ format_command DIFFERENCE_STR, &block
103
+ end
104
+
105
+ def union(&block)
106
+ format_command UNION_STR, &block
107
+ end
108
+
109
+ def intersection(&block)
110
+ format_command INTERSECTION_STR, &block
111
+ end
112
+
113
+ def render(args={}, &block)
114
+ format_command RENDER_STR, args, &block
115
+ end
116
+
117
+ def minkowski(&block)
118
+ format_command MINKOWSKI_STR, &block
119
+ end
120
+
121
+ def hull(&block)
122
+ format_command HULL_STR, &block
123
+ end
124
+
125
+ def background()
126
+ format_output BACKGROUND_STR
127
+ yield if block_given?
128
+ end
129
+
130
+ def debug()
131
+ format_output DEBUG_STR
132
+ yield if block_given?
133
+ end
134
+
135
+ def root()
136
+ format_output ROOT_STR
137
+ yield if block_given?
138
+ end
139
+
140
+ def disable()
141
+ format_output DISABLE_STR
142
+ yield if block_given?
143
+ end
144
+
145
+ def cube(args={})
146
+ format_command CUBE_STR, args
147
+ end
148
+
149
+ def sphere(args={})
150
+ if args.include?(:d)
151
+ args[:r] = args[:d]/2.0
152
+ args.delete(:d)
153
+ end
154
+ format_command SPHERE_STR, args
155
+ end
156
+
157
+ def polyhedron(args={})
158
+ format_command POLYHEDRON_STR, args
159
+ end
160
+
161
+ def square(args={})
162
+ format_command SQUARE_STR, args
163
+ end
164
+
165
+ def circle(args={})
166
+ if args.include?(:d)
167
+ args[:r] = args[:d]/2.0
168
+ args.delete(:d)
169
+ end
170
+ format_command CIRCLE_STR, args
171
+ end
172
+
173
+ def polygon(args={})
174
+ format_command POLYGON_STR, args
175
+ end
176
+
177
+ def surface(args={})
178
+ format_command SURFACE_STR, args
179
+ end
180
+
181
+ def cylinder(args={})
182
+ if args.include?(:d)
183
+ args[:r] = args[:d]/2.0
184
+ args.delete(:d)
185
+ end
186
+ if args.include?(:d1)
187
+ args[:r1] = args[:d1]/2.0
188
+ args.delete(:d1)
189
+ end
190
+ if args.include?(:d2)
191
+ args[:r2] = args[:d2]/2.0
192
+ args.delete(:d2)
193
+ end
194
+ format_command CYLINDER_STR, args
195
+ end
196
+
197
+ def rotate(args={}, &block)
198
+ vector_input(args, :a)
199
+ format_command ROTATE_STR, args, &block
200
+ end
201
+
202
+ def translate(args={}, &block)
203
+ vector_input(args, :v)
204
+ format_command TRANSLATE_STR, args, &block
205
+ end
206
+
207
+ def scale(args={}, &block)
208
+ vector_input(args, :v)
209
+ format_command SCALE_STR, args, &block
210
+ end
211
+
212
+ def mirror(args={}, &block)
213
+ vector_input(args, :v)
214
+ format_command MIRROR_STR, args, &block
215
+ end
216
+
217
+ def multmatrix(args={}, &block)
218
+ format_command MULTMATRIX_STR, args, &block
219
+ end
220
+
221
+ def color(args={}, &block)
222
+ unless args.include?(:color)
223
+ args[:color] = [args.fetch(:r, 0), args.fetch(:g, 0), args.fetch(:b, 0), args.fetch(:a, 1)].to_s
224
+ else
225
+ args[:color] = "\"#{args[:color]}\""
226
+ end
227
+ delete_from(args, :r, :g, :b, :a)
228
+ format_command(COLOR_STR, args[:color], &block)
229
+ end
230
+
231
+ def format_command(cmd_str, args={}, &block)
232
+ unless args.kind_of? String
233
+ arg_str = args.collect { |k, v| "#{format_key(k)} = #{format_value(v)}" }.join(', ')
234
+ else
235
+ arg_str = args
236
+ end
237
+ format_block cmd_str % {args: arg_str}, &block
238
+ end
239
+
240
+ def format_key(key)
241
+ key = key.to_s
242
+ key.prepend('$') if key.match("^f[asn]$")
243
+ key
244
+ end
245
+
246
+ def format_value(var)
247
+ if var.is_a?(Vector) or var.is_a?(Matrix)
248
+ return var.to_a.to_s
249
+ elsif var.is_a? String
250
+ return '"' + var + '"'
251
+ else
252
+ return var.to_s
253
+ end
254
+ end
255
+
256
+ def delete_from(hash, *keys)
257
+ keys.each { |k| hash.delete(k) }
258
+ end
259
+
260
+ def vector_input(args, element)
261
+ unless args.include?(element)
262
+ args[element] = [args.fetch(:x, 0), args.fetch(:y, 0)]
263
+ args[element].push(args[:z]) if args.include?(:z)
264
+ delete_from(args, :x, :y, :z)
265
+ end
266
+ end
267
+
268
+ def format_block(output_str)
269
+ format_output output_str.concat(' ')
270
+ if block_given?
271
+ start_block
272
+ yield
273
+ end_block
274
+ else
275
+ new_line unless output_str.include?(';')
276
+ end
277
+ end
278
+
279
+ def new_line
280
+ format_output "\n"
281
+ end
282
+
283
+ def start_block()
284
+ format_output START_BLOCK
285
+ end
286
+
287
+ def end_block()
288
+ format_output END_BLOCK
289
+ end
290
+
291
+ def end_all_blocks()
292
+ end_block while @@tab_level > 0
293
+ end
294
+
295
+ def space_string(str, tab_level)
296
+ ((' '*TAB_SIZE)*tab_level) + str
297
+ end
298
+
299
+ def raw_output(str)
300
+ if @@output_file
301
+ File.open(@@output_file, 'a') { |f| f.print(str) }
302
+ else
303
+ print str
304
+ end
305
+ end
306
+
307
+ def format_output(str)
308
+ @@prev_output ||= ""
309
+ @@tab_level ||= 0
310
+ str.lines do |l|
311
+ l.concat("\n") if l.match('[;\}\{>]')
312
+ @@tab_level-=1 if(l.include?('}')) && @@tab_level > 0
313
+ l = space_string(l, @@tab_level) if @@prev_output.include?("\n")
314
+ raw_output(l)
315
+ @@tab_level+=1 if(l.include?('{'))
316
+ @@prev_output = l
317
+ end
318
+ end
319
+
320
+ def self.start_output
321
+ @@output_file ||= nil
322
+ if ARGV[0] && ARGV[0].include?(".scad")
323
+ @@output_file = ARGV[0]
324
+ ARGV.shift
325
+ end
326
+ if @@output_file
327
+ File.open(@@output_file, 'w') do |f|
328
+ f.puts "//created with rubyscad #{VERSION}\n\n"
329
+ end
330
+ end
331
+ end
332
+
333
+ def self.extended(mod)
334
+ start_output
335
+ end
336
+
337
+ def self.included(mod)
338
+ start_output
339
+ end
340
+
341
+ start_output if __FILE__== $0
342
+
343
+ def lookup(x, points)
344
+ xmin, xmax = [0.0, 0.0]
345
+ points.keys.sort.reverse_each do |k|
346
+ if k <= x
347
+ xmin = k
348
+ break
349
+ end
350
+ end
351
+ points.keys.sort.each do |k|
352
+ if k >= x
353
+ xmax = k
354
+ break
355
+ end
356
+ end
357
+ return points[xmax] if x == xmax
358
+ return points[xmin] if x == xmin
359
+ return points[xmin] + (((x - xmin) * (points[xmax] - points[xmin])) / (xmax - xmin))
360
+ end
361
+
362
+ def dxf_cross(args={})
363
+ return 0.0
364
+ end
365
+
366
+ def dxf_dim(args={})
367
+ return 0.0
368
+ end
369
+ end