rubyscad 1.0.6 → 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
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