gerber 0 → 1

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.
@@ -0,0 +1,6 @@
1
+ require 'minitest/autorun'
2
+ require 'gerber/layer'
3
+
4
+ describe Gerber::Layer do
5
+ let(:layer) { Gerber::Layer.new }
6
+ end
@@ -0,0 +1,481 @@
1
+ require 'minitest/autorun'
2
+ require 'gerber/layer/parser'
3
+
4
+ class Gerber
5
+ class Layer
6
+ class Parser
7
+ def geometry
8
+ self.layer.geometry
9
+ end
10
+
11
+ def dcode
12
+ @dcode
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ describe Gerber::Layer::Parser do
19
+ Arc = Gerber::Arc
20
+ Line = Gerber::Line
21
+ Point = Gerber::Point
22
+
23
+ let(:parser) { Gerber::Layer::Parser.new }
24
+
25
+ it "must default to absolute mode" do
26
+ parser.coordinate_mode.must_equal :absolute
27
+ end
28
+
29
+ it "must default to single quadrant mode" do
30
+ parser.quadrant_mode.must_equal :single
31
+ end
32
+
33
+ describe "when validating Geometry" do
34
+ it "must accept Arcs" do
35
+ parser.is_valid_geometry(Arc.new(nil, nil, nil, nil)).must_equal true
36
+ end
37
+
38
+ it "must accept Lines" do
39
+ parser.is_valid_geometry(Line.new).must_equal true
40
+ end
41
+
42
+ it "must accept Points" do
43
+ parser.is_valid_geometry(Point[0,0]).must_equal true
44
+ end
45
+ end
46
+
47
+ describe "when parsing a D code" do
48
+ it "must start drawing for D01" do
49
+ parser.parse_dcode('D01')
50
+ parser.dcode.must_equal 1
51
+ end
52
+
53
+ it "must stop drawing for D02" do
54
+ parser.parse_dcode('D02')
55
+ parser.dcode.must_equal 2
56
+ end
57
+
58
+ it "must flash for D03" do
59
+ parser.parse_dcode('D03')
60
+ parser.dcode.must_equal 3
61
+ end
62
+
63
+ it "must set the current aperture number" do
64
+ original_state = parser.dcode
65
+ parser.parse_dcode('D11')
66
+ parser.dcode.must_equal original_state
67
+ parser.current_aperture.must_equal 11
68
+ parser.geometry[11].must_be_instance_of(Array)
69
+ end
70
+ end
71
+
72
+ describe "when parsing a G code" do
73
+ it "must raise an exception if the units have not been set" do
74
+ lambda { parser.parse_gcode(1, 2, 3, 4, 5, 1) }.must_raise Gerber::ParseError
75
+ end
76
+
77
+ describe "when a G74 is parsed" do
78
+ before do
79
+ parser.parse_gcode(74)
80
+ end
81
+
82
+ it "must stay in single quadrant mode" do
83
+ parser.quadrant_mode.must_equal :single
84
+ end
85
+ end
86
+
87
+ describe "when a G75 is parsed" do
88
+ before do
89
+ parser.parse_gcode(75)
90
+ end
91
+
92
+ it "must set multi quadrant mode" do
93
+ parser.quadrant_mode.must_equal :multi
94
+ end
95
+
96
+ describe "when a G74 is parsed" do
97
+ before do
98
+ parser.parse_gcode(74)
99
+ end
100
+
101
+ it "must return to single quadrant mode" do
102
+ parser.quadrant_mode.must_equal :single
103
+ end
104
+ end
105
+ end
106
+
107
+ describe "when G90 is parsed" do
108
+ before do
109
+ parser.parse_gcode(90)
110
+ end
111
+
112
+ it "must stay in absolute mode" do
113
+ parser.coordinate_mode.must_equal :absolute
114
+ end
115
+ end
116
+
117
+ describe "when G91 is parsed" do
118
+ before do
119
+ parser.parse_gcode(91)
120
+ end
121
+
122
+ it "must set incremental mode" do
123
+ parser.coordinate_mode.must_equal :incremental
124
+ end
125
+
126
+ describe "when a G90 is parsed" do
127
+ before do
128
+ parser.parse_gcode(90)
129
+ end
130
+
131
+ it "must return to absolute mode" do
132
+ parser.coordinate_mode.must_equal :absolute
133
+ end
134
+ end
135
+ end
136
+
137
+ describe "when units have been set" do
138
+ before do
139
+ parser.parse_gcode(71, nil, nil, nil, nil, nil)
140
+ end
141
+
142
+ it "must raise an exception if an aperture has not been set" do
143
+ lambda { parser.parse_gcode(1, 2, 3, 4, 5, 1) }.must_raise Gerber::ParseError
144
+ end
145
+
146
+ it "must parse the deprecated G54 and set the current aperture" do
147
+ parser.parse_gcode(54, nil, nil, nil, nil, 10)
148
+ parser.current_aperture.must_equal 10
149
+ parser.geometry[10].must_be_instance_of(Array)
150
+ end
151
+
152
+ it "must reject a G54 without a D code" do
153
+ skip "Not relevant in the latest version of the file format"
154
+ lambda { parser.parse_gcode(54, nil, nil, nil, nil, nil) }.must_raise Gerber::ParseError
155
+ end
156
+
157
+ describe "when an aperture has been set" do
158
+ before do
159
+ parser.current_aperture = 10
160
+ end
161
+
162
+ it "G1D1 must generate a Line" do
163
+ parser.parse_gcode(1, 2, 3, 4, 5, 1)
164
+ parser.geometry.last.last.must_be_kind_of(Geometry::Line)
165
+ end
166
+
167
+ it "G1D2 must move the current position but not generate geometry" do
168
+ parser.parse_gcode(1, 2, 3, 4, 5, 2)
169
+ parser.geometry.last.length.must_equal 0
170
+ parser.instance_variable_get(:@position).must_equal Geometry::Point[2.mm,3.mm]
171
+ end
172
+
173
+ it "G1D3 must generate a Point" do
174
+ parser.parse_gcode(1, 2, 3, 4, 5, 3)
175
+ parser.geometry.last.last.must_be_kind_of(Geometry::Point)
176
+ end
177
+
178
+ describe "when circular interpolation" do
179
+ it "must reject a dcode other than 1 or 2" do
180
+ skip
181
+ lambda { parser.parse_gcode(2, 1, 2, 3, 4, 5) }.must_raise Gerber::ParseError
182
+ lambda { parser.parse_gcode(3, 1, 2, 3, 4, 5) }.must_raise Gerber::ParseError
183
+ end
184
+
185
+ describe "when in absolute mode" do
186
+ describe "when in single quadrant mode" do
187
+ before do
188
+ parser.parse_gcode(74)
189
+ parser.parse_gcode(1, 11, 6, nil, nil, 2) # Set the current position
190
+ end
191
+
192
+ describe "when parsing four clockwise arcs" do
193
+ before do
194
+ parser.parse_gcode(2, 7, 2, 4, 0, 1)
195
+ parser.parse_gcode(2, 3, 6, 0, 4, nil)
196
+ parser.parse_gcode(nil, 7, 10, 4, 0, nil)
197
+ parser.parse_gcode(nil, 11, 6, 0, 4, nil)
198
+ end
199
+
200
+ it "must generate 4 Arcs" do
201
+ parser.geometry[10].length.must_equal 4
202
+ parser.geometry[10].all? {|a| a.kind_of?(Geometry::Arc)}.must_equal(true)
203
+ end
204
+
205
+ it "must generate a proper first Arc" do
206
+ arc = parser.geometry[10].first
207
+ arc.center.must_equal Point[7.mm, 6.mm]
208
+ arc.first.must_equal Point[7.mm, 2.mm]
209
+ arc.last.must_equal Point[11.mm, 6.mm]
210
+ end
211
+
212
+ it "must generate a proper second Arc" do
213
+ arc = parser.geometry[10][1]
214
+ arc.center.must_equal Point[7.mm, 6.mm]
215
+ arc.first.must_equal Point[3.mm, 6.mm]
216
+ arc.last.must_equal Point[7.mm, 2.mm]
217
+ end
218
+
219
+ it "must generate a proper third Arc" do
220
+ arc = parser.geometry[10][2]
221
+ arc.center.must_equal Point[7.mm, 6.mm]
222
+ arc.first.must_equal Point[7.mm, 10.mm]
223
+ arc.last.must_equal Point[3.mm, 6.mm]
224
+ end
225
+
226
+ it "must generate a proper fourth Arc" do
227
+ arc = parser.geometry[10].last
228
+ arc.center.must_equal Point[7.mm, 6.mm]
229
+ arc.first.must_equal Point[11.mm, 6.mm]
230
+ arc.last.must_equal Point[7.mm, 10.mm]
231
+ end
232
+ end
233
+
234
+ describe "when parsing a counterclockwise arc" do
235
+ before do
236
+ parser.parse_gcode(3, 7, 10, 4, 0, 1)
237
+ end
238
+
239
+ it "must generate an Arc" do
240
+ parser.geometry[10].last.must_be_kind_of(Geometry::Arc)
241
+ arc = parser.geometry[10].last
242
+ arc.center.must_equal Point[7.mm, 6.mm]
243
+ arc.first.must_equal Point[11.mm, 6.mm]
244
+ arc.last.must_equal Point[7.mm, 10.mm]
245
+ end
246
+
247
+ it "must set the current position to the Arc's end point" do
248
+ parser.position.must_equal Point[7.mm, 10.mm]
249
+ end
250
+
251
+ describe "when parsing another arc with a modal function number" do
252
+ before do
253
+ parser.parse_gcode(nil, 3, 6, 0, 4, nil)
254
+ end
255
+
256
+ it "must generate an Arc" do
257
+ parser.geometry[10].last.must_be_kind_of(Geometry::Arc)
258
+ arc = parser.geometry[10].last
259
+ arc.center.must_equal Point[7.mm, 6.mm]
260
+ arc.first.must_equal Point[7.mm, 10.mm]
261
+ arc.last.must_equal Point[3.mm, 6.mm]
262
+ end
263
+
264
+ it "must set the current position to the Arc's end point" do
265
+ parser.position.must_equal Point[3.mm, 6.mm]
266
+ end
267
+
268
+ describe "when parsing a third arc" do
269
+ before do
270
+ parser.parse_gcode(nil, 7, 2, 4, 0, nil)
271
+ end
272
+
273
+ it "must generate an Arc" do
274
+ parser.geometry[10].last.must_be_kind_of(Geometry::Arc)
275
+ arc = parser.geometry[10].last
276
+ arc.center.must_equal Point[7.mm, 6.mm]
277
+ arc.first.must_equal Point[3.mm, 6.mm]
278
+ arc.last.must_equal Point[7.mm, 2.mm]
279
+ end
280
+
281
+ it "must set the current position to the Arc's end point" do
282
+ parser.position.must_equal Point[7.mm, 2.mm]
283
+ end
284
+
285
+ describe "when parsing the final arc in the circle" do
286
+ before do
287
+ parser.parse_gcode(nil, 11, 6, 0, 4, nil)
288
+ end
289
+
290
+ it "must generate an Arc" do
291
+ parser.geometry[10].last.must_be_kind_of(Geometry::Arc)
292
+ arc = parser.geometry[10].last
293
+ arc.center.must_equal Point[7.mm, 6.mm]
294
+ arc.first.must_equal Point[7.mm, 2.mm]
295
+ arc.last.must_equal Point[11.mm, 6.mm]
296
+ end
297
+
298
+ it "must set the current position to the Arc's end point" do
299
+ parser.position.must_equal Point[11.mm, 6.mm]
300
+ end
301
+ end
302
+ end
303
+ end
304
+ end
305
+ end
306
+
307
+ describe "when in multi quadrant mode" do
308
+ before do
309
+ parser.parse_gcode(75)
310
+ parser.parse_gcode(1, 3, -2, nil, nil, 2) # Set the current position
311
+ end
312
+
313
+ describe "when parsing a clockwise arc" do
314
+ before do
315
+ parser.parse_gcode(2, -3, -2, -3, 4, 1)
316
+ end
317
+
318
+ it "must generate an Arc" do
319
+ parser.geometry[10].last.must_be_kind_of(Geometry::Arc)
320
+ arc = parser.geometry[10].last
321
+ arc.center.must_equal Point[0.mm, 2.mm]
322
+ arc.first.must_equal Point[-3.mm, -2.mm]
323
+ arc.last.must_equal Point[3.mm, -2.mm]
324
+ end
325
+
326
+ it "must set the current position to the endpoint of the Arc" do
327
+ parser.position.must_equal Point[-3.mm, -2.mm]
328
+ end
329
+ end
330
+
331
+ describe "when parsing a counterclockwise arc" do
332
+ before do
333
+ parser.parse_gcode(3, -3, -2, -3, 4, 1)
334
+ end
335
+
336
+ it "must generate an Arc" do
337
+ parser.geometry[10].last.must_be_kind_of(Geometry::Arc)
338
+ arc = parser.geometry[10].last
339
+ arc.center.must_equal Point[0.mm, 2.mm]
340
+ arc.first.must_equal Point[3.mm, -2.mm]
341
+ arc.last.must_equal Point[-3.mm, -2.mm]
342
+ end
343
+
344
+ it "must set the current position to the endpoint of the Arc" do
345
+ parser.position.must_equal Point[-3.mm, -2.mm]
346
+ end
347
+ end
348
+ end
349
+ end
350
+
351
+ describe "when in incremental mode" do
352
+ before do
353
+ parser.parse_gcode(91)
354
+ end
355
+
356
+ describe "when in single quadrant mode" do
357
+ before do
358
+ parser.parse_gcode(74)
359
+ parser.parse_gcode(1, 11, 6, nil, nil, 2) # Set the current position
360
+ end
361
+
362
+ describe "when parsing four clockwise arcs" do
363
+ before do
364
+ parser.parse_gcode(2, -4, -4, 4, 0, 1)
365
+ parser.parse_gcode(2, -4, 4, 0, 4, nil)
366
+ parser.parse_gcode(nil, 4, 4, 4, 0, nil)
367
+ parser.parse_gcode(nil, 4, -4, 0, 4, nil)
368
+ end
369
+
370
+ it "must generate 4 Arcs" do
371
+ parser.geometry[10].length.must_equal 4
372
+ parser.geometry[10].all? {|a| a.kind_of?(Geometry::Arc)}.must_equal(true)
373
+ end
374
+
375
+ it "must generate a proper first Arc" do
376
+ arc = parser.geometry[10].first
377
+ arc.center.must_equal Point[7.mm, 6.mm]
378
+ arc.first.must_equal Point[7.mm, 2.mm]
379
+ arc.last.must_equal Point[11.mm, 6.mm]
380
+ end
381
+
382
+ it "must generate a proper second Arc" do
383
+ arc = parser.geometry[10][1]
384
+ arc.center.must_equal Point[7.mm, 6.mm]
385
+ arc.first.must_equal Point[3.mm, 6.mm]
386
+ arc.last.must_equal Point[7.mm, 2.mm]
387
+ end
388
+
389
+ it "must generate a proper third Arc" do
390
+ arc = parser.geometry[10][2]
391
+ arc.center.must_equal Point[7.mm, 6.mm]
392
+ arc.first.must_equal Point[7.mm, 10.mm]
393
+ arc.last.must_equal Point[3.mm, 6.mm]
394
+ end
395
+
396
+ it "must generate a proper fourth Arc" do
397
+ arc = parser.geometry[10].last
398
+ arc.center.must_equal Point[7.mm, 6.mm]
399
+ arc.first.must_equal Point[11.mm, 6.mm]
400
+ arc.last.must_equal Point[7.mm, 10.mm]
401
+ end
402
+ end
403
+
404
+ describe "when parsing a counterclockwise arc" do
405
+ before do
406
+ parser.parse_gcode(3, -4, 4, 4, 0, 1)
407
+ end
408
+
409
+ it "must generate an Arc" do
410
+ parser.geometry[10].last.must_be_kind_of(Geometry::Arc)
411
+ arc = parser.geometry[10].last
412
+ arc.center.must_equal Point[7.mm, 6.mm]
413
+ arc.first.must_equal Point[11.mm, 6.mm]
414
+ arc.last.must_equal Point[7.mm, 10.mm]
415
+ end
416
+
417
+ it "must set the current position to the Arc's end point" do
418
+ parser.position.must_equal Point[7.mm, 10.mm]
419
+ end
420
+
421
+ describe "when parsing another arc with a modal function number" do
422
+ before do
423
+ parser.parse_gcode(nil, -4, -4, 0, 4, nil)
424
+ end
425
+
426
+ it "must generate an Arc" do
427
+ parser.geometry[10].last.must_be_kind_of(Geometry::Arc)
428
+ arc = parser.geometry[10].last
429
+ arc.center.must_equal Point[7.mm, 6.mm]
430
+ arc.first.must_equal Point[7.mm, 10.mm]
431
+ arc.last.must_equal Point[3.mm, 6.mm]
432
+ end
433
+
434
+ it "must set the current position to the Arc's end point" do
435
+ parser.position.must_equal Point[3.mm, 6.mm]
436
+ end
437
+
438
+ describe "when parsing a third arc" do
439
+ before do
440
+ parser.parse_gcode(nil, 4, -4, 4, 0, nil)
441
+ end
442
+
443
+ it "must generate an Arc" do
444
+ parser.geometry[10].last.must_be_kind_of(Geometry::Arc)
445
+ arc = parser.geometry[10].last
446
+ arc.center.must_equal Point[7.mm, 6.mm]
447
+ arc.first.must_equal Point[3.mm, 6.mm]
448
+ arc.last.must_equal Point[7.mm, 2.mm]
449
+ end
450
+
451
+ it "must set the current position to the Arc's end point" do
452
+ parser.position.must_equal Point[7.mm, 2.mm]
453
+ end
454
+
455
+ describe "when parsing the final arc in the circle" do
456
+ before do
457
+ parser.parse_gcode(nil, 4, 4, 0, 4, nil)
458
+ end
459
+
460
+ it "must generate an Arc" do
461
+ parser.geometry[10].last.must_be_kind_of(Geometry::Arc)
462
+ arc = parser.geometry[10].last
463
+ arc.center.must_equal Point[7.mm, 6.mm]
464
+ arc.first.must_equal Point[7.mm, 2.mm]
465
+ arc.last.must_equal Point[11.mm, 6.mm]
466
+ end
467
+
468
+ it "must set the current position to the Arc's end point" do
469
+ parser.position.must_equal Point[11.mm, 6.mm]
470
+ end
471
+ end
472
+ end
473
+ end
474
+ end
475
+ end
476
+ end
477
+ end
478
+ end
479
+ end
480
+ end
481
+ end