summaryrefslogtreecommitdiff
path: root/gerber/tests
diff options
context:
space:
mode:
Diffstat (limited to 'gerber/tests')
-rw-r--r--gerber/tests/golden/example_am_exposure_modifier.pngbin0 -> 10091 bytes
-rw-r--r--gerber/tests/golden/example_coincident_hole.pngbin0 -> 47261 bytes
-rw-r--r--gerber/tests/golden/example_cutin_multiple.pngbin0 -> 1348 bytes
-rw-r--r--gerber/tests/golden/example_flash_circle.pngbin0 -> 5978 bytes
-rw-r--r--gerber/tests/golden/example_flash_obround.pngbin0 -> 3443 bytes
-rw-r--r--gerber/tests/golden/example_flash_polygon.pngbin0 -> 4087 bytes
-rw-r--r--gerber/tests/golden/example_flash_rectangle.pngbin0 -> 1731 bytes
-rw-r--r--gerber/tests/golden/example_fully_coincident.pngbin0 -> 71825 bytes
-rw-r--r--gerber/tests/golden/example_holes_dont_clear.pngbin0 -> 11552 bytes
-rw-r--r--gerber/tests/golden/example_not_overlapping_contour.pngbin0 -> 71825 bytes
-rw-r--r--gerber/tests/golden/example_not_overlapping_touching.pngbin0 -> 96557 bytes
-rw-r--r--gerber/tests/golden/example_overlapping_contour.pngbin0 -> 33301 bytes
-rw-r--r--gerber/tests/golden/example_overlapping_touching.pngbin0 -> 33301 bytes
-rw-r--r--gerber/tests/golden/example_simple_contour.pngbin0 -> 31830 bytes
-rw-r--r--gerber/tests/golden/example_single_contour.pngbin0 -> 556 bytes
-rw-r--r--gerber/tests/golden/example_single_contour_3.pngbin0 -> 2297 bytes
-rw-r--r--gerber/tests/golden/example_single_quadrant.gbr16
-rw-r--r--gerber/tests/golden/example_single_quadrant.pngbin0 -> 9658 bytes
-rw-r--r--gerber/tests/golden/example_two_square_boxes.gbr16
-rw-r--r--gerber/tests/golden/example_two_square_boxes.pngbin0 -> 18219 bytes
-rw-r--r--gerber/tests/resources/example_am_exposure_modifier.gbr16
-rw-r--r--gerber/tests/resources/example_coincident_hole.gbr24
-rw-r--r--gerber/tests/resources/example_cutin.gbr18
-rw-r--r--gerber/tests/resources/example_cutin_multiple.gbr28
-rw-r--r--gerber/tests/resources/example_flash_circle.gbr10
-rw-r--r--gerber/tests/resources/example_flash_obround.gbr10
-rw-r--r--gerber/tests/resources/example_flash_polygon.gbr10
-rw-r--r--gerber/tests/resources/example_flash_rectangle.gbr10
-rw-r--r--gerber/tests/resources/example_fully_coincident.gbr23
-rw-r--r--gerber/tests/resources/example_holes_dont_clear.gbr13
-rw-r--r--gerber/tests/resources/example_level_holes.gbr39
-rw-r--r--gerber/tests/resources/example_not_overlapping_contour.gbr20
-rw-r--r--gerber/tests/resources/example_not_overlapping_touching.gbr20
-rw-r--r--gerber/tests/resources/example_overlapping_contour.gbr20
-rw-r--r--gerber/tests/resources/example_overlapping_touching.gbr20
-rw-r--r--gerber/tests/resources/example_simple_contour.gbr16
-rw-r--r--gerber/tests/resources/example_single_contour_1.gbr15
-rw-r--r--gerber/tests/resources/example_single_contour_2.gbr15
-rw-r--r--gerber/tests/resources/example_single_contour_3.gbr15
-rw-r--r--gerber/tests/resources/example_single_quadrant.gbr18
-rw-r--r--gerber/tests/resources/example_two_square_boxes.gbr19
-rw-r--r--gerber/tests/resources/ipc-d-356.ipc115
-rw-r--r--gerber/tests/resources/multiline_read.ger9
-rw-r--r--gerber/tests/resources/top_copper.GTL3458
-rw-r--r--gerber/tests/test_am_statements.py383
-rw-r--r--gerber/tests/test_cairo_backend.py189
-rw-r--r--gerber/tests/test_cam.py96
-rw-r--r--gerber/tests/test_common.py29
-rw-r--r--gerber/tests/test_excellon.py195
-rw-r--r--gerber/tests/test_excellon_statements.py480
-rw-r--r--gerber/tests/test_gerber_statements.py655
-rw-r--r--gerber/tests/test_ipc356.py139
-rw-r--r--gerber/tests/test_layers.py33
-rw-r--r--gerber/tests/test_primitives.py1270
-rw-r--r--gerber/tests/test_rs274x.py46
-rw-r--r--gerber/tests/test_rs274x_backend.py185
-rw-r--r--gerber/tests/test_utils.py78
-rw-r--r--gerber/tests/tests.py11
58 files changed, 4253 insertions, 3529 deletions
diff --git a/gerber/tests/golden/example_am_exposure_modifier.png b/gerber/tests/golden/example_am_exposure_modifier.png
new file mode 100644
index 0000000..dac951f
--- /dev/null
+++ b/gerber/tests/golden/example_am_exposure_modifier.png
Binary files differ
diff --git a/gerber/tests/golden/example_coincident_hole.png b/gerber/tests/golden/example_coincident_hole.png
new file mode 100644
index 0000000..9855b11
--- /dev/null
+++ b/gerber/tests/golden/example_coincident_hole.png
Binary files differ
diff --git a/gerber/tests/golden/example_cutin_multiple.png b/gerber/tests/golden/example_cutin_multiple.png
new file mode 100644
index 0000000..ebc1191
--- /dev/null
+++ b/gerber/tests/golden/example_cutin_multiple.png
Binary files differ
diff --git a/gerber/tests/golden/example_flash_circle.png b/gerber/tests/golden/example_flash_circle.png
new file mode 100644
index 0000000..0c407f6
--- /dev/null
+++ b/gerber/tests/golden/example_flash_circle.png
Binary files differ
diff --git a/gerber/tests/golden/example_flash_obround.png b/gerber/tests/golden/example_flash_obround.png
new file mode 100644
index 0000000..2fd4dc3
--- /dev/null
+++ b/gerber/tests/golden/example_flash_obround.png
Binary files differ
diff --git a/gerber/tests/golden/example_flash_polygon.png b/gerber/tests/golden/example_flash_polygon.png
new file mode 100644
index 0000000..89a964b
--- /dev/null
+++ b/gerber/tests/golden/example_flash_polygon.png
Binary files differ
diff --git a/gerber/tests/golden/example_flash_rectangle.png b/gerber/tests/golden/example_flash_rectangle.png
new file mode 100644
index 0000000..797e0c3
--- /dev/null
+++ b/gerber/tests/golden/example_flash_rectangle.png
Binary files differ
diff --git a/gerber/tests/golden/example_fully_coincident.png b/gerber/tests/golden/example_fully_coincident.png
new file mode 100644
index 0000000..4e522ff
--- /dev/null
+++ b/gerber/tests/golden/example_fully_coincident.png
Binary files differ
diff --git a/gerber/tests/golden/example_holes_dont_clear.png b/gerber/tests/golden/example_holes_dont_clear.png
new file mode 100644
index 0000000..7efb67b
--- /dev/null
+++ b/gerber/tests/golden/example_holes_dont_clear.png
Binary files differ
diff --git a/gerber/tests/golden/example_not_overlapping_contour.png b/gerber/tests/golden/example_not_overlapping_contour.png
new file mode 100644
index 0000000..4e522ff
--- /dev/null
+++ b/gerber/tests/golden/example_not_overlapping_contour.png
Binary files differ
diff --git a/gerber/tests/golden/example_not_overlapping_touching.png b/gerber/tests/golden/example_not_overlapping_touching.png
new file mode 100644
index 0000000..d485495
--- /dev/null
+++ b/gerber/tests/golden/example_not_overlapping_touching.png
Binary files differ
diff --git a/gerber/tests/golden/example_overlapping_contour.png b/gerber/tests/golden/example_overlapping_contour.png
new file mode 100644
index 0000000..7504311
--- /dev/null
+++ b/gerber/tests/golden/example_overlapping_contour.png
Binary files differ
diff --git a/gerber/tests/golden/example_overlapping_touching.png b/gerber/tests/golden/example_overlapping_touching.png
new file mode 100644
index 0000000..7504311
--- /dev/null
+++ b/gerber/tests/golden/example_overlapping_touching.png
Binary files differ
diff --git a/gerber/tests/golden/example_simple_contour.png b/gerber/tests/golden/example_simple_contour.png
new file mode 100644
index 0000000..564ae14
--- /dev/null
+++ b/gerber/tests/golden/example_simple_contour.png
Binary files differ
diff --git a/gerber/tests/golden/example_single_contour.png b/gerber/tests/golden/example_single_contour.png
new file mode 100644
index 0000000..3341638
--- /dev/null
+++ b/gerber/tests/golden/example_single_contour.png
Binary files differ
diff --git a/gerber/tests/golden/example_single_contour_3.png b/gerber/tests/golden/example_single_contour_3.png
new file mode 100644
index 0000000..1eecfee
--- /dev/null
+++ b/gerber/tests/golden/example_single_contour_3.png
Binary files differ
diff --git a/gerber/tests/golden/example_single_quadrant.gbr b/gerber/tests/golden/example_single_quadrant.gbr
new file mode 100644
index 0000000..b0a3166
--- /dev/null
+++ b/gerber/tests/golden/example_single_quadrant.gbr
@@ -0,0 +1,16 @@
+%FSLAX23Y23*%
+%MOIN*%
+%ADD10C,0.01*%
+G74*
+D10*
+%LPD*%
+G01X1100Y600D02*
+G03X700Y1000I-400J0D01*
+G03X300Y600I0J-400D01*
+G03X700Y200I400J0D01*
+G03X1100Y600I0J400D01*
+G01X300D02*
+X1100D01*
+X700Y200D02*
+Y1000D01*
+M02*
diff --git a/gerber/tests/golden/example_single_quadrant.png b/gerber/tests/golden/example_single_quadrant.png
new file mode 100644
index 0000000..89b763f
--- /dev/null
+++ b/gerber/tests/golden/example_single_quadrant.png
Binary files differ
diff --git a/gerber/tests/golden/example_two_square_boxes.gbr b/gerber/tests/golden/example_two_square_boxes.gbr
new file mode 100644
index 0000000..b5c60d1
--- /dev/null
+++ b/gerber/tests/golden/example_two_square_boxes.gbr
@@ -0,0 +1,16 @@
+%FSLAX25Y25*%
+%MOMM*%
+%ADD10C,0.01*%
+D10*
+%LPD*%
+G01X0Y0D02*
+X500000D01*
+Y500000D01*
+X0D01*
+Y0D01*
+X600000D02*
+X1100000D01*
+Y500000D01*
+X600000D01*
+Y0D01*
+M02*
diff --git a/gerber/tests/golden/example_two_square_boxes.png b/gerber/tests/golden/example_two_square_boxes.png
new file mode 100644
index 0000000..98d0518
--- /dev/null
+++ b/gerber/tests/golden/example_two_square_boxes.png
Binary files differ
diff --git a/gerber/tests/resources/example_am_exposure_modifier.gbr b/gerber/tests/resources/example_am_exposure_modifier.gbr
new file mode 100644
index 0000000..5f3f3dd
--- /dev/null
+++ b/gerber/tests/resources/example_am_exposure_modifier.gbr
@@ -0,0 +1,16 @@
+G04 Umaco example for exposure modifier and clearing area*
+%FSLAX26Y26*%
+%MOIN*%
+%AMSQUAREWITHHOLE*
+21,0.1,1,1,0,0,0*
+1,0,0.5,0,0*%
+%ADD10SQUAREWITHHOLE*%
+%ADD11C,1*%
+G01*
+%LPD*%
+D11*
+X-1000000Y-250000D02*
+X1000000Y250000D01*
+D10*
+X0Y0D03*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_coincident_hole.gbr b/gerber/tests/resources/example_coincident_hole.gbr
new file mode 100644
index 0000000..4f896ea
--- /dev/null
+++ b/gerber/tests/resources/example_coincident_hole.gbr
@@ -0,0 +1,24 @@
+G04 ex2: overlapping*
+%FSLAX24Y24*%
+%MOMM*%
+%SRX1Y1I0.000J0.000*%
+%ADD10C,1.00000*%
+G01*
+%LPD*%
+G36*
+X0Y50000D02*
+Y100000D01*
+X100000D01*
+Y0D01*
+X0D01*
+Y50000D01*
+G04 first fully coincident linear segment*
+X10000D01*
+X50000Y10000D01*
+X90000Y50000D01*
+X50000Y90000D01*
+X10000Y50000D01*
+G04 second fully coincident linear segment*
+X0D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_cutin.gbr b/gerber/tests/resources/example_cutin.gbr
new file mode 100644
index 0000000..365e5e1
--- /dev/null
+++ b/gerber/tests/resources/example_cutin.gbr
@@ -0,0 +1,18 @@
+G04 Umaco uut-in example*
+%FSLAX24Y24*%
+G75*
+G36*
+X20000Y100000D02*
+G01*
+X120000D01*
+Y20000D01*
+X20000D01*
+Y60000D01*
+X50000D01*
+G03*
+X50000Y60000I30000J0D01*
+G01*
+X20000D01*
+Y100000D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_cutin_multiple.gbr b/gerber/tests/resources/example_cutin_multiple.gbr
new file mode 100644
index 0000000..8e19429
--- /dev/null
+++ b/gerber/tests/resources/example_cutin_multiple.gbr
@@ -0,0 +1,28 @@
+G04 multiple cutins*
+%FSLAX24Y24*%
+%MOMM*%
+%SRX1Y1I0.000J0.000*%
+%ADD10C,1.00000*%
+%LPD*%
+G36*
+X1220000Y2570000D02*
+G01*
+Y2720000D01*
+X1310000D01*
+Y2570000D01*
+X1250000D01*
+Y2600000D01*
+X1290000D01*
+Y2640000D01*
+X1250000D01*
+Y2670000D01*
+X1290000D01*
+Y2700000D01*
+X1250000D01*
+Y2670000D01*
+Y2640000D01*
+Y2600000D01*
+Y2570000D01*
+X1220000D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_flash_circle.gbr b/gerber/tests/resources/example_flash_circle.gbr
new file mode 100644
index 0000000..20b2566
--- /dev/null
+++ b/gerber/tests/resources/example_flash_circle.gbr
@@ -0,0 +1,10 @@
+G04 Flashes of circular apertures*
+%FSLAX24Y24*%
+%MOMM*%
+%ADD10C,0.5*%
+%ADD11C,0.5X0.25*%
+D10*
+X000000Y000000D03*
+D11*
+X010000D03*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_flash_obround.gbr b/gerber/tests/resources/example_flash_obround.gbr
new file mode 100644
index 0000000..5313f82
--- /dev/null
+++ b/gerber/tests/resources/example_flash_obround.gbr
@@ -0,0 +1,10 @@
+G04 Flashes of rectangular apertures*
+%FSLAX24Y24*%
+%MOMM*%
+%ADD10O,0.46X0.26*%
+%ADD11O,0.46X0.26X0.19*%
+D10*
+X000000Y000000D03*
+D11*
+X010000D03*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_flash_polygon.gbr b/gerber/tests/resources/example_flash_polygon.gbr
new file mode 100644
index 0000000..177cf9b
--- /dev/null
+++ b/gerber/tests/resources/example_flash_polygon.gbr
@@ -0,0 +1,10 @@
+G04 Flashes of rectangular apertures*
+%FSLAX24Y24*%
+%MOMM*%
+%ADD10P,.40X6*%
+%ADD11P,.40X6X0.0X0.19*%
+D10*
+X000000Y000000D03*
+D11*
+X010000D03*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_flash_rectangle.gbr b/gerber/tests/resources/example_flash_rectangle.gbr
new file mode 100644
index 0000000..8fde812
--- /dev/null
+++ b/gerber/tests/resources/example_flash_rectangle.gbr
@@ -0,0 +1,10 @@
+G04 Flashes of rectangular apertures*
+%FSLAX24Y24*%
+%MOMM*%
+%ADD10R,0.44X0.25*%
+%ADD11R,0.44X0.25X0.19*%
+D10*
+X000000Y000000D03*
+D11*
+X010000D03*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_fully_coincident.gbr b/gerber/tests/resources/example_fully_coincident.gbr
new file mode 100644
index 0000000..3764128
--- /dev/null
+++ b/gerber/tests/resources/example_fully_coincident.gbr
@@ -0,0 +1,23 @@
+G04 ex1: non overlapping*
+%FSLAX24Y24*%
+%MOMM*%
+%ADD10C,1.00000*%
+G01*
+%LPD*%
+G36*
+X0Y50000D02*
+Y100000D01*
+X100000D01*
+Y0D01*
+X0D01*
+Y50000D01*
+G04 first fully coincident linear segment*
+X-10000D01*
+X-50000Y10000D01*
+X-90000Y50000D01*
+X-50000Y90000D01*
+X-10000Y50000D01*
+G04 second fully coincident linear segment*
+X0D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_holes_dont_clear.gbr b/gerber/tests/resources/example_holes_dont_clear.gbr
new file mode 100644
index 0000000..deeebd0
--- /dev/null
+++ b/gerber/tests/resources/example_holes_dont_clear.gbr
@@ -0,0 +1,13 @@
+G04 Demonstrates that apertures with holes do not clear the area - only the aperture hole*
+%FSLAX26Y26*%
+%MOIN*%
+%ADD10C,1X0.5*%
+%ADD11C,0.1*%
+G01*
+%LPD*%
+D11*
+X-1000000Y-250000D02*
+X1000000Y250000D01*
+D10*
+X0Y0D03*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_level_holes.gbr b/gerber/tests/resources/example_level_holes.gbr
new file mode 100644
index 0000000..1b4e189
--- /dev/null
+++ b/gerber/tests/resources/example_level_holes.gbr
@@ -0,0 +1,39 @@
+G04 This file illustrates how to use levels to create holes*
+%FSLAX25Y25*%
+%MOMM*%
+G01*
+G04 First level: big square - dark polarity*
+%LPD*%
+G36*
+X250000Y250000D02*
+X1750000D01*
+Y1750000D01*
+X250000D01*
+Y250000D01*
+G37*
+G04 Second level: big circle - clear polarity*
+%LPC*%
+G36*
+G75*
+X500000Y1000000D02*
+G03*
+X500000Y1000000I500000J0D01*
+G37*
+G04 Third level: small square - dark polarity*
+%LPD*%
+G36*
+X750000Y750000D02*
+X1250000D01*
+Y1250000D01*
+X750000D01*
+Y750000D01*
+G37*
+G04 Fourth level: small circle - clear polarity*
+%LPC*%
+G36*
+G75*
+X1150000Y1000000D02*
+G03*
+X1150000Y1000000I250000J0D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_not_overlapping_contour.gbr b/gerber/tests/resources/example_not_overlapping_contour.gbr
new file mode 100644
index 0000000..e3ea631
--- /dev/null
+++ b/gerber/tests/resources/example_not_overlapping_contour.gbr
@@ -0,0 +1,20 @@
+G04 Non-overlapping contours*
+%FSLAX24Y24*%
+%MOMM*%
+%ADD10C,1.00000*%
+G01*
+%LPD*%
+G36*
+X0Y50000D02*
+Y100000D01*
+X100000D01*
+Y0D01*
+X0D01*
+Y50000D01*
+X-10000D02*
+X-50000Y10000D01*
+X-90000Y50000D01*
+X-50000Y90000D01*
+X-10000Y50000D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_not_overlapping_touching.gbr b/gerber/tests/resources/example_not_overlapping_touching.gbr
new file mode 100644
index 0000000..3b9b955
--- /dev/null
+++ b/gerber/tests/resources/example_not_overlapping_touching.gbr
@@ -0,0 +1,20 @@
+G04 Non-overlapping and touching*
+%FSLAX24Y24*%
+%MOMM*%
+%ADD10C,1.00000*%
+G01*
+%LPD*%
+G36*
+X0Y50000D02*
+Y100000D01*
+X100000D01*
+Y0D01*
+X0D01*
+Y50000D01*
+D02*
+X-50000Y10000D01*
+X-90000Y50000D01*
+X-50000Y90000D01*
+X0Y50000D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_overlapping_contour.gbr b/gerber/tests/resources/example_overlapping_contour.gbr
new file mode 100644
index 0000000..74886a2
--- /dev/null
+++ b/gerber/tests/resources/example_overlapping_contour.gbr
@@ -0,0 +1,20 @@
+G04 Overlapping contours*
+%FSLAX24Y24*%
+%MOMM*%
+%ADD10C,1.00000*%
+G01*
+%LPD*%
+G36*
+X0Y50000D02*
+Y100000D01*
+X100000D01*
+Y0D01*
+X0D01*
+Y50000D01*
+X10000D02*
+X50000Y10000D01*
+X90000Y50000D01*
+X50000Y90000D01*
+X10000Y50000D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_overlapping_touching.gbr b/gerber/tests/resources/example_overlapping_touching.gbr
new file mode 100644
index 0000000..27fce15
--- /dev/null
+++ b/gerber/tests/resources/example_overlapping_touching.gbr
@@ -0,0 +1,20 @@
+G04 Overlapping and touching*
+%FSLAX24Y24*%
+%MOMM*%
+%ADD10C,1.00000*%
+G01*
+%LPD*%
+G36*
+X0Y50000D02*
+Y100000D01*
+X100000D01*
+Y0D01*
+X0D01*
+Y50000D01*
+D02*
+X50000Y10000D01*
+X90000Y50000D01*
+X50000Y90000D01*
+X0Y50000D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_simple_contour.gbr b/gerber/tests/resources/example_simple_contour.gbr
new file mode 100644
index 0000000..d851760
--- /dev/null
+++ b/gerber/tests/resources/example_simple_contour.gbr
@@ -0,0 +1,16 @@
+G04 Ucamco ex. 4.6.4: Simple contour*
+%FSLAX25Y25*%
+%MOIN*%
+%ADD10C,0.010*%
+G36*
+X200000Y300000D02*
+G01*
+X700000D01*
+Y100000D01*
+X1100000Y500000D01*
+X700000Y900000D01*
+Y700000D01*
+X200000D01*
+Y300000D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_single_contour_1.gbr b/gerber/tests/resources/example_single_contour_1.gbr
new file mode 100644
index 0000000..e9f9a75
--- /dev/null
+++ b/gerber/tests/resources/example_single_contour_1.gbr
@@ -0,0 +1,15 @@
+G04 Ucamco ex. 4.6.5: Single contour #1*
+%FSLAX25Y25*%
+%MOMM*%
+%ADD11C,0.01*%
+G01*
+D11*
+X3000Y5000D01*
+G36*
+X50000Y50000D02*
+X60000D01*
+Y60000D01*
+X50000D01*
+Y50000Y50000D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_single_contour_2.gbr b/gerber/tests/resources/example_single_contour_2.gbr
new file mode 100644
index 0000000..085c72c
--- /dev/null
+++ b/gerber/tests/resources/example_single_contour_2.gbr
@@ -0,0 +1,15 @@
+G04 Ucamco ex. 4.6.5: Single contour #2*
+%FSLAX25Y25*%
+%MOMM*%
+%ADD11C,0.01*%
+G01*
+D11*
+X3000Y5000D01*
+X50000Y50000D02*
+G36*
+X60000D01*
+Y60000D01*
+X50000D01*
+Y50000Y50000D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_single_contour_3.gbr b/gerber/tests/resources/example_single_contour_3.gbr
new file mode 100644
index 0000000..40de149
--- /dev/null
+++ b/gerber/tests/resources/example_single_contour_3.gbr
@@ -0,0 +1,15 @@
+G04 Ucamco ex. 4.6.5: Single contour #2*
+%FSLAX25Y25*%
+%MOMM*%
+%ADD11C,0.01*%
+G01*
+D11*
+X3000Y5000D01*
+X50000Y50000D01*
+G36*
+X60000D01*
+Y60000D01*
+X50000D01*
+Y50000Y50000D01*
+G37*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_single_quadrant.gbr b/gerber/tests/resources/example_single_quadrant.gbr
new file mode 100644
index 0000000..c398601
--- /dev/null
+++ b/gerber/tests/resources/example_single_quadrant.gbr
@@ -0,0 +1,18 @@
+G04 Ucamco ex. 4.5.8: Single quadrant*
+%FSLAX23Y23*%
+%MOIN*%
+%ADD10C,0.010*%
+G74*
+D10*
+X1100Y600D02*
+G03*
+X700Y1000I400J0D01*
+X300Y600I0J400D01*
+X700Y200I400J0D01*
+X1100Y600I0J400D01*
+X300D02*
+G01*
+X1100D01*
+X700Y200D02*
+Y1000D01*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/example_two_square_boxes.gbr b/gerber/tests/resources/example_two_square_boxes.gbr
new file mode 100644
index 0000000..54a8ac1
--- /dev/null
+++ b/gerber/tests/resources/example_two_square_boxes.gbr
@@ -0,0 +1,19 @@
+G04 Ucamco ex. 1: Two square boxes*
+%FSLAX25Y25*%
+%MOMM*%
+%TF.Part,Other*%
+%LPD*%
+%ADD10C,0.010*%
+D10*
+X0Y0D02*
+G01*
+X500000Y0D01*
+Y500000D01*
+X0D01*
+Y0D01*
+X600000D02*
+X1100000D01*
+Y500000D01*
+X600000D01*
+Y0D01*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/ipc-d-356.ipc b/gerber/tests/resources/ipc-d-356.ipc
new file mode 100644
index 0000000..2ed3f49
--- /dev/null
+++ b/gerber/tests/resources/ipc-d-356.ipc
@@ -0,0 +1,115 @@
+C IPC-D-356 generated by EAGLE Version 7.1.0 Copyright (c) 1988-2014 CadSoft
+C Database /Some/Path/To/File
+C
+P JOB EAGLE 7.1 NETLIST, DATE: 2/20/15 12:00 AM
+P UNITS CUST 0
+P DIM N
+P NNAME1 A_REALLY_LONG_NET_NAME
+317GND VIA D 24PA00X 14900Y 1450X 396Y 396
+317GND VIA D 24PA00X 3850Y 8500X 396Y 396
+317GND VIA D 24PA00X 6200Y 10650X 396Y 396
+317GND VIA D 24PA00X 8950Y 1000X 396Y 396
+317GND VIA D 24PA00X 11800Y 2250X 396Y 396
+317GND VIA D 24PA00X 15350Y 3200X 396Y 396
+317GND VIA D 24PA00X 13200Y 3800X 396Y 396
+317GND VIA D 24PA00X 9700Y 12050X 396Y 396
+317GND VIA D 24PA00X 13950Y 11900X 396Y 396
+317GND VIA D 24PA00X 13050Y 7050X 396Y 396
+317GND VIA D 24PA00X 13000Y 8400X 396Y 396
+317N$3 VIA D 24PA00X 11350Y 10100X 396Y 396
+317N$3 VIA D 24PA00X 13250Y 5700X 396Y 396
+317VCC VIA D 24PA00X 15550Y 6850X 396Y 396
+327N$3 C1 -+ A01X 9700Y 10402X1575Y 630R270
+327GND C1 -- A01X 9700Y 13198X1575Y 630R270
+327VCC C2 -+ A01X 13950Y 9677X1535Y 630R270
+327GND C2 -- A01X 13950Y 13023X1535Y 630R270
+327VCC C3 -1 A01X 3850Y 9924X 512Y 591R270
+327GND C3 -2 A01X 3850Y 9176X 512Y 591R270
+327VCC C4 -1 A01X 10374Y 1000X 512Y 591R180
+327GND C4 -2 A01X 9626Y 1000X 512Y 591R180
+327VCC C5 -1 A01X 14700Y 3924X 512Y 591R270
+327GND C5 -2 A01X 14700Y 3176X 512Y 591R270
+317DMX+ DMX -1 D 40PA00X 5050Y 13900X 600Y1200R 90
+317DMX- DMX -2 D 40PA00X 6050Y 13900X 600Y1200R 90
+317GND DMX -3 D 40PA00X 7050Y 13900X 600Y1200R 90
+317PIC_MCLR J1 -1 D 35PA00X 16900Y 6400X 554Y 554R 90
+317VCC J1 -2 D 35PA00X 17900Y 6900X 554Y 554R 90
+317GND J1 -3 D 35PA00X 16900Y 7400X 554Y 554R 90
+317PIC_PGD J1 -4 D 35PA00X 17900Y 7900X 554Y 554R 90
+317PIC_PGC J1 -5 D 35PA00X 16900Y 8400X 554Y 554R 90
+317 J1 -6 D 35PA00X 17900Y 8900X 554Y 554R 90
+327N$4 L1 -1 A01X 13950Y 6382X 748Y1339R 90
+327VCC L1 -2 A01X 13950Y 7918X 748Y1339R 90
+327N$5 LED1 -A A01X 16313Y 1450X 472Y 472R 0
+327GND LED1 -C A01X 15487Y 1450X 472Y 472R 0
+317 MIDI -1 D 40PA00X 1200Y 9500X 600Y1200R 0
+317 MIDI -2 D 40PA00X 1200Y 8500X 600Y1200R 0
+317 MIDI -3 D 40PA00X 1200Y 7500X 600Y1200R 0
+317N$9 MIDI -4 D 40PA00X 1200Y 6500X 600Y1200R 0
+317N$10 MIDI -5 D 40PA00X 1200Y 5500X 600Y1200R 0
+317N$3 PWR -1 D 40PA00X 17050Y 13750X 600Y1200R 90
+317GND PWR -2 D 40PA00X 18050Y 13750X 600Y1200R 90
+327DMX+ R1 -1 A01X 5076Y 11500X 512Y 591R 0
+327DMX- R1 -2 A01X 5824Y 11500X 512Y 591R 0
+327VCC R2 -1 A01X 14376Y 5300X 512Y 591R 0
+327PIC_MCLR R2 -2 A01X 15124Y 5300X 512Y 591R 0
+327N$9 R3 -1 A01X 3126Y 6500X 512Y 591R 0
+327N$6 R3 -2 A01X 3874Y 6500X 512Y 591R 0
+327PIC_RX R4 -1 A01X 9600Y 2624X 512Y 591R270
+327VCC R4 -2 A01X 9600Y 1876X 512Y 591R270
+327VCC R5 -1 A01X 17974Y 1450X 512Y 591R180
+327N$5 R5 -2 A01X 17226Y 1450X 512Y 591R180
+327N$3 U1 -1 A01X 12330Y 5710X 420Y 850R 90
+327N$4 U1 -2 A01X 12330Y 6380X 420Y 850R 90
+327GND U1 -3 A01X 12330Y 7050X 420Y 850R 90
+327VCC U1 -4 A01X 12330Y 7720X 420Y 850R 90
+327GND U1 -5 A01X 12330Y 8390X 420Y 850R 90
+327 U1 -6 A01X 9050Y 7050X4252Y4098R 90
+327PIC_MCLR U2 -1 A01X 11123Y 4063X 157Y 591R270
+327 U2 -2 A01X 11123Y 3807X 157Y 591R270
+327 U2 -3 A01X 11123Y 3552X 157Y 591R270
+327N$1 U2 -4 A01X 11123Y 3296X 157Y 591R270
+327N$2 U2 -5 A01X 11123Y 3040X 157Y 591R270
+327PIC_RX U2 -6 A01X 11123Y 2784X 157Y 591R270
+327 U2 -7 A01X 11123Y 2528X 157Y 591R270
+327GND U2 -8 A01X 11123Y 2272X 157Y 591R270
+327 U2 -9 A01X 11123Y 2016X 157Y 591R270
+327 U2 -10 A01X 11123Y 1760X 157Y 591R270
+327 U2 -11 A01X 11123Y 1504X 157Y 591R270
+327 U2 -12 A01X 11123Y 1248X 157Y 591R270
+327VCC U2 -13 A01X 11123Y 993X 157Y 591R270
+327 U2 -14 A01X 11123Y 737X 157Y 591R270
+327 U2 -15 A01X 13977Y 737X 157Y 591R270
+327 U2 -16 A01X 13977Y 993X 157Y 591R270
+327 U2 -17 A01X 13977Y 1248X 157Y 591R270
+327 U2 -18 A01X 13977Y 1504X 157Y 591R270
+327 U2 -19 A01X 13977Y 1760X 157Y 591R270
+327 U2 -20 A01X 13977Y 2016X 157Y 591R270
+327PIC_PGD U2 -21 A01X 13977Y 2272X 157Y 591R270
+327PIC_PGC U2 -22 A01X 13977Y 2528X 157Y 591R270
+327 U2 -23 A01X 13977Y 2784X 157Y 591R270
+327 U2 -24 A01X 13977Y 3040X 157Y 591R270
+327 U2 -25 A01X 13977Y 3296X 157Y 591R270
+327 U2 -26 A01X 13977Y 3552X 157Y 591R270
+327GND U2 -27 A01X 13977Y 3807X 157Y 591R270
+327VCC U2 -28 A01X 13977Y 4063X 157Y 591R270
+327N$2 U3 -1 A01X 4700Y 7540X 260Y 800R 0
+327VCC U3 -2 A01X 5200Y 7540X 260Y 800R 0
+327VCC U3 -3 A01X 5700Y 7540X 260Y 800R 0
+327N$1 U3 -4 A01X 6200Y 7540X 260Y 800R 0
+327GND U3 -5 A01X 6200Y 9960X 260Y 800R 0
+327DMX- U3 -6 A01X 5700Y 9960X 260Y 800R 0
+327DMX+ U3 -7 A01X 5200Y 9960X 260Y 800R 0
+327VCC U3 -8 A01X 4700Y 9960X 260Y 800R 0
+327 U4 -1 A01X 4704Y 3850X 394Y 500R 0
+327N$6 U4 -2 A01X 4704Y 2800X 394Y 500R 0
+327N$10 U4 -3 A01X 4704Y 1800X 394Y 500R 0
+327 U4 -4 A01X 4704Y 750X 394Y 500R 0
+327GND U4 -5 A01X 8396Y 750X 394Y 500R 0
+327PIC_RX U4 -6 A01X 8396Y 1800X 394Y 500R 0
+327 U4 -7 A01X 8396Y 2800X 394Y 500R 0
+327VCC U4 -8 A01X 8396Y 3850X 394Y 500R 0
+327NNAME1 NA -69 A01X 8396Y 3850X 394Y 500R 0
+389BOARD_EDGE X0Y0 X22500 Y15000 X0
+089 X1300Y240
+999
diff --git a/gerber/tests/resources/multiline_read.ger b/gerber/tests/resources/multiline_read.ger
new file mode 100644
index 0000000..02242e4
--- /dev/null
+++ b/gerber/tests/resources/multiline_read.ger
@@ -0,0 +1,9 @@
+G75*
+G71*
+%OFA0B0*%
+%FSLAX23Y23*%
+%IPPOS*%
+%LPD*%
+%ADD10C,0.1*%
+%LPD*%D10*
+M02* \ No newline at end of file
diff --git a/gerber/tests/resources/top_copper.GTL b/gerber/tests/resources/top_copper.GTL
index cedd2fd..d53f5ec 100644
--- a/gerber/tests/resources/top_copper.GTL
+++ b/gerber/tests/resources/top_copper.GTL
@@ -1,3457 +1 @@
-G75*
-%MOIN*%
-%OFA0B0*%
-%FSLAX24Y24*%
-%IPPOS*%
-%LPD*%
-%AMOC8*
-5,1,8,0,0,1.08239X$1,22.5*
-%
-%ADD10C,0.0000*%
-%ADD11R,0.0260X0.0800*%
-%ADD12R,0.0591X0.0157*%
-%ADD13R,0.4098X0.4252*%
-%ADD14R,0.0850X0.0420*%
-%ADD15R,0.0630X0.1575*%
-%ADD16R,0.0591X0.0512*%
-%ADD17R,0.0512X0.0591*%
-%ADD18R,0.0630X0.1535*%
-%ADD19R,0.1339X0.0748*%
-%ADD20C,0.0004*%
-%ADD21C,0.0554*%
-%ADD22R,0.0394X0.0500*%
-%ADD23C,0.0600*%
-%ADD24R,0.0472X0.0472*%
-%ADD25C,0.0160*%
-%ADD26C,0.0396*%
-%ADD27C,0.0240*%
-D10*
-X000300Y003064D02*
-X000300Y018064D01*
-X022800Y018064D01*
-X022800Y003064D01*
-X000300Y003064D01*
-X001720Y005114D02*
-X001722Y005164D01*
-X001728Y005214D01*
-X001738Y005263D01*
-X001752Y005311D01*
-X001769Y005358D01*
-X001790Y005403D01*
-X001815Y005447D01*
-X001843Y005488D01*
-X001875Y005527D01*
-X001909Y005564D01*
-X001946Y005598D01*
-X001986Y005628D01*
-X002028Y005655D01*
-X002072Y005679D01*
-X002118Y005700D01*
-X002165Y005716D01*
-X002213Y005729D01*
-X002263Y005738D01*
-X002312Y005743D01*
-X002363Y005744D01*
-X002413Y005741D01*
-X002462Y005734D01*
-X002511Y005723D01*
-X002559Y005708D01*
-X002605Y005690D01*
-X002650Y005668D01*
-X002693Y005642D01*
-X002734Y005613D01*
-X002773Y005581D01*
-X002809Y005546D01*
-X002841Y005508D01*
-X002871Y005468D01*
-X002898Y005425D01*
-X002921Y005381D01*
-X002940Y005335D01*
-X002956Y005287D01*
-X002968Y005238D01*
-X002976Y005189D01*
-X002980Y005139D01*
-X002980Y005089D01*
-X002976Y005039D01*
-X002968Y004990D01*
-X002956Y004941D01*
-X002940Y004893D01*
-X002921Y004847D01*
-X002898Y004803D01*
-X002871Y004760D01*
-X002841Y004720D01*
-X002809Y004682D01*
-X002773Y004647D01*
-X002734Y004615D01*
-X002693Y004586D01*
-X002650Y004560D01*
-X002605Y004538D01*
-X002559Y004520D01*
-X002511Y004505D01*
-X002462Y004494D01*
-X002413Y004487D01*
-X002363Y004484D01*
-X002312Y004485D01*
-X002263Y004490D01*
-X002213Y004499D01*
-X002165Y004512D01*
-X002118Y004528D01*
-X002072Y004549D01*
-X002028Y004573D01*
-X001986Y004600D01*
-X001946Y004630D01*
-X001909Y004664D01*
-X001875Y004701D01*
-X001843Y004740D01*
-X001815Y004781D01*
-X001790Y004825D01*
-X001769Y004870D01*
-X001752Y004917D01*
-X001738Y004965D01*
-X001728Y005014D01*
-X001722Y005064D01*
-X001720Y005114D01*
-X001670Y016064D02*
-X001672Y016114D01*
-X001678Y016164D01*
-X001688Y016213D01*
-X001702Y016261D01*
-X001719Y016308D01*
-X001740Y016353D01*
-X001765Y016397D01*
-X001793Y016438D01*
-X001825Y016477D01*
-X001859Y016514D01*
-X001896Y016548D01*
-X001936Y016578D01*
-X001978Y016605D01*
-X002022Y016629D01*
-X002068Y016650D01*
-X002115Y016666D01*
-X002163Y016679D01*
-X002213Y016688D01*
-X002262Y016693D01*
-X002313Y016694D01*
-X002363Y016691D01*
-X002412Y016684D01*
-X002461Y016673D01*
-X002509Y016658D01*
-X002555Y016640D01*
-X002600Y016618D01*
-X002643Y016592D01*
-X002684Y016563D01*
-X002723Y016531D01*
-X002759Y016496D01*
-X002791Y016458D01*
-X002821Y016418D01*
-X002848Y016375D01*
-X002871Y016331D01*
-X002890Y016285D01*
-X002906Y016237D01*
-X002918Y016188D01*
-X002926Y016139D01*
-X002930Y016089D01*
-X002930Y016039D01*
-X002926Y015989D01*
-X002918Y015940D01*
-X002906Y015891D01*
-X002890Y015843D01*
-X002871Y015797D01*
-X002848Y015753D01*
-X002821Y015710D01*
-X002791Y015670D01*
-X002759Y015632D01*
-X002723Y015597D01*
-X002684Y015565D01*
-X002643Y015536D01*
-X002600Y015510D01*
-X002555Y015488D01*
-X002509Y015470D01*
-X002461Y015455D01*
-X002412Y015444D01*
-X002363Y015437D01*
-X002313Y015434D01*
-X002262Y015435D01*
-X002213Y015440D01*
-X002163Y015449D01*
-X002115Y015462D01*
-X002068Y015478D01*
-X002022Y015499D01*
-X001978Y015523D01*
-X001936Y015550D01*
-X001896Y015580D01*
-X001859Y015614D01*
-X001825Y015651D01*
-X001793Y015690D01*
-X001765Y015731D01*
-X001740Y015775D01*
-X001719Y015820D01*
-X001702Y015867D01*
-X001688Y015915D01*
-X001678Y015964D01*
-X001672Y016014D01*
-X001670Y016064D01*
-X020060Y012714D02*
-X020062Y012764D01*
-X020068Y012814D01*
-X020078Y012863D01*
-X020091Y012912D01*
-X020109Y012959D01*
-X020130Y013005D01*
-X020154Y013048D01*
-X020182Y013090D01*
-X020213Y013130D01*
-X020247Y013167D01*
-X020284Y013201D01*
-X020324Y013232D01*
-X020366Y013260D01*
-X020409Y013284D01*
-X020455Y013305D01*
-X020502Y013323D01*
-X020551Y013336D01*
-X020600Y013346D01*
-X020650Y013352D01*
-X020700Y013354D01*
-X020750Y013352D01*
-X020800Y013346D01*
-X020849Y013336D01*
-X020898Y013323D01*
-X020945Y013305D01*
-X020991Y013284D01*
-X021034Y013260D01*
-X021076Y013232D01*
-X021116Y013201D01*
-X021153Y013167D01*
-X021187Y013130D01*
-X021218Y013090D01*
-X021246Y013048D01*
-X021270Y013005D01*
-X021291Y012959D01*
-X021309Y012912D01*
-X021322Y012863D01*
-X021332Y012814D01*
-X021338Y012764D01*
-X021340Y012714D01*
-X021338Y012664D01*
-X021332Y012614D01*
-X021322Y012565D01*
-X021309Y012516D01*
-X021291Y012469D01*
-X021270Y012423D01*
-X021246Y012380D01*
-X021218Y012338D01*
-X021187Y012298D01*
-X021153Y012261D01*
-X021116Y012227D01*
-X021076Y012196D01*
-X021034Y012168D01*
-X020991Y012144D01*
-X020945Y012123D01*
-X020898Y012105D01*
-X020849Y012092D01*
-X020800Y012082D01*
-X020750Y012076D01*
-X020700Y012074D01*
-X020650Y012076D01*
-X020600Y012082D01*
-X020551Y012092D01*
-X020502Y012105D01*
-X020455Y012123D01*
-X020409Y012144D01*
-X020366Y012168D01*
-X020324Y012196D01*
-X020284Y012227D01*
-X020247Y012261D01*
-X020213Y012298D01*
-X020182Y012338D01*
-X020154Y012380D01*
-X020130Y012423D01*
-X020109Y012469D01*
-X020091Y012516D01*
-X020078Y012565D01*
-X020068Y012614D01*
-X020062Y012664D01*
-X020060Y012714D01*
-X020170Y016064D02*
-X020172Y016114D01*
-X020178Y016164D01*
-X020188Y016213D01*
-X020202Y016261D01*
-X020219Y016308D01*
-X020240Y016353D01*
-X020265Y016397D01*
-X020293Y016438D01*
-X020325Y016477D01*
-X020359Y016514D01*
-X020396Y016548D01*
-X020436Y016578D01*
-X020478Y016605D01*
-X020522Y016629D01*
-X020568Y016650D01*
-X020615Y016666D01*
-X020663Y016679D01*
-X020713Y016688D01*
-X020762Y016693D01*
-X020813Y016694D01*
-X020863Y016691D01*
-X020912Y016684D01*
-X020961Y016673D01*
-X021009Y016658D01*
-X021055Y016640D01*
-X021100Y016618D01*
-X021143Y016592D01*
-X021184Y016563D01*
-X021223Y016531D01*
-X021259Y016496D01*
-X021291Y016458D01*
-X021321Y016418D01*
-X021348Y016375D01*
-X021371Y016331D01*
-X021390Y016285D01*
-X021406Y016237D01*
-X021418Y016188D01*
-X021426Y016139D01*
-X021430Y016089D01*
-X021430Y016039D01*
-X021426Y015989D01*
-X021418Y015940D01*
-X021406Y015891D01*
-X021390Y015843D01*
-X021371Y015797D01*
-X021348Y015753D01*
-X021321Y015710D01*
-X021291Y015670D01*
-X021259Y015632D01*
-X021223Y015597D01*
-X021184Y015565D01*
-X021143Y015536D01*
-X021100Y015510D01*
-X021055Y015488D01*
-X021009Y015470D01*
-X020961Y015455D01*
-X020912Y015444D01*
-X020863Y015437D01*
-X020813Y015434D01*
-X020762Y015435D01*
-X020713Y015440D01*
-X020663Y015449D01*
-X020615Y015462D01*
-X020568Y015478D01*
-X020522Y015499D01*
-X020478Y015523D01*
-X020436Y015550D01*
-X020396Y015580D01*
-X020359Y015614D01*
-X020325Y015651D01*
-X020293Y015690D01*
-X020265Y015731D01*
-X020240Y015775D01*
-X020219Y015820D01*
-X020202Y015867D01*
-X020188Y015915D01*
-X020178Y015964D01*
-X020172Y016014D01*
-X020170Y016064D01*
-X020060Y008714D02*
-X020062Y008764D01*
-X020068Y008814D01*
-X020078Y008863D01*
-X020091Y008912D01*
-X020109Y008959D01*
-X020130Y009005D01*
-X020154Y009048D01*
-X020182Y009090D01*
-X020213Y009130D01*
-X020247Y009167D01*
-X020284Y009201D01*
-X020324Y009232D01*
-X020366Y009260D01*
-X020409Y009284D01*
-X020455Y009305D01*
-X020502Y009323D01*
-X020551Y009336D01*
-X020600Y009346D01*
-X020650Y009352D01*
-X020700Y009354D01*
-X020750Y009352D01*
-X020800Y009346D01*
-X020849Y009336D01*
-X020898Y009323D01*
-X020945Y009305D01*
-X020991Y009284D01*
-X021034Y009260D01*
-X021076Y009232D01*
-X021116Y009201D01*
-X021153Y009167D01*
-X021187Y009130D01*
-X021218Y009090D01*
-X021246Y009048D01*
-X021270Y009005D01*
-X021291Y008959D01*
-X021309Y008912D01*
-X021322Y008863D01*
-X021332Y008814D01*
-X021338Y008764D01*
-X021340Y008714D01*
-X021338Y008664D01*
-X021332Y008614D01*
-X021322Y008565D01*
-X021309Y008516D01*
-X021291Y008469D01*
-X021270Y008423D01*
-X021246Y008380D01*
-X021218Y008338D01*
-X021187Y008298D01*
-X021153Y008261D01*
-X021116Y008227D01*
-X021076Y008196D01*
-X021034Y008168D01*
-X020991Y008144D01*
-X020945Y008123D01*
-X020898Y008105D01*
-X020849Y008092D01*
-X020800Y008082D01*
-X020750Y008076D01*
-X020700Y008074D01*
-X020650Y008076D01*
-X020600Y008082D01*
-X020551Y008092D01*
-X020502Y008105D01*
-X020455Y008123D01*
-X020409Y008144D01*
-X020366Y008168D01*
-X020324Y008196D01*
-X020284Y008227D01*
-X020247Y008261D01*
-X020213Y008298D01*
-X020182Y008338D01*
-X020154Y008380D01*
-X020130Y008423D01*
-X020109Y008469D01*
-X020091Y008516D01*
-X020078Y008565D01*
-X020068Y008614D01*
-X020062Y008664D01*
-X020060Y008714D01*
-X020170Y005064D02*
-X020172Y005114D01*
-X020178Y005164D01*
-X020188Y005213D01*
-X020202Y005261D01*
-X020219Y005308D01*
-X020240Y005353D01*
-X020265Y005397D01*
-X020293Y005438D01*
-X020325Y005477D01*
-X020359Y005514D01*
-X020396Y005548D01*
-X020436Y005578D01*
-X020478Y005605D01*
-X020522Y005629D01*
-X020568Y005650D01*
-X020615Y005666D01*
-X020663Y005679D01*
-X020713Y005688D01*
-X020762Y005693D01*
-X020813Y005694D01*
-X020863Y005691D01*
-X020912Y005684D01*
-X020961Y005673D01*
-X021009Y005658D01*
-X021055Y005640D01*
-X021100Y005618D01*
-X021143Y005592D01*
-X021184Y005563D01*
-X021223Y005531D01*
-X021259Y005496D01*
-X021291Y005458D01*
-X021321Y005418D01*
-X021348Y005375D01*
-X021371Y005331D01*
-X021390Y005285D01*
-X021406Y005237D01*
-X021418Y005188D01*
-X021426Y005139D01*
-X021430Y005089D01*
-X021430Y005039D01*
-X021426Y004989D01*
-X021418Y004940D01*
-X021406Y004891D01*
-X021390Y004843D01*
-X021371Y004797D01*
-X021348Y004753D01*
-X021321Y004710D01*
-X021291Y004670D01*
-X021259Y004632D01*
-X021223Y004597D01*
-X021184Y004565D01*
-X021143Y004536D01*
-X021100Y004510D01*
-X021055Y004488D01*
-X021009Y004470D01*
-X020961Y004455D01*
-X020912Y004444D01*
-X020863Y004437D01*
-X020813Y004434D01*
-X020762Y004435D01*
-X020713Y004440D01*
-X020663Y004449D01*
-X020615Y004462D01*
-X020568Y004478D01*
-X020522Y004499D01*
-X020478Y004523D01*
-X020436Y004550D01*
-X020396Y004580D01*
-X020359Y004614D01*
-X020325Y004651D01*
-X020293Y004690D01*
-X020265Y004731D01*
-X020240Y004775D01*
-X020219Y004820D01*
-X020202Y004867D01*
-X020188Y004915D01*
-X020178Y004964D01*
-X020172Y005014D01*
-X020170Y005064D01*
-D11*
-X006500Y010604D03*
-X006000Y010604D03*
-X005500Y010604D03*
-X005000Y010604D03*
-X005000Y013024D03*
-X005500Y013024D03*
-X006000Y013024D03*
-X006500Y013024D03*
-D12*
-X011423Y007128D03*
-X011423Y006872D03*
-X011423Y006616D03*
-X011423Y006360D03*
-X011423Y006104D03*
-X011423Y005848D03*
-X011423Y005592D03*
-X011423Y005336D03*
-X011423Y005080D03*
-X011423Y004825D03*
-X011423Y004569D03*
-X011423Y004313D03*
-X011423Y004057D03*
-X011423Y003801D03*
-X014277Y003801D03*
-X014277Y004057D03*
-X014277Y004313D03*
-X014277Y004569D03*
-X014277Y004825D03*
-X014277Y005080D03*
-X014277Y005336D03*
-X014277Y005592D03*
-X014277Y005848D03*
-X014277Y006104D03*
-X014277Y006360D03*
-X014277Y006616D03*
-X014277Y006872D03*
-X014277Y007128D03*
-D13*
-X009350Y010114D03*
-D14*
-X012630Y010114D03*
-X012630Y010784D03*
-X012630Y011454D03*
-X012630Y009444D03*
-X012630Y008774D03*
-D15*
-X010000Y013467D03*
-X010000Y016262D03*
-D16*
-X004150Y012988D03*
-X004150Y012240D03*
-X009900Y005688D03*
-X009900Y004940D03*
-X015000Y006240D03*
-X015000Y006988D03*
-D17*
-X014676Y008364D03*
-X015424Y008364D03*
-X017526Y004514D03*
-X018274Y004514D03*
-X010674Y004064D03*
-X009926Y004064D03*
-X004174Y009564D03*
-X003426Y009564D03*
-X005376Y014564D03*
-X006124Y014564D03*
-D18*
-X014250Y016088D03*
-X014250Y012741D03*
-D19*
-X014250Y010982D03*
-X014250Y009447D03*
-D20*
-X022869Y007639D02*
-X022869Y013789D01*
-D21*
-X018200Y011964D03*
-X017200Y011464D03*
-X017200Y010464D03*
-X018200Y009964D03*
-X018200Y010964D03*
-X017200Y009464D03*
-D22*
-X008696Y006914D03*
-X008696Y005864D03*
-X008696Y004864D03*
-X008696Y003814D03*
-X005004Y003814D03*
-X005004Y004864D03*
-X005004Y005864D03*
-X005004Y006914D03*
-D23*
-X001800Y008564D02*
-X001200Y008564D01*
-X001200Y009564D02*
-X001800Y009564D01*
-X001800Y010564D02*
-X001200Y010564D01*
-X001200Y011564D02*
-X001800Y011564D01*
-X001800Y012564D02*
-X001200Y012564D01*
-X005350Y016664D02*
-X005350Y017264D01*
-X006350Y017264D02*
-X006350Y016664D01*
-X007350Y016664D02*
-X007350Y017264D01*
-X017350Y017114D02*
-X017350Y016514D01*
-X018350Y016514D02*
-X018350Y017114D01*
-D24*
-X016613Y004514D03*
-X015787Y004514D03*
-D25*
-X015200Y004514D01*
-X014868Y004649D02*
-X014732Y004649D01*
-X014842Y004586D02*
-X014842Y004443D01*
-X014896Y004311D01*
-X014997Y004211D01*
-X015129Y004156D01*
-X015271Y004156D01*
-X015395Y004207D01*
-X015484Y004118D01*
-X016089Y004118D01*
-X016183Y004212D01*
-X016183Y004817D01*
-X016089Y004911D01*
-X015484Y004911D01*
-X015395Y004821D01*
-X015271Y004872D01*
-X015129Y004872D01*
-X014997Y004818D01*
-X014896Y004717D01*
-X014842Y004586D01*
-X014842Y004491D02*
-X014732Y004491D01*
-X014732Y004332D02*
-X014888Y004332D01*
-X014732Y004174D02*
-X015086Y004174D01*
-X015314Y004174D02*
-X015428Y004174D01*
-X014732Y004015D02*
-X019505Y004015D01*
-X019568Y003922D02*
-X019568Y003922D01*
-X019568Y003922D01*
-X019286Y004335D01*
-X019286Y004335D01*
-X019139Y004814D01*
-X019139Y005315D01*
-X019286Y005793D01*
-X019286Y005793D01*
-X019568Y006207D01*
-X019568Y006207D01*
-X019960Y006519D01*
-X019960Y006519D01*
-X020426Y006702D01*
-X020926Y006740D01*
-X020926Y006740D01*
-X021414Y006628D01*
-X021414Y006628D01*
-X021847Y006378D01*
-X021847Y006378D01*
-X022188Y006011D01*
-X022188Y006011D01*
-X022320Y005737D01*
-X022320Y015392D01*
-X022188Y015118D01*
-X022188Y015118D01*
-X021847Y014751D01*
-X021847Y014751D01*
-X021414Y014500D01*
-X021414Y014500D01*
-X020926Y014389D01*
-X020926Y014389D01*
-X020426Y014426D01*
-X020426Y014426D01*
-X019960Y014609D01*
-X019960Y014609D01*
-X019568Y014922D01*
-X019568Y014922D01*
-X019568Y014922D01*
-X019286Y015335D01*
-X019286Y015335D01*
-X019139Y015814D01*
-X019139Y016315D01*
-X019286Y016793D01*
-X019286Y016793D01*
-X019568Y017207D01*
-X019568Y017207D01*
-X019568Y017207D01*
-X019960Y017519D01*
-X019960Y017519D01*
-X020126Y017584D01*
-X016626Y017584D01*
-X016637Y017573D01*
-X016924Y017287D01*
-X016960Y017375D01*
-X017089Y017504D01*
-X017258Y017574D01*
-X017441Y017574D01*
-X017611Y017504D01*
-X017740Y017375D01*
-X017810Y017206D01*
-X017810Y016423D01*
-X017740Y016254D01*
-X017611Y016124D01*
-X017441Y016054D01*
-X017258Y016054D01*
-X017089Y016124D01*
-X016960Y016254D01*
-X016890Y016423D01*
-X016890Y016557D01*
-X016841Y016577D01*
-X016284Y017134D01*
-X010456Y017134D01*
-X010475Y017116D01*
-X010475Y016310D01*
-X010475Y016310D01*
-X010495Y016216D01*
-X010477Y016123D01*
-X010475Y016120D01*
-X010475Y015408D01*
-X010381Y015315D01*
-X010305Y015315D01*
-X010358Y015186D01*
-X010358Y015043D01*
-X010304Y014911D01*
-X010203Y014811D01*
-X010071Y014756D01*
-X009929Y014756D01*
-X009797Y014811D01*
-X009696Y014911D01*
-X009642Y015043D01*
-X009642Y015186D01*
-X009695Y015315D01*
-X009619Y015315D01*
-X009525Y015408D01*
-X009525Y017116D01*
-X009544Y017134D01*
-X009416Y017134D01*
-X009330Y017048D01*
-X009330Y014080D01*
-X009525Y013885D01*
-X009525Y014320D01*
-X009619Y014414D01*
-X010381Y014414D01*
-X010475Y014320D01*
-X010475Y013747D01*
-X011403Y013747D01*
-X011506Y013704D01*
-X011688Y013522D01*
-X011721Y013522D01*
-X011853Y013468D01*
-X011954Y013367D01*
-X013755Y013367D01*
-X013755Y013525D02*
-X011685Y013525D01*
-X011526Y013684D02*
-X013893Y013684D01*
-X013911Y013689D02*
-X013866Y013677D01*
-X013825Y013653D01*
-X013791Y013619D01*
-X013767Y013578D01*
-X013755Y013533D01*
-X013755Y012819D01*
-X014173Y012819D01*
-X014173Y013689D01*
-X013911Y013689D01*
-X014173Y013684D02*
-X014327Y013684D01*
-X014327Y013689D02*
-X014327Y012819D01*
-X014173Y012819D01*
-X014173Y012664D01*
-X014327Y012664D01*
-X014327Y011793D01*
-X014589Y011793D01*
-X014634Y011806D01*
-X014675Y011829D01*
-X014709Y011863D01*
-X014733Y011904D01*
-X014745Y011950D01*
-X014745Y012664D01*
-X014327Y012664D01*
-X014327Y012819D01*
-X014745Y012819D01*
-X014745Y013533D01*
-X014733Y013578D01*
-X014709Y013619D01*
-X014675Y013653D01*
-X014634Y013677D01*
-X014589Y013689D01*
-X014327Y013689D01*
-X014327Y013525D02*
-X014173Y013525D01*
-X014173Y013367D02*
-X014327Y013367D01*
-X014327Y013208D02*
-X014173Y013208D01*
-X014173Y013050D02*
-X014327Y013050D01*
-X014327Y012891D02*
-X014173Y012891D01*
-X014173Y012733D02*
-X010475Y012733D01*
-X010475Y012613D02*
-X010475Y013187D01*
-X011232Y013187D01*
-X011292Y013126D01*
-X011292Y013093D01*
-X011346Y012961D01*
-X011447Y012861D01*
-X011579Y012806D01*
-X011721Y012806D01*
-X011853Y012861D01*
-X011954Y012961D01*
-X012008Y013093D01*
-X012008Y013236D01*
-X011954Y013367D01*
-X012008Y013208D02*
-X013755Y013208D01*
-X013755Y013050D02*
-X011990Y013050D01*
-X011883Y012891D02*
-X013755Y012891D01*
-X013755Y012664D02*
-X013755Y011950D01*
-X013767Y011904D01*
-X013791Y011863D01*
-X013825Y011829D01*
-X013866Y011806D01*
-X013911Y011793D01*
-X014173Y011793D01*
-X014173Y012664D01*
-X013755Y012664D01*
-X013755Y012574D02*
-X010436Y012574D01*
-X010475Y012613D02*
-X010381Y012519D01*
-X009619Y012519D01*
-X009525Y012613D01*
-X009525Y013234D01*
-X009444Y013234D01*
-X009341Y013277D01*
-X009263Y013356D01*
-X009263Y013356D01*
-X008813Y013806D01*
-X008770Y013909D01*
-X008770Y017220D01*
-X008813Y017323D01*
-X009074Y017584D01*
-X007681Y017584D01*
-X007740Y017525D01*
-X007810Y017356D01*
-X007810Y016573D01*
-X007740Y016404D01*
-X007611Y016274D01*
-X007441Y016204D01*
-X007258Y016204D01*
-X007089Y016274D01*
-X006960Y016404D01*
-X006890Y016573D01*
-X006890Y017356D01*
-X006960Y017525D01*
-X007019Y017584D01*
-X006681Y017584D01*
-X006740Y017525D01*
-X006810Y017356D01*
-X006810Y016573D01*
-X006740Y016404D01*
-X006611Y016274D01*
-X006590Y016266D01*
-X006590Y015367D01*
-X006553Y015278D01*
-X006340Y015065D01*
-X006340Y015020D01*
-X006446Y015020D01*
-X006540Y014926D01*
-X006540Y014203D01*
-X006446Y014109D01*
-X006240Y014109D01*
-X006240Y013961D01*
-X006297Y014018D01*
-X006429Y014072D01*
-X006571Y014072D01*
-X006703Y014018D01*
-X006804Y013917D01*
-X006858Y013786D01*
-X006858Y013643D01*
-X006804Y013511D01*
-X006786Y013494D01*
-X006790Y013491D01*
-X006790Y012558D01*
-X006696Y012464D01*
-X006304Y012464D01*
-X006250Y012518D01*
-X006196Y012464D01*
-X005804Y012464D01*
-X005750Y012518D01*
-X005696Y012464D01*
-X005304Y012464D01*
-X005264Y012504D01*
-X005241Y012480D01*
-X005199Y012457D01*
-X005154Y012444D01*
-X005000Y012444D01*
-X005000Y013024D01*
-X005000Y013024D01*
-X005000Y012444D01*
-X004846Y012444D01*
-X004801Y012457D01*
-X004759Y012480D01*
-X004726Y012514D01*
-X004702Y012555D01*
-X004690Y012601D01*
-X004690Y013024D01*
-X005000Y013024D01*
-X005000Y013024D01*
-X004964Y012988D01*
-X004150Y012988D01*
-X004198Y012940D02*
-X004198Y013036D01*
-X004625Y013036D01*
-X004625Y013268D01*
-X004613Y013314D01*
-X004589Y013355D01*
-X004556Y013388D01*
-X004515Y013412D01*
-X004469Y013424D01*
-X004198Y013424D01*
-X004198Y013036D01*
-X004102Y013036D01*
-X004102Y012940D01*
-X003675Y012940D01*
-X003675Y012709D01*
-X003687Y012663D01*
-X003711Y012622D01*
-X003732Y012600D01*
-X003695Y012562D01*
-X003695Y011918D01*
-X003788Y011824D01*
-X003904Y011824D01*
-X003846Y011767D01*
-X003792Y011636D01*
-X003792Y011493D01*
-X003846Y011361D01*
-X003947Y011261D01*
-X004079Y011206D01*
-X004221Y011206D01*
-X004353Y011261D01*
-X004454Y011361D01*
-X004508Y011493D01*
-X004508Y011636D01*
-X004454Y011767D01*
-X004396Y011824D01*
-X004512Y011824D01*
-X004605Y011918D01*
-X004605Y012562D01*
-X004568Y012600D01*
-X004589Y012622D01*
-X004613Y012663D01*
-X004625Y012709D01*
-X004625Y012940D01*
-X004198Y012940D01*
-X004198Y013050D02*
-X004102Y013050D01*
-X004102Y013036D02*
-X004102Y013424D01*
-X003831Y013424D01*
-X003785Y013412D01*
-X003744Y013388D01*
-X003711Y013355D01*
-X003687Y013314D01*
-X003675Y013268D01*
-X003675Y013036D01*
-X004102Y013036D01*
-X004102Y013208D02*
-X004198Y013208D01*
-X004198Y013367D02*
-X004102Y013367D01*
-X003723Y013367D02*
-X000780Y013367D01*
-X000780Y013525D02*
-X004720Y013525D01*
-X004726Y013535D02*
-X004702Y013494D01*
-X004690Y013448D01*
-X004690Y013024D01*
-X005000Y013024D01*
-X005000Y012264D01*
-X005750Y011514D01*
-X005750Y010604D01*
-X005500Y010604D01*
-X005500Y010024D01*
-X005654Y010024D01*
-X005699Y010037D01*
-X005741Y010060D01*
-X005750Y010070D01*
-X005759Y010060D01*
-X005801Y010037D01*
-X005846Y010024D01*
-X006000Y010024D01*
-X006154Y010024D01*
-X006199Y010037D01*
-X006241Y010060D01*
-X006260Y010080D01*
-X006260Y008267D01*
-X006297Y008178D01*
-X006364Y008111D01*
-X006364Y008111D01*
-X006821Y007654D01*
-X006149Y007654D01*
-X005240Y008564D01*
-X005240Y010080D01*
-X005259Y010060D01*
-X005301Y010037D01*
-X005346Y010024D01*
-X005500Y010024D01*
-X005500Y010604D01*
-X005500Y010604D01*
-X005500Y010604D01*
-X005690Y010604D01*
-X006000Y010604D01*
-X006000Y010024D01*
-X006000Y010604D01*
-X006000Y010604D01*
-X006000Y010604D01*
-X005750Y010604D01*
-X005500Y010604D02*
-X006000Y010604D01*
-X006000Y011184D01*
-X005846Y011184D01*
-X005801Y011172D01*
-X005759Y011148D01*
-X005741Y011148D01*
-X005699Y011172D01*
-X005654Y011184D01*
-X005500Y011184D01*
-X005346Y011184D01*
-X005301Y011172D01*
-X005259Y011148D01*
-X005213Y011148D01*
-X005196Y011164D02*
-X005236Y011125D01*
-X005259Y011148D01*
-X005196Y011164D02*
-X004804Y011164D01*
-X004710Y011071D01*
-X004710Y010138D01*
-X004760Y010088D01*
-X004760Y009309D01*
-X004753Y009324D01*
-X004590Y009488D01*
-X004590Y009926D01*
-X004496Y010020D01*
-X003852Y010020D01*
-X003800Y009968D01*
-X003748Y010020D01*
-X003104Y010020D01*
-X003010Y009926D01*
-X003010Y009804D01*
-X002198Y009804D01*
-X002190Y009825D01*
-X002061Y009954D01*
-X001891Y010024D01*
-X001108Y010024D01*
-X000939Y009954D01*
-X000810Y009825D01*
-X000780Y009752D01*
-X000780Y010376D01*
-X000810Y010304D01*
-X000939Y010174D01*
-X001108Y010104D01*
-X001891Y010104D01*
-X002061Y010174D01*
-X002190Y010304D01*
-X002260Y010473D01*
-X002260Y010656D01*
-X002190Y010825D01*
-X002061Y010954D01*
-X001891Y011024D01*
-X001108Y011024D01*
-X000939Y010954D01*
-X000810Y010825D01*
-X000780Y010752D01*
-X000780Y011376D01*
-X000810Y011304D01*
-X000939Y011174D01*
-X001108Y011104D01*
-X001891Y011104D01*
-X002061Y011174D01*
-X002190Y011304D01*
-X002260Y011473D01*
-X002260Y011656D01*
-X002190Y011825D01*
-X002061Y011954D01*
-X001891Y012024D01*
-X001108Y012024D01*
-X000939Y011954D01*
-X000810Y011825D01*
-X000780Y011752D01*
-X000780Y012376D01*
-X000810Y012304D01*
-X000939Y012174D01*
-X001108Y012104D01*
-X001891Y012104D01*
-X002061Y012174D01*
-X002190Y012304D01*
-X002260Y012473D01*
-X002260Y012656D01*
-X002190Y012825D01*
-X002061Y012954D01*
-X001891Y013024D01*
-X001108Y013024D01*
-X000939Y012954D01*
-X000810Y012825D01*
-X000780Y012752D01*
-X000780Y015356D01*
-X000786Y015335D01*
-X001068Y014922D01*
-X001068Y014922D01*
-X001068Y014922D01*
-X001460Y014609D01*
-X001926Y014426D01*
-X002426Y014389D01*
-X002914Y014500D01*
-X003347Y014751D01*
-X003347Y014751D01*
-X003688Y015118D01*
-X003905Y015569D01*
-X003980Y016064D01*
-X003905Y016560D01*
-X003688Y017011D01*
-X003347Y017378D01*
-X002990Y017584D01*
-X005019Y017584D01*
-X004960Y017525D01*
-X004890Y017356D01*
-X004890Y016573D01*
-X004960Y016404D01*
-X005089Y016274D01*
-X005110Y016266D01*
-X005110Y015020D01*
-X005054Y015020D01*
-X004960Y014926D01*
-X004960Y014203D01*
-X005054Y014109D01*
-X005260Y014109D01*
-X005260Y013549D01*
-X005241Y013568D01*
-X005199Y013592D01*
-X005154Y013604D01*
-X005000Y013604D01*
-X004846Y013604D01*
-X004801Y013592D01*
-X004759Y013568D01*
-X004726Y013535D01*
-X004690Y013367D02*
-X004577Y013367D01*
-X004625Y013208D02*
-X004690Y013208D01*
-X004690Y013050D02*
-X004625Y013050D01*
-X004625Y012891D02*
-X004690Y012891D01*
-X004690Y012733D02*
-X004625Y012733D01*
-X004593Y012574D02*
-X004697Y012574D01*
-X004605Y012416D02*
-X013755Y012416D01*
-X013755Y012257D02*
-X011559Y012257D01*
-X011559Y012307D02*
-X011465Y012400D01*
-X007235Y012400D01*
-X007141Y012307D01*
-X007141Y008013D01*
-X006740Y008414D01*
-X006740Y010088D01*
-X006790Y010138D01*
-X006790Y011071D01*
-X006696Y011164D01*
-X006304Y011164D01*
-X006264Y011125D01*
-X006241Y011148D01*
-X006287Y011148D01*
-X006241Y011148D02*
-X006199Y011172D01*
-X006154Y011184D01*
-X006000Y011184D01*
-X006000Y010604D01*
-X006000Y010604D01*
-X006000Y010672D02*
-X006000Y010672D01*
-X006000Y010514D02*
-X006000Y010514D01*
-X006000Y010355D02*
-X006000Y010355D01*
-X006000Y010197D02*
-X006000Y010197D01*
-X006000Y010038D02*
-X006000Y010038D01*
-X006202Y010038D02*
-X006260Y010038D01*
-X006260Y009880D02*
-X005240Y009880D01*
-X005240Y010038D02*
-X005297Y010038D01*
-X005500Y010038D02*
-X005500Y010038D01*
-X005500Y010197D02*
-X005500Y010197D01*
-X005500Y010355D02*
-X005500Y010355D01*
-X005500Y010514D02*
-X005500Y010514D01*
-X005500Y010604D02*
-X005500Y011184D01*
-X005500Y010604D01*
-X005500Y010604D01*
-X005500Y010672D02*
-X005500Y010672D01*
-X005500Y010831D02*
-X005500Y010831D01*
-X005500Y010989D02*
-X005500Y010989D01*
-X005500Y011148D02*
-X005500Y011148D01*
-X005741Y011148D02*
-X005750Y011139D01*
-X005759Y011148D01*
-X006000Y011148D02*
-X006000Y011148D01*
-X006000Y010989D02*
-X006000Y010989D01*
-X006000Y010831D02*
-X006000Y010831D01*
-X006500Y010604D02*
-X006500Y008314D01*
-X007150Y007664D01*
-X009450Y007664D01*
-X010750Y006364D01*
-X011419Y006364D01*
-X011423Y006360D01*
-X011377Y006364D01*
-X011423Y006104D02*
-X010660Y006104D01*
-X009350Y007414D01*
-X006050Y007414D01*
-X005000Y008464D01*
-X005000Y010604D01*
-X004710Y010672D02*
-X002253Y010672D01*
-X002260Y010514D02*
-X004710Y010514D01*
-X004710Y010355D02*
-X002211Y010355D01*
-X002083Y010197D02*
-X004710Y010197D01*
-X004760Y010038D02*
-X000780Y010038D01*
-X000780Y009880D02*
-X000865Y009880D01*
-X000917Y010197D02*
-X000780Y010197D01*
-X000780Y010355D02*
-X000789Y010355D01*
-X000780Y010831D02*
-X000816Y010831D01*
-X000780Y010989D02*
-X001024Y010989D01*
-X001003Y011148D02*
-X000780Y011148D01*
-X000780Y011306D02*
-X000809Y011306D01*
-X000780Y011782D02*
-X000792Y011782D01*
-X000780Y011940D02*
-X000925Y011940D01*
-X000780Y012099D02*
-X003695Y012099D01*
-X003695Y012257D02*
-X002144Y012257D01*
-X002236Y012416D02*
-X003695Y012416D01*
-X003707Y012574D02*
-X002260Y012574D01*
-X002228Y012733D02*
-X003675Y012733D01*
-X003675Y012891D02*
-X002124Y012891D01*
-X002075Y011940D02*
-X003695Y011940D01*
-X003861Y011782D02*
-X002208Y011782D01*
-X002260Y011623D02*
-X003792Y011623D01*
-X003804Y011465D02*
-X002257Y011465D01*
-X002191Y011306D02*
-X003902Y011306D01*
-X004150Y011564D02*
-X004150Y012240D01*
-X004605Y012257D02*
-X007141Y012257D01*
-X007141Y012099D02*
-X004605Y012099D01*
-X004605Y011940D02*
-X007141Y011940D01*
-X007141Y011782D02*
-X004439Y011782D01*
-X004508Y011623D02*
-X007141Y011623D01*
-X007141Y011465D02*
-X004496Y011465D01*
-X004398Y011306D02*
-X007141Y011306D01*
-X007141Y011148D02*
-X006713Y011148D01*
-X006790Y010989D02*
-X007141Y010989D01*
-X007141Y010831D02*
-X006790Y010831D01*
-X006790Y010672D02*
-X007141Y010672D01*
-X007141Y010514D02*
-X006790Y010514D01*
-X006790Y010355D02*
-X007141Y010355D01*
-X007141Y010197D02*
-X006790Y010197D01*
-X006740Y010038D02*
-X007141Y010038D01*
-X007141Y009880D02*
-X006740Y009880D01*
-X006740Y009721D02*
-X007141Y009721D01*
-X007141Y009563D02*
-X006740Y009563D01*
-X006740Y009404D02*
-X007141Y009404D01*
-X007141Y009246D02*
-X006740Y009246D01*
-X006740Y009087D02*
-X007141Y009087D01*
-X007141Y008929D02*
-X006740Y008929D01*
-X006740Y008770D02*
-X007141Y008770D01*
-X007141Y008612D02*
-X006740Y008612D01*
-X006740Y008453D02*
-X007141Y008453D01*
-X007141Y008295D02*
-X006859Y008295D01*
-X007017Y008136D02*
-X007141Y008136D01*
-X006656Y007819D02*
-X005984Y007819D01*
-X005826Y007978D02*
-X006497Y007978D01*
-X006339Y008136D02*
-X005667Y008136D01*
-X005509Y008295D02*
-X006260Y008295D01*
-X006260Y008453D02*
-X005350Y008453D01*
-X005240Y008612D02*
-X006260Y008612D01*
-X006260Y008770D02*
-X005240Y008770D01*
-X005240Y008929D02*
-X006260Y008929D01*
-X006260Y009087D02*
-X005240Y009087D01*
-X005240Y009246D02*
-X006260Y009246D01*
-X006260Y009404D02*
-X005240Y009404D01*
-X005240Y009563D02*
-X006260Y009563D01*
-X006260Y009721D02*
-X005240Y009721D01*
-X004760Y009721D02*
-X004590Y009721D01*
-X004590Y009563D02*
-X004760Y009563D01*
-X004760Y009404D02*
-X004673Y009404D01*
-X004550Y009188D02*
-X004174Y009564D01*
-X004590Y009880D02*
-X004760Y009880D01*
-X004550Y009188D02*
-X004550Y006114D01*
-X004800Y005864D01*
-X005004Y005864D01*
-X004647Y005678D02*
-X004647Y005548D01*
-X004740Y005454D01*
-X005267Y005454D01*
-X005360Y005548D01*
-X005360Y006181D01*
-X005267Y006274D01*
-X004790Y006274D01*
-X004790Y006504D01*
-X005267Y006504D01*
-X005360Y006598D01*
-X005360Y007231D01*
-X005267Y007324D01*
-X004790Y007324D01*
-X004790Y008344D01*
-X004797Y008328D01*
-X005847Y007278D01*
-X005914Y007211D01*
-X006002Y007174D01*
-X008320Y007174D01*
-X008320Y006933D01*
-X008678Y006933D01*
-X008678Y006896D01*
-X008320Y006896D01*
-X008320Y006641D01*
-X008332Y006595D01*
-X008356Y006554D01*
-X008389Y006520D01*
-X008430Y006497D01*
-X008476Y006484D01*
-X008678Y006484D01*
-X008678Y006896D01*
-X008715Y006896D01*
-X008715Y006933D01*
-X009073Y006933D01*
-X009073Y007174D01*
-X009251Y007174D01*
-X010337Y006088D01*
-X010278Y006088D01*
-X010262Y006104D01*
-X009538Y006104D01*
-X009445Y006011D01*
-X009445Y005928D01*
-X009276Y005928D01*
-X009188Y005892D01*
-X009064Y005768D01*
-X009053Y005757D01*
-X009053Y006181D01*
-X008960Y006274D01*
-X008433Y006274D01*
-X008340Y006181D01*
-X008340Y005548D01*
-X008433Y005454D01*
-X008960Y005454D01*
-X008960Y005455D01*
-X008960Y005274D01*
-X008960Y005274D01*
-X008433Y005274D01*
-X008340Y005181D01*
-X008340Y004548D01*
-X008433Y004454D01*
-X008960Y004454D01*
-X009053Y004548D01*
-X009053Y004627D01*
-X009136Y004661D01*
-X009203Y004728D01*
-X009403Y004928D01*
-X009428Y004988D01*
-X009852Y004988D01*
-X009852Y004892D01*
-X009425Y004892D01*
-X009425Y004661D01*
-X009437Y004615D01*
-X009461Y004574D01*
-X009494Y004540D01*
-X009535Y004517D01*
-X009581Y004504D01*
-X009589Y004504D01*
-X009510Y004426D01*
-X009510Y004311D01*
-X009453Y004368D01*
-X009321Y004422D01*
-X009179Y004422D01*
-X009047Y004368D01*
-X008984Y004304D01*
-X008899Y004304D01*
-X008811Y004268D01*
-X008767Y004224D01*
-X008433Y004224D01*
-X008340Y004131D01*
-X008340Y003544D01*
-X005360Y003544D01*
-X005360Y004131D01*
-X005267Y004224D01*
-X004740Y004224D01*
-X004647Y004131D01*
-X004647Y003544D01*
-X002937Y003544D01*
-X002964Y003550D01*
-X003397Y003801D01*
-X003397Y003801D01*
-X003738Y004168D01*
-X003955Y004619D01*
-X004030Y005114D01*
-X003955Y005610D01*
-X003738Y006061D01*
-X003397Y006428D01*
-X002964Y006678D01*
-X002964Y006678D01*
-X002476Y006790D01*
-X002476Y006790D01*
-X001976Y006752D01*
-X001510Y006569D01*
-X001118Y006257D01*
-X000836Y005843D01*
-X000780Y005660D01*
-X000780Y008376D01*
-X000810Y008304D01*
-X000939Y008174D01*
-X001108Y008104D01*
-X001891Y008104D01*
-X002061Y008174D01*
-X002190Y008304D01*
-X002198Y008324D01*
-X003701Y008324D01*
-X004060Y007965D01*
-X004060Y005267D01*
-X004097Y005178D01*
-X004164Y005111D01*
-X004497Y004778D01*
-X004564Y004711D01*
-X004647Y004677D01*
-X004647Y004548D01*
-X004740Y004454D01*
-X005267Y004454D01*
-X005360Y004548D01*
-X005360Y005181D01*
-X005267Y005274D01*
-X004740Y005274D01*
-X004710Y005244D01*
-X004540Y005414D01*
-X004540Y005785D01*
-X004647Y005678D01*
-X004647Y005600D02*
-X004540Y005600D01*
-X004540Y005442D02*
-X008960Y005442D01*
-X008960Y005283D02*
-X004670Y005283D01*
-X004309Y004966D02*
-X004008Y004966D01*
-X004030Y005114D02*
-X004030Y005114D01*
-X004028Y005125D02*
-X004150Y005125D01*
-X004060Y005283D02*
-X004005Y005283D01*
-X003981Y005442D02*
-X004060Y005442D01*
-X004060Y005600D02*
-X003957Y005600D01*
-X003883Y005759D02*
-X004060Y005759D01*
-X004060Y005917D02*
-X003807Y005917D01*
-X003738Y006061D02*
-X003738Y006061D01*
-X003724Y006076D02*
-X004060Y006076D01*
-X004060Y006234D02*
-X003577Y006234D01*
-X003430Y006393D02*
-X004060Y006393D01*
-X004060Y006551D02*
-X003184Y006551D01*
-X003397Y006428D02*
-X003397Y006428D01*
-X002825Y006710D02*
-X004060Y006710D01*
-X004060Y006868D02*
-X000780Y006868D01*
-X000780Y006710D02*
-X001868Y006710D01*
-X001976Y006752D02*
-X001976Y006752D01*
-X001510Y006569D02*
-X001510Y006569D01*
-X001488Y006551D02*
-X000780Y006551D01*
-X000780Y006393D02*
-X001289Y006393D01*
-X001118Y006257D02*
-X001118Y006257D01*
-X001118Y006257D01*
-X001103Y006234D02*
-X000780Y006234D01*
-X000780Y006076D02*
-X000995Y006076D01*
-X000887Y005917D02*
-X000780Y005917D01*
-X000836Y005843D02*
-X000836Y005843D01*
-X000810Y005759D02*
-X000780Y005759D01*
-X000780Y007027D02*
-X004060Y007027D01*
-X004060Y007185D02*
-X000780Y007185D01*
-X000780Y007344D02*
-X004060Y007344D01*
-X004060Y007502D02*
-X000780Y007502D01*
-X000780Y007661D02*
-X004060Y007661D01*
-X004060Y007819D02*
-X000780Y007819D01*
-X000780Y007978D02*
-X004047Y007978D01*
-X003889Y008136D02*
-X001969Y008136D01*
-X002181Y008295D02*
-X003730Y008295D01*
-X003800Y008564D02*
-X001500Y008564D01*
-X001031Y008136D02*
-X000780Y008136D01*
-X000780Y008295D02*
-X000819Y008295D01*
-X001500Y009564D02*
-X003426Y009564D01*
-X003010Y009880D02*
-X002135Y009880D01*
-X002184Y010831D02*
-X004710Y010831D01*
-X004710Y010989D02*
-X001976Y010989D01*
-X001997Y011148D02*
-X004787Y011148D01*
-X005702Y010038D02*
-X005797Y010038D01*
-X004830Y008295D02*
-X004790Y008295D01*
-X004790Y008136D02*
-X004989Y008136D01*
-X005147Y007978D02*
-X004790Y007978D01*
-X004790Y007819D02*
-X005306Y007819D01*
-X005464Y007661D02*
-X004790Y007661D01*
-X004790Y007502D02*
-X005623Y007502D01*
-X005781Y007344D02*
-X004790Y007344D01*
-X005360Y007185D02*
-X005976Y007185D01*
-X006143Y007661D02*
-X006814Y007661D01*
-X005360Y007027D02*
-X008320Y007027D01*
-X008320Y006868D02*
-X005360Y006868D01*
-X005360Y006710D02*
-X008320Y006710D01*
-X008358Y006551D02*
-X005314Y006551D01*
-X005307Y006234D02*
-X008393Y006234D01*
-X008340Y006076D02*
-X005360Y006076D01*
-X005360Y005917D02*
-X008340Y005917D01*
-X008340Y005759D02*
-X005360Y005759D01*
-X005360Y005600D02*
-X008340Y005600D01*
-X008340Y005125D02*
-X005360Y005125D01*
-X005360Y004966D02*
-X008340Y004966D01*
-X008340Y004808D02*
-X005360Y004808D01*
-X005360Y004649D02*
-X008340Y004649D01*
-X008397Y004491D02*
-X005303Y004491D01*
-X005317Y004174D02*
-X008383Y004174D01*
-X008340Y004015D02*
-X005360Y004015D01*
-X005360Y003857D02*
-X008340Y003857D01*
-X008340Y003698D02*
-X005360Y003698D01*
-X004647Y003698D02*
-X003220Y003698D01*
-X003449Y003857D02*
-X004647Y003857D01*
-X004647Y004015D02*
-X003596Y004015D01*
-X003738Y004168D02*
-X003738Y004168D01*
-X003741Y004174D02*
-X004690Y004174D01*
-X004704Y004491D02*
-X003894Y004491D01*
-X003955Y004619D02*
-X003955Y004619D01*
-X003960Y004649D02*
-X004647Y004649D01*
-X004467Y004808D02*
-X003984Y004808D01*
-X003817Y004332D02*
-X009012Y004332D01*
-X008996Y004491D02*
-X009575Y004491D01*
-X009510Y004332D02*
-X009488Y004332D01*
-X009250Y004064D02*
-X008946Y004064D01*
-X008696Y003814D01*
-X009053Y003758D02*
-X009053Y003544D01*
-X020126Y003544D01*
-X019960Y003609D01*
-X019960Y003609D01*
-X019568Y003922D01*
-X019650Y003857D02*
-X014732Y003857D01*
-X014732Y003698D02*
-X019848Y003698D01*
-X019397Y004174D02*
-X018704Y004174D01*
-X018710Y004195D02*
-X018710Y004466D01*
-X018322Y004466D01*
-X018322Y004039D01*
-X018554Y004039D01*
-X018599Y004051D01*
-X018640Y004075D01*
-X018674Y004109D01*
-X018698Y004150D01*
-X018710Y004195D01*
-X018710Y004332D02*
-X019288Y004332D01*
-X019238Y004491D02*
-X018322Y004491D01*
-X018322Y004466D02*
-X018322Y004562D01*
-X018710Y004562D01*
-X018710Y004833D01*
-X018698Y004879D01*
-X018674Y004920D01*
-X018640Y004954D01*
-X018599Y004977D01*
-X018554Y004990D01*
-X018322Y004990D01*
-X018322Y004562D01*
-X018226Y004562D01*
-X018226Y004990D01*
-X017994Y004990D01*
-X017949Y004977D01*
-X017908Y004954D01*
-X017886Y004932D01*
-X017848Y004970D01*
-X017204Y004970D01*
-X017110Y004876D01*
-X017110Y004754D01*
-X017010Y004754D01*
-X017010Y004817D01*
-X016916Y004911D01*
-X016311Y004911D01*
-X016217Y004817D01*
-X016217Y004212D01*
-X016311Y004118D01*
-X016916Y004118D01*
-X017010Y004212D01*
-X017010Y004274D01*
-X017110Y004274D01*
-X017110Y004153D01*
-X017204Y004059D01*
-X017848Y004059D01*
-X017886Y004097D01*
-X017908Y004075D01*
-X017949Y004051D01*
-X017994Y004039D01*
-X018226Y004039D01*
-X018226Y004466D01*
-X018322Y004466D01*
-X018322Y004332D02*
-X018226Y004332D01*
-X018226Y004174D02*
-X018322Y004174D01*
-X018322Y004649D02*
-X018226Y004649D01*
-X018226Y004808D02*
-X018322Y004808D01*
-X018322Y004966D02*
-X018226Y004966D01*
-X017930Y004966D02*
-X017851Y004966D01*
-X017526Y004514D02*
-X016613Y004514D01*
-X016217Y004491D02*
-X016183Y004491D01*
-X016183Y004649D02*
-X016217Y004649D01*
-X016217Y004808D02*
-X016183Y004808D01*
-X016670Y005096D02*
-X016758Y005133D01*
-X018836Y007211D01*
-X018903Y007278D01*
-X018940Y007367D01*
-X018940Y010512D01*
-X018903Y010600D01*
-X018634Y010870D01*
-X018637Y010877D01*
-X018637Y011051D01*
-X018571Y011212D01*
-X018448Y011335D01*
-X018287Y011401D01*
-X018113Y011401D01*
-X017952Y011335D01*
-X017829Y011212D01*
-X017818Y011185D01*
-X017634Y011370D01*
-X017637Y011377D01*
-X017637Y011551D01*
-X017571Y011712D01*
-X017448Y011835D01*
-X017287Y011901D01*
-X017113Y011901D01*
-X016952Y011835D01*
-X016829Y011712D01*
-X016763Y011551D01*
-X016763Y011377D01*
-X016829Y011217D01*
-X016952Y011094D01*
-X017113Y011027D01*
-X017287Y011027D01*
-X017295Y011030D01*
-X017460Y010865D01*
-X017460Y010823D01*
-X017448Y010835D01*
-X017287Y010901D01*
-X017113Y010901D01*
-X016952Y010835D01*
-X016829Y010712D01*
-X016763Y010551D01*
-X016763Y010377D01*
-X016829Y010217D01*
-X016952Y010094D01*
-X017113Y010027D01*
-X017287Y010027D01*
-X017448Y010094D01*
-X017460Y010106D01*
-X017460Y009823D01*
-X017448Y009835D01*
-X017287Y009901D01*
-X017113Y009901D01*
-X016952Y009835D01*
-X016829Y009712D01*
-X016763Y009551D01*
-X016763Y009377D01*
-X016829Y009217D01*
-X016952Y009094D01*
-X016960Y009091D01*
-X016960Y008914D01*
-X016651Y008604D01*
-X015840Y008604D01*
-X015840Y008726D01*
-X015746Y008820D01*
-X015102Y008820D01*
-X015064Y008782D01*
-X015042Y008804D01*
-X015001Y008827D01*
-X014956Y008840D01*
-X014724Y008840D01*
-X014724Y008412D01*
-X014628Y008412D01*
-X014628Y008316D01*
-X014240Y008316D01*
-X014240Y008045D01*
-X014252Y008000D01*
-X014276Y007959D01*
-X014310Y007925D01*
-X014345Y007904D01*
-X013152Y007904D01*
-X013064Y007868D01*
-X012997Y007800D01*
-X012564Y007368D01*
-X011375Y007368D01*
-X011372Y007366D01*
-X011061Y007366D01*
-X010968Y007273D01*
-X010968Y006604D01*
-X010849Y006604D01*
-X009625Y007828D01*
-X011465Y007828D01*
-X011559Y007922D01*
-X011559Y012307D01*
-X011559Y012099D02*
-X013755Y012099D01*
-X013758Y011940D02*
-X011559Y011940D01*
-X011559Y011782D02*
-X012096Y011782D01*
-X012139Y011824D02*
-X012045Y011731D01*
-X012045Y011178D01*
-X012090Y011133D01*
-X012061Y011105D01*
-X012037Y011064D01*
-X012025Y011018D01*
-X012025Y010809D01*
-X012605Y010809D01*
-X012605Y010759D01*
-X012025Y010759D01*
-X012025Y010551D01*
-X012037Y010505D01*
-X012061Y010464D01*
-X012090Y010435D01*
-X012045Y010391D01*
-X012045Y009838D01*
-X012104Y009779D01*
-X012045Y009721D01*
-X012045Y009168D01*
-X012104Y009109D01*
-X012045Y009051D01*
-X012045Y008498D01*
-X012139Y008404D01*
-X013121Y008404D01*
-X013201Y008484D01*
-X013324Y008484D01*
-X013347Y008461D01*
-X013479Y008406D01*
-X013621Y008406D01*
-X013753Y008461D01*
-X013854Y008561D01*
-X013908Y008693D01*
-X013908Y008836D01*
-X013876Y008913D01*
-X014986Y008913D01*
-X015079Y009006D01*
-X015079Y009887D01*
-X014986Y009981D01*
-X013682Y009981D01*
-X013708Y010043D01*
-X013708Y010186D01*
-X013654Y010317D01*
-X013553Y010418D01*
-X013421Y010472D01*
-X013279Y010472D01*
-X013176Y010430D01*
-X013170Y010435D01*
-X013199Y010464D01*
-X013223Y010505D01*
-X013235Y010551D01*
-X013235Y010759D01*
-X012655Y010759D01*
-X012655Y010809D01*
-X013235Y010809D01*
-X013235Y011018D01*
-X013223Y011064D01*
-X013199Y011105D01*
-X013176Y011128D01*
-X013229Y011106D01*
-X013371Y011106D01*
-X013401Y011118D01*
-X013401Y011062D01*
-X014170Y011062D01*
-X014170Y010902D01*
-X014330Y010902D01*
-X014330Y010428D01*
-X014943Y010428D01*
-X014989Y010440D01*
-X015030Y010464D01*
-X015063Y010498D01*
-X015087Y010539D01*
-X015099Y010584D01*
-X015099Y010902D01*
-X014330Y010902D01*
-X014330Y011062D01*
-X015099Y011062D01*
-X015099Y011380D01*
-X015087Y011426D01*
-X015063Y011467D01*
-X015030Y011500D01*
-X014989Y011524D01*
-X014943Y011536D01*
-X014330Y011536D01*
-X014330Y011062D01*
-X014170Y011062D01*
-X014170Y011536D01*
-X013658Y011536D01*
-X013604Y011667D01*
-X013503Y011768D01*
-X013371Y011822D01*
-X013229Y011822D01*
-X013154Y011792D01*
-X013121Y011824D01*
-X012139Y011824D01*
-X012045Y011623D02*
-X011559Y011623D01*
-X011559Y011465D02*
-X012045Y011465D01*
-X012045Y011306D02*
-X011559Y011306D01*
-X011559Y011148D02*
-X012075Y011148D01*
-X012025Y010989D02*
-X011559Y010989D01*
-X011559Y010831D02*
-X012025Y010831D01*
-X012025Y010672D02*
-X011559Y010672D01*
-X011559Y010514D02*
-X012035Y010514D01*
-X012045Y010355D02*
-X011559Y010355D01*
-X011559Y010197D02*
-X012045Y010197D01*
-X012045Y010038D02*
-X011559Y010038D01*
-X011559Y009880D02*
-X012045Y009880D01*
-X012046Y009721D02*
-X011559Y009721D01*
-X011559Y009563D02*
-X012045Y009563D01*
-X012045Y009404D02*
-X011559Y009404D01*
-X011559Y009246D02*
-X012045Y009246D01*
-X012082Y009087D02*
-X011559Y009087D01*
-X011559Y008929D02*
-X012045Y008929D01*
-X012045Y008770D02*
-X011559Y008770D01*
-X011559Y008612D02*
-X012045Y008612D01*
-X012090Y008453D02*
-X011559Y008453D01*
-X011559Y008295D02*
-X014240Y008295D01*
-X014240Y008412D02*
-X014628Y008412D01*
-X014628Y008840D01*
-X014396Y008840D01*
-X014351Y008827D01*
-X014310Y008804D01*
-X014276Y008770D01*
-X014252Y008729D01*
-X014240Y008683D01*
-X014240Y008412D01*
-X014240Y008453D02*
-X013735Y008453D01*
-X013874Y008612D02*
-X014240Y008612D01*
-X014276Y008770D02*
-X013908Y008770D01*
-X013365Y008453D02*
-X013170Y008453D01*
-X013016Y007819D02*
-X009634Y007819D01*
-X009793Y007661D02*
-X012857Y007661D01*
-X012699Y007502D02*
-X009951Y007502D01*
-X010110Y007344D02*
-X011039Y007344D01*
-X010968Y007185D02*
-X010268Y007185D01*
-X010427Y007027D02*
-X010968Y007027D01*
-X010968Y006868D02*
-X010585Y006868D01*
-X010744Y006710D02*
-X010968Y006710D01*
-X011423Y007128D02*
-X012663Y007128D01*
-X013200Y007664D01*
-X015250Y007664D01*
-X015424Y007838D01*
-X015424Y008364D01*
-X016750Y008364D01*
-X017200Y008814D01*
-X017200Y009464D01*
-X016817Y009246D02*
-X015079Y009246D01*
-X015079Y009404D02*
-X016763Y009404D01*
-X016768Y009563D02*
-X015079Y009563D01*
-X015079Y009721D02*
-X016839Y009721D01*
-X017061Y009880D02*
-X015079Y009880D01*
-X015073Y010514D02*
-X016763Y010514D01*
-X016772Y010355D02*
-X013615Y010355D01*
-X013557Y010428D02*
-X014170Y010428D01*
-X014170Y010902D01*
-X013401Y010902D01*
-X013401Y010584D01*
-X013413Y010539D01*
-X013437Y010498D01*
-X013470Y010464D01*
-X013511Y010440D01*
-X013557Y010428D01*
-X013427Y010514D02*
-X013225Y010514D01*
-X013235Y010672D02*
-X013401Y010672D01*
-X013401Y010831D02*
-X013235Y010831D01*
-X013235Y010989D02*
-X014170Y010989D01*
-X014170Y010831D02*
-X014330Y010831D01*
-X014330Y010989D02*
-X017336Y010989D01*
-X017452Y010831D02*
-X017460Y010831D01*
-X017700Y010964D02*
-X017200Y011464D01*
-X016792Y011306D02*
-X015099Y011306D01*
-X015099Y011148D02*
-X016898Y011148D01*
-X016948Y010831D02*
-X015099Y010831D01*
-X015099Y010672D02*
-X016813Y010672D01*
-X016849Y010197D02*
-X013703Y010197D01*
-X013706Y010038D02*
-X017086Y010038D01*
-X017314Y010038D02*
-X017460Y010038D01*
-X017460Y009880D02*
-X017339Y009880D01*
-X017940Y009588D02*
-X017960Y009573D01*
-X018025Y009541D01*
-X018093Y009518D01*
-X018164Y009507D01*
-X018191Y009507D01*
-X018191Y009956D01*
-X018209Y009956D01*
-X018209Y009507D01*
-X018236Y009507D01*
-X018307Y009518D01*
-X018375Y009541D01*
-X018440Y009573D01*
-X018460Y009588D01*
-X018460Y007514D01*
-X017940Y006994D01*
-X017940Y009588D01*
-X017940Y009563D02*
-X017981Y009563D01*
-X017940Y009404D02*
-X018460Y009404D01*
-X018460Y009246D02*
-X017940Y009246D01*
-X017940Y009087D02*
-X018460Y009087D01*
-X018460Y008929D02*
-X017940Y008929D01*
-X017940Y008770D02*
-X018460Y008770D01*
-X018460Y008612D02*
-X017940Y008612D01*
-X017940Y008453D02*
-X018460Y008453D01*
-X018460Y008295D02*
-X017940Y008295D01*
-X017940Y008136D02*
-X018460Y008136D01*
-X018460Y007978D02*
-X017940Y007978D01*
-X017940Y007819D02*
-X018460Y007819D01*
-X018460Y007661D02*
-X017940Y007661D01*
-X017940Y007502D02*
-X018449Y007502D01*
-X018290Y007344D02*
-X017940Y007344D01*
-X017940Y007185D02*
-X018132Y007185D01*
-X017973Y007027D02*
-X017940Y007027D01*
-X017700Y006814D02*
-X017700Y010964D01*
-X017697Y011306D02*
-X017924Y011306D01*
-X017952Y011594D02*
-X018113Y011527D01*
-X018287Y011527D01*
-X018448Y011594D01*
-X018571Y011717D01*
-X018637Y011877D01*
-X018637Y012051D01*
-X018571Y012212D01*
-X018448Y012335D01*
-X018287Y012401D01*
-X018113Y012401D01*
-X017952Y012335D01*
-X017829Y012212D01*
-X017763Y012051D01*
-X017763Y011877D01*
-X017829Y011717D01*
-X017952Y011594D01*
-X017923Y011623D02*
-X017607Y011623D01*
-X017637Y011465D02*
-X022320Y011465D01*
-X022320Y011623D02*
-X020956Y011623D01*
-X020847Y011594D02*
-X021132Y011671D01*
-X021388Y011818D01*
-X021596Y012027D01*
-X021744Y012282D01*
-X021820Y012567D01*
-X021820Y012862D01*
-X021744Y013147D01*
-X021596Y013402D01*
-X021388Y013611D01*
-X021132Y013758D01*
-X020847Y013834D01*
-X020553Y013834D01*
-X020268Y013758D01*
-X020012Y013611D01*
-X019804Y013402D01*
-X019656Y013147D01*
-X019580Y012862D01*
-X019580Y012567D01*
-X019656Y012282D01*
-X019804Y012027D01*
-X020012Y011818D01*
-X020268Y011671D01*
-X020553Y011594D01*
-X020847Y011594D01*
-X020444Y011623D02*
-X018477Y011623D01*
-X018598Y011782D02*
-X020075Y011782D01*
-X019890Y011940D02*
-X018637Y011940D01*
-X018617Y012099D02*
-X019762Y012099D01*
-X019671Y012257D02*
-X018525Y012257D01*
-X017875Y012257D02*
-X014745Y012257D01*
-X014745Y012099D02*
-X017783Y012099D01*
-X017763Y011940D02*
-X014742Y011940D01*
-X014327Y011940D02*
-X014173Y011940D01*
-X014173Y012099D02*
-X014327Y012099D01*
-X014327Y012257D02*
-X014173Y012257D01*
-X014173Y012416D02*
-X014327Y012416D01*
-X014327Y012574D02*
-X014173Y012574D01*
-X014327Y012733D02*
-X019580Y012733D01*
-X019588Y012891D02*
-X014745Y012891D01*
-X014745Y013050D02*
-X019630Y013050D01*
-X019692Y013208D02*
-X014745Y013208D01*
-X014745Y013367D02*
-X019783Y013367D01*
-X019927Y013525D02*
-X014745Y013525D01*
-X014607Y013684D02*
-X020139Y013684D01*
-X021261Y013684D02*
-X022320Y013684D01*
-X022320Y013842D02*
-X010475Y013842D01*
-X010475Y014001D02*
-X022320Y014001D01*
-X022320Y014159D02*
-X010475Y014159D01*
-X010475Y014318D02*
-X022320Y014318D01*
-X022320Y014476D02*
-X021308Y014476D01*
-X021647Y014635D02*
-X022320Y014635D01*
-X022320Y014793D02*
-X021887Y014793D01*
-X021847Y014751D02*
-X021847Y014751D01*
-X022034Y014952D02*
-X022320Y014952D01*
-X022320Y015110D02*
-X022181Y015110D01*
-X022261Y015269D02*
-X022320Y015269D01*
-X020299Y014476D02*
-X009330Y014476D01*
-X009330Y014318D02*
-X009525Y014318D01*
-X009525Y014159D02*
-X009330Y014159D01*
-X009409Y014001D02*
-X009525Y014001D01*
-X008935Y013684D02*
-X006858Y013684D01*
-X006835Y013842D02*
-X008797Y013842D01*
-X008770Y014001D02*
-X006720Y014001D01*
-X006496Y014159D02*
-X008770Y014159D01*
-X008770Y014318D02*
-X006540Y014318D01*
-X006540Y014476D02*
-X008770Y014476D01*
-X008770Y014635D02*
-X006540Y014635D01*
-X006540Y014793D02*
-X008770Y014793D01*
-X008770Y014952D02*
-X006514Y014952D01*
-X006385Y015110D02*
-X008770Y015110D01*
-X008770Y015269D02*
-X006544Y015269D01*
-X006590Y015427D02*
-X008770Y015427D01*
-X008770Y015586D02*
-X006590Y015586D01*
-X006590Y015744D02*
-X008770Y015744D01*
-X008770Y015903D02*
-X006590Y015903D01*
-X006590Y016061D02*
-X008770Y016061D01*
-X008770Y016220D02*
-X007479Y016220D01*
-X007221Y016220D02*
-X006590Y016220D01*
-X006715Y016378D02*
-X006985Y016378D01*
-X006905Y016537D02*
-X006795Y016537D01*
-X006810Y016695D02*
-X006890Y016695D01*
-X006890Y016854D02*
-X006810Y016854D01*
-X006810Y017012D02*
-X006890Y017012D01*
-X006890Y017171D02*
-X006810Y017171D01*
-X006810Y017329D02*
-X006890Y017329D01*
-X006945Y017488D02*
-X006755Y017488D01*
-X006350Y016964D02*
-X006350Y015414D01*
-X006100Y015164D01*
-X006100Y014588D01*
-X006124Y014564D01*
-X006000Y014490D01*
-X006000Y013024D01*
-X005500Y013024D02*
-X005500Y014440D01*
-X005376Y014564D01*
-X005350Y014590D01*
-X005350Y016964D01*
-X004890Y017012D02*
-X003687Y017012D01*
-X003688Y017011D02*
-X003688Y017011D01*
-X003764Y016854D02*
-X004890Y016854D01*
-X004890Y016695D02*
-X003840Y016695D01*
-X003905Y016560D02*
-X003905Y016560D01*
-X003909Y016537D02*
-X004905Y016537D01*
-X004985Y016378D02*
-X003933Y016378D01*
-X003957Y016220D02*
-X005110Y016220D01*
-X005110Y016061D02*
-X003980Y016061D01*
-X003980Y016064D02*
-X003980Y016064D01*
-X003956Y015903D02*
-X005110Y015903D01*
-X005110Y015744D02*
-X003932Y015744D01*
-X003908Y015586D02*
-X005110Y015586D01*
-X005110Y015427D02*
-X003837Y015427D01*
-X003761Y015269D02*
-X005110Y015269D01*
-X005110Y015110D02*
-X003681Y015110D01*
-X003688Y015118D02*
-X003688Y015118D01*
-X003534Y014952D02*
-X004986Y014952D01*
-X004960Y014793D02*
-X003387Y014793D01*
-X003347Y014751D02*
-X003347Y014751D01*
-X003147Y014635D02*
-X004960Y014635D01*
-X004960Y014476D02*
-X002808Y014476D01*
-X002914Y014500D02*
-X002914Y014500D01*
-X002426Y014389D02*
-X002426Y014389D01*
-X001926Y014426D02*
-X001926Y014426D01*
-X001799Y014476D02*
-X000780Y014476D01*
-X000780Y014318D02*
-X004960Y014318D01*
-X005004Y014159D02*
-X000780Y014159D01*
-X000780Y014001D02*
-X005260Y014001D01*
-X005260Y013842D02*
-X000780Y013842D01*
-X000780Y013684D02*
-X005260Y013684D01*
-X005000Y013604D02*
-X005000Y013024D01*
-X005000Y013604D01*
-X005000Y013525D02*
-X005000Y013525D01*
-X005000Y013367D02*
-X005000Y013367D01*
-X005000Y013208D02*
-X005000Y013208D01*
-X005000Y013050D02*
-X005000Y013050D01*
-X005000Y013024D02*
-X005000Y013024D01*
-X005000Y012891D02*
-X005000Y012891D01*
-X005000Y012733D02*
-X005000Y012733D01*
-X005000Y012574D02*
-X005000Y012574D01*
-X003675Y013050D02*
-X000780Y013050D01*
-X000780Y013208D02*
-X003675Y013208D01*
-X001460Y014609D02*
-X001460Y014609D01*
-X001428Y014635D02*
-X000780Y014635D01*
-X000780Y014793D02*
-X001229Y014793D01*
-X001048Y014952D02*
-X000780Y014952D01*
-X000780Y015110D02*
-X000940Y015110D01*
-X000832Y015269D02*
-X000780Y015269D01*
-X000786Y015335D02*
-X000786Y015335D01*
-X003347Y017378D02*
-X003347Y017378D01*
-X003392Y017329D02*
-X004890Y017329D01*
-X004890Y017171D02*
-X003539Y017171D01*
-X003157Y017488D02*
-X004945Y017488D01*
-X007755Y017488D02*
-X008978Y017488D01*
-X008819Y017329D02*
-X007810Y017329D01*
-X007810Y017171D02*
-X008770Y017171D01*
-X008770Y017012D02*
-X007810Y017012D01*
-X007810Y016854D02*
-X008770Y016854D01*
-X008770Y016695D02*
-X007810Y016695D01*
-X007795Y016537D02*
-X008770Y016537D01*
-X008770Y016378D02*
-X007715Y016378D01*
-X009330Y016378D02*
-X009525Y016378D01*
-X009525Y016220D02*
-X009330Y016220D01*
-X009330Y016061D02*
-X009525Y016061D01*
-X009525Y015903D02*
-X009330Y015903D01*
-X009330Y015744D02*
-X009525Y015744D01*
-X009525Y015586D02*
-X009330Y015586D01*
-X009330Y015427D02*
-X009525Y015427D01*
-X009676Y015269D02*
-X009330Y015269D01*
-X009330Y015110D02*
-X009642Y015110D01*
-X009680Y014952D02*
-X009330Y014952D01*
-X009330Y014793D02*
-X009839Y014793D01*
-X010161Y014793D02*
-X013933Y014793D01*
-X013946Y014761D02*
-X014047Y014661D01*
-X014179Y014606D01*
-X014321Y014606D01*
-X014453Y014661D01*
-X014554Y014761D01*
-X014608Y014893D01*
-X014608Y015036D01*
-X014557Y015160D01*
-X014631Y015160D01*
-X014725Y015254D01*
-X014725Y016922D01*
-X014631Y017015D01*
-X013869Y017015D01*
-X013775Y016922D01*
-X013775Y015254D01*
-X013869Y015160D01*
-X013943Y015160D01*
-X013892Y015036D01*
-X013892Y014893D01*
-X013946Y014761D01*
-X013892Y014952D02*
-X010320Y014952D01*
-X010358Y015110D02*
-X013923Y015110D01*
-X013775Y015269D02*
-X010324Y015269D01*
-X010475Y015427D02*
-X013775Y015427D01*
-X013775Y015586D02*
-X010475Y015586D01*
-X010475Y015744D02*
-X013775Y015744D01*
-X013775Y015903D02*
-X010475Y015903D01*
-X010475Y016061D02*
-X013775Y016061D01*
-X013775Y016220D02*
-X010494Y016220D01*
-X010475Y016378D02*
-X013775Y016378D01*
-X013775Y016537D02*
-X010475Y016537D01*
-X010475Y016695D02*
-X013775Y016695D01*
-X013775Y016854D02*
-X010475Y016854D01*
-X010475Y017012D02*
-X013866Y017012D01*
-X014634Y017012D02*
-X016406Y017012D01*
-X016564Y016854D02*
-X014725Y016854D01*
-X014725Y016695D02*
-X016723Y016695D01*
-X016890Y016537D02*
-X014725Y016537D01*
-X014725Y016378D02*
-X016908Y016378D01*
-X016994Y016220D02*
-X014725Y016220D01*
-X014725Y016061D02*
-X017242Y016061D01*
-X017458Y016061D02*
-X018242Y016061D01*
-X018258Y016054D02*
-X018441Y016054D01*
-X018611Y016124D01*
-X018740Y016254D01*
-X018810Y016423D01*
-X018810Y017206D01*
-X018740Y017375D01*
-X018611Y017504D01*
-X018441Y017574D01*
-X018258Y017574D01*
-X018089Y017504D01*
-X017960Y017375D01*
-X017890Y017206D01*
-X017890Y016423D01*
-X017960Y016254D01*
-X018089Y016124D01*
-X018258Y016054D01*
-X018458Y016061D02*
-X019139Y016061D01*
-X019139Y015903D02*
-X014725Y015903D01*
-X014725Y015744D02*
-X019160Y015744D01*
-X019209Y015586D02*
-X014725Y015586D01*
-X014725Y015427D02*
-X019258Y015427D01*
-X019332Y015269D02*
-X014725Y015269D01*
-X014577Y015110D02*
-X019440Y015110D01*
-X019548Y014952D02*
-X014608Y014952D01*
-X014567Y014793D02*
-X019729Y014793D01*
-X019928Y014635D02*
-X014390Y014635D01*
-X014110Y014635D02*
-X009330Y014635D01*
-X010000Y015114D02*
-X010000Y016262D01*
-X010250Y016214D01*
-X009525Y016537D02*
-X009330Y016537D01*
-X009330Y016695D02*
-X009525Y016695D01*
-X009525Y016854D02*
-X009330Y016854D01*
-X009330Y017012D02*
-X009525Y017012D01*
-X006280Y014001D02*
-X006240Y014001D01*
-X006500Y013714D02*
-X006500Y013024D01*
-X006790Y013050D02*
-X009525Y013050D01*
-X009525Y013208D02*
-X006790Y013208D01*
-X006790Y013367D02*
-X009252Y013367D01*
-X009093Y013525D02*
-X006809Y013525D01*
-X006790Y012891D02*
-X009525Y012891D01*
-X009525Y012733D02*
-X006790Y012733D01*
-X006790Y012574D02*
-X009564Y012574D01*
-X010475Y012891D02*
-X011417Y012891D01*
-X011310Y013050D02*
-X010475Y013050D01*
-X012630Y011454D02*
-X013290Y011454D01*
-X013300Y011464D01*
-X013622Y011623D02*
-X016793Y011623D01*
-X016763Y011465D02*
-X015064Y011465D01*
-X014330Y011465D02*
-X014170Y011465D01*
-X014170Y011306D02*
-X014330Y011306D01*
-X014330Y011148D02*
-X014170Y011148D01*
-X014170Y010672D02*
-X014330Y010672D01*
-X014330Y010514D02*
-X014170Y010514D01*
-X013350Y010114D02*
-X012630Y010114D01*
-X013469Y011782D02*
-X016899Y011782D01*
-X017501Y011782D02*
-X017802Y011782D01*
-X018476Y011306D02*
-X022320Y011306D01*
-X022320Y011148D02*
-X018597Y011148D01*
-X018637Y010989D02*
-X022320Y010989D01*
-X022320Y010831D02*
-X018673Y010831D01*
-X018831Y010672D02*
-X022320Y010672D01*
-X022320Y010514D02*
-X018939Y010514D01*
-X018940Y010355D02*
-X022320Y010355D01*
-X022320Y010197D02*
-X018940Y010197D01*
-X018940Y010038D02*
-X022320Y010038D01*
-X022320Y009880D02*
-X018940Y009880D01*
-X018940Y009721D02*
-X020204Y009721D01*
-X020268Y009758D02*
-X020012Y009611D01*
-X019804Y009402D01*
-X019656Y009147D01*
-X019580Y008862D01*
-X019580Y008567D01*
-X019656Y008282D01*
-X019804Y008027D01*
-X020012Y007818D01*
-X020268Y007671D01*
-X020553Y007594D01*
-X020847Y007594D01*
-X021132Y007671D01*
-X021388Y007818D01*
-X021596Y008027D01*
-X021744Y008282D01*
-X021820Y008567D01*
-X021820Y008862D01*
-X021744Y009147D01*
-X021596Y009402D01*
-X021388Y009611D01*
-X021132Y009758D01*
-X020847Y009834D01*
-X020553Y009834D01*
-X020268Y009758D01*
-X019965Y009563D02*
-X018940Y009563D01*
-X018940Y009404D02*
-X019806Y009404D01*
-X019714Y009246D02*
-X018940Y009246D01*
-X018940Y009087D02*
-X019640Y009087D01*
-X019598Y008929D02*
-X018940Y008929D01*
-X018940Y008770D02*
-X019580Y008770D01*
-X019580Y008612D02*
-X018940Y008612D01*
-X018940Y008453D02*
-X019610Y008453D01*
-X019653Y008295D02*
-X018940Y008295D01*
-X018940Y008136D02*
-X019740Y008136D01*
-X019853Y007978D02*
-X018940Y007978D01*
-X018940Y007819D02*
-X020011Y007819D01*
-X020304Y007661D02*
-X018940Y007661D01*
-X018940Y007502D02*
-X022320Y007502D01*
-X022320Y007344D02*
-X018931Y007344D01*
-X018810Y007185D02*
-X022320Y007185D01*
-X022320Y007027D02*
-X018652Y007027D01*
-X018493Y006868D02*
-X022320Y006868D01*
-X022320Y006710D02*
-X021056Y006710D01*
-X021547Y006551D02*
-X022320Y006551D01*
-X022320Y006393D02*
-X021821Y006393D01*
-X021981Y006234D02*
-X022320Y006234D01*
-X022320Y006076D02*
-X022128Y006076D01*
-X022233Y005917D02*
-X022320Y005917D01*
-X022309Y005759D02*
-X022320Y005759D01*
-X020528Y006710D02*
-X018335Y006710D01*
-X018176Y006551D02*
-X020042Y006551D01*
-X019801Y006393D02*
-X018018Y006393D01*
-X017859Y006234D02*
-X019603Y006234D01*
-X019479Y006076D02*
-X017701Y006076D01*
-X017542Y005917D02*
-X019371Y005917D01*
-X019276Y005759D02*
-X017384Y005759D01*
-X017225Y005600D02*
-X019227Y005600D01*
-X019178Y005442D02*
-X017067Y005442D01*
-X016908Y005283D02*
-X019139Y005283D01*
-X019139Y005125D02*
-X016738Y005125D01*
-X016670Y005096D02*
-X014732Y005096D01*
-X014732Y003656D01*
-X014639Y003562D01*
-X013916Y003562D01*
-X013822Y003656D01*
-X013822Y006632D01*
-X013774Y006632D01*
-X013703Y006561D01*
-X013571Y006506D01*
-X013429Y006506D01*
-X013297Y006561D01*
-X013196Y006661D01*
-X013142Y006793D01*
-X013142Y006936D01*
-X013196Y007067D01*
-X013297Y007168D01*
-X013429Y007222D01*
-X013571Y007222D01*
-X013703Y007168D01*
-X013759Y007112D01*
-X013802Y007112D01*
-X013802Y007128D01*
-X014277Y007128D01*
-X014277Y007386D01*
-X013958Y007386D01*
-X013912Y007374D01*
-X013871Y007350D01*
-X013838Y007317D01*
-X013814Y007276D01*
-X013802Y007230D01*
-X013802Y007128D01*
-X014277Y007128D01*
-X014277Y007128D01*
-X014277Y007128D01*
-X014277Y007386D01*
-X014592Y007386D01*
-X014594Y007388D01*
-X014635Y007412D01*
-X014681Y007424D01*
-X014952Y007424D01*
-X014952Y007036D01*
-X015048Y007036D01*
-X015475Y007036D01*
-X015475Y007268D01*
-X015463Y007314D01*
-X015439Y007355D01*
-X015406Y007388D01*
-X015365Y007412D01*
-X015319Y007424D01*
-X015048Y007424D01*
-X015048Y007036D01*
-X015048Y006940D01*
-X015475Y006940D01*
-X015475Y006709D01*
-X015463Y006663D01*
-X015439Y006622D01*
-X015418Y006600D01*
-X015449Y006569D01*
-X015579Y006622D01*
-X015721Y006622D01*
-X015853Y006568D01*
-X015954Y006467D01*
-X016008Y006336D01*
-X016008Y006193D01*
-X015954Y006061D01*
-X015853Y005961D01*
-X015721Y005906D01*
-X015579Y005906D01*
-X015455Y005957D01*
-X015455Y005918D01*
-X015369Y005832D01*
-X016379Y005832D01*
-X017460Y006914D01*
-X017460Y009106D01*
-X017448Y009094D01*
-X017440Y009091D01*
-X017440Y008767D01*
-X017403Y008678D01*
-X017336Y008611D01*
-X016886Y008161D01*
-X016798Y008124D01*
-X015840Y008124D01*
-X015840Y008003D01*
-X015746Y007909D01*
-X015664Y007909D01*
-X015664Y007791D01*
-X015627Y007702D01*
-X015453Y007528D01*
-X015453Y007528D01*
-X015386Y007461D01*
-X015298Y007424D01*
-X013299Y007424D01*
-X012799Y006924D01*
-X012711Y006888D01*
-X011878Y006888D01*
-X011878Y005599D01*
-X011897Y005618D01*
-X012029Y005672D01*
-X012171Y005672D01*
-X012303Y005618D01*
-X012404Y005517D01*
-X012458Y005386D01*
-X012458Y005243D01*
-X012404Y005111D01*
-X012303Y005011D01*
-X012171Y004956D01*
-X012029Y004956D01*
-X011897Y005011D01*
-X011878Y005030D01*
-X011878Y004218D01*
-X011886Y004205D01*
-X011898Y004159D01*
-X011898Y004057D01*
-X011423Y004057D01*
-X011423Y004057D01*
-X011898Y004057D01*
-X011898Y003954D01*
-X011886Y003909D01*
-X011878Y003895D01*
-X011878Y003656D01*
-X011784Y003562D01*
-X011061Y003562D01*
-X011014Y003610D01*
-X010999Y003601D01*
-X010954Y003589D01*
-X010722Y003589D01*
-X010722Y004016D01*
-X010626Y004016D01*
-X010626Y003589D01*
-X010394Y003589D01*
-X010349Y003601D01*
-X010308Y003625D01*
-X010286Y003647D01*
-X010248Y003609D01*
-X009604Y003609D01*
-X009510Y003703D01*
-X009510Y003818D01*
-X009453Y003761D01*
-X009321Y003706D01*
-X009179Y003706D01*
-X009053Y003758D01*
-X009053Y003698D02*
-X009515Y003698D01*
-X009250Y004064D02*
-X009926Y004064D01*
-X010286Y004482D02*
-X010254Y004514D01*
-X010265Y004517D01*
-X010306Y004540D01*
-X010339Y004574D01*
-X010363Y004615D01*
-X010375Y004661D01*
-X010375Y004892D01*
-X009948Y004892D01*
-X009948Y004988D01*
-X010375Y004988D01*
-X010375Y005220D01*
-X010363Y005266D01*
-X010339Y005307D01*
-X010318Y005328D01*
-X010355Y005366D01*
-X010355Y005608D01*
-X010968Y005608D01*
-X010968Y005481D01*
-X010968Y004536D01*
-X010954Y004540D01*
-X010722Y004540D01*
-X010722Y004112D01*
-X010948Y004112D01*
-X010948Y004057D01*
-X011423Y004057D01*
-X011406Y004040D01*
-X010674Y004064D01*
-X010722Y004016D02*
-X010722Y004112D01*
-X010626Y004112D01*
-X010626Y004540D01*
-X010394Y004540D01*
-X010349Y004527D01*
-X010308Y004504D01*
-X010286Y004482D01*
-X010277Y004491D02*
-X010295Y004491D01*
-X010372Y004649D02*
-X010968Y004649D01*
-X010968Y004808D02*
-X010375Y004808D01*
-X010375Y005125D02*
-X010968Y005125D01*
-X010968Y005283D02*
-X010353Y005283D01*
-X010355Y005442D02*
-X010968Y005442D01*
-X010968Y005600D02*
-X010355Y005600D01*
-X010060Y005848D02*
-X009900Y005688D01*
-X009324Y005688D01*
-X009200Y005564D01*
-X009200Y005064D01*
-X009000Y004864D01*
-X008696Y004864D01*
-X009108Y004649D02*
-X009428Y004649D01*
-X009425Y004808D02*
-X009283Y004808D01*
-X009419Y004966D02*
-X009852Y004966D01*
-X009948Y004966D02*
-X010968Y004966D01*
-X011423Y005336D02*
-X011445Y005314D01*
-X012100Y005314D01*
-X011880Y005600D02*
-X011878Y005600D01*
-X011878Y005759D02*
-X013822Y005759D01*
-X013822Y005917D02*
-X011878Y005917D01*
-X011878Y006076D02*
-X013822Y006076D01*
-X013822Y006234D02*
-X011878Y006234D01*
-X011878Y006393D02*
-X013822Y006393D01*
-X013822Y006551D02*
-X013680Y006551D01*
-X013320Y006551D02*
-X011878Y006551D01*
-X011878Y006710D02*
-X013176Y006710D01*
-X013142Y006868D02*
-X011878Y006868D01*
-X012902Y007027D02*
-X013180Y007027D01*
-X013060Y007185D02*
-X013339Y007185D01*
-X013219Y007344D02*
-X013865Y007344D01*
-X013802Y007185D02*
-X013661Y007185D01*
-X013507Y006872D02*
-X013500Y006864D01*
-X013507Y006872D02*
-X014277Y006872D01*
-X014277Y007128D02*
-X014861Y007128D01*
-X015000Y006988D01*
-X015048Y007027D02*
-X017460Y007027D01*
-X017460Y007185D02*
-X015475Y007185D01*
-X015446Y007344D02*
-X017460Y007344D01*
-X017460Y007502D02*
-X015427Y007502D01*
-X015586Y007661D02*
-X017460Y007661D01*
-X017460Y007819D02*
-X015664Y007819D01*
-X015815Y007978D02*
-X017460Y007978D01*
-X017460Y008136D02*
-X016827Y008136D01*
-X017020Y008295D02*
-X017460Y008295D01*
-X017460Y008453D02*
-X017178Y008453D01*
-X017337Y008612D02*
-X017460Y008612D01*
-X017460Y008770D02*
-X017440Y008770D01*
-X017440Y008929D02*
-X017460Y008929D01*
-X017460Y009087D02*
-X017440Y009087D01*
-X016960Y009087D02*
-X015079Y009087D01*
-X015002Y008929D02*
-X016960Y008929D01*
-X016817Y008770D02*
-X015795Y008770D01*
-X015840Y008612D02*
-X016658Y008612D01*
-X018191Y009563D02*
-X018209Y009563D01*
-X018209Y009721D02*
-X018191Y009721D01*
-X018191Y009880D02*
-X018209Y009880D01*
-X018209Y009973D02*
-X018191Y009973D01*
-X018191Y010421D01*
-X018164Y010421D01*
-X018093Y010410D01*
-X018025Y010388D01*
-X017960Y010355D01*
-X017940Y010341D01*
-X017940Y010606D01*
-X017952Y010594D01*
-X018113Y010527D01*
-X018287Y010527D01*
-X018295Y010530D01*
-X018460Y010365D01*
-X018460Y010341D01*
-X018440Y010355D01*
-X018375Y010388D01*
-X018307Y010410D01*
-X018236Y010421D01*
-X018209Y010421D01*
-X018209Y009973D01*
-X018209Y010038D02*
-X018191Y010038D01*
-X018191Y010197D02*
-X018209Y010197D01*
-X018209Y010355D02*
-X018191Y010355D01*
-X018311Y010514D02*
-X017940Y010514D01*
-X017940Y010355D02*
-X017960Y010355D01*
-X018440Y010355D02*
-X018460Y010355D01*
-X018700Y010464D02*
-X018200Y010964D01*
-X018700Y010464D02*
-X018700Y007414D01*
-X016622Y005336D01*
-X014277Y005336D01*
-X014277Y005592D02*
-X016478Y005592D01*
-X017700Y006814D01*
-X017415Y006868D02*
-X015475Y006868D01*
-X015475Y006710D02*
-X017256Y006710D01*
-X017098Y006551D02*
-X015869Y006551D01*
-X015984Y006393D02*
-X016939Y006393D01*
-X016781Y006234D02*
-X016008Y006234D01*
-X015960Y006076D02*
-X016622Y006076D01*
-X016464Y005917D02*
-X015748Y005917D01*
-X015552Y005917D02*
-X015454Y005917D01*
-X015650Y006264D02*
-X015024Y006264D01*
-X015000Y006240D01*
-X014952Y007185D02*
-X015048Y007185D01*
-X015048Y007344D02*
-X014952Y007344D01*
-X014277Y007344D02*
-X014277Y007344D01*
-X014277Y007185D02*
-X014277Y007185D01*
-X014265Y007978D02*
-X011559Y007978D01*
-X011559Y008136D02*
-X014240Y008136D01*
-X014628Y008453D02*
-X014724Y008453D01*
-X014724Y008612D02*
-X014628Y008612D01*
-X014628Y008770D02*
-X014724Y008770D01*
-X018419Y009563D02*
-X018460Y009563D01*
-X021196Y009721D02*
-X022320Y009721D01*
-X022320Y009563D02*
-X021435Y009563D01*
-X021594Y009404D02*
-X022320Y009404D01*
-X022320Y009246D02*
-X021686Y009246D01*
-X021760Y009087D02*
-X022320Y009087D01*
-X022320Y008929D02*
-X021802Y008929D01*
-X021820Y008770D02*
-X022320Y008770D01*
-X022320Y008612D02*
-X021820Y008612D01*
-X021790Y008453D02*
-X022320Y008453D01*
-X022320Y008295D02*
-X021747Y008295D01*
-X021660Y008136D02*
-X022320Y008136D01*
-X022320Y007978D02*
-X021547Y007978D01*
-X021389Y007819D02*
-X022320Y007819D01*
-X022320Y007661D02*
-X021096Y007661D01*
-X019139Y004966D02*
-X018618Y004966D01*
-X018710Y004808D02*
-X019141Y004808D01*
-X019190Y004649D02*
-X018710Y004649D01*
-X017201Y004966D02*
-X014732Y004966D01*
-X014732Y004808D02*
-X014987Y004808D01*
-X013822Y004808D02*
-X011878Y004808D01*
-X011878Y004966D02*
-X012004Y004966D01*
-X012196Y004966D02*
-X013822Y004966D01*
-X013822Y005125D02*
-X012409Y005125D01*
-X012458Y005283D02*
-X013822Y005283D01*
-X013822Y005442D02*
-X012435Y005442D01*
-X012320Y005600D02*
-X013822Y005600D01*
-X013822Y004649D02*
-X011878Y004649D01*
-X011878Y004491D02*
-X013822Y004491D01*
-X013822Y004332D02*
-X011878Y004332D01*
-X011894Y004174D02*
-X013822Y004174D01*
-X013822Y004015D02*
-X011898Y004015D01*
-X011878Y003857D02*
-X013822Y003857D01*
-X013822Y003698D02*
-X011878Y003698D01*
-X011423Y004057D02*
-X010948Y004057D01*
-X010948Y004016D01*
-X010722Y004016D01*
-X010722Y004015D02*
-X010626Y004015D01*
-X010626Y003857D02*
-X010722Y003857D01*
-X010722Y003698D02*
-X010626Y003698D01*
-X010626Y004174D02*
-X010722Y004174D01*
-X010722Y004332D02*
-X010626Y004332D01*
-X010626Y004491D02*
-X010722Y004491D01*
-X011423Y004057D02*
-X011423Y004057D01*
-X011423Y005848D02*
-X010060Y005848D01*
-X009890Y005848D02*
-X009900Y005688D01*
-X009510Y006076D02*
-X009053Y006076D01*
-X009053Y005917D02*
-X009250Y005917D01*
-X009055Y005759D02*
-X009053Y005759D01*
-X009000Y006234D02*
-X010191Y006234D01*
-X010032Y006393D02*
-X004790Y006393D01*
-X004566Y005759D02*
-X004540Y005759D01*
-X004300Y005314D02*
-X004300Y008064D01*
-X003800Y008564D01*
-X004300Y005314D02*
-X004700Y004914D01*
-X004954Y004914D01*
-X005004Y004864D01*
-X002964Y003550D02*
-X002964Y003550D01*
-X008678Y006551D02*
-X008715Y006551D01*
-X008715Y006484D02*
-X008917Y006484D01*
-X008963Y006497D01*
-X009004Y006520D01*
-X009037Y006554D01*
-X009061Y006595D01*
-X009073Y006641D01*
-X009073Y006896D01*
-X008715Y006896D01*
-X008715Y006484D01*
-X008715Y006710D02*
-X008678Y006710D01*
-X008678Y006868D02*
-X008715Y006868D01*
-X009073Y006868D02*
-X009557Y006868D01*
-X009715Y006710D02*
-X009073Y006710D01*
-X009035Y006551D02*
-X009874Y006551D01*
-X009398Y007027D02*
-X009073Y007027D01*
-X014745Y012416D02*
-X019620Y012416D01*
-X019580Y012574D02*
-X014745Y012574D01*
-X014250Y014964D02*
-X014250Y016088D01*
-X016722Y017488D02*
-X017073Y017488D01*
-X016941Y017329D02*
-X016881Y017329D01*
-X017627Y017488D02*
-X018073Y017488D01*
-X017941Y017329D02*
-X017759Y017329D01*
-X017810Y017171D02*
-X017890Y017171D01*
-X017890Y017012D02*
-X017810Y017012D01*
-X017810Y016854D02*
-X017890Y016854D01*
-X017890Y016695D02*
-X017810Y016695D01*
-X017810Y016537D02*
-X017890Y016537D01*
-X017908Y016378D02*
-X017792Y016378D01*
-X017706Y016220D02*
-X017994Y016220D01*
-X018706Y016220D02*
-X019139Y016220D01*
-X019158Y016378D02*
-X018792Y016378D01*
-X018810Y016537D02*
-X019207Y016537D01*
-X019256Y016695D02*
-X018810Y016695D01*
-X018810Y016854D02*
-X019328Y016854D01*
-X019436Y017012D02*
-X018810Y017012D01*
-X018810Y017171D02*
-X019544Y017171D01*
-X019722Y017329D02*
-X018759Y017329D01*
-X018627Y017488D02*
-X019921Y017488D01*
-X021473Y013525D02*
-X022320Y013525D01*
-X022320Y013367D02*
-X021617Y013367D01*
-X021708Y013208D02*
-X022320Y013208D01*
-X022320Y013050D02*
-X021770Y013050D01*
-X021812Y012891D02*
-X022320Y012891D01*
-X022320Y012733D02*
-X021820Y012733D01*
-X021820Y012574D02*
-X022320Y012574D01*
-X022320Y012416D02*
-X021780Y012416D01*
-X021729Y012257D02*
-X022320Y012257D01*
-X022320Y012099D02*
-X021638Y012099D01*
-X021510Y011940D02*
-X022320Y011940D01*
-X022320Y011782D02*
-X021325Y011782D01*
-X017110Y004808D02*
-X017010Y004808D01*
-X016972Y004174D02*
-X017110Y004174D01*
-X016255Y004174D02*
-X016145Y004174D01*
-X016183Y004332D02*
-X016217Y004332D01*
-X000856Y012257D02*
-X000780Y012257D01*
-X000780Y012891D02*
-X000876Y012891D01*
-D26*
-X004150Y011564D03*
-X006500Y013714D03*
-X010000Y015114D03*
-X011650Y013164D03*
-X013300Y011464D03*
-X013350Y010114D03*
-X013550Y008764D03*
-X013500Y006864D03*
-X012100Y005314D03*
-X009250Y004064D03*
-X015200Y004514D03*
-X015650Y006264D03*
-X015850Y009914D03*
-X014250Y014964D03*
-D27*
-X011650Y013164D02*
-X011348Y013467D01*
-X010000Y013467D01*
-X009952Y013514D01*
-X009500Y013514D01*
-X009050Y013964D01*
-X009050Y017164D01*
-X009300Y017414D01*
-X016400Y017414D01*
-X017000Y016814D01*
-X017350Y016814D01*
-X014250Y010982D02*
-X014052Y010784D01*
-X012630Y010784D01*
-X012632Y009447D02*
-X012630Y009444D01*
-X012632Y009447D02*
-X014250Y009447D01*
-X013550Y008764D02*
-X012640Y008764D01*
-X012630Y008774D01*
-M02*
+G75*%MOIN*%%OFA0B0*%%FSLAX24Y24*%%IPPOS*%%LPD*%G04This is a comment,:*%AMOC8*5,1,8,0,0,1.08239,22.5*%%ADD10C,0.0000*%%ADD11R,0.0260X0.0800*%%ADD12R,0.0591X0.0157*%%ADD13R,0.4098X0.4252*%%ADD14R,0.0850X0.0420*%%ADD15R,0.0630X0.1575*%%ADD16R,0.0591X0.0512*%%ADD17R,0.0512X0.0591*%%ADD18R,0.0630X0.1535*%%ADD19R,0.1339X0.0748*%%ADD20C,0.0004*%%ADD21C,0.0554*%%ADD22R,0.0394X0.0500*%%ADD23C,0.0600*%%ADD24R,0.0472X0.0472*%%ADD25C,0.0160*%%ADD26C,0.0396*%%ADD27C,0.0240*%D10*X000300Y003064D02*X000300Y018064D01*X022800Y018064D01*X022800Y003064D01*X000300Y003064D01*X001720Y005114D02*X001722Y005164D01*X001728Y005214D01*X001738Y005263D01*X001752Y005311D01*X001769Y005358D01*X001790Y005403D01*X001815Y005447D01*X001843Y005488D01*X001875Y005527D01*X001909Y005564D01*X001946Y005598D01*X001986Y005628D01*X002028Y005655D01*X002072Y005679D01*X002118Y005700D01*X002165Y005716D01*X002213Y005729D01*X002263Y005738D01*X002312Y005743D01*X002363Y005744D01*X002413Y005741D01*X002462Y005734D01*X002511Y005723D01*X002559Y005708D01*X002605Y005690D01*X002650Y005668D01*X002693Y005642D01*X002734Y005613D01*X002773Y005581D01*X002809Y005546D01*X002841Y005508D01*X002871Y005468D01*X002898Y005425D01*X002921Y005381D01*X002940Y005335D01*X002956Y005287D01*X002968Y005238D01*X002976Y005189D01*X002980Y005139D01*X002980Y005089D01*X002976Y005039D01*X002968Y004990D01*X002956Y004941D01*X002940Y004893D01*X002921Y004847D01*X002898Y004803D01*X002871Y004760D01*X002841Y004720D01*X002809Y004682D01*X002773Y004647D01*X002734Y004615D01*X002693Y004586D01*X002650Y004560D01*X002605Y004538D01*X002559Y004520D01*X002511Y004505D01*X002462Y004494D01*X002413Y004487D01*X002363Y004484D01*X002312Y004485D01*X002263Y004490D01*X002213Y004499D01*X002165Y004512D01*X002118Y004528D01*X002072Y004549D01*X002028Y004573D01*X001986Y004600D01*X001946Y004630D01*X001909Y004664D01*X001875Y004701D01*X001843Y004740D01*X001815Y004781D01*X001790Y004825D01*X001769Y004870D01*X001752Y004917D01*X001738Y004965D01*X001728Y005014D01*X001722Y005064D01*X001720Y005114D01*X001670Y016064D02*X001672Y016114D01*X001678Y016164D01*X001688Y016213D01*X001702Y016261D01*X001719Y016308D01*X001740Y016353D01*X001765Y016397D01*X001793Y016438D01*X001825Y016477D01*X001859Y016514D01*X001896Y016548D01*X001936Y016578D01*X001978Y016605D01*X002022Y016629D01*X002068Y016650D01*X002115Y016666D01*X002163Y016679D01*X002213Y016688D01*X002262Y016693D01*X002313Y016694D01*X002363Y016691D01*X002412Y016684D01*X002461Y016673D01*X002509Y016658D01*X002555Y016640D01*X002600Y016618D01*X002643Y016592D01*X002684Y016563D01*X002723Y016531D01*X002759Y016496D01*X002791Y016458D01*X002821Y016418D01*X002848Y016375D01*X002871Y016331D01*X002890Y016285D01*X002906Y016237D01*X002918Y016188D01*X002926Y016139D01*X002930Y016089D01*X002930Y016039D01*X002926Y015989D01*X002918Y015940D01*X002906Y015891D01*X002890Y015843D01*X002871Y015797D01*X002848Y015753D01*X002821Y015710D01*X002791Y015670D01*X002759Y015632D01*X002723Y015597D01*X002684Y015565D01*X002643Y015536D01*X002600Y015510D01*X002555Y015488D01*X002509Y015470D01*X002461Y015455D01*X002412Y015444D01*X002363Y015437D01*X002313Y015434D01*X002262Y015435D01*X002213Y015440D01*X002163Y015449D01*X002115Y015462D01*X002068Y015478D01*X002022Y015499D01*X001978Y015523D01*X001936Y015550D01*X001896Y015580D01*X001859Y015614D01*X001825Y015651D01*X001793Y015690D01*X001765Y015731D01*X001740Y015775D01*X001719Y015820D01*X001702Y015867D01*X001688Y015915D01*X001678Y015964D01*X001672Y016014D01*X001670Y016064D01*X020060Y012714D02*X020062Y012764D01*X020068Y012814D01*X020078Y012863D01*X020091Y012912D01*X020109Y012959D01*X020130Y013005D01*X020154Y013048D01*X020182Y013090D01*X020213Y013130D01*X020247Y013167D01*X020284Y013201D01*X020324Y013232D01*X020366Y013260D01*X020409Y013284D01*X020455Y013305D01*X020502Y013323D01*X020551Y013336D01*X020600Y013346D01*X020650Y013352D01*X020700Y013354D01*X020750Y013352D01*X020800Y013346D01*X020849Y013336D01*X020898Y013323D01*X020945Y013305D01*X020991Y013284D01*X021034Y013260D01*X021076Y013232D01*X021116Y013201D01*X021153Y013167D01*X021187Y013130D01*X021218Y013090D01*X021246Y013048D01*X021270Y013005D01*X021291Y012959D01*X021309Y012912D01*X021322Y012863D01*X021332Y012814D01*X021338Y012764D01*X021340Y012714D01*X021338Y012664D01*X021332Y012614D01*X021322Y012565D01*X021309Y012516D01*X021291Y012469D01*X021270Y012423D01*X021246Y012380D01*X021218Y012338D01*X021187Y012298D01*X021153Y012261D01*X021116Y012227D01*X021076Y012196D01*X021034Y012168D01*X020991Y012144D01*X020945Y012123D01*X020898Y012105D01*X020849Y012092D01*X020800Y012082D01*X020750Y012076D01*X020700Y012074D01*X020650Y012076D01*X020600Y012082D01*X020551Y012092D01*X020502Y012105D01*X020455Y012123D01*X020409Y012144D01*X020366Y012168D01*X020324Y012196D01*X020284Y012227D01*X020247Y012261D01*X020213Y012298D01*X020182Y012338D01*X020154Y012380D01*X020130Y012423D01*X020109Y012469D01*X020091Y012516D01*X020078Y012565D01*X020068Y012614D01*X020062Y012664D01*X020060Y012714D01*X020170Y016064D02*X020172Y016114D01*X020178Y016164D01*X020188Y016213D01*X020202Y016261D01*X020219Y016308D01*X020240Y016353D01*X020265Y016397D01*X020293Y016438D01*X020325Y016477D01*X020359Y016514D01*X020396Y016548D01*X020436Y016578D01*X020478Y016605D01*X020522Y016629D01*X020568Y016650D01*X020615Y016666D01*X020663Y016679D01*X020713Y016688D01*X020762Y016693D01*X020813Y016694D01*X020863Y016691D01*X020912Y016684D01*X020961Y016673D01*X021009Y016658D01*X021055Y016640D01*X021100Y016618D01*X021143Y016592D01*X021184Y016563D01*X021223Y016531D01*X021259Y016496D01*X021291Y016458D01*X021321Y016418D01*X021348Y016375D01*X021371Y016331D01*X021390Y016285D01*X021406Y016237D01*X021418Y016188D01*X021426Y016139D01*X021430Y016089D01*X021430Y016039D01*X021426Y015989D01*X021418Y015940D01*X021406Y015891D01*X021390Y015843D01*X021371Y015797D01*X021348Y015753D01*X021321Y015710D01*X021291Y015670D01*X021259Y015632D01*X021223Y015597D01*X021184Y015565D01*X021143Y015536D01*X021100Y015510D01*X021055Y015488D01*X021009Y015470D01*X020961Y015455D01*X020912Y015444D01*X020863Y015437D01*X020813Y015434D01*X020762Y015435D01*X020713Y015440D01*X020663Y015449D01*X020615Y015462D01*X020568Y015478D01*X020522Y015499D01*X020478Y015523D01*X020436Y015550D01*X020396Y015580D01*X020359Y015614D01*X020325Y015651D01*X020293Y015690D01*X020265Y015731D01*X020240Y015775D01*X020219Y015820D01*X020202Y015867D01*X020188Y015915D01*X020178Y015964D01*X020172Y016014D01*X020170Y016064D01*X020060Y008714D02*X020062Y008764D01*X020068Y008814D01*X020078Y008863D01*X020091Y008912D01*X020109Y008959D01*X020130Y009005D01*X020154Y009048D01*X020182Y009090D01*X020213Y009130D01*X020247Y009167D01*X020284Y009201D01*X020324Y009232D01*X020366Y009260D01*X020409Y009284D01*X020455Y009305D01*X020502Y009323D01*X020551Y009336D01*X020600Y009346D01*X020650Y009352D01*X020700Y009354D01*X020750Y009352D01*X020800Y009346D01*X020849Y009336D01*X020898Y009323D01*X020945Y009305D01*X020991Y009284D01*X021034Y009260D01*X021076Y009232D01*X021116Y009201D01*X021153Y009167D01*X021187Y009130D01*X021218Y009090D01*X021246Y009048D01*X021270Y009005D01*X021291Y008959D01*X021309Y008912D01*X021322Y008863D01*X021332Y008814D01*X021338Y008764D01*X021340Y008714D01*X021338Y008664D01*X021332Y008614D01*X021322Y008565D01*X021309Y008516D01*X021291Y008469D01*X021270Y008423D01*X021246Y008380D01*X021218Y008338D01*X021187Y008298D01*X021153Y008261D01*X021116Y008227D01*X021076Y008196D01*X021034Y008168D01*X020991Y008144D01*X020945Y008123D01*X020898Y008105D01*X020849Y008092D01*X020800Y008082D01*X020750Y008076D01*X020700Y008074D01*X020650Y008076D01*X020600Y008082D01*X020551Y008092D01*X020502Y008105D01*X020455Y008123D01*X020409Y008144D01*X020366Y008168D01*X020324Y008196D01*X020284Y008227D01*X020247Y008261D01*X020213Y008298D01*X020182Y008338D01*X020154Y008380D01*X020130Y008423D01*X020109Y008469D01*X020091Y008516D01*X020078Y008565D01*X020068Y008614D01*X020062Y008664D01*X020060Y008714D01*X020170Y005064D02*X020172Y005114D01*X020178Y005164D01*X020188Y005213D01*X020202Y005261D01*X020219Y005308D01*X020240Y005353D01*X020265Y005397D01*X020293Y005438D01*X020325Y005477D01*X020359Y005514D01*X020396Y005548D01*X020436Y005578D01*X020478Y005605D01*X020522Y005629D01*X020568Y005650D01*X020615Y005666D01*X020663Y005679D01*X020713Y005688D01*X020762Y005693D01*X020813Y005694D01*X020863Y005691D01*X020912Y005684D01*X020961Y005673D01*X021009Y005658D01*X021055Y005640D01*X021100Y005618D01*X021143Y005592D01*X021184Y005563D01*X021223Y005531D01*X021259Y005496D01*X021291Y005458D01*X021321Y005418D01*X021348Y005375D01*X021371Y005331D01*X021390Y005285D01*X021406Y005237D01*X021418Y005188D01*X021426Y005139D01*X021430Y005089D01*X021430Y005039D01*X021426Y004989D01*X021418Y004940D01*X021406Y004891D01*X021390Y004843D01*X021371Y004797D01*X021348Y004753D01*X021321Y004710D01*X021291Y004670D01*X021259Y004632D01*X021223Y004597D01*X021184Y004565D01*X021143Y004536D01*X021100Y004510D01*X021055Y004488D01*X021009Y004470D01*X020961Y004455D01*X020912Y004444D01*X020863Y004437D01*X020813Y004434D01*X020762Y004435D01*X020713Y004440D01*X020663Y004449D01*X020615Y004462D01*X020568Y004478D01*X020522Y004499D01*X020478Y004523D01*X020436Y004550D01*X020396Y004580D01*X020359Y004614D01*X020325Y004651D01*X020293Y004690D01*X020265Y004731D01*X020240Y004775D01*X020219Y004820D01*X020202Y004867D01*X020188Y004915D01*X020178Y004964D01*X020172Y005014D01*X020170Y005064D01*D11*X006500Y010604D03*X006000Y010604D03*X005500Y010604D03*X005000Y010604D03*X005000Y013024D03*X005500Y013024D03*X006000Y013024D03*X006500Y013024D03*D12*X011423Y007128D03*X011423Y006872D03*X011423Y006616D03*X011423Y006360D03*X011423Y006104D03*X011423Y005848D03*X011423Y005592D03*X011423Y005336D03*X011423Y005080D03*X011423Y004825D03*X011423Y004569D03*X011423Y004313D03*X011423Y004057D03*X011423Y003801D03*X014277Y003801D03*X014277Y004057D03*X014277Y004313D03*X014277Y004569D03*X014277Y004825D03*X014277Y005080D03*X014277Y005336D03*X014277Y005592D03*X014277Y005848D03*X014277Y006104D03*X014277Y006360D03*X014277Y006616D03*X014277Y006872D03*X014277Y007128D03*D13*X009350Y010114D03*D14*X012630Y010114D03*X012630Y010784D03*X012630Y011454D03*X012630Y009444D03*X012630Y008774D03*D15*X010000Y013467D03*X010000Y016262D03*D16*X004150Y012988D03*X004150Y012240D03*X009900Y005688D03*X009900Y004940D03*X015000Y006240D03*X015000Y006988D03*D17*X014676Y008364D03*X015424Y008364D03*X017526Y004514D03*X018274Y004514D03*X010674Y004064D03*X009926Y004064D03*X004174Y009564D03*X003426Y009564D03*X005376Y014564D03*X006124Y014564D03*D18*X014250Y016088D03*X014250Y012741D03*D19*X014250Y010982D03*X014250Y009447D03*D20*X022869Y007639D02*X022869Y013789D01*D21*X018200Y011964D03*X017200Y011464D03*X017200Y010464D03*X018200Y009964D03*X018200Y010964D03*X017200Y009464D03*D22*X008696Y006914D03*X008696Y005864D03*X008696Y004864D03*X008696Y003814D03*X005004Y003814D03*X005004Y004864D03*X005004Y005864D03*X005004Y006914D03*D23*X001800Y008564D02*X001200Y008564D01*X001200Y009564D02*X001800Y009564D01*X001800Y010564D02*X001200Y010564D01*X001200Y011564D02*X001800Y011564D01*X001800Y012564D02*X001200Y012564D01*X005350Y016664D02*X005350Y017264D01*X006350Y017264D02*X006350Y016664D01*X007350Y016664D02*X007350Y017264D01*X017350Y017114D02*X017350Y016514D01*X018350Y016514D02*X018350Y017114D01*D24*X016613Y004514D03*X015787Y004514D03*D25*X015200Y004514D01*X014868Y004649D02*X014732Y004649D01*X014842Y004586D02*X014842Y004443D01*X014896Y004311D01*X014997Y004211D01*X015129Y004156D01*X015271Y004156D01*X015395Y004207D01*X015484Y004118D01*X016089Y004118D01*X016183Y004212D01*X016183Y004817D01*X016089Y004911D01*X015484Y004911D01*X015395Y004821D01*X015271Y004872D01*X015129Y004872D01*X014997Y004818D01*X014896Y004717D01*X014842Y004586D01*X014842Y004491D02*X014732Y004491D01*X014732Y004332D02*X014888Y004332D01*X014732Y004174D02*X015086Y004174D01*X015314Y004174D02*X015428Y004174D01*X014732Y004015D02*X019505Y004015D01*X019568Y003922D02*X019568Y003922D01*X019568Y003922D01*X019286Y004335D01*X019286Y004335D01*X019139Y004814D01*X019139Y005315D01*X019286Y005793D01*X019286Y005793D01*X019568Y006207D01*X019568Y006207D01*X019960Y006519D01*X019960Y006519D01*X020426Y006702D01*X020926Y006740D01*X020926Y006740D01*X021414Y006628D01*X021414Y006628D01*X021847Y006378D01*X021847Y006378D01*X022188Y006011D01*X022188Y006011D01*X022320Y005737D01*X022320Y015392D01*X022188Y015118D01*X022188Y015118D01*X021847Y014751D01*X021847Y014751D01*X021414Y014500D01*X021414Y014500D01*X020926Y014389D01*X020926Y014389D01*X020426Y014426D01*X020426Y014426D01*X019960Y014609D01*X019960Y014609D01*X019568Y014922D01*X019568Y014922D01*X019568Y014922D01*X019286Y015335D01*X019286Y015335D01*X019139Y015814D01*X019139Y016315D01*X019286Y016793D01*X019286Y016793D01*X019568Y017207D01*X019568Y017207D01*X019568Y017207D01*X019960Y017519D01*X019960Y017519D01*X020126Y017584D01*X016626Y017584D01*X016637Y017573D01*X016924Y017287D01*X016960Y017375D01*X017089Y017504D01*X017258Y017574D01*X017441Y017574D01*X017611Y017504D01*X017740Y017375D01*X017810Y017206D01*X017810Y016423D01*X017740Y016254D01*X017611Y016124D01*X017441Y016054D01*X017258Y016054D01*X017089Y016124D01*X016960Y016254D01*X016890Y016423D01*X016890Y016557D01*X016841Y016577D01*X016284Y017134D01*X010456Y017134D01*X010475Y017116D01*X010475Y016310D01*X010475Y016310D01*X010495Y016216D01*X010477Y016123D01*X010475Y016120D01*X010475Y015408D01*X010381Y015315D01*X010305Y015315D01*X010358Y015186D01*X010358Y015043D01*X010304Y014911D01*X010203Y014811D01*X010071Y014756D01*X009929Y014756D01*X009797Y014811D01*X009696Y014911D01*X009642Y015043D01*X009642Y015186D01*X009695Y015315D01*X009619Y015315D01*X009525Y015408D01*X009525Y017116D01*X009544Y017134D01*X009416Y017134D01*X009330Y017048D01*X009330Y014080D01*X009525Y013885D01*X009525Y014320D01*X009619Y014414D01*X010381Y014414D01*X010475Y014320D01*X010475Y013747D01*X011403Y013747D01*X011506Y013704D01*X011688Y013522D01*X011721Y013522D01*X011853Y013468D01*X011954Y013367D01*X013755Y013367D01*X013755Y013525D02*X011685Y013525D01*X011526Y013684D02*X013893Y013684D01*X013911Y013689D02*X013866Y013677D01*X013825Y013653D01*X013791Y013619D01*X013767Y013578D01*X013755Y013533D01*X013755Y012819D01*X014173Y012819D01*X014173Y013689D01*X013911Y013689D01*X014173Y013684D02*X014327Y013684D01*X014327Y013689D02*X014327Y012819D01*X014173Y012819D01*X014173Y012664D01*X014327Y012664D01*X014327Y011793D01*X014589Y011793D01*X014634Y011806D01*X014675Y011829D01*X014709Y011863D01*X014733Y011904D01*X014745Y011950D01*X014745Y012664D01*X014327Y012664D01*X014327Y012819D01*X014745Y012819D01*X014745Y013533D01*X014733Y013578D01*X014709Y013619D01*X014675Y013653D01*X014634Y013677D01*X014589Y013689D01*X014327Y013689D01*X014327Y013525D02*X014173Y013525D01*X014173Y013367D02*X014327Y013367D01*X014327Y013208D02*X014173Y013208D01*X014173Y013050D02*X014327Y013050D01*X014327Y012891D02*X014173Y012891D01*X014173Y012733D02*X010475Y012733D01*X010475Y012613D02*X010475Y013187D01*X011232Y013187D01*X011292Y013126D01*X011292Y013093D01*X011346Y012961D01*X011447Y012861D01*X011579Y012806D01*X011721Y012806D01*X011853Y012861D01*X011954Y012961D01*X012008Y013093D01*X012008Y013236D01*X011954Y013367D01*X012008Y013208D02*X013755Y013208D01*X013755Y013050D02*X011990Y013050D01*X011883Y012891D02*X013755Y012891D01*X013755Y012664D02*X013755Y011950D01*X013767Y011904D01*X013791Y011863D01*X013825Y011829D01*X013866Y011806D01*X013911Y011793D01*X014173Y011793D01*X014173Y012664D01*X013755Y012664D01*X013755Y012574D02*X010436Y012574D01*X010475Y012613D02*X010381Y012519D01*X009619Y012519D01*X009525Y012613D01*X009525Y013234D01*X009444Y013234D01*X009341Y013277D01*X009263Y013356D01*X009263Y013356D01*X008813Y013806D01*X008770Y013909D01*X008770Y017220D01*X008813Y017323D01*X009074Y017584D01*X007681Y017584D01*X007740Y017525D01*X007810Y017356D01*X007810Y016573D01*X007740Y016404D01*X007611Y016274D01*X007441Y016204D01*X007258Y016204D01*X007089Y016274D01*X006960Y016404D01*X006890Y016573D01*X006890Y017356D01*X006960Y017525D01*X007019Y017584D01*X006681Y017584D01*X006740Y017525D01*X006810Y017356D01*X006810Y016573D01*X006740Y016404D01*X006611Y016274D01*X006590Y016266D01*X006590Y015367D01*X006553Y015278D01*X006340Y015065D01*X006340Y015020D01*X006446Y015020D01*X006540Y014926D01*X006540Y014203D01*X006446Y014109D01*X006240Y014109D01*X006240Y013961D01*X006297Y014018D01*X006429Y014072D01*X006571Y014072D01*X006703Y014018D01*X006804Y013917D01*X006858Y013786D01*X006858Y013643D01*X006804Y013511D01*X006786Y013494D01*X006790Y013491D01*X006790Y012558D01*X006696Y012464D01*X006304Y012464D01*X006250Y012518D01*X006196Y012464D01*X005804Y012464D01*X005750Y012518D01*X005696Y012464D01*X005304Y012464D01*X005264Y012504D01*X005241Y012480D01*X005199Y012457D01*X005154Y012444D01*X005000Y012444D01*X005000Y013024D01*X005000Y013024D01*X005000Y012444D01*X004846Y012444D01*X004801Y012457D01*X004759Y012480D01*X004726Y012514D01*X004702Y012555D01*X004690Y012601D01*X004690Y013024D01*X005000Y013024D01*X005000Y013024D01*X004964Y012988D01*X004150Y012988D01*X004198Y012940D02*X004198Y013036D01*X004625Y013036D01*X004625Y013268D01*X004613Y013314D01*X004589Y013355D01*X004556Y013388D01*X004515Y013412D01*X004469Y013424D01*X004198Y013424D01*X004198Y013036D01*X004102Y013036D01*X004102Y012940D01*X003675Y012940D01*X003675Y012709D01*X003687Y012663D01*X003711Y012622D01*X003732Y012600D01*X003695Y012562D01*X003695Y011918D01*X003788Y011824D01*X003904Y011824D01*X003846Y011767D01*X003792Y011636D01*X003792Y011493D01*X003846Y011361D01*X003947Y011261D01*X004079Y011206D01*X004221Y011206D01*X004353Y011261D01*X004454Y011361D01*X004508Y011493D01*X004508Y011636D01*X004454Y011767D01*X004396Y011824D01*X004512Y011824D01*X004605Y011918D01*X004605Y012562D01*X004568Y012600D01*X004589Y012622D01*X004613Y012663D01*X004625Y012709D01*X004625Y012940D01*X004198Y012940D01*X004198Y013050D02*X004102Y013050D01*X004102Y013036D02*X004102Y013424D01*X003831Y013424D01*X003785Y013412D01*X003744Y013388D01*X003711Y013355D01*X003687Y013314D01*X003675Y013268D01*X003675Y013036D01*X004102Y013036D01*X004102Y013208D02*X004198Y013208D01*X004198Y013367D02*X004102Y013367D01*X003723Y013367D02*X000780Y013367D01*X000780Y013525D02*X004720Y013525D01*X004726Y013535D02*X004702Y013494D01*X004690Y013448D01*X004690Y013024D01*X005000Y013024D01*X005000Y012264D01*X005750Y011514D01*X005750Y010604D01*X005500Y010604D01*X005500Y010024D01*X005654Y010024D01*X005699Y010037D01*X005741Y010060D01*X005750Y010070D01*X005759Y010060D01*X005801Y010037D01*X005846Y010024D01*X006000Y010024D01*X006154Y010024D01*X006199Y010037D01*X006241Y010060D01*X006260Y010080D01*X006260Y008267D01*X006297Y008178D01*X006364Y008111D01*X006364Y008111D01*X006821Y007654D01*X006149Y007654D01*X005240Y008564D01*X005240Y010080D01*X005259Y010060D01*X005301Y010037D01*X005346Y010024D01*X005500Y010024D01*X005500Y010604D01*X005500Y010604D01*X005500Y010604D01*X005690Y010604D01*X006000Y010604D01*X006000Y010024D01*X006000Y010604D01*X006000Y010604D01*X006000Y010604D01*X005750Y010604D01*X005500Y010604D02*X006000Y010604D01*X006000Y011184D01*X005846Y011184D01*X005801Y011172D01*X005759Y011148D01*X005741Y011148D01*X005699Y011172D01*X005654Y011184D01*X005500Y011184D01*X005346Y011184D01*X005301Y011172D01*X005259Y011148D01*X005213Y011148D01*X005196Y011164D02*X005236Y011125D01*X005259Y011148D01*X005196Y011164D02*X004804Y011164D01*X004710Y011071D01*X004710Y010138D01*X004760Y010088D01*X004760Y009309D01*X004753Y009324D01*X004590Y009488D01*X004590Y009926D01*X004496Y010020D01*X003852Y010020D01*X003800Y009968D01*X003748Y010020D01*X003104Y010020D01*X003010Y009926D01*X003010Y009804D01*X002198Y009804D01*X002190Y009825D01*X002061Y009954D01*X001891Y010024D01*X001108Y010024D01*X000939Y009954D01*X000810Y009825D01*X000780Y009752D01*X000780Y010376D01*X000810Y010304D01*X000939Y010174D01*X001108Y010104D01*X001891Y010104D01*X002061Y010174D01*X002190Y010304D01*X002260Y010473D01*X002260Y010656D01*X002190Y010825D01*X002061Y010954D01*X001891Y011024D01*X001108Y011024D01*X000939Y010954D01*X000810Y010825D01*X000780Y010752D01*X000780Y011376D01*X000810Y011304D01*X000939Y011174D01*X001108Y011104D01*X001891Y011104D01*X002061Y011174D01*X002190Y011304D01*X002260Y011473D01*X002260Y011656D01*X002190Y011825D01*X002061Y011954D01*X001891Y012024D01*X001108Y012024D01*X000939Y011954D01*X000810Y011825D01*X000780Y011752D01*X000780Y012376D01*X000810Y012304D01*X000939Y012174D01*X001108Y012104D01*X001891Y012104D01*X002061Y012174D01*X002190Y012304D01*X002260Y012473D01*X002260Y012656D01*X002190Y012825D01*X002061Y012954D01*X001891Y013024D01*X001108Y013024D01*X000939Y012954D01*X000810Y012825D01*X000780Y012752D01*X000780Y015356D01*X000786Y015335D01*X001068Y014922D01*X001068Y014922D01*X001068Y014922D01*X001460Y014609D01*X001926Y014426D01*X002426Y014389D01*X002914Y014500D01*X003347Y014751D01*X003347Y014751D01*X003688Y015118D01*X003905Y015569D01*X003980Y016064D01*X003905Y016560D01*X003688Y017011D01*X003347Y017378D01*X002990Y017584D01*X005019Y017584D01*X004960Y017525D01*X004890Y017356D01*X004890Y016573D01*X004960Y016404D01*X005089Y016274D01*X005110Y016266D01*X005110Y015020D01*X005054Y015020D01*X004960Y014926D01*X004960Y014203D01*X005054Y014109D01*X005260Y014109D01*X005260Y013549D01*X005241Y013568D01*X005199Y013592D01*X005154Y013604D01*X005000Y013604D01*X004846Y013604D01*X004801Y013592D01*X004759Y013568D01*X004726Y013535D01*X004690Y013367D02*X004577Y013367D01*X004625Y013208D02*X004690Y013208D01*X004690Y013050D02*X004625Y013050D01*X004625Y012891D02*X004690Y012891D01*X004690Y012733D02*X004625Y012733D01*X004593Y012574D02*X004697Y012574D01*X004605Y012416D02*X013755Y012416D01*X013755Y012257D02*X011559Y012257D01*X011559Y012307D02*X011465Y012400D01*X007235Y012400D01*X007141Y012307D01*X007141Y008013D01*X006740Y008414D01*X006740Y010088D01*X006790Y010138D01*X006790Y011071D01*X006696Y011164D01*X006304Y011164D01*X006264Y011125D01*X006241Y011148D01*X006287Y011148D01*X006241Y011148D02*X006199Y011172D01*X006154Y011184D01*X006000Y011184D01*X006000Y010604D01*X006000Y010604D01*X006000Y010672D02*X006000Y010672D01*X006000Y010514D02*X006000Y010514D01*X006000Y010355D02*X006000Y010355D01*X006000Y010197D02*X006000Y010197D01*X006000Y010038D02*X006000Y010038D01*X006202Y010038D02*X006260Y010038D01*X006260Y009880D02*X005240Y009880D01*X005240Y010038D02*X005297Y010038D01*X005500Y010038D02*X005500Y010038D01*X005500Y010197D02*X005500Y010197D01*X005500Y010355D02*X005500Y010355D01*X005500Y010514D02*X005500Y010514D01*X005500Y010604D02*X005500Y011184D01*X005500Y010604D01*X005500Y010604D01*X005500Y010672D02*X005500Y010672D01*X005500Y010831D02*X005500Y010831D01*X005500Y010989D02*X005500Y010989D01*X005500Y011148D02*X005500Y011148D01*X005741Y011148D02*X005750Y011139D01*X005759Y011148D01*X006000Y011148D02*X006000Y011148D01*X006000Y010989D02*X006000Y010989D01*X006000Y010831D02*X006000Y010831D01*X006500Y010604D02*X006500Y008314D01*X007150Y007664D01*X009450Y007664D01*X010750Y006364D01*X011419Y006364D01*X011423Y006360D01*X011377Y006364D01*X011423Y006104D02*X010660Y006104D01*X009350Y007414D01*X006050Y007414D01*X005000Y008464D01*X005000Y010604D01*X004710Y010672D02*X002253Y010672D01*X002260Y010514D02*X004710Y010514D01*X004710Y010355D02*X002211Y010355D01*X002083Y010197D02*X004710Y010197D01*X004760Y010038D02*X000780Y010038D01*X000780Y009880D02*X000865Y009880D01*X000917Y010197D02*X000780Y010197D01*X000780Y010355D02*X000789Y010355D01*X000780Y010831D02*X000816Y010831D01*X000780Y010989D02*X001024Y010989D01*X001003Y011148D02*X000780Y011148D01*X000780Y011306D02*X000809Y011306D01*X000780Y011782D02*X000792Y011782D01*X000780Y011940D02*X000925Y011940D01*X000780Y012099D02*X003695Y012099D01*X003695Y012257D02*X002144Y012257D01*X002236Y012416D02*X003695Y012416D01*X003707Y012574D02*X002260Y012574D01*X002228Y012733D02*X003675Y012733D01*X003675Y012891D02*X002124Y012891D01*X002075Y011940D02*X003695Y011940D01*X003861Y011782D02*X002208Y011782D01*X002260Y011623D02*X003792Y011623D01*X003804Y011465D02*X002257Y011465D01*X002191Y011306D02*X003902Y011306D01*X004150Y011564D02*X004150Y012240D01*X004605Y012257D02*X007141Y012257D01*X007141Y012099D02*X004605Y012099D01*X004605Y011940D02*X007141Y011940D01*X007141Y011782D02*X004439Y011782D01*X004508Y011623D02*X007141Y011623D01*X007141Y011465D02*X004496Y011465D01*X004398Y011306D02*X007141Y011306D01*X007141Y011148D02*X006713Y011148D01*X006790Y010989D02*X007141Y010989D01*X007141Y010831D02*X006790Y010831D01*X006790Y010672D02*X007141Y010672D01*X007141Y010514D02*X006790Y010514D01*X006790Y010355D02*X007141Y010355D01*X007141Y010197D02*X006790Y010197D01*X006740Y010038D02*X007141Y010038D01*X007141Y009880D02*X006740Y009880D01*X006740Y009721D02*X007141Y009721D01*X007141Y009563D02*X006740Y009563D01*X006740Y009404D02*X007141Y009404D01*X007141Y009246D02*X006740Y009246D01*X006740Y009087D02*X007141Y009087D01*X007141Y008929D02*X006740Y008929D01*X006740Y008770D02*X007141Y008770D01*X007141Y008612D02*X006740Y008612D01*X006740Y008453D02*X007141Y008453D01*X007141Y008295D02*X006859Y008295D01*X007017Y008136D02*X007141Y008136D01*X006656Y007819D02*X005984Y007819D01*X005826Y007978D02*X006497Y007978D01*X006339Y008136D02*X005667Y008136D01*X005509Y008295D02*X006260Y008295D01*X006260Y008453D02*X005350Y008453D01*X005240Y008612D02*X006260Y008612D01*X006260Y008770D02*X005240Y008770D01*X005240Y008929D02*X006260Y008929D01*X006260Y009087D02*X005240Y009087D01*X005240Y009246D02*X006260Y009246D01*X006260Y009404D02*X005240Y009404D01*X005240Y009563D02*X006260Y009563D01*X006260Y009721D02*X005240Y009721D01*X004760Y009721D02*X004590Y009721D01*X004590Y009563D02*X004760Y009563D01*X004760Y009404D02*X004673Y009404D01*X004550Y009188D02*X004174Y009564D01*X004590Y009880D02*X004760Y009880D01*X004550Y009188D02*X004550Y006114D01*X004800Y005864D01*X005004Y005864D01*X004647Y005678D02*X004647Y005548D01*X004740Y005454D01*X005267Y005454D01*X005360Y005548D01*X005360Y006181D01*X005267Y006274D01*X004790Y006274D01*X004790Y006504D01*X005267Y006504D01*X005360Y006598D01*X005360Y007231D01*X005267Y007324D01*X004790Y007324D01*X004790Y008344D01*X004797Y008328D01*X005847Y007278D01*X005914Y007211D01*X006002Y007174D01*X008320Y007174D01*X008320Y006933D01*X008678Y006933D01*X008678Y006896D01*X008320Y006896D01*X008320Y006641D01*X008332Y006595D01*X008356Y006554D01*X008389Y006520D01*X008430Y006497D01*X008476Y006484D01*X008678Y006484D01*X008678Y006896D01*X008715Y006896D01*X008715Y006933D01*X009073Y006933D01*X009073Y007174D01*X009251Y007174D01*X010337Y006088D01*X010278Y006088D01*X010262Y006104D01*X009538Y006104D01*X009445Y006011D01*X009445Y005928D01*X009276Y005928D01*X009188Y005892D01*X009064Y005768D01*X009053Y005757D01*X009053Y006181D01*X008960Y006274D01*X008433Y006274D01*X008340Y006181D01*X008340Y005548D01*X008433Y005454D01*X008960Y005454D01*X008960Y005455D01*X008960Y005274D01*X008960Y005274D01*X008433Y005274D01*X008340Y005181D01*X008340Y004548D01*X008433Y004454D01*X008960Y004454D01*X009053Y004548D01*X009053Y004627D01*X009136Y004661D01*X009203Y004728D01*X009403Y004928D01*X009428Y004988D01*X009852Y004988D01*X009852Y004892D01*X009425Y004892D01*X009425Y004661D01*X009437Y004615D01*X009461Y004574D01*X009494Y004540D01*X009535Y004517D01*X009581Y004504D01*X009589Y004504D01*X009510Y004426D01*X009510Y004311D01*X009453Y004368D01*X009321Y004422D01*X009179Y004422D01*X009047Y004368D01*X008984Y004304D01*X008899Y004304D01*X008811Y004268D01*X008767Y004224D01*X008433Y004224D01*X008340Y004131D01*X008340Y003544D01*X005360Y003544D01*X005360Y004131D01*X005267Y004224D01*X004740Y004224D01*X004647Y004131D01*X004647Y003544D01*X002937Y003544D01*X002964Y003550D01*X003397Y003801D01*X003397Y003801D01*X003738Y004168D01*X003955Y004619D01*X004030Y005114D01*X003955Y005610D01*X003738Y006061D01*X003397Y006428D01*X002964Y006678D01*X002964Y006678D01*X002476Y006790D01*X002476Y006790D01*X001976Y006752D01*X001510Y006569D01*X001118Y006257D01*X000836Y005843D01*X000780Y005660D01*X000780Y008376D01*X000810Y008304D01*X000939Y008174D01*X001108Y008104D01*X001891Y008104D01*X002061Y008174D01*X002190Y008304D01*X002198Y008324D01*X003701Y008324D01*X004060Y007965D01*X004060Y005267D01*X004097Y005178D01*X004164Y005111D01*X004497Y004778D01*X004564Y004711D01*X004647Y004677D01*X004647Y004548D01*X004740Y004454D01*X005267Y004454D01*X005360Y004548D01*X005360Y005181D01*X005267Y005274D01*X004740Y005274D01*X004710Y005244D01*X004540Y005414D01*X004540Y005785D01*X004647Y005678D01*X004647Y005600D02*X004540Y005600D01*X004540Y005442D02*X008960Y005442D01*X008960Y005283D02*X004670Y005283D01*X004309Y004966D02*X004008Y004966D01*X004030Y005114D02*X004030Y005114D01*X004028Y005125D02*X004150Y005125D01*X004060Y005283D02*X004005Y005283D01*X003981Y005442D02*X004060Y005442D01*X004060Y005600D02*X003957Y005600D01*X003883Y005759D02*X004060Y005759D01*X004060Y005917D02*X003807Y005917D01*X003738Y006061D02*X003738Y006061D01*X003724Y006076D02*X004060Y006076D01*X004060Y006234D02*X003577Y006234D01*X003430Y006393D02*X004060Y006393D01*X004060Y006551D02*X003184Y006551D01*X003397Y006428D02*X003397Y006428D01*X002825Y006710D02*X004060Y006710D01*X004060Y006868D02*X000780Y006868D01*X000780Y006710D02*X001868Y006710D01*X001976Y006752D02*X001976Y006752D01*X001510Y006569D02*X001510Y006569D01*X001488Y006551D02*X000780Y006551D01*X000780Y006393D02*X001289Y006393D01*X001118Y006257D02*X001118Y006257D01*X001118Y006257D01*X001103Y006234D02*X000780Y006234D01*X000780Y006076D02*X000995Y006076D01*X000887Y005917D02*X000780Y005917D01*X000836Y005843D02*X000836Y005843D01*X000810Y005759D02*X000780Y005759D01*X000780Y007027D02*X004060Y007027D01*X004060Y007185D02*X000780Y007185D01*X000780Y007344D02*X004060Y007344D01*X004060Y007502D02*X000780Y007502D01*X000780Y007661D02*X004060Y007661D01*X004060Y007819D02*X000780Y007819D01*X000780Y007978D02*X004047Y007978D01*X003889Y008136D02*X001969Y008136D01*X002181Y008295D02*X003730Y008295D01*X003800Y008564D02*X001500Y008564D01*X001031Y008136D02*X000780Y008136D01*X000780Y008295D02*X000819Y008295D01*X001500Y009564D02*X003426Y009564D01*X003010Y009880D02*X002135Y009880D01*X002184Y010831D02*X004710Y010831D01*X004710Y010989D02*X001976Y010989D01*X001997Y011148D02*X004787Y011148D01*X005702Y010038D02*X005797Y010038D01*X004830Y008295D02*X004790Y008295D01*X004790Y008136D02*X004989Y008136D01*X005147Y007978D02*X004790Y007978D01*X004790Y007819D02*X005306Y007819D01*X005464Y007661D02*X004790Y007661D01*X004790Y007502D02*X005623Y007502D01*X005781Y007344D02*X004790Y007344D01*X005360Y007185D02*X005976Y007185D01*X006143Y007661D02*X006814Y007661D01*X005360Y007027D02*X008320Y007027D01*X008320Y006868D02*X005360Y006868D01*X005360Y006710D02*X008320Y006710D01*X008358Y006551D02*X005314Y006551D01*X005307Y006234D02*X008393Y006234D01*X008340Y006076D02*X005360Y006076D01*X005360Y005917D02*X008340Y005917D01*X008340Y005759D02*X005360Y005759D01*X005360Y005600D02*X008340Y005600D01*X008340Y005125D02*X005360Y005125D01*X005360Y004966D02*X008340Y004966D01*X008340Y004808D02*X005360Y004808D01*X005360Y004649D02*X008340Y004649D01*X008397Y004491D02*X005303Y004491D01*X005317Y004174D02*X008383Y004174D01*X008340Y004015D02*X005360Y004015D01*X005360Y003857D02*X008340Y003857D01*X008340Y003698D02*X005360Y003698D01*X004647Y003698D02*X003220Y003698D01*X003449Y003857D02*X004647Y003857D01*X004647Y004015D02*X003596Y004015D01*X003738Y004168D02*X003738Y004168D01*X003741Y004174D02*X004690Y004174D01*X004704Y004491D02*X003894Y004491D01*X003955Y004619D02*X003955Y004619D01*X003960Y004649D02*X004647Y004649D01*X004467Y004808D02*X003984Y004808D01*X003817Y004332D02*X009012Y004332D01*X008996Y004491D02*X009575Y004491D01*X009510Y004332D02*X009488Y004332D01*X009250Y004064D02*X008946Y004064D01*X008696Y003814D01*X009053Y003758D02*X009053Y003544D01*X020126Y003544D01*X019960Y003609D01*X019960Y003609D01*X019568Y003922D01*X019650Y003857D02*X014732Y003857D01*X014732Y003698D02*X019848Y003698D01*X019397Y004174D02*X018704Y004174D01*X018710Y004195D02*X018710Y004466D01*X018322Y004466D01*X018322Y004039D01*X018554Y004039D01*X018599Y004051D01*X018640Y004075D01*X018674Y004109D01*X018698Y004150D01*X018710Y004195D01*X018710Y004332D02*X019288Y004332D01*X019238Y004491D02*X018322Y004491D01*X018322Y004466D02*X018322Y004562D01*X018710Y004562D01*X018710Y004833D01*X018698Y004879D01*X018674Y004920D01*X018640Y004954D01*X018599Y004977D01*X018554Y004990D01*X018322Y004990D01*X018322Y004562D01*X018226Y004562D01*X018226Y004990D01*X017994Y004990D01*X017949Y004977D01*X017908Y004954D01*X017886Y004932D01*X017848Y004970D01*X017204Y004970D01*X017110Y004876D01*X017110Y004754D01*X017010Y004754D01*X017010Y004817D01*X016916Y004911D01*X016311Y004911D01*X016217Y004817D01*X016217Y004212D01*X016311Y004118D01*X016916Y004118D01*X017010Y004212D01*X017010Y004274D01*X017110Y004274D01*X017110Y004153D01*X017204Y004059D01*X017848Y004059D01*X017886Y004097D01*X017908Y004075D01*X017949Y004051D01*X017994Y004039D01*X018226Y004039D01*X018226Y004466D01*X018322Y004466D01*X018322Y004332D02*X018226Y004332D01*X018226Y004174D02*X018322Y004174D01*X018322Y004649D02*X018226Y004649D01*X018226Y004808D02*X018322Y004808D01*X018322Y004966D02*X018226Y004966D01*X017930Y004966D02*X017851Y004966D01*X017526Y004514D02*X016613Y004514D01*X016217Y004491D02*X016183Y004491D01*X016183Y004649D02*X016217Y004649D01*X016217Y004808D02*X016183Y004808D01*X016670Y005096D02*X016758Y005133D01*X018836Y007211D01*X018903Y007278D01*X018940Y007367D01*X018940Y010512D01*X018903Y010600D01*X018634Y010870D01*X018637Y010877D01*X018637Y011051D01*X018571Y011212D01*X018448Y011335D01*X018287Y011401D01*X018113Y011401D01*X017952Y011335D01*X017829Y011212D01*X017818Y011185D01*X017634Y011370D01*X017637Y011377D01*X017637Y011551D01*X017571Y011712D01*X017448Y011835D01*X017287Y011901D01*X017113Y011901D01*X016952Y011835D01*X016829Y011712D01*X016763Y011551D01*X016763Y011377D01*X016829Y011217D01*X016952Y011094D01*X017113Y011027D01*X017287Y011027D01*X017295Y011030D01*X017460Y010865D01*X017460Y010823D01*X017448Y010835D01*X017287Y010901D01*X017113Y010901D01*X016952Y010835D01*X016829Y010712D01*X016763Y010551D01*X016763Y010377D01*X016829Y010217D01*X016952Y010094D01*X017113Y010027D01*X017287Y010027D01*X017448Y010094D01*X017460Y010106D01*X017460Y009823D01*X017448Y009835D01*X017287Y009901D01*X017113Y009901D01*X016952Y009835D01*X016829Y009712D01*X016763Y009551D01*X016763Y009377D01*X016829Y009217D01*X016952Y009094D01*X016960Y009091D01*X016960Y008914D01*X016651Y008604D01*X015840Y008604D01*X015840Y008726D01*X015746Y008820D01*X015102Y008820D01*X015064Y008782D01*X015042Y008804D01*X015001Y008827D01*X014956Y008840D01*X014724Y008840D01*X014724Y008412D01*X014628Y008412D01*X014628Y008316D01*X014240Y008316D01*X014240Y008045D01*X014252Y008000D01*X014276Y007959D01*X014310Y007925D01*X014345Y007904D01*X013152Y007904D01*X013064Y007868D01*X012997Y007800D01*X012564Y007368D01*X011375Y007368D01*X011372Y007366D01*X011061Y007366D01*X010968Y007273D01*X010968Y006604D01*X010849Y006604D01*X009625Y007828D01*X011465Y007828D01*X011559Y007922D01*X011559Y012307D01*X011559Y012099D02*X013755Y012099D01*X013758Y011940D02*X011559Y011940D01*X011559Y011782D02*X012096Y011782D01*X012139Y011824D02*X012045Y011731D01*X012045Y011178D01*X012090Y011133D01*X012061Y011105D01*X012037Y011064D01*X012025Y011018D01*X012025Y010809D01*X012605Y010809D01*X012605Y010759D01*X012025Y010759D01*X012025Y010551D01*X012037Y010505D01*X012061Y010464D01*X012090Y010435D01*X012045Y010391D01*X012045Y009838D01*X012104Y009779D01*X012045Y009721D01*X012045Y009168D01*X012104Y009109D01*X012045Y009051D01*X012045Y008498D01*X012139Y008404D01*X013121Y008404D01*X013201Y008484D01*X013324Y008484D01*X013347Y008461D01*X013479Y008406D01*X013621Y008406D01*X013753Y008461D01*X013854Y008561D01*X013908Y008693D01*X013908Y008836D01*X013876Y008913D01*X014986Y008913D01*X015079Y009006D01*X015079Y009887D01*X014986Y009981D01*X013682Y009981D01*X013708Y010043D01*X013708Y010186D01*X013654Y010317D01*X013553Y010418D01*X013421Y010472D01*X013279Y010472D01*X013176Y010430D01*X013170Y010435D01*X013199Y010464D01*X013223Y010505D01*X013235Y010551D01*X013235Y010759D01*X012655Y010759D01*X012655Y010809D01*X013235Y010809D01*X013235Y011018D01*X013223Y011064D01*X013199Y011105D01*X013176Y011128D01*X013229Y011106D01*X013371Y011106D01*X013401Y011118D01*X013401Y011062D01*X014170Y011062D01*X014170Y010902D01*X014330Y010902D01*X014330Y010428D01*X014943Y010428D01*X014989Y010440D01*X015030Y010464D01*X015063Y010498D01*X015087Y010539D01*X015099Y010584D01*X015099Y010902D01*X014330Y010902D01*X014330Y011062D01*X015099Y011062D01*X015099Y011380D01*X015087Y011426D01*X015063Y011467D01*X015030Y011500D01*X014989Y011524D01*X014943Y011536D01*X014330Y011536D01*X014330Y011062D01*X014170Y011062D01*X014170Y011536D01*X013658Y011536D01*X013604Y011667D01*X013503Y011768D01*X013371Y011822D01*X013229Y011822D01*X013154Y011792D01*X013121Y011824D01*X012139Y011824D01*X012045Y011623D02*X011559Y011623D01*X011559Y011465D02*X012045Y011465D01*X012045Y011306D02*X011559Y011306D01*X011559Y011148D02*X012075Y011148D01*X012025Y010989D02*X011559Y010989D01*X011559Y010831D02*X012025Y010831D01*X012025Y010672D02*X011559Y010672D01*X011559Y010514D02*X012035Y010514D01*X012045Y010355D02*X011559Y010355D01*X011559Y010197D02*X012045Y010197D01*X012045Y010038D02*X011559Y010038D01*X011559Y009880D02*X012045Y009880D01*X012046Y009721D02*X011559Y009721D01*X011559Y009563D02*X012045Y009563D01*X012045Y009404D02*X011559Y009404D01*X011559Y009246D02*X012045Y009246D01*X012082Y009087D02*X011559Y009087D01*X011559Y008929D02*X012045Y008929D01*X012045Y008770D02*X011559Y008770D01*X011559Y008612D02*X012045Y008612D01*X012090Y008453D02*X011559Y008453D01*X011559Y008295D02*X014240Y008295D01*X014240Y008412D02*X014628Y008412D01*X014628Y008840D01*X014396Y008840D01*X014351Y008827D01*X014310Y008804D01*X014276Y008770D01*X014252Y008729D01*X014240Y008683D01*X014240Y008412D01*X014240Y008453D02*X013735Y008453D01*X013874Y008612D02*X014240Y008612D01*X014276Y008770D02*X013908Y008770D01*X013365Y008453D02*X013170Y008453D01*X013016Y007819D02*X009634Y007819D01*X009793Y007661D02*X012857Y007661D01*X012699Y007502D02*X009951Y007502D01*X010110Y007344D02*X011039Y007344D01*X010968Y007185D02*X010268Y007185D01*X010427Y007027D02*X010968Y007027D01*X010968Y006868D02*X010585Y006868D01*X010744Y006710D02*X010968Y006710D01*X011423Y007128D02*X012663Y007128D01*X013200Y007664D01*X015250Y007664D01*X015424Y007838D01*X015424Y008364D01*X016750Y008364D01*X017200Y008814D01*X017200Y009464D01*X016817Y009246D02*X015079Y009246D01*X015079Y009404D02*X016763Y009404D01*X016768Y009563D02*X015079Y009563D01*X015079Y009721D02*X016839Y009721D01*X017061Y009880D02*X015079Y009880D01*X015073Y010514D02*X016763Y010514D01*X016772Y010355D02*X013615Y010355D01*X013557Y010428D02*X014170Y010428D01*X014170Y010902D01*X013401Y010902D01*X013401Y010584D01*X013413Y010539D01*X013437Y010498D01*X013470Y010464D01*X013511Y010440D01*X013557Y010428D01*X013427Y010514D02*X013225Y010514D01*X013235Y010672D02*X013401Y010672D01*X013401Y010831D02*X013235Y010831D01*X013235Y010989D02*X014170Y010989D01*X014170Y010831D02*X014330Y010831D01*X014330Y010989D02*X017336Y010989D01*X017452Y010831D02*X017460Y010831D01*X017700Y010964D02*X017200Y011464D01*X016792Y011306D02*X015099Y011306D01*X015099Y011148D02*X016898Y011148D01*X016948Y010831D02*X015099Y010831D01*X015099Y010672D02*X016813Y010672D01*X016849Y010197D02*X013703Y010197D01*X013706Y010038D02*X017086Y010038D01*X017314Y010038D02*X017460Y010038D01*X017460Y009880D02*X017339Y009880D01*X017940Y009588D02*X017960Y009573D01*X018025Y009541D01*X018093Y009518D01*X018164Y009507D01*X018191Y009507D01*X018191Y009956D01*X018209Y009956D01*X018209Y009507D01*X018236Y009507D01*X018307Y009518D01*X018375Y009541D01*X018440Y009573D01*X018460Y009588D01*X018460Y007514D01*X017940Y006994D01*X017940Y009588D01*X017940Y009563D02*X017981Y009563D01*X017940Y009404D02*X018460Y009404D01*X018460Y009246D02*X017940Y009246D01*X017940Y009087D02*X018460Y009087D01*X018460Y008929D02*X017940Y008929D01*X017940Y008770D02*X018460Y008770D01*X018460Y008612D02*X017940Y008612D01*X017940Y008453D02*X018460Y008453D01*X018460Y008295D02*X017940Y008295D01*X017940Y008136D02*X018460Y008136D01*X018460Y007978D02*X017940Y007978D01*X017940Y007819D02*X018460Y007819D01*X018460Y007661D02*X017940Y007661D01*X017940Y007502D02*X018449Y007502D01*X018290Y007344D02*X017940Y007344D01*X017940Y007185D02*X018132Y007185D01*X017973Y007027D02*X017940Y007027D01*X017700Y006814D02*X017700Y010964D01*X017697Y011306D02*X017924Y011306D01*X017952Y011594D02*X018113Y011527D01*X018287Y011527D01*X018448Y011594D01*X018571Y011717D01*X018637Y011877D01*X018637Y012051D01*X018571Y012212D01*X018448Y012335D01*X018287Y012401D01*X018113Y012401D01*X017952Y012335D01*X017829Y012212D01*X017763Y012051D01*X017763Y011877D01*X017829Y011717D01*X017952Y011594D01*X017923Y011623D02*X017607Y011623D01*X017637Y011465D02*X022320Y011465D01*X022320Y011623D02*X020956Y011623D01*X020847Y011594D02*X021132Y011671D01*X021388Y011818D01*X021596Y012027D01*X021744Y012282D01*X021820Y012567D01*X021820Y012862D01*X021744Y013147D01*X021596Y013402D01*X021388Y013611D01*X021132Y013758D01*X020847Y013834D01*X020553Y013834D01*X020268Y013758D01*X020012Y013611D01*X019804Y013402D01*X019656Y013147D01*X019580Y012862D01*X019580Y012567D01*X019656Y012282D01*X019804Y012027D01*X020012Y011818D01*X020268Y011671D01*X020553Y011594D01*X020847Y011594D01*X020444Y011623D02*X018477Y011623D01*X018598Y011782D02*X020075Y011782D01*X019890Y011940D02*X018637Y011940D01*X018617Y012099D02*X019762Y012099D01*X019671Y012257D02*X018525Y012257D01*X017875Y012257D02*X014745Y012257D01*X014745Y012099D02*X017783Y012099D01*X017763Y011940D02*X014742Y011940D01*X014327Y011940D02*X014173Y011940D01*X014173Y012099D02*X014327Y012099D01*X014327Y012257D02*X014173Y012257D01*X014173Y012416D02*X014327Y012416D01*X014327Y012574D02*X014173Y012574D01*X014327Y012733D02*X019580Y012733D01*X019588Y012891D02*X014745Y012891D01*X014745Y013050D02*X019630Y013050D01*X019692Y013208D02*X014745Y013208D01*X014745Y013367D02*X019783Y013367D01*X019927Y013525D02*X014745Y013525D01*X014607Y013684D02*X020139Y013684D01*X021261Y013684D02*X022320Y013684D01*X022320Y013842D02*X010475Y013842D01*X010475Y014001D02*X022320Y014001D01*X022320Y014159D02*X010475Y014159D01*X010475Y014318D02*X022320Y014318D01*X022320Y014476D02*X021308Y014476D01*X021647Y014635D02*X022320Y014635D01*X022320Y014793D02*X021887Y014793D01*X021847Y014751D02*X021847Y014751D01*X022034Y014952D02*X022320Y014952D01*X022320Y015110D02*X022181Y015110D01*X022261Y015269D02*X022320Y015269D01*X020299Y014476D02*X009330Y014476D01*X009330Y014318D02*X009525Y014318D01*X009525Y014159D02*X009330Y014159D01*X009409Y014001D02*X009525Y014001D01*X008935Y013684D02*X006858Y013684D01*X006835Y013842D02*X008797Y013842D01*X008770Y014001D02*X006720Y014001D01*X006496Y014159D02*X008770Y014159D01*X008770Y014318D02*X006540Y014318D01*X006540Y014476D02*X008770Y014476D01*X008770Y014635D02*X006540Y014635D01*X006540Y014793D02*X008770Y014793D01*X008770Y014952D02*X006514Y014952D01*X006385Y015110D02*X008770Y015110D01*X008770Y015269D02*X006544Y015269D01*X006590Y015427D02*X008770Y015427D01*X008770Y015586D02*X006590Y015586D01*X006590Y015744D02*X008770Y015744D01*X008770Y015903D02*X006590Y015903D01*X006590Y016061D02*X008770Y016061D01*X008770Y016220D02*X007479Y016220D01*X007221Y016220D02*X006590Y016220D01*X006715Y016378D02*X006985Y016378D01*X006905Y016537D02*X006795Y016537D01*X006810Y016695D02*X006890Y016695D01*X006890Y016854D02*X006810Y016854D01*X006810Y017012D02*X006890Y017012D01*X006890Y017171D02*X006810Y017171D01*X006810Y017329D02*X006890Y017329D01*X006945Y017488D02*X006755Y017488D01*X006350Y016964D02*X006350Y015414D01*X006100Y015164D01*X006100Y014588D01*X006124Y014564D01*X006000Y014490D01*X006000Y013024D01*X005500Y013024D02*X005500Y014440D01*X005376Y014564D01*X005350Y014590D01*X005350Y016964D01*X004890Y017012D02*X003687Y017012D01*X003688Y017011D02*X003688Y017011D01*X003764Y016854D02*X004890Y016854D01*X004890Y016695D02*X003840Y016695D01*X003905Y016560D02*X003905Y016560D01*X003909Y016537D02*X004905Y016537D01*X004985Y016378D02*X003933Y016378D01*X003957Y016220D02*X005110Y016220D01*X005110Y016061D02*X003980Y016061D01*X003980Y016064D02*X003980Y016064D01*X003956Y015903D02*X005110Y015903D01*X005110Y015744D02*X003932Y015744D01*X003908Y015586D02*X005110Y015586D01*X005110Y015427D02*X003837Y015427D01*X003761Y015269D02*X005110Y015269D01*X005110Y015110D02*X003681Y015110D01*X003688Y015118D02*X003688Y015118D01*X003534Y014952D02*X004986Y014952D01*X004960Y014793D02*X003387Y014793D01*X003347Y014751D02*X003347Y014751D01*X003147Y014635D02*X004960Y014635D01*X004960Y014476D02*X002808Y014476D01*X002914Y014500D02*X002914Y014500D01*X002426Y014389D02*X002426Y014389D01*X001926Y014426D02*X001926Y014426D01*X001799Y014476D02*X000780Y014476D01*X000780Y014318D02*X004960Y014318D01*X005004Y014159D02*X000780Y014159D01*X000780Y014001D02*X005260Y014001D01*X005260Y013842D02*X000780Y013842D01*X000780Y013684D02*X005260Y013684D01*X005000Y013604D02*X005000Y013024D01*X005000Y013604D01*X005000Y013525D02*X005000Y013525D01*X005000Y013367D02*X005000Y013367D01*X005000Y013208D02*X005000Y013208D01*X005000Y013050D02*X005000Y013050D01*X005000Y013024D02*X005000Y013024D01*X005000Y012891D02*X005000Y012891D01*X005000Y012733D02*X005000Y012733D01*X005000Y012574D02*X005000Y012574D01*X003675Y013050D02*X000780Y013050D01*X000780Y013208D02*X003675Y013208D01*X001460Y014609D02*X001460Y014609D01*X001428Y014635D02*X000780Y014635D01*X000780Y014793D02*X001229Y014793D01*X001048Y014952D02*X000780Y014952D01*X000780Y015110D02*X000940Y015110D01*X000832Y015269D02*X000780Y015269D01*X000786Y015335D02*X000786Y015335D01*X003347Y017378D02*X003347Y017378D01*X003392Y017329D02*X004890Y017329D01*X004890Y017171D02*X003539Y017171D01*X003157Y017488D02*X004945Y017488D01*X007755Y017488D02*X008978Y017488D01*X008819Y017329D02*X007810Y017329D01*X007810Y017171D02*X008770Y017171D01*X008770Y017012D02*X007810Y017012D01*X007810Y016854D02*X008770Y016854D01*X008770Y016695D02*X007810Y016695D01*X007795Y016537D02*X008770Y016537D01*X008770Y016378D02*X007715Y016378D01*X009330Y016378D02*X009525Y016378D01*X009525Y016220D02*X009330Y016220D01*X009330Y016061D02*X009525Y016061D01*X009525Y015903D02*X009330Y015903D01*X009330Y015744D02*X009525Y015744D01*X009525Y015586D02*X009330Y015586D01*X009330Y015427D02*X009525Y015427D01*X009676Y015269D02*X009330Y015269D01*X009330Y015110D02*X009642Y015110D01*X009680Y014952D02*X009330Y014952D01*X009330Y014793D02*X009839Y014793D01*X010161Y014793D02*X013933Y014793D01*X013946Y014761D02*X014047Y014661D01*X014179Y014606D01*X014321Y014606D01*X014453Y014661D01*X014554Y014761D01*X014608Y014893D01*X014608Y015036D01*X014557Y015160D01*X014631Y015160D01*X014725Y015254D01*X014725Y016922D01*X014631Y017015D01*X013869Y017015D01*X013775Y016922D01*X013775Y015254D01*X013869Y015160D01*X013943Y015160D01*X013892Y015036D01*X013892Y014893D01*X013946Y014761D01*X013892Y014952D02*X010320Y014952D01*X010358Y015110D02*X013923Y015110D01*X013775Y015269D02*X010324Y015269D01*X010475Y015427D02*X013775Y015427D01*X013775Y015586D02*X010475Y015586D01*X010475Y015744D02*X013775Y015744D01*X013775Y015903D02*X010475Y015903D01*X010475Y016061D02*X013775Y016061D01*X013775Y016220D02*X010494Y016220D01*X010475Y016378D02*X013775Y016378D01*X013775Y016537D02*X010475Y016537D01*X010475Y016695D02*X013775Y016695D01*X013775Y016854D02*X010475Y016854D01*X010475Y017012D02*X013866Y017012D01*X014634Y017012D02*X016406Y017012D01*X016564Y016854D02*X014725Y016854D01*X014725Y016695D02*X016723Y016695D01*X016890Y016537D02*X014725Y016537D01*X014725Y016378D02*X016908Y016378D01*X016994Y016220D02*X014725Y016220D01*X014725Y016061D02*X017242Y016061D01*X017458Y016061D02*X018242Y016061D01*X018258Y016054D02*X018441Y016054D01*X018611Y016124D01*X018740Y016254D01*X018810Y016423D01*X018810Y017206D01*X018740Y017375D01*X018611Y017504D01*X018441Y017574D01*X018258Y017574D01*X018089Y017504D01*X017960Y017375D01*X017890Y017206D01*X017890Y016423D01*X017960Y016254D01*X018089Y016124D01*X018258Y016054D01*X018458Y016061D02*X019139Y016061D01*X019139Y015903D02*X014725Y015903D01*X014725Y015744D02*X019160Y015744D01*X019209Y015586D02*X014725Y015586D01*X014725Y015427D02*X019258Y015427D01*X019332Y015269D02*X014725Y015269D01*X014577Y015110D02*X019440Y015110D01*X019548Y014952D02*X014608Y014952D01*X014567Y014793D02*X019729Y014793D01*X019928Y014635D02*X014390Y014635D01*X014110Y014635D02*X009330Y014635D01*X010000Y015114D02*X010000Y016262D01*X010250Y016214D01*X009525Y016537D02*X009330Y016537D01*X009330Y016695D02*X009525Y016695D01*X009525Y016854D02*X009330Y016854D01*X009330Y017012D02*X009525Y017012D01*X006280Y014001D02*X006240Y014001D01*X006500Y013714D02*X006500Y013024D01*X006790Y013050D02*X009525Y013050D01*X009525Y013208D02*X006790Y013208D01*X006790Y013367D02*X009252Y013367D01*X009093Y013525D02*X006809Y013525D01*X006790Y012891D02*X009525Y012891D01*X009525Y012733D02*X006790Y012733D01*X006790Y012574D02*X009564Y012574D01*X010475Y012891D02*X011417Y012891D01*X011310Y013050D02*X010475Y013050D01*X012630Y011454D02*X013290Y011454D01*X013300Y011464D01*X013622Y011623D02*X016793Y011623D01*X016763Y011465D02*X015064Y011465D01*X014330Y011465D02*X014170Y011465D01*X014170Y011306D02*X014330Y011306D01*X014330Y011148D02*X014170Y011148D01*X014170Y010672D02*X014330Y010672D01*X014330Y010514D02*X014170Y010514D01*X013350Y010114D02*X012630Y010114D01*X013469Y011782D02*X016899Y011782D01*X017501Y011782D02*X017802Y011782D01*X018476Y011306D02*X022320Y011306D01*X022320Y011148D02*X018597Y011148D01*X018637Y010989D02*X022320Y010989D01*X022320Y010831D02*X018673Y010831D01*X018831Y010672D02*X022320Y010672D01*X022320Y010514D02*X018939Y010514D01*X018940Y010355D02*X022320Y010355D01*X022320Y010197D02*X018940Y010197D01*X018940Y010038D02*X022320Y010038D01*X022320Y009880D02*X018940Y009880D01*X018940Y009721D02*X020204Y009721D01*X020268Y009758D02*X020012Y009611D01*X019804Y009402D01*X019656Y009147D01*X019580Y008862D01*X019580Y008567D01*X019656Y008282D01*X019804Y008027D01*X020012Y007818D01*X020268Y007671D01*X020553Y007594D01*X020847Y007594D01*X021132Y007671D01*X021388Y007818D01*X021596Y008027D01*X021744Y008282D01*X021820Y008567D01*X021820Y008862D01*X021744Y009147D01*X021596Y009402D01*X021388Y009611D01*X021132Y009758D01*X020847Y009834D01*X020553Y009834D01*X020268Y009758D01*X019965Y009563D02*X018940Y009563D01*X018940Y009404D02*X019806Y009404D01*X019714Y009246D02*X018940Y009246D01*X018940Y009087D02*X019640Y009087D01*X019598Y008929D02*X018940Y008929D01*X018940Y008770D02*X019580Y008770D01*X019580Y008612D02*X018940Y008612D01*X018940Y008453D02*X019610Y008453D01*X019653Y008295D02*X018940Y008295D01*X018940Y008136D02*X019740Y008136D01*X019853Y007978D02*X018940Y007978D01*X018940Y007819D02*X020011Y007819D01*X020304Y007661D02*X018940Y007661D01*X018940Y007502D02*X022320Y007502D01*X022320Y007344D02*X018931Y007344D01*X018810Y007185D02*X022320Y007185D01*X022320Y007027D02*X018652Y007027D01*X018493Y006868D02*X022320Y006868D01*X022320Y006710D02*X021056Y006710D01*X021547Y006551D02*X022320Y006551D01*X022320Y006393D02*X021821Y006393D01*X021981Y006234D02*X022320Y006234D01*X022320Y006076D02*X022128Y006076D01*X022233Y005917D02*X022320Y005917D01*X022309Y005759D02*X022320Y005759D01*X020528Y006710D02*X018335Y006710D01*X018176Y006551D02*X020042Y006551D01*X019801Y006393D02*X018018Y006393D01*X017859Y006234D02*X019603Y006234D01*X019479Y006076D02*X017701Y006076D01*X017542Y005917D02*X019371Y005917D01*X019276Y005759D02*X017384Y005759D01*X017225Y005600D02*X019227Y005600D01*X019178Y005442D02*X017067Y005442D01*X016908Y005283D02*X019139Y005283D01*X019139Y005125D02*X016738Y005125D01*X016670Y005096D02*X014732Y005096D01*X014732Y003656D01*X014639Y003562D01*X013916Y003562D01*X013822Y003656D01*X013822Y006632D01*X013774Y006632D01*X013703Y006561D01*X013571Y006506D01*X013429Y006506D01*X013297Y006561D01*X013196Y006661D01*X013142Y006793D01*X013142Y006936D01*X013196Y007067D01*X013297Y007168D01*X013429Y007222D01*X013571Y007222D01*X013703Y007168D01*X013759Y007112D01*X013802Y007112D01*X013802Y007128D01*X014277Y007128D01*X014277Y007386D01*X013958Y007386D01*X013912Y007374D01*X013871Y007350D01*X013838Y007317D01*X013814Y007276D01*X013802Y007230D01*X013802Y007128D01*X014277Y007128D01*X014277Y007128D01*X014277Y007128D01*X014277Y007386D01*X014592Y007386D01*X014594Y007388D01*X014635Y007412D01*X014681Y007424D01*X014952Y007424D01*X014952Y007036D01*X015048Y007036D01*X015475Y007036D01*X015475Y007268D01*X015463Y007314D01*X015439Y007355D01*X015406Y007388D01*X015365Y007412D01*X015319Y007424D01*X015048Y007424D01*X015048Y007036D01*X015048Y006940D01*X015475Y006940D01*X015475Y006709D01*X015463Y006663D01*X015439Y006622D01*X015418Y006600D01*X015449Y006569D01*X015579Y006622D01*X015721Y006622D01*X015853Y006568D01*X015954Y006467D01*X016008Y006336D01*X016008Y006193D01*X015954Y006061D01*X015853Y005961D01*X015721Y005906D01*X015579Y005906D01*X015455Y005957D01*X015455Y005918D01*X015369Y005832D01*X016379Y005832D01*X017460Y006914D01*X017460Y009106D01*X017448Y009094D01*X017440Y009091D01*X017440Y008767D01*X017403Y008678D01*X017336Y008611D01*X016886Y008161D01*X016798Y008124D01*X015840Y008124D01*X015840Y008003D01*X015746Y007909D01*X015664Y007909D01*X015664Y007791D01*X015627Y007702D01*X015453Y007528D01*X015453Y007528D01*X015386Y007461D01*X015298Y007424D01*X013299Y007424D01*X012799Y006924D01*X012711Y006888D01*X011878Y006888D01*X011878Y005599D01*X011897Y005618D01*X012029Y005672D01*X012171Y005672D01*X012303Y005618D01*X012404Y005517D01*X012458Y005386D01*X012458Y005243D01*X012404Y005111D01*X012303Y005011D01*X012171Y004956D01*X012029Y004956D01*X011897Y005011D01*X011878Y005030D01*X011878Y004218D01*X011886Y004205D01*X011898Y004159D01*X011898Y004057D01*X011423Y004057D01*X011423Y004057D01*X011898Y004057D01*X011898Y003954D01*X011886Y003909D01*X011878Y003895D01*X011878Y003656D01*X011784Y003562D01*X011061Y003562D01*X011014Y003610D01*X010999Y003601D01*X010954Y003589D01*X010722Y003589D01*X010722Y004016D01*X010626Y004016D01*X010626Y003589D01*X010394Y003589D01*X010349Y003601D01*X010308Y003625D01*X010286Y003647D01*X010248Y003609D01*X009604Y003609D01*X009510Y003703D01*X009510Y003818D01*X009453Y003761D01*X009321Y003706D01*X009179Y003706D01*X009053Y003758D01*X009053Y003698D02*X009515Y003698D01*X009250Y004064D02*X009926Y004064D01*X010286Y004482D02*X010254Y004514D01*X010265Y004517D01*X010306Y004540D01*X010339Y004574D01*X010363Y004615D01*X010375Y004661D01*X010375Y004892D01*X009948Y004892D01*X009948Y004988D01*X010375Y004988D01*X010375Y005220D01*X010363Y005266D01*X010339Y005307D01*X010318Y005328D01*X010355Y005366D01*X010355Y005608D01*X010968Y005608D01*X010968Y005481D01*X010968Y004536D01*X010954Y004540D01*X010722Y004540D01*X010722Y004112D01*X010948Y004112D01*X010948Y004057D01*X011423Y004057D01*X011406Y004040D01*X010674Y004064D01*X010722Y004016D02*X010722Y004112D01*X010626Y004112D01*X010626Y004540D01*X010394Y004540D01*X010349Y004527D01*X010308Y004504D01*X010286Y004482D01*X010277Y004491D02*X010295Y004491D01*X010372Y004649D02*X010968Y004649D01*X010968Y004808D02*X010375Y004808D01*X010375Y005125D02*X010968Y005125D01*X010968Y005283D02*X010353Y005283D01*X010355Y005442D02*X010968Y005442D01*X010968Y005600D02*X010355Y005600D01*X010060Y005848D02*X009900Y005688D01*X009324Y005688D01*X009200Y005564D01*X009200Y005064D01*X009000Y004864D01*X008696Y004864D01*X009108Y004649D02*X009428Y004649D01*X009425Y004808D02*X009283Y004808D01*X009419Y004966D02*X009852Y004966D01*X009948Y004966D02*X010968Y004966D01*X011423Y005336D02*X011445Y005314D01*X012100Y005314D01*X011880Y005600D02*X011878Y005600D01*X011878Y005759D02*X013822Y005759D01*X013822Y005917D02*X011878Y005917D01*X011878Y006076D02*X013822Y006076D01*X013822Y006234D02*X011878Y006234D01*X011878Y006393D02*X013822Y006393D01*X013822Y006551D02*X013680Y006551D01*X013320Y006551D02*X011878Y006551D01*X011878Y006710D02*X013176Y006710D01*X013142Y006868D02*X011878Y006868D01*X012902Y007027D02*X013180Y007027D01*X013060Y007185D02*X013339Y007185D01*X013219Y007344D02*X013865Y007344D01*X013802Y007185D02*X013661Y007185D01*X013507Y006872D02*X013500Y006864D01*X013507Y006872D02*X014277Y006872D01*X014277Y007128D02*X014861Y007128D01*X015000Y006988D01*X015048Y007027D02*X017460Y007027D01*X017460Y007185D02*X015475Y007185D01*X015446Y007344D02*X017460Y007344D01*X017460Y007502D02*X015427Y007502D01*X015586Y007661D02*X017460Y007661D01*X017460Y007819D02*X015664Y007819D01*X015815Y007978D02*X017460Y007978D01*X017460Y008136D02*X016827Y008136D01*X017020Y008295D02*X017460Y008295D01*X017460Y008453D02*X017178Y008453D01*X017337Y008612D02*X017460Y008612D01*X017460Y008770D02*X017440Y008770D01*X017440Y008929D02*X017460Y008929D01*X017460Y009087D02*X017440Y009087D01*X016960Y009087D02*X015079Y009087D01*X015002Y008929D02*X016960Y008929D01*X016817Y008770D02*X015795Y008770D01*X015840Y008612D02*X016658Y008612D01*X018191Y009563D02*X018209Y009563D01*X018209Y009721D02*X018191Y009721D01*X018191Y009880D02*X018209Y009880D01*X018209Y009973D02*X018191Y009973D01*X018191Y010421D01*X018164Y010421D01*X018093Y010410D01*X018025Y010388D01*X017960Y010355D01*X017940Y010341D01*X017940Y010606D01*X017952Y010594D01*X018113Y010527D01*X018287Y010527D01*X018295Y010530D01*X018460Y010365D01*X018460Y010341D01*X018440Y010355D01*X018375Y010388D01*X018307Y010410D01*X018236Y010421D01*X018209Y010421D01*X018209Y009973D01*X018209Y010038D02*X018191Y010038D01*X018191Y010197D02*X018209Y010197D01*X018209Y010355D02*X018191Y010355D01*X018311Y010514D02*X017940Y010514D01*X017940Y010355D02*X017960Y010355D01*X018440Y010355D02*X018460Y010355D01*X018700Y010464D02*X018200Y010964D01*X018700Y010464D02*X018700Y007414D01*X016622Y005336D01*X014277Y005336D01*X014277Y005592D02*X016478Y005592D01*X017700Y006814D01*X017415Y006868D02*X015475Y006868D01*X015475Y006710D02*X017256Y006710D01*X017098Y006551D02*X015869Y006551D01*X015984Y006393D02*X016939Y006393D01*X016781Y006234D02*X016008Y006234D01*X015960Y006076D02*X016622Y006076D01*X016464Y005917D02*X015748Y005917D01*X015552Y005917D02*X015454Y005917D01*X015650Y006264D02*X015024Y006264D01*X015000Y006240D01*X014952Y007185D02*X015048Y007185D01*X015048Y007344D02*X014952Y007344D01*X014277Y007344D02*X014277Y007344D01*X014277Y007185D02*X014277Y007185D01*X014265Y007978D02*X011559Y007978D01*X011559Y008136D02*X014240Y008136D01*X014628Y008453D02*X014724Y008453D01*X014724Y008612D02*X014628Y008612D01*X014628Y008770D02*X014724Y008770D01*X018419Y009563D02*X018460Y009563D01*X021196Y009721D02*X022320Y009721D01*X022320Y009563D02*X021435Y009563D01*X021594Y009404D02*X022320Y009404D01*X022320Y009246D02*X021686Y009246D01*X021760Y009087D02*X022320Y009087D01*X022320Y008929D02*X021802Y008929D01*X021820Y008770D02*X022320Y008770D01*X022320Y008612D02*X021820Y008612D01*X021790Y008453D02*X022320Y008453D01*X022320Y008295D02*X021747Y008295D01*X021660Y008136D02*X022320Y008136D01*X022320Y007978D02*X021547Y007978D01*X021389Y007819D02*X022320Y007819D01*X022320Y007661D02*X021096Y007661D01*X019139Y004966D02*X018618Y004966D01*X018710Y004808D02*X019141Y004808D01*X019190Y004649D02*X018710Y004649D01*X017201Y004966D02*X014732Y004966D01*X014732Y004808D02*X014987Y004808D01*X013822Y004808D02*X011878Y004808D01*X011878Y004966D02*X012004Y004966D01*X012196Y004966D02*X013822Y004966D01*X013822Y005125D02*X012409Y005125D01*X012458Y005283D02*X013822Y005283D01*X013822Y005442D02*X012435Y005442D01*X012320Y005600D02*X013822Y005600D01*X013822Y004649D02*X011878Y004649D01*X011878Y004491D02*X013822Y004491D01*X013822Y004332D02*X011878Y004332D01*X011894Y004174D02*X013822Y004174D01*X013822Y004015D02*X011898Y004015D01*X011878Y003857D02*X013822Y003857D01*X013822Y003698D02*X011878Y003698D01*X011423Y004057D02*X010948Y004057D01*X010948Y004016D01*X010722Y004016D01*X010722Y004015D02*X010626Y004015D01*X010626Y003857D02*X010722Y003857D01*X010722Y003698D02*X010626Y003698D01*X010626Y004174D02*X010722Y004174D01*X010722Y004332D02*X010626Y004332D01*X010626Y004491D02*X010722Y004491D01*X011423Y004057D02*X011423Y004057D01*X011423Y005848D02*X010060Y005848D01*X009890Y005848D02*X009900Y005688D01*X009510Y006076D02*X009053Y006076D01*X009053Y005917D02*X009250Y005917D01*X009055Y005759D02*X009053Y005759D01*X009000Y006234D02*X010191Y006234D01*X010032Y006393D02*X004790Y006393D01*X004566Y005759D02*X004540Y005759D01*X004300Y005314D02*X004300Y008064D01*X003800Y008564D01*X004300Y005314D02*X004700Y004914D01*X004954Y004914D01*X005004Y004864D01*X002964Y003550D02*X002964Y003550D01*X008678Y006551D02*X008715Y006551D01*X008715Y006484D02*X008917Y006484D01*X008963Y006497D01*X009004Y006520D01*X009037Y006554D01*X009061Y006595D01*X009073Y006641D01*X009073Y006896D01*X008715Y006896D01*X008715Y006484D01*X008715Y006710D02*X008678Y006710D01*X008678Y006868D02*X008715Y006868D01*X009073Y006868D02*X009557Y006868D01*X009715Y006710D02*X009073Y006710D01*X009035Y006551D02*X009874Y006551D01*X009398Y007027D02*X009073Y007027D01*X014745Y012416D02*X019620Y012416D01*X019580Y012574D02*X014745Y012574D01*X014250Y014964D02*X014250Y016088D01*X016722Y017488D02*X017073Y017488D01*X016941Y017329D02*X016881Y017329D01*X017627Y017488D02*X018073Y017488D01*X017941Y017329D02*X017759Y017329D01*X017810Y017171D02*X017890Y017171D01*X017890Y017012D02*X017810Y017012D01*X017810Y016854D02*X017890Y016854D01*X017890Y016695D02*X017810Y016695D01*X017810Y016537D02*X017890Y016537D01*X017908Y016378D02*X017792Y016378D01*X017706Y016220D02*X017994Y016220D01*X018706Y016220D02*X019139Y016220D01*X019158Y016378D02*X018792Y016378D01*X018810Y016537D02*X019207Y016537D01*X019256Y016695D02*X018810Y016695D01*X018810Y016854D02*X019328Y016854D01*X019436Y017012D02*X018810Y017012D01*X018810Y017171D02*X019544Y017171D01*X019722Y017329D02*X018759Y017329D01*X018627Y017488D02*X019921Y017488D01*X021473Y013525D02*X022320Y013525D01*X022320Y013367D02*X021617Y013367D01*X021708Y013208D02*X022320Y013208D01*X022320Y013050D02*X021770Y013050D01*X021812Y012891D02*X022320Y012891D01*X022320Y012733D02*X021820Y012733D01*X021820Y012574D02*X022320Y012574D01*X022320Y012416D02*X021780Y012416D01*X021729Y012257D02*X022320Y012257D01*X022320Y012099D02*X021638Y012099D01*X021510Y011940D02*X022320Y011940D01*X022320Y011782D02*X021325Y011782D01*X017110Y004808D02*X017010Y004808D01*X016972Y004174D02*X017110Y004174D01*X016255Y004174D02*X016145Y004174D01*X016183Y004332D02*X016217Y004332D01*X000856Y012257D02*X000780Y012257D01*X000780Y012891D02*X000876Y012891D01*D26*X004150Y011564D03*X006500Y013714D03*X010000Y015114D03*X011650Y013164D03*X013300Y011464D03*X013350Y010114D03*X013550Y008764D03*X013500Y006864D03*X012100Y005314D03*X009250Y004064D03*X015200Y004514D03*X015650Y006264D03*X015850Y009914D03*X014250Y014964D03*D27*X011650Y013164D02*X011348Y013467D01*X010000Y013467D01*X009952Y013514D01*X009500Y013514D01*X009050Y013964D01*X009050Y017164D01*X009300Y017414D01*X016400Y017414D01*X017000Y016814D01*X017350Y016814D01*X014250Y010982D02*X014052Y010784D01*X012630Y010784D01*X012632Y009447D02*X012630Y009444D01*X012632Y009447D02*X014250Y009447D01*X013550Y008764D02*X012640Y008764D01*X012630Y008774D01*M02* \ No newline at end of file
diff --git a/gerber/tests/test_am_statements.py b/gerber/tests/test_am_statements.py
new file mode 100644
index 0000000..98a7332
--- /dev/null
+++ b/gerber/tests/test_am_statements.py
@@ -0,0 +1,383 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Author: Hamilton Kibbe <ham@hamiltonkib.be>
+
+from .tests import *
+from ..am_statements import *
+from ..am_statements import inch, metric
+
+
+def test_AMPrimitive_ctor():
+ for exposure in ('on', 'off', 'ON', 'OFF'):
+ for code in (0, 1, 2, 4, 5, 6, 7, 20, 21, 22):
+ p = AMPrimitive(code, exposure)
+ assert_equal(p.code, code)
+ assert_equal(p.exposure, exposure.lower())
+
+
+def test_AMPrimitive_validation():
+ assert_raises(TypeError, AMPrimitive, '1', 'off')
+ assert_raises(ValueError, AMPrimitive, 0, 'exposed')
+ assert_raises(ValueError, AMPrimitive, 3, 'off')
+
+
+def test_AMPrimitive_conversion():
+ p = AMPrimitive(4, 'on')
+ assert_raises(NotImplementedError, p.to_inch)
+ assert_raises(NotImplementedError, p.to_metric)
+
+
+def test_AMCommentPrimitive_ctor():
+ c = AMCommentPrimitive(0, ' This is a comment *')
+ assert_equal(c.code, 0)
+ assert_equal(c.comment, 'This is a comment')
+
+
+def test_AMCommentPrimitive_validation():
+ assert_raises(ValueError, AMCommentPrimitive, 1, 'This is a comment')
+
+
+def test_AMCommentPrimitive_factory():
+ c = AMCommentPrimitive.from_gerber('0 Rectangle with rounded corners. *')
+ assert_equal(c.code, 0)
+ assert_equal(c.comment, 'Rectangle with rounded corners.')
+
+
+def test_AMCommentPrimitive_dump():
+ c = AMCommentPrimitive(0, 'Rectangle with rounded corners.')
+ assert_equal(c.to_gerber(), '0 Rectangle with rounded corners. *')
+
+
+def test_AMCommentPrimitive_conversion():
+ c = AMCommentPrimitive(0, 'Rectangle with rounded corners.')
+ ci = c
+ cm = c
+ ci.to_inch()
+ cm.to_metric()
+ assert_equal(c, ci)
+ assert_equal(c, cm)
+
+
+def test_AMCommentPrimitive_string():
+ c = AMCommentPrimitive(0, 'Test Comment')
+ assert_equal(str(c), '<Aperture Macro Comment: Test Comment>')
+
+
+def test_AMCirclePrimitive_ctor():
+ test_cases = ((1, 'on', 0, (0, 0)),
+ (1, 'off', 1, (0, 1)),
+ (1, 'on', 2.5, (0, 2)),
+ (1, 'off', 5.0, (3, 3)))
+ for code, exposure, diameter, position in test_cases:
+ c = AMCirclePrimitive(code, exposure, diameter, position)
+ assert_equal(c.code, code)
+ assert_equal(c.exposure, exposure)
+ assert_equal(c.diameter, diameter)
+ assert_equal(c.position, position)
+
+
+def test_AMCirclePrimitive_validation():
+ assert_raises(ValueError, AMCirclePrimitive, 2, 'on', 0, (0, 0))
+
+
+def test_AMCirclePrimitive_factory():
+ c = AMCirclePrimitive.from_gerber('1,0,5,0,0*')
+ assert_equal(c.code, 1)
+ assert_equal(c.exposure, 'off')
+ assert_equal(c.diameter, 5)
+ assert_equal(c.position, (0, 0))
+
+
+def test_AMCirclePrimitive_dump():
+ c = AMCirclePrimitive(1, 'off', 5, (0, 0))
+ assert_equal(c.to_gerber(), '1,0,5,0,0*')
+ c = AMCirclePrimitive(1, 'on', 5, (0, 0))
+ assert_equal(c.to_gerber(), '1,1,5,0,0*')
+
+
+def test_AMCirclePrimitive_conversion():
+ c = AMCirclePrimitive(1, 'off', 25.4, (25.4, 0))
+ c.to_inch()
+ assert_equal(c.diameter, 1)
+ assert_equal(c.position, (1, 0))
+
+ c = AMCirclePrimitive(1, 'off', 1, (1, 0))
+ c.to_metric()
+ assert_equal(c.diameter, 25.4)
+ assert_equal(c.position, (25.4, 0))
+
+
+def test_AMVectorLinePrimitive_validation():
+ assert_raises(ValueError, AMVectorLinePrimitive,
+ 3, 'on', 0.1, (0, 0), (3.3, 5.4), 0)
+
+
+def test_AMVectorLinePrimitive_factory():
+ l = AMVectorLinePrimitive.from_gerber('20,1,0.9,0,0.45,12,0.45,0*')
+ assert_equal(l.code, 20)
+ assert_equal(l.exposure, 'on')
+ assert_equal(l.width, 0.9)
+ assert_equal(l.start, (0, 0.45))
+ assert_equal(l.end, (12, 0.45))
+ assert_equal(l.rotation, 0)
+
+
+def test_AMVectorLinePrimitive_dump():
+ l = AMVectorLinePrimitive.from_gerber('20,1,0.9,0,0.45,12,0.45,0*')
+ assert_equal(l.to_gerber(), '20,1,0.9,0.0,0.45,12.0,0.45,0.0*')
+
+
+def test_AMVectorLinePrimtive_conversion():
+ l = AMVectorLinePrimitive(20, 'on', 25.4, (0, 0), (25.4, 25.4), 0)
+ l.to_inch()
+ assert_equal(l.width, 1)
+ assert_equal(l.start, (0, 0))
+ assert_equal(l.end, (1, 1))
+
+ l = AMVectorLinePrimitive(20, 'on', 1, (0, 0), (1, 1), 0)
+ l.to_metric()
+ assert_equal(l.width, 25.4)
+ assert_equal(l.start, (0, 0))
+ assert_equal(l.end, (25.4, 25.4))
+
+
+def test_AMOutlinePrimitive_validation():
+ assert_raises(ValueError, AMOutlinePrimitive, 7, 'on',
+ (0, 0), [(3.3, 5.4), (4.0, 5.4), (0, 0)], 0)
+ assert_raises(ValueError, AMOutlinePrimitive, 4, 'on',
+ (0, 0), [(3.3, 5.4), (4.0, 5.4), (0, 1)], 0)
+
+
+def test_AMOutlinePrimitive_factory():
+ o = AMOutlinePrimitive.from_gerber('4,1,3,0,0,3,3,3,0,0,0,0*')
+ assert_equal(o.code, 4)
+ assert_equal(o.exposure, 'on')
+ assert_equal(o.start_point, (0, 0))
+ assert_equal(o.points, [(3, 3), (3, 0), (0, 0)])
+ assert_equal(o.rotation, 0)
+
+
+def test_AMOUtlinePrimitive_dump():
+ o = AMOutlinePrimitive(4, 'on', (0, 0), [(3, 3), (3, 0), (0, 0)], 0)
+ # New lines don't matter for Gerber, but we insert them to make it easier to remove
+ # For test purposes we can ignore them
+ assert_equal(o.to_gerber().replace('\n', ''), '4,1,3,0,0,3,3,3,0,0,0,0*')
+
+
+
+def test_AMOutlinePrimitive_conversion():
+ o = AMOutlinePrimitive(
+ 4, 'on', (0, 0), [(25.4, 25.4), (25.4, 0), (0, 0)], 0)
+ o.to_inch()
+ assert_equal(o.start_point, (0, 0))
+ assert_equal(o.points, ((1., 1.), (1., 0.), (0., 0.)))
+
+ o = AMOutlinePrimitive(4, 'on', (0, 0), [(1, 1), (1, 0), (0, 0)], 0)
+ o.to_metric()
+ assert_equal(o.start_point, (0, 0))
+ assert_equal(o.points, ((25.4, 25.4), (25.4, 0), (0, 0)))
+
+
+def test_AMPolygonPrimitive_validation():
+ assert_raises(ValueError, AMPolygonPrimitive, 6, 'on', 3, (3.3, 5.4), 3, 0)
+ assert_raises(ValueError, AMPolygonPrimitive, 5, 'on', 2, (3.3, 5.4), 3, 0)
+ assert_raises(ValueError, AMPolygonPrimitive, 5, 'on', 13, (3.3, 5.4), 3, 0)
+
+
+def test_AMPolygonPrimitive_factory():
+ p = AMPolygonPrimitive.from_gerber('5,1,3,3.3,5.4,3,0')
+ assert_equal(p.code, 5)
+ assert_equal(p.exposure, 'on')
+ assert_equal(p.vertices, 3)
+ assert_equal(p.position, (3.3, 5.4))
+ assert_equal(p.diameter, 3)
+ assert_equal(p.rotation, 0)
+
+
+def test_AMPolygonPrimitive_dump():
+ p = AMPolygonPrimitive(5, 'on', 3, (3.3, 5.4), 3, 0)
+ assert_equal(p.to_gerber(), '5,1,3,3.3,5.4,3,0*')
+
+
+def test_AMPolygonPrimitive_conversion():
+ p = AMPolygonPrimitive(5, 'off', 3, (25.4, 0), 25.4, 0)
+ p.to_inch()
+ assert_equal(p.diameter, 1)
+ assert_equal(p.position, (1, 0))
+
+ p = AMPolygonPrimitive(5, 'off', 3, (1, 0), 1, 0)
+ p.to_metric()
+ assert_equal(p.diameter, 25.4)
+ assert_equal(p.position, (25.4, 0))
+
+
+def test_AMMoirePrimitive_validation():
+ assert_raises(ValueError, AMMoirePrimitive, 7,
+ (0, 0), 5.1, 0.2, 0.4, 6, 0.1, 6.1, 0)
+
+
+def test_AMMoirePrimitive_factory():
+ m = AMMoirePrimitive.from_gerber('6,0,0,5,0.5,0.5,2,0.1,6,0*')
+ assert_equal(m.code, 6)
+ assert_equal(m.position, (0, 0))
+ assert_equal(m.diameter, 5)
+ assert_equal(m.ring_thickness, 0.5)
+ assert_equal(m.gap, 0.5)
+ assert_equal(m.max_rings, 2)
+ assert_equal(m.crosshair_thickness, 0.1)
+ assert_equal(m.crosshair_length, 6)
+ assert_equal(m.rotation, 0)
+
+
+def test_AMMoirePrimitive_dump():
+ m = AMMoirePrimitive.from_gerber('6,0,0,5,0.5,0.5,2,0.1,6,0*')
+ assert_equal(m.to_gerber(), '6,0,0,5.0,0.5,0.5,2,0.1,6.0,0.0*')
+
+
+def test_AMMoirePrimitive_conversion():
+ m = AMMoirePrimitive(6, (25.4, 25.4), 25.4, 25.4, 25.4, 6, 25.4, 25.4, 0)
+ m.to_inch()
+ assert_equal(m.position, (1., 1.))
+ assert_equal(m.diameter, 1.)
+ assert_equal(m.ring_thickness, 1.)
+ assert_equal(m.gap, 1.)
+ assert_equal(m.crosshair_thickness, 1.)
+ assert_equal(m.crosshair_length, 1.)
+
+ m = AMMoirePrimitive(6, (1, 1), 1, 1, 1, 6, 1, 1, 0)
+ m.to_metric()
+ assert_equal(m.position, (25.4, 25.4))
+ assert_equal(m.diameter, 25.4)
+ assert_equal(m.ring_thickness, 25.4)
+ assert_equal(m.gap, 25.4)
+ assert_equal(m.crosshair_thickness, 25.4)
+ assert_equal(m.crosshair_length, 25.4)
+
+
+def test_AMThermalPrimitive_validation():
+ assert_raises(ValueError, AMThermalPrimitive, 8, (0.0, 0.0), 7, 5, 0.2, 0.0)
+ assert_raises(TypeError, AMThermalPrimitive, 7, (0.0, '0'), 7, 5, 0.2, 0.0)
+
+
+
+def test_AMThermalPrimitive_factory():
+ t = AMThermalPrimitive.from_gerber('7,0,0,7,6,0.2,45*')
+ assert_equal(t.code, 7)
+ assert_equal(t.position, (0, 0))
+ assert_equal(t.outer_diameter, 7)
+ assert_equal(t.inner_diameter, 6)
+ assert_equal(t.gap, 0.2)
+ assert_equal(t.rotation, 45)
+
+
+
+def test_AMThermalPrimitive_dump():
+ t = AMThermalPrimitive.from_gerber('7,0,0,7,6,0.2,30*')
+ assert_equal(t.to_gerber(), '7,0,0,7.0,6.0,0.2,30.0*')
+
+
+
+def test_AMThermalPrimitive_conversion():
+ t = AMThermalPrimitive(7, (25.4, 25.4), 25.4, 25.4, 25.4, 0.0)
+ t.to_inch()
+ assert_equal(t.position, (1., 1.))
+ assert_equal(t.outer_diameter, 1.)
+ assert_equal(t.inner_diameter, 1.)
+ assert_equal(t.gap, 1.)
+
+ t = AMThermalPrimitive(7, (1, 1), 1, 1, 1, 0)
+ t.to_metric()
+ assert_equal(t.position, (25.4, 25.4))
+ assert_equal(t.outer_diameter, 25.4)
+ assert_equal(t.inner_diameter, 25.4)
+ assert_equal(t.gap, 25.4)
+
+
+def test_AMCenterLinePrimitive_validation():
+ assert_raises(ValueError, AMCenterLinePrimitive,
+ 22, 1, 0.2, 0.5, (0, 0), 0)
+
+
+def test_AMCenterLinePrimtive_factory():
+ l = AMCenterLinePrimitive.from_gerber('21,1,6.8,1.2,3.4,0.6,0*')
+ assert_equal(l.code, 21)
+ assert_equal(l.exposure, 'on')
+ assert_equal(l.width, 6.8)
+ assert_equal(l.height, 1.2)
+ assert_equal(l.center, (3.4, 0.6))
+ assert_equal(l.rotation, 0)
+
+
+def test_AMCenterLinePrimitive_dump():
+ l = AMCenterLinePrimitive.from_gerber('21,1,6.8,1.2,3.4,0.6,0*')
+ assert_equal(l.to_gerber(), '21,1,6.8,1.2,3.4,0.6,0.0*')
+
+
+def test_AMCenterLinePrimitive_conversion():
+ l = AMCenterLinePrimitive(21, 'on', 25.4, 25.4, (25.4, 25.4), 0)
+ l.to_inch()
+ assert_equal(l.width, 1.)
+ assert_equal(l.height, 1.)
+ assert_equal(l.center, (1., 1.))
+
+ l = AMCenterLinePrimitive(21, 'on', 1, 1, (1, 1), 0)
+ l.to_metric()
+ assert_equal(l.width, 25.4)
+ assert_equal(l.height, 25.4)
+ assert_equal(l.center, (25.4, 25.4))
+
+
+def test_AMLowerLeftLinePrimitive_validation():
+ assert_raises(ValueError, AMLowerLeftLinePrimitive,
+ 23, 1, 0.2, 0.5, (0, 0), 0)
+
+
+def test_AMLowerLeftLinePrimtive_factory():
+ l = AMLowerLeftLinePrimitive.from_gerber('22,1,6.8,1.2,3.4,0.6,0*')
+ assert_equal(l.code, 22)
+ assert_equal(l.exposure, 'on')
+ assert_equal(l.width, 6.8)
+ assert_equal(l.height, 1.2)
+ assert_equal(l.lower_left, (3.4, 0.6))
+ assert_equal(l.rotation, 0)
+
+
+def test_AMLowerLeftLinePrimitive_dump():
+ l = AMLowerLeftLinePrimitive.from_gerber('22,1,6.8,1.2,3.4,0.6,0*')
+ assert_equal(l.to_gerber(), '22,1,6.8,1.2,3.4,0.6,0.0*')
+
+
+def test_AMLowerLeftLinePrimitive_conversion():
+ l = AMLowerLeftLinePrimitive(22, 'on', 25.4, 25.4, (25.4, 25.4), 0)
+ l.to_inch()
+ assert_equal(l.width, 1.)
+ assert_equal(l.height, 1.)
+ assert_equal(l.lower_left, (1., 1.))
+
+ l = AMLowerLeftLinePrimitive(22, 'on', 1, 1, (1, 1), 0)
+ l.to_metric()
+ assert_equal(l.width, 25.4)
+ assert_equal(l.height, 25.4)
+ assert_equal(l.lower_left, (25.4, 25.4))
+
+
+def test_AMUnsupportPrimitive():
+ u = AMUnsupportPrimitive.from_gerber('Test')
+ assert_equal(u.primitive, 'Test')
+ u = AMUnsupportPrimitive('Test')
+ assert_equal(u.to_gerber(), 'Test')
+
+
+def test_AMUnsupportPrimitive_smoketest():
+ u = AMUnsupportPrimitive.from_gerber('Test')
+ u.to_inch()
+ u.to_metric()
+
+
+def test_inch():
+ assert_equal(inch(25.4), 1)
+
+
+def test_metric():
+ assert_equal(metric(1), 25.4)
diff --git a/gerber/tests/test_cairo_backend.py b/gerber/tests/test_cairo_backend.py
new file mode 100644
index 0000000..625a23e
--- /dev/null
+++ b/gerber/tests/test_cairo_backend.py
@@ -0,0 +1,189 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Author: Garret Fick <garret@ficksworkshop.com>
+import io
+import os
+
+from ..render.cairo_backend import GerberCairoContext
+from ..rs274x import read
+from .tests import *
+from nose.tools import assert_tuple_equal
+
+def test_render_two_boxes():
+ """Umaco exapmle of two boxes"""
+ _test_render('resources/example_two_square_boxes.gbr', 'golden/example_two_square_boxes.png')
+
+
+def test_render_single_quadrant():
+ """Umaco exapmle of a single quadrant arc"""
+ _test_render('resources/example_single_quadrant.gbr', 'golden/example_single_quadrant.png')
+
+
+def test_render_simple_contour():
+ """Umaco exapmle of a simple arrow-shaped contour"""
+ gerber = _test_render('resources/example_simple_contour.gbr', 'golden/example_simple_contour.png')
+
+ # Check the resulting dimensions
+ assert_tuple_equal(((2.0, 11.0), (1.0, 9.0)), gerber.bounding_box)
+
+
+def test_render_single_contour_1():
+ """Umaco example of a single contour
+
+ The resulting image for this test is used by other tests because they must generate the same output."""
+ _test_render('resources/example_single_contour_1.gbr', 'golden/example_single_contour.png')
+
+
+def test_render_single_contour_2():
+ """Umaco exapmle of a single contour, alternate contour end order
+
+ The resulting image for this test is used by other tests because they must generate the same output."""
+ _test_render('resources/example_single_contour_2.gbr', 'golden/example_single_contour.png')
+
+
+def test_render_single_contour_3():
+ """Umaco exapmle of a single contour with extra line"""
+ _test_render('resources/example_single_contour_3.gbr', 'golden/example_single_contour_3.png')
+
+
+def test_render_not_overlapping_contour():
+ """Umaco example of D02 staring a second contour"""
+ _test_render('resources/example_not_overlapping_contour.gbr', 'golden/example_not_overlapping_contour.png')
+
+
+def test_render_not_overlapping_touching():
+ """Umaco example of D02 staring a second contour"""
+ _test_render('resources/example_not_overlapping_touching.gbr', 'golden/example_not_overlapping_touching.png')
+
+
+def test_render_overlapping_touching():
+ """Umaco example of D02 staring a second contour"""
+ _test_render('resources/example_overlapping_touching.gbr', 'golden/example_overlapping_touching.png')
+
+
+def test_render_overlapping_contour():
+ """Umaco example of D02 staring a second contour"""
+ _test_render('resources/example_overlapping_contour.gbr', 'golden/example_overlapping_contour.png')
+
+
+def _DISABLED_test_render_level_holes():
+ """Umaco example of using multiple levels to create multiple holes"""
+
+ # TODO This is clearly rendering wrong. I'm temporarily checking this in because there are more
+ # rendering fixes in the related repository that may resolve these.
+ _test_render('resources/example_level_holes.gbr', 'golden/example_overlapping_contour.png')
+
+
+def _DISABLED_test_render_cutin():
+ """Umaco example of using a cutin"""
+
+ # TODO This is clearly rendering wrong.
+ _test_render('resources/example_cutin.gbr', 'golden/example_cutin.png')
+
+
+def test_render_fully_coincident():
+ """Umaco example of coincident lines rendering two contours"""
+
+ _test_render('resources/example_fully_coincident.gbr', 'golden/example_fully_coincident.png')
+
+
+def test_render_coincident_hole():
+ """Umaco example of coincident lines rendering a hole in the contour"""
+
+ _test_render('resources/example_coincident_hole.gbr', 'golden/example_coincident_hole.png')
+
+
+def test_render_cutin_multiple():
+ """Umaco example of a region with multiple cutins"""
+
+ _test_render('resources/example_cutin_multiple.gbr', 'golden/example_cutin_multiple.png')
+
+
+def test_flash_circle():
+ """Umaco example a simple circular flash with and without a hole"""
+
+ _test_render('resources/example_flash_circle.gbr', 'golden/example_flash_circle.png')
+
+
+def test_flash_rectangle():
+ """Umaco example a simple rectangular flash with and without a hole"""
+
+ _test_render('resources/example_flash_rectangle.gbr', 'golden/example_flash_rectangle.png')
+
+
+def test_flash_obround():
+ """Umaco example a simple obround flash with and without a hole"""
+
+ _test_render('resources/example_flash_obround.gbr', 'golden/example_flash_obround.png')
+
+
+def test_flash_polygon():
+ """Umaco example a simple polygon flash with and without a hole"""
+
+ _test_render('resources/example_flash_polygon.gbr', 'golden/example_flash_polygon.png')
+
+
+def test_holes_dont_clear():
+ """Umaco example that an aperture with a hole does not clear the area"""
+
+ _test_render('resources/example_holes_dont_clear.gbr', 'golden/example_holes_dont_clear.png')
+
+
+def test_render_am_exposure_modifier():
+ """Umaco example that an aperture macro with a hole does not clear the area"""
+
+ _test_render('resources/example_am_exposure_modifier.gbr', 'golden/example_am_exposure_modifier.png')
+
+
+def _resolve_path(path):
+ return os.path.join(os.path.dirname(__file__),
+ path)
+
+
+def _test_render(gerber_path, png_expected_path, create_output_path = None):
+ """Render the gerber file and compare to the expected PNG output.
+
+ Parameters
+ ----------
+ gerber_path : string
+ Path to Gerber file to open
+ png_expected_path : string
+ Path to the PNG file to compare to
+ create_output : string|None
+ If not None, write the generated PNG to the specified path.
+ This is primarily to help with
+ """
+
+ gerber_path = _resolve_path(gerber_path)
+ png_expected_path = _resolve_path(png_expected_path)
+ if create_output_path:
+ create_output_path = _resolve_path(create_output_path)
+
+ gerber = read(gerber_path)
+
+ # Create PNG image to the memory stream
+ ctx = GerberCairoContext()
+ gerber.render(ctx)
+
+ actual_bytes = ctx.dump(None)
+
+ # If we want to write the file bytes, do it now. This happens
+ if create_output_path:
+ with open(create_output_path, 'wb') as out_file:
+ out_file.write(actual_bytes)
+ # Creating the output is dangerous - it could overwrite the expected result.
+ # So if we are creating the output, we make the test fail on purpose so you
+ # won't forget to disable this
+ assert_false(True, 'Test created the output %s. This needs to be disabled to make sure the test behaves correctly' % (create_output_path,))
+
+ # Read the expected PNG file
+
+ with open(png_expected_path, 'rb') as expected_file:
+ expected_bytes = expected_file.read()
+
+ # Don't directly use assert_equal otherwise any failure pollutes the test results
+ equal = (expected_bytes == actual_bytes)
+ assert_true(equal)
+
+ return gerber
diff --git a/gerber/tests/test_cam.py b/gerber/tests/test_cam.py
index ce4ec44..a557e8c 100644
--- a/gerber/tests/test_cam.py
+++ b/gerber/tests/test_cam.py
@@ -4,7 +4,7 @@
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
from ..cam import CamFile, FileSettings
-from tests import *
+from .tests import *
def test_filesettings_defaults():
@@ -54,15 +54,107 @@ def test_filesettings_dict_assign():
assert_equal(fs.zero_suppression, 'leading')
assert_equal(fs.format, (1, 2))
+
def test_camfile_init():
""" Smoke test CamFile test
"""
cf = CamFile()
+
def test_camfile_settings():
""" Test CamFile Default Settings
"""
cf = CamFile()
assert_equal(cf.settings, FileSettings())
+
+
+def test_bounds_override_smoketest():
+ cf = CamFile()
+ cf.bounds
+
+
+def test_zeros():
+ """ Test zero/zero_suppression interaction
+ """
+ fs = FileSettings()
+ assert_equal(fs.zero_suppression, 'trailing')
+ assert_equal(fs.zeros, 'leading')
+
+ fs['zero_suppression'] = 'leading'
+ assert_equal(fs.zero_suppression, 'leading')
+ assert_equal(fs.zeros, 'trailing')
+
+ fs.zero_suppression = 'trailing'
+ assert_equal(fs.zero_suppression, 'trailing')
+ assert_equal(fs.zeros, 'leading')
+
+ fs['zeros'] = 'trailing'
+ assert_equal(fs.zeros, 'trailing')
+ assert_equal(fs.zero_suppression, 'leading')
+
+ fs.zeros = 'leading'
+ assert_equal(fs.zeros, 'leading')
+ assert_equal(fs.zero_suppression, 'trailing')
+
+ fs = FileSettings(zeros='leading')
+ assert_equal(fs.zeros, 'leading')
+ assert_equal(fs.zero_suppression, 'trailing')
+
+ fs = FileSettings(zero_suppression='leading')
+ assert_equal(fs.zeros, 'trailing')
+ assert_equal(fs.zero_suppression, 'leading')
+
+ fs = FileSettings(zeros='leading', zero_suppression='trailing')
+ assert_equal(fs.zeros, 'leading')
+ assert_equal(fs.zero_suppression, 'trailing')
+
+ fs = FileSettings(zeros='trailing', zero_suppression='leading')
+ assert_equal(fs.zeros, 'trailing')
+ assert_equal(fs.zero_suppression, 'leading')
+
+
+def test_filesettings_validation():
+ """ Test FileSettings constructor argument validation
+ """
+<<<<<<< HEAD
+ # absolute-ish is not a valid notation
+ assert_raises(ValueError, FileSettings, 'absolute-ish',
+ 'inch', None, (2, 5), None)
+
+ # degrees kelvin isn't a valid unit for a CAM file
+ assert_raises(ValueError, FileSettings, 'absolute',
+ 'degrees kelvin', None, (2, 5), None)
+
+ assert_raises(ValueError, FileSettings, 'absolute',
+ 'inch', 'leading', (2, 5), 'leading')
- \ No newline at end of file
+ # Technnically this should be an error, but Eangle files often do this incorrectly so we
+ # allow it
+ #assert_raises(ValueError, FileSettings, 'absolute',
+ # 'inch', 'following', (2, 5), None)
+
+=======
+ assert_raises(ValueError, FileSettings, 'absolute-ish',
+ 'inch', None, (2, 5), None)
+ assert_raises(ValueError, FileSettings, 'absolute',
+ 'degrees kelvin', None, (2, 5), None)
+ assert_raises(ValueError, FileSettings, 'absolute',
+ 'inch', 'leading', (2, 5), 'leading')
+ assert_raises(ValueError, FileSettings, 'absolute',
+ 'inch', 'following', (2, 5), None)
+>>>>>>> 5476da8... Fix a bunch of rendering bugs.
+ assert_raises(ValueError, FileSettings, 'absolute',
+ 'inch', None, (2, 5), 'following')
+ assert_raises(ValueError, FileSettings, 'absolute',
+ 'inch', None, (2, 5, 6), None)
+
+
+def test_key_validation():
+ fs = FileSettings()
+ assert_raises(KeyError, fs.__getitem__, 'octopus')
+ assert_raises(KeyError, fs.__setitem__, 'octopus', 'do not care')
+ assert_raises(ValueError, fs.__setitem__, 'notation', 'absolute-ish')
+ assert_raises(ValueError, fs.__setitem__, 'units', 'degrees kelvin')
+ assert_raises(ValueError, fs.__setitem__, 'zero_suppression', 'following')
+ assert_raises(ValueError, fs.__setitem__, 'zeros', 'following')
+ assert_raises(ValueError, fs.__setitem__, 'format', (2, 5, 6))
diff --git a/gerber/tests/test_common.py b/gerber/tests/test_common.py
index 1e1efe5..357ed18 100644
--- a/gerber/tests/test_common.py
+++ b/gerber/tests/test_common.py
@@ -2,23 +2,40 @@
# -*- coding: utf-8 -*-
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
-from ..common import read
+from ..exceptions import ParseError
+from ..common import read, loads
from ..excellon import ExcellonFile
from ..rs274x import GerberFile
-from tests import *
+from .tests import *
import os
NCDRILL_FILE = os.path.join(os.path.dirname(__file__),
- 'resources/ncdrill.DRD')
+ 'resources/ncdrill.DRD')
TOP_COPPER_FILE = os.path.join(os.path.dirname(__file__),
- 'resources/top_copper.GTL')
+ 'resources/top_copper.GTL')
+
def test_file_type_detection():
""" Test file type detection
"""
ncdrill = read(NCDRILL_FILE)
top_copper = read(TOP_COPPER_FILE)
- assert(isinstance(ncdrill, ExcellonFile))
- assert(isinstance(top_copper, GerberFile))
+ assert_true(isinstance(ncdrill, ExcellonFile))
+ assert_true(isinstance(top_copper, GerberFile))
+
+
+def test_load_from_string():
+ with open(NCDRILL_FILE, 'rU') as f:
+ ncdrill = loads(f.read())
+ with open(TOP_COPPER_FILE, 'rU') as f:
+ top_copper = loads(f.read())
+ assert_true(isinstance(ncdrill, ExcellonFile))
+ assert_true(isinstance(top_copper, GerberFile))
+
+
+def test_file_type_validation():
+ """ Test file format validation
+ """
+ assert_raises(ParseError, read, 'LICENSE')
diff --git a/gerber/tests/test_excellon.py b/gerber/tests/test_excellon.py
index 72e3d7d..1402938 100644
--- a/gerber/tests/test_excellon.py
+++ b/gerber/tests/test_excellon.py
@@ -2,31 +2,198 @@
# -*- coding: utf-8 -*-
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
-from ..excellon import read, detect_excellon_format, ExcellonFile
-from tests import *
-
import os
+from ..cam import FileSettings
+from ..excellon import read, detect_excellon_format, ExcellonFile, ExcellonParser
+from ..excellon_statements import ExcellonTool
+from .tests import *
+
+
NCDRILL_FILE = os.path.join(os.path.dirname(__file__),
- 'resources/ncdrill.DRD')
+ 'resources/ncdrill.DRD')
+
def test_format_detection():
""" Test file type detection
"""
- settings = detect_excellon_format(NCDRILL_FILE)
+ with open(NCDRILL_FILE, "rU") as f:
+ data = f.read()
+ settings = detect_excellon_format(data)
assert_equal(settings['format'], (2, 4))
- assert_equal(settings['zero_suppression'], 'leading')
+ assert_equal(settings['zeros'], 'trailing')
+
+ settings = detect_excellon_format(filename=NCDRILL_FILE)
+ assert_equal(settings['format'], (2, 4))
+ assert_equal(settings['zeros'], 'trailing')
+
def test_read():
ncdrill = read(NCDRILL_FILE)
assert(isinstance(ncdrill, ExcellonFile))
-
+
+
+def test_write():
+ ncdrill = read(NCDRILL_FILE)
+ ncdrill.write('test.ncd')
+ with open(NCDRILL_FILE, "rU") as src:
+ srclines = src.readlines()
+ with open('test.ncd', "rU") as res:
+ for idx, line in enumerate(res):
+ assert_equal(line.strip(), srclines[idx].strip())
+ os.remove('test.ncd')
+
+
def test_read_settings():
ncdrill = read(NCDRILL_FILE)
- assert_equal(ncdrill.settings.format, (2, 4))
- assert_equal(ncdrill.settings.zero_suppression, 'leading')
-
-
-
-
-
+ assert_equal(ncdrill.settings['format'], (2, 4))
+ assert_equal(ncdrill.settings['zeros'], 'trailing')
+
+
+def test_bounds():
+ ncdrill = read(NCDRILL_FILE)
+ xbound, ybound = ncdrill.bounds
+ assert_array_almost_equal(xbound, (0.1300, 2.1430))
+ assert_array_almost_equal(ybound, (0.3946, 1.7164))
+
+
+def test_report():
+ ncdrill = read(NCDRILL_FILE)
+
+
+def test_conversion():
+ import copy
+ ncdrill = read(NCDRILL_FILE)
+ assert_equal(ncdrill.settings.units, 'inch')
+ ncdrill_inch = copy.deepcopy(ncdrill)
+ ncdrill.to_metric()
+ assert_equal(ncdrill.settings.units, 'metric')
+ inch_primitives = ncdrill_inch.primitives
+ for tool in iter(ncdrill_inch.tools.values()):
+ tool.to_metric()
+ for primitive in inch_primitives:
+ primitive.to_metric()
+ for statement in ncdrill_inch.statements:
+ statement.to_metric()
+
+ for m_tool, i_tool in zip(iter(ncdrill.tools.values()),
+ iter(ncdrill_inch.tools.values())):
+ assert_equal(i_tool, m_tool)
+
+ for m, i in zip(ncdrill.primitives, inch_primitives):
+ assert_equal(m.position, i.position, '%s not equal to %s' % (m, i))
+ assert_equal(m.diameter, i.diameter, '%s not equal to %s' % (m, i))
+
+
+def test_parser_hole_count():
+ settings = FileSettings(**detect_excellon_format(NCDRILL_FILE))
+ p = ExcellonParser(settings)
+ p.parse(NCDRILL_FILE)
+ assert_equal(p.hole_count, 36)
+
+
+def test_parser_hole_sizes():
+ settings = FileSettings(**detect_excellon_format(NCDRILL_FILE))
+ p = ExcellonParser(settings)
+ p.parse(NCDRILL_FILE)
+ assert_equal(p.hole_sizes, [0.0236, 0.0354, 0.04, 0.126, 0.128])
+
+
+def test_parse_whitespace():
+ p = ExcellonParser(FileSettings())
+ assert_equal(p._parse_line(' '), None)
+
+
+def test_parse_comment():
+ p = ExcellonParser(FileSettings())
+ p._parse_line(';A comment')
+ assert_equal(p.statements[0].comment, 'A comment')
+
+
+def test_parse_format_comment():
+ p = ExcellonParser(FileSettings())
+ p._parse_line('; FILE_FORMAT=9:9 ')
+ assert_equal(p.format, (9, 9))
+
+
+def test_parse_header():
+ p = ExcellonParser(FileSettings())
+ p._parse_line('M48 ')
+ assert_equal(p.state, 'HEADER')
+ p._parse_line('M95 ')
+ assert_equal(p.state, 'DRILL')
+
+
+def test_parse_rout():
+ p = ExcellonParser(FileSettings())
+ p._parse_line('G00 ')
+ assert_equal(p.state, 'ROUT')
+ p._parse_line('G05 ')
+ assert_equal(p.state, 'DRILL')
+
+
+def test_parse_version():
+ p = ExcellonParser(FileSettings())
+ p._parse_line('VER,1 ')
+ assert_equal(p.statements[0].version, 1)
+ p._parse_line('VER,2 ')
+ assert_equal(p.statements[1].version, 2)
+
+
+def test_parse_format():
+ p = ExcellonParser(FileSettings())
+ p._parse_line('FMAT,1 ')
+ assert_equal(p.statements[0].format, 1)
+ p._parse_line('FMAT,2 ')
+ assert_equal(p.statements[1].format, 2)
+
+
+def test_parse_units():
+ settings = FileSettings(units='inch', zeros='trailing')
+ p = ExcellonParser(settings)
+ p._parse_line(';METRIC,LZ')
+ assert_equal(p.units, 'inch')
+ assert_equal(p.zeros, 'trailing')
+ p._parse_line('METRIC,LZ')
+ assert_equal(p.units, 'metric')
+ assert_equal(p.zeros, 'leading')
+
+
+def test_parse_incremental_mode():
+ settings = FileSettings(units='inch', zeros='trailing')
+ p = ExcellonParser(settings)
+ assert_equal(p.notation, 'absolute')
+ p._parse_line('ICI,ON ')
+ assert_equal(p.notation, 'incremental')
+ p._parse_line('ICI,OFF ')
+ assert_equal(p.notation, 'absolute')
+
+
+def test_parse_absolute_mode():
+ settings = FileSettings(units='inch', zeros='trailing')
+ p = ExcellonParser(settings)
+ assert_equal(p.notation, 'absolute')
+ p._parse_line('ICI,ON ')
+ assert_equal(p.notation, 'incremental')
+ p._parse_line('G90 ')
+ assert_equal(p.notation, 'absolute')
+
+
+def test_parse_repeat_hole():
+ p = ExcellonParser(FileSettings())
+ p.active_tool = ExcellonTool(FileSettings(), number=8)
+ p._parse_line('R03X1.5Y1.5')
+ assert_equal(p.statements[0].count, 3)
+
+
+def test_parse_incremental_position():
+ p = ExcellonParser(FileSettings(notation='incremental'))
+ p._parse_line('X01Y01')
+ p._parse_line('X01Y01')
+ assert_equal(p.pos, [2., 2.])
+
+
+def test_parse_unknown():
+ p = ExcellonParser(FileSettings())
+ p._parse_line('Not A Valid Statement')
+ assert_equal(p.statements[0].stmt, 'Not A Valid Statement')
diff --git a/gerber/tests/test_excellon_statements.py b/gerber/tests/test_excellon_statements.py
index f2e17ee..8e6e06e 100644
--- a/gerber/tests/test_excellon_statements.py
+++ b/gerber/tests/test_excellon_statements.py
@@ -3,31 +3,62 @@
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
-from .tests import assert_equal, assert_raises
+from .tests import assert_equal, assert_not_equal, assert_raises
from ..excellon_statements import *
from ..cam import FileSettings
+def test_excellon_statement_implementation():
+ stmt = ExcellonStatement()
+ assert_raises(NotImplementedError, stmt.from_excellon, None)
+ assert_raises(NotImplementedError, stmt.to_excellon)
+
+
+def test_excellontstmt():
+ """ Smoke test ExcellonStatement
+ """
+ stmt = ExcellonStatement()
+ stmt.to_inch()
+ stmt.to_metric()
+ stmt.offset()
+
+
def test_excellontool_factory():
- """ Test ExcellonTool factory method
+ """ Test ExcellonTool factory methods
"""
- exc_line = 'T8F00S00C0.12500'
+ exc_line = 'T8F01B02S00003H04Z05C0.12500'
settings = FileSettings(format=(2, 5), zero_suppression='trailing',
- units='inch', notation='absolute')
+ units='inch', notation='absolute')
tool = ExcellonTool.from_excellon(exc_line, settings)
+ assert_equal(tool.number, 8)
+ assert_equal(tool.diameter, 0.125)
+ assert_equal(tool.feed_rate, 1)
+ assert_equal(tool.retract_rate, 2)
+ assert_equal(tool.rpm, 3)
+ assert_equal(tool.max_hit_count, 4)
+ assert_equal(tool.depth_offset, 5)
+
+ stmt = {'number': 8, 'feed_rate': 1, 'retract_rate': 2, 'rpm': 3,
+ 'diameter': 0.125, 'max_hit_count': 4, 'depth_offset': 5}
+ tool = ExcellonTool.from_dict(settings, stmt)
+ assert_equal(tool.number, 8)
assert_equal(tool.diameter, 0.125)
- assert_equal(tool.feed_rate, 0)
- assert_equal(tool.rpm, 0)
+ assert_equal(tool.feed_rate, 1)
+ assert_equal(tool.retract_rate, 2)
+ assert_equal(tool.rpm, 3)
+ assert_equal(tool.max_hit_count, 4)
+ assert_equal(tool.depth_offset, 5)
def test_excellontool_dump():
""" Test ExcellonTool to_excellon()
"""
- exc_lines = ['T1F00S00C0.01200', 'T2F00S00C0.01500', 'T3F00S00C0.01968',
- 'T4F00S00C0.02800', 'T5F00S00C0.03300', 'T6F00S00C0.03800',
- 'T7F00S00C0.04300', 'T8F00S00C0.12500', 'T9F00S00C0.13000', ]
+ exc_lines = ['T01F0S0C0.01200', 'T02F0S0C0.01500', 'T03F0S0C0.01968',
+ 'T04F0S0C0.02800', 'T05F0S0C0.03300', 'T06F0S0C0.03800',
+ 'T07F0S0C0.04300', 'T08F0S0C0.12500', 'T09F0S0C0.13000',
+ 'T08B01F02H03S00003C0.12500Z04', 'T01F0S300.999C0.01200']
settings = FileSettings(format=(2, 5), zero_suppression='trailing',
- units='inch', notation='absolute')
+ units='inch', notation='absolute')
for line in exc_lines:
tool = ExcellonTool.from_excellon(line, settings)
assert_equal(tool.to_excellon(), line)
@@ -35,7 +66,7 @@ def test_excellontool_dump():
def test_excellontool_order():
settings = FileSettings(format=(2, 5), zero_suppression='trailing',
- units='inch', notation='absolute')
+ units='inch', notation='absolute')
line = 'T8F00S00C0.12500'
tool1 = ExcellonTool.from_excellon(line, settings)
line = 'T8C0.12500F00S00'
@@ -45,6 +76,47 @@ def test_excellontool_order():
assert_equal(tool1.rpm, tool2.rpm)
+def test_excellontool_conversion():
+ tool = ExcellonTool.from_dict(FileSettings(units='metric'),
+ {'number': 8, 'diameter': 25.4})
+ tool.to_inch()
+ assert_equal(tool.diameter, 1.)
+ tool = ExcellonTool.from_dict(FileSettings(units='inch'),
+ {'number': 8, 'diameter': 1.})
+ tool.to_metric()
+ assert_equal(tool.diameter, 25.4)
+
+ # Shouldn't change units if we're already using target units
+ tool = ExcellonTool.from_dict(FileSettings(units='inch'),
+ {'number': 8, 'diameter': 25.4})
+ tool.to_inch()
+ assert_equal(tool.diameter, 25.4)
+ tool = ExcellonTool.from_dict(FileSettings(units='metric'),
+ {'number': 8, 'diameter': 1.})
+ tool.to_metric()
+ assert_equal(tool.diameter, 1.)
+
+
+def test_excellontool_repr():
+ tool = ExcellonTool.from_dict(FileSettings(),
+ {'number': 8, 'diameter': 0.125})
+ assert_equal(str(tool), '<ExcellonTool 08: 0.125in. dia.>')
+ tool = ExcellonTool.from_dict(FileSettings(units='metric'),
+ {'number': 8, 'diameter': 0.125})
+ assert_equal(str(tool), '<ExcellonTool 08: 0.125mm dia.>')
+
+
+def test_excellontool_equality():
+ t = ExcellonTool.from_dict(
+ FileSettings(), {'number': 8, 'diameter': 0.125})
+ t1 = ExcellonTool.from_dict(
+ FileSettings(), {'number': 8, 'diameter': 0.125})
+ assert_equal(t, t1)
+ t1 = ExcellonTool.from_dict(FileSettings(units='metric'),
+ {'number': 8, 'diameter': 0.125})
+ assert_not_equal(t, t1)
+
+
def test_toolselection_factory():
""" Test ToolSelectionStmt factory method
"""
@@ -54,6 +126,9 @@ def test_toolselection_factory():
stmt = ToolSelectionStmt.from_excellon('T0223')
assert_equal(stmt.tool, 2)
assert_equal(stmt.compensation_index, 23)
+ stmt = ToolSelectionStmt.from_excellon('T042')
+ assert_equal(stmt.tool, 42)
+ assert_equal(stmt.compensation_index, None)
def test_toolselection_dump():
@@ -65,32 +140,202 @@ def test_toolselection_dump():
assert_equal(stmt.to_excellon(), line)
+def test_z_axis_infeed_rate_factory():
+ """ Test ZAxisInfeedRateStmt factory method
+ """
+ stmt = ZAxisInfeedRateStmt.from_excellon('F01')
+ assert_equal(stmt.rate, 1)
+ stmt = ZAxisInfeedRateStmt.from_excellon('F2')
+ assert_equal(stmt.rate, 2)
+ stmt = ZAxisInfeedRateStmt.from_excellon('F03')
+ assert_equal(stmt.rate, 3)
+
+
+def test_z_axis_infeed_rate_dump():
+ """ Test ZAxisInfeedRateStmt to_excellon()
+ """
+ inputs = [
+ ('F01', 'F01'),
+ ('F2', 'F02'),
+ ('F00003', 'F03')
+ ]
+ for input_rate, expected_output in inputs:
+ stmt = ZAxisInfeedRateStmt.from_excellon(input_rate)
+ assert_equal(stmt.to_excellon(), expected_output)
+
+
def test_coordinatestmt_factory():
""" Test CoordinateStmt factory method
"""
+ settings = FileSettings(format=(2, 5), zero_suppression='trailing',
+ units='inch', notation='absolute')
+
line = 'X0278207Y0065293'
- stmt = CoordinateStmt.from_excellon(line)
+ stmt = CoordinateStmt.from_excellon(line, settings)
assert_equal(stmt.x, 2.78207)
assert_equal(stmt.y, 0.65293)
- line = 'X02945'
- stmt = CoordinateStmt.from_excellon(line)
- assert_equal(stmt.x, 2.945)
+ # line = 'X02945'
+ # stmt = CoordinateStmt.from_excellon(line)
+ # assert_equal(stmt.x, 2.945)
+
+ # line = 'Y00575'
+ # stmt = CoordinateStmt.from_excellon(line)
+ # assert_equal(stmt.y, 0.575)
+
+ settings = FileSettings(format=(2, 4), zero_suppression='leading',
+ units='inch', notation='absolute')
+
+ line = 'X9660Y4639'
+ stmt = CoordinateStmt.from_excellon(line, settings)
+ assert_equal(stmt.x, 0.9660)
+ assert_equal(stmt.y, 0.4639)
+ assert_equal(stmt.to_excellon(settings), "X9660Y4639")
+ assert_equal(stmt.units, 'inch')
- line = 'Y00575'
- stmt = CoordinateStmt.from_excellon(line)
- assert_equal(stmt.y, 0.575)
+ settings.units = 'metric'
+ stmt = CoordinateStmt.from_excellon(line, settings)
+ assert_equal(stmt.units, 'metric')
def test_coordinatestmt_dump():
""" Test CoordinateStmt to_excellon()
"""
- lines = ['X0278207Y0065293', 'X0243795', 'Y0082528', 'Y0086028',
- 'X0251295Y0081528', 'X02525Y0078', 'X0255Y00575', 'Y0052',
- 'X02675', 'Y00575', 'X02425', 'Y0052', 'X023', ]
+ lines = ['X278207Y65293', 'X243795', 'Y82528', 'Y86028',
+ 'X251295Y81528', 'X2525Y78', 'X255Y575', 'Y52',
+ 'X2675', 'Y575', 'X2425', 'Y52', 'X23', ]
+ settings = FileSettings(format=(2, 4), zero_suppression='leading',
+ units='inch', notation='absolute')
for line in lines:
- stmt = CoordinateStmt.from_excellon(line)
- assert_equal(stmt.to_excellon(), line)
+ stmt = CoordinateStmt.from_excellon(line, settings)
+ assert_equal(stmt.to_excellon(settings), line)
+
+
+def test_coordinatestmt_conversion():
+
+ settings = FileSettings()
+ settings.units = 'metric'
+ stmt = CoordinateStmt.from_excellon('X254Y254', settings)
+
+ # No effect
+ stmt.to_metric()
+ assert_equal(stmt.x, 25.4)
+ assert_equal(stmt.y, 25.4)
+
+ stmt.to_inch()
+ assert_equal(stmt.units, 'inch')
+ assert_equal(stmt.x, 1.)
+ assert_equal(stmt.y, 1.)
+
+ # No effect
+ stmt.to_inch()
+ assert_equal(stmt.x, 1.)
+ assert_equal(stmt.y, 1.)
+
+ settings.units = 'inch'
+ stmt = CoordinateStmt.from_excellon('X01Y01', settings)
+
+ # No effect
+ stmt.to_inch()
+ assert_equal(stmt.x, 1.)
+ assert_equal(stmt.y, 1.)
+
+ stmt.to_metric()
+ assert_equal(stmt.units, 'metric')
+ assert_equal(stmt.x, 25.4)
+ assert_equal(stmt.y, 25.4)
+
+ # No effect
+ stmt.to_metric()
+ assert_equal(stmt.x, 25.4)
+ assert_equal(stmt.y, 25.4)
+
+
+def test_coordinatestmt_offset():
+ stmt = CoordinateStmt.from_excellon('X01Y01', FileSettings())
+ stmt.offset()
+ assert_equal(stmt.x, 1)
+ assert_equal(stmt.y, 1)
+ stmt.offset(1, 0)
+ assert_equal(stmt.x, 2.)
+ assert_equal(stmt.y, 1.)
+ stmt.offset(0, 1)
+ assert_equal(stmt.x, 2.)
+ assert_equal(stmt.y, 2.)
+
+
+def test_coordinatestmt_string():
+ settings = FileSettings(format=(2, 4), zero_suppression='leading',
+ units='inch', notation='absolute')
+ stmt = CoordinateStmt.from_excellon('X9660Y4639', settings)
+ assert_equal(str(stmt), '<Coordinate Statement: X: 0.966 Y: 0.4639 >')
+
+
+def test_repeathole_stmt_factory():
+ stmt = RepeatHoleStmt.from_excellon('R0004X015Y32',
+ FileSettings(zeros='leading',
+ units='inch'))
+ assert_equal(stmt.count, 4)
+ assert_equal(stmt.xdelta, 1.5)
+ assert_equal(stmt.ydelta, 32)
+ assert_equal(stmt.units, 'inch')
+
+ stmt = RepeatHoleStmt.from_excellon('R0004X015Y32',
+ FileSettings(zeros='leading',
+ units='metric'))
+ assert_equal(stmt.units, 'metric')
+
+
+def test_repeatholestmt_dump():
+ line = 'R4X015Y32'
+ stmt = RepeatHoleStmt.from_excellon(line, FileSettings())
+ assert_equal(stmt.to_excellon(FileSettings()), line)
+
+
+def test_repeatholestmt_conversion():
+ line = 'R4X0254Y254'
+ settings = FileSettings()
+ settings.units = 'metric'
+ stmt = RepeatHoleStmt.from_excellon(line, settings)
+
+ # No effect
+ stmt.to_metric()
+ assert_equal(stmt.xdelta, 2.54)
+ assert_equal(stmt.ydelta, 25.4)
+
+ stmt.to_inch()
+ assert_equal(stmt.units, 'inch')
+ assert_equal(stmt.xdelta, 0.1)
+ assert_equal(stmt.ydelta, 1.)
+
+ # no effect
+ stmt.to_inch()
+ assert_equal(stmt.xdelta, 0.1)
+ assert_equal(stmt.ydelta, 1.)
+
+ line = 'R4X01Y1'
+ settings.units = 'inch'
+ stmt = RepeatHoleStmt.from_excellon(line, settings)
+
+ # no effect
+ stmt.to_inch()
+ assert_equal(stmt.xdelta, 1.)
+ assert_equal(stmt.ydelta, 10.)
+
+ stmt.to_metric()
+ assert_equal(stmt.units, 'metric')
+ assert_equal(stmt.xdelta, 25.4)
+ assert_equal(stmt.ydelta, 254.)
+
+ # No effect
+ stmt.to_metric()
+ assert_equal(stmt.xdelta, 25.4)
+ assert_equal(stmt.ydelta, 254.)
+
+
+def test_repeathole_str():
+ stmt = RepeatHoleStmt.from_excellon('R4X015Y32', FileSettings())
+ assert_equal(str(stmt), '<Repeat Hole: 4 times, offset X: 1.5 Y: 32>')
def test_commentstmt_factory():
@@ -118,18 +363,147 @@ def test_commentstmt_dump():
assert_equal(stmt.to_excellon(), line)
+def test_header_begin_stmt():
+ stmt = HeaderBeginStmt()
+ assert_equal(stmt.to_excellon(None), 'M48')
+
+
+def test_header_end_stmt():
+ stmt = HeaderEndStmt()
+ assert_equal(stmt.to_excellon(None), 'M95')
+
+
+def test_rewindstop_stmt():
+ stmt = RewindStopStmt()
+ assert_equal(stmt.to_excellon(None), '%')
+
+
+def test_z_axis_rout_position_stmt():
+ stmt = ZAxisRoutPositionStmt()
+ assert_equal(stmt.to_excellon(None), 'M15')
+
+
+def test_retract_with_clamping_stmt():
+ stmt = RetractWithClampingStmt()
+ assert_equal(stmt.to_excellon(None), 'M16')
+
+
+def test_retract_without_clamping_stmt():
+ stmt = RetractWithoutClampingStmt()
+ assert_equal(stmt.to_excellon(None), 'M17')
+
+
+def test_cutter_compensation_off_stmt():
+ stmt = CutterCompensationOffStmt()
+ assert_equal(stmt.to_excellon(None), 'G40')
+
+
+def test_cutter_compensation_left_stmt():
+ stmt = CutterCompensationLeftStmt()
+ assert_equal(stmt.to_excellon(None), 'G41')
+
+
+def test_cutter_compensation_right_stmt():
+ stmt = CutterCompensationRightStmt()
+ assert_equal(stmt.to_excellon(None), 'G42')
+
+
+def test_endofprogramstmt_factory():
+ settings = FileSettings(units='inch')
+ stmt = EndOfProgramStmt.from_excellon('M30X01Y02', settings)
+ assert_equal(stmt.x, 1.)
+ assert_equal(stmt.y, 2.)
+ assert_equal(stmt.units, 'inch')
+ settings.units = 'metric'
+ stmt = EndOfProgramStmt.from_excellon('M30X01', settings)
+ assert_equal(stmt.x, 1.)
+ assert_equal(stmt.y, None)
+ assert_equal(stmt.units, 'metric')
+ stmt = EndOfProgramStmt.from_excellon('M30Y02', FileSettings())
+ assert_equal(stmt.x, None)
+ assert_equal(stmt.y, 2.)
+
+
+def test_endofprogramStmt_dump():
+ lines = ['M30X01Y02', ]
+ for line in lines:
+ stmt = EndOfProgramStmt.from_excellon(line, FileSettings())
+ assert_equal(stmt.to_excellon(FileSettings()), line)
+
+
+def test_endofprogramstmt_conversion():
+ settings = FileSettings()
+ settings.units = 'metric'
+ stmt = EndOfProgramStmt.from_excellon('M30X0254Y254', settings)
+ # No effect
+ stmt.to_metric()
+ assert_equal(stmt.x, 2.54)
+ assert_equal(stmt.y, 25.4)
+
+ stmt.to_inch()
+ assert_equal(stmt.units, 'inch')
+ assert_equal(stmt.x, 0.1)
+ assert_equal(stmt.y, 1.0)
+
+ # No effect
+ stmt.to_inch()
+ assert_equal(stmt.x, 0.1)
+ assert_equal(stmt.y, 1.0)
+
+ settings.units = 'inch'
+ stmt = EndOfProgramStmt.from_excellon('M30X01Y1', settings)
+
+ # No effect
+ stmt.to_inch()
+ assert_equal(stmt.x, 1.)
+ assert_equal(stmt.y, 10.0)
+
+ stmt.to_metric()
+ assert_equal(stmt.units, 'metric')
+ assert_equal(stmt.x, 25.4)
+ assert_equal(stmt.y, 254.)
+
+ # No effect
+ stmt.to_metric()
+ assert_equal(stmt.x, 25.4)
+ assert_equal(stmt.y, 254.)
+
+
+def test_endofprogramstmt_offset():
+ stmt = EndOfProgramStmt(1, 1)
+ stmt.offset()
+ assert_equal(stmt.x, 1)
+ assert_equal(stmt.y, 1)
+ stmt.offset(1, 0)
+ assert_equal(stmt.x, 2.)
+ assert_equal(stmt.y, 1.)
+ stmt.offset(0, 1)
+ assert_equal(stmt.x, 2.)
+ assert_equal(stmt.y, 2.)
+
+
def test_unitstmt_factory():
""" Test UnitStmt factory method
"""
line = 'INCH,LZ'
stmt = UnitStmt.from_excellon(line)
assert_equal(stmt.units, 'inch')
- assert_equal(stmt.zero_suppression, 'trailing')
+ assert_equal(stmt.zeros, 'leading')
+
+ line = 'INCH,TZ'
+ stmt = UnitStmt.from_excellon(line)
+ assert_equal(stmt.units, 'inch')
+ assert_equal(stmt.zeros, 'trailing')
+
+ line = 'METRIC,LZ'
+ stmt = UnitStmt.from_excellon(line)
+ assert_equal(stmt.units, 'metric')
+ assert_equal(stmt.zeros, 'leading')
line = 'METRIC,TZ'
stmt = UnitStmt.from_excellon(line)
assert_equal(stmt.units, 'metric')
- assert_equal(stmt.zero_suppression, 'leading')
+ assert_equal(stmt.zeros, 'trailing')
def test_unitstmt_dump():
@@ -141,6 +515,16 @@ def test_unitstmt_dump():
assert_equal(stmt.to_excellon(), line)
+def test_unitstmt_conversion():
+ stmt = UnitStmt.from_excellon('METRIC,TZ')
+ stmt.to_inch()
+ assert_equal(stmt.units, 'inch')
+
+ stmt = UnitStmt.from_excellon('INCH,TZ')
+ stmt.to_metric()
+ assert_equal(stmt.units, 'metric')
+
+
def test_incrementalmode_factory():
""" Test IncrementalModeStmt factory method
"""
@@ -188,6 +572,7 @@ def test_versionstmt_dump():
stmt = VersionStmt.from_excellon(line)
assert_equal(stmt.to_excellon(), line)
+
def test_versionstmt_validation():
""" Test VersionStmt input validation
"""
@@ -268,3 +653,48 @@ def test_measmodestmt_validation():
"""
assert_raises(ValueError, MeasuringModeStmt.from_excellon, 'M70')
assert_raises(ValueError, MeasuringModeStmt, 'millimeters')
+
+
+def test_measmodestmt_conversion():
+ line = 'M72'
+ stmt = MeasuringModeStmt.from_excellon(line)
+ assert_equal(stmt.units, 'inch')
+ stmt.to_metric()
+ assert_equal(stmt.units, 'metric')
+
+ line = 'M71'
+ stmt = MeasuringModeStmt.from_excellon(line)
+ assert_equal(stmt.units, 'metric')
+ stmt.to_inch()
+ assert_equal(stmt.units, 'inch')
+
+
+def test_routemode_stmt():
+ stmt = RouteModeStmt()
+ assert_equal(stmt.to_excellon(FileSettings()), 'G00')
+
+
+def test_linearmode_stmt():
+ stmt = LinearModeStmt()
+ assert_equal(stmt.to_excellon(FileSettings()), 'G01')
+
+
+def test_drillmode_stmt():
+ stmt = DrillModeStmt()
+ assert_equal(stmt.to_excellon(FileSettings()), 'G05')
+
+
+def test_absolutemode_stmt():
+ stmt = AbsoluteModeStmt()
+ assert_equal(stmt.to_excellon(FileSettings()), 'G90')
+
+
+def test_unknownstmt():
+ stmt = UnknownStmt('TEST')
+ assert_equal(stmt.stmt, 'TEST')
+ assert_equal(str(stmt), '<Unknown Statement: TEST>')
+
+
+def test_unknownstmt_dump():
+ stmt = UnknownStmt('TEST')
+ assert_equal(stmt.to_excellon(FileSettings()), 'TEST')
diff --git a/gerber/tests/test_gerber_statements.py b/gerber/tests/test_gerber_statements.py
index a463c9d..2157390 100644
--- a/gerber/tests/test_gerber_statements.py
+++ b/gerber/tests/test_gerber_statements.py
@@ -5,6 +5,19 @@
from .tests import *
from ..gerber_statements import *
+from ..cam import FileSettings
+
+
+def test_Statement_smoketest():
+ stmt = Statement('Test')
+ assert_equal(stmt.type, 'Test')
+ stmt.to_metric()
+ assert_in('units=metric', str(stmt))
+ stmt.to_inch()
+ assert_in('units=inch', str(stmt))
+ stmt.to_metric()
+ stmt.offset(1, 1)
+ assert_in('type=Test', str(stmt))
def test_FSParamStmt_factory():
@@ -24,6 +37,7 @@ def test_FSParamStmt_factory():
assert_equal(fs.notation, 'incremental')
assert_equal(fs.format, (2, 7))
+
def test_FSParamStmt():
""" Test FSParamStmt initialization
"""
@@ -37,6 +51,7 @@ def test_FSParamStmt():
assert_equal(stmt.notation, notation)
assert_equal(stmt.format, fmt)
+
def test_FSParamStmt_dump():
""" Test FSParamStmt to_gerber()
"""
@@ -48,6 +63,23 @@ def test_FSParamStmt_dump():
fs = FSParamStmt.from_dict(stmt)
assert_equal(fs.to_gerber(), '%FSTIX25Y25*%')
+ settings = FileSettings(zero_suppression='leading', notation='absolute')
+ assert_equal(fs.to_gerber(settings), '%FSLAX25Y25*%')
+
+
+def test_FSParamStmt_string():
+ """ Test FSParamStmt.__str__()
+ """
+ stmt = {'param': 'FS', 'zero': 'L', 'notation': 'A', 'x': '27'}
+ fs = FSParamStmt.from_dict(stmt)
+ assert_equal(str(fs),
+ '<Format Spec: 2:7 leading zero suppression absolute notation>')
+
+ stmt = {'param': 'FS', 'zero': 'T', 'notation': 'I', 'x': '25'}
+ fs = FSParamStmt.from_dict(stmt)
+ assert_equal(str(fs),
+ '<Format Spec: 2:5 trailing zero suppression incremental notation>')
+
def test_MOParamStmt_factory():
""" Test MOParamStruct factory
@@ -64,6 +96,13 @@ def test_MOParamStmt_factory():
assert_equal(mo.param, 'MO')
assert_equal(mo.mode, 'metric')
+ stmt = {'param': 'MO'}
+ mo = MOParamStmt.from_dict(stmt)
+ assert_equal(mo.mode, None)
+ stmt = {'param': 'MO', 'mo': 'degrees kelvin'}
+ assert_raises(ValueError, MOParamStmt.from_dict, stmt)
+
+
def test_MOParamStmt():
""" Test MOParamStmt initialization
"""
@@ -89,6 +128,30 @@ def test_MOParamStmt_dump():
assert_equal(mo.to_gerber(), '%MOMM*%')
+def test_MOParamStmt_conversion():
+ stmt = {'param': 'MO', 'mo': 'MM'}
+ mo = MOParamStmt.from_dict(stmt)
+ mo.to_inch()
+ assert_equal(mo.mode, 'inch')
+
+ stmt = {'param': 'MO', 'mo': 'IN'}
+ mo = MOParamStmt.from_dict(stmt)
+ mo.to_metric()
+ assert_equal(mo.mode, 'metric')
+
+
+def test_MOParamStmt_string():
+ """ Test MOParamStmt.__str__()
+ """
+ stmt = {'param': 'MO', 'mo': 'IN'}
+ mo = MOParamStmt.from_dict(stmt)
+ assert_equal(str(mo), '<Mode: inches>')
+
+ stmt = {'param': 'MO', 'mo': 'MM'}
+ mo = MOParamStmt.from_dict(stmt)
+ assert_equal(str(mo), '<Mode: millimeters>')
+
+
def test_IPParamStmt_factory():
""" Test IPParamStruct factory
"""
@@ -100,6 +163,7 @@ def test_IPParamStmt_factory():
ip = IPParamStmt.from_dict(stmt)
assert_equal(ip.ip, 'negative')
+
def test_IPParamStmt():
""" Test IPParamStmt initialization
"""
@@ -122,14 +186,44 @@ def test_IPParamStmt_dump():
assert_equal(ip.to_gerber(), '%IPNEG*%')
+def test_IPParamStmt_string():
+ stmt = {'param': 'IP', 'ip': 'POS'}
+ ip = IPParamStmt.from_dict(stmt)
+ assert_equal(str(ip), '<Image Polarity: positive>')
+
+ stmt = {'param': 'IP', 'ip': 'NEG'}
+ ip = IPParamStmt.from_dict(stmt)
+ assert_equal(str(ip), '<Image Polarity: negative>')
+
+
+def test_IRParamStmt_factory():
+ stmt = {'param': 'IR', 'angle': '45'}
+ ir = IRParamStmt.from_dict(stmt)
+ assert_equal(ir.param, 'IR')
+ assert_equal(ir.angle, 45)
+
+
+def test_IRParamStmt_dump():
+ stmt = {'param': 'IR', 'angle': '45'}
+ ir = IRParamStmt.from_dict(stmt)
+ assert_equal(ir.to_gerber(), '%IR45*%')
+
+
+def test_IRParamStmt_string():
+ stmt = {'param': 'IR', 'angle': '45'}
+ ir = IRParamStmt.from_dict(stmt)
+ assert_equal(str(ir), '<Image Angle: 45>')
+
+
def test_OFParamStmt_factory():
- """ Test OFParamStmt factory
+ """ Test OFParamStmt factory
"""
stmt = {'param': 'OF', 'a': '0.1234567', 'b': '0.1234567'}
of = OFParamStmt.from_dict(stmt)
assert_equal(of.a, 0.1234567)
assert_equal(of.b, 0.1234567)
+
def test_OFParamStmt():
""" Test IPParamStmt initialization
"""
@@ -139,13 +233,142 @@ def test_OFParamStmt():
assert_equal(stmt.param, param)
assert_equal(stmt.a, val)
assert_equal(stmt.b, val)
-
+
+
def test_OFParamStmt_dump():
""" Test OFParamStmt to_gerber()
"""
- stmt = {'param': 'OF', 'a': '0.1234567', 'b': '0.1234567'}
+ stmt = {'param': 'OF', 'a': '0.123456', 'b': '0.123456'}
+ of = OFParamStmt.from_dict(stmt)
+ assert_equal(of.to_gerber(), '%OFA0.12345B0.12345*%')
+
+
+def test_OFParamStmt_conversion():
+ stmt = {'param': 'OF', 'a': '2.54', 'b': '25.4'}
+ of = OFParamStmt.from_dict(stmt)
+ of.units = 'metric'
+
+ # No effect
+ of.to_metric()
+ assert_equal(of.a, 2.54)
+ assert_equal(of.b, 25.4)
+
+ of.to_inch()
+ assert_equal(of.units, 'inch')
+ assert_equal(of.a, 0.1)
+ assert_equal(of.b, 1.0)
+
+ # No effect
+ of.to_inch()
+ assert_equal(of.a, 0.1)
+ assert_equal(of.b, 1.0)
+
+ stmt = {'param': 'OF', 'a': '0.1', 'b': '1.0'}
+ of = OFParamStmt.from_dict(stmt)
+ of.units = 'inch'
+
+ # No effect
+ of.to_inch()
+ assert_equal(of.a, 0.1)
+ assert_equal(of.b, 1.0)
+
+ of.to_metric()
+ assert_equal(of.units, 'metric')
+ assert_equal(of.a, 2.54)
+ assert_equal(of.b, 25.4)
+
+ # No effect
+ of.to_metric()
+ assert_equal(of.a, 2.54)
+ assert_equal(of.b, 25.4)
+
+
+def test_OFParamStmt_offset():
+ s = OFParamStmt('OF', 0, 0)
+ s.offset(1, 0)
+ assert_equal(s.a, 1.)
+ assert_equal(s.b, 0.)
+ s.offset(0, 1)
+ assert_equal(s.a, 1.)
+ assert_equal(s.b, 1.)
+
+
+def test_OFParamStmt_string():
+ """ Test OFParamStmt __str__
+ """
+ stmt = {'param': 'OF', 'a': '0.123456', 'b': '0.123456'}
of = OFParamStmt.from_dict(stmt)
- assert_equal(of.to_gerber(), '%OFA0.123456B0.123456*%')
+ assert_equal(str(of), '<Offset: X: 0.123456 Y: 0.123456 >')
+
+
+def test_SFParamStmt_factory():
+ stmt = {'param': 'SF', 'a': '1.4', 'b': '0.9'}
+ sf = SFParamStmt.from_dict(stmt)
+ assert_equal(sf.param, 'SF')
+ assert_equal(sf.a, 1.4)
+ assert_equal(sf.b, 0.9)
+
+
+def test_SFParamStmt_dump():
+ stmt = {'param': 'SF', 'a': '1.4', 'b': '0.9'}
+ sf = SFParamStmt.from_dict(stmt)
+ assert_equal(sf.to_gerber(), '%SFA1.4B0.9*%')
+
+
+def test_SFParamStmt_conversion():
+ stmt = {'param': 'OF', 'a': '2.54', 'b': '25.4'}
+ of = SFParamStmt.from_dict(stmt)
+ of.units = 'metric'
+ of.to_metric()
+
+ # No effect
+ assert_equal(of.a, 2.54)
+ assert_equal(of.b, 25.4)
+
+ of.to_inch()
+ assert_equal(of.units, 'inch')
+ assert_equal(of.a, 0.1)
+ assert_equal(of.b, 1.0)
+
+ # No effect
+ of.to_inch()
+ assert_equal(of.a, 0.1)
+ assert_equal(of.b, 1.0)
+
+ stmt = {'param': 'OF', 'a': '0.1', 'b': '1.0'}
+ of = SFParamStmt.from_dict(stmt)
+ of.units = 'inch'
+
+ # No effect
+ of.to_inch()
+ assert_equal(of.a, 0.1)
+ assert_equal(of.b, 1.0)
+
+ of.to_metric()
+ assert_equal(of.units, 'metric')
+ assert_equal(of.a, 2.54)
+ assert_equal(of.b, 25.4)
+
+ # No effect
+ of.to_metric()
+ assert_equal(of.a, 2.54)
+ assert_equal(of.b, 25.4)
+
+
+def test_SFParamStmt_offset():
+ s = SFParamStmt('OF', 0, 0)
+ s.offset(1, 0)
+ assert_equal(s.a, 1.)
+ assert_equal(s.b, 0.)
+ s.offset(0, 1)
+ assert_equal(s.a, 1.)
+ assert_equal(s.b, 1.)
+
+
+def test_SFParamStmt_string():
+ stmt = {'param': 'SF', 'a': '1.4', 'b': '0.9'}
+ sf = SFParamStmt.from_dict(stmt)
+ assert_equal(str(sf), '<Scale Factor: X: 1.4 Y: 0.9>')
def test_LPParamStmt_factory():
@@ -159,6 +382,7 @@ def test_LPParamStmt_factory():
lp = LPParamStmt.from_dict(stmt)
assert_equal(lp.lp, 'dark')
+
def test_LPParamStmt_dump():
""" Test LPParamStmt to_gerber()
"""
@@ -171,6 +395,130 @@ def test_LPParamStmt_dump():
assert_equal(lp.to_gerber(), '%LPD*%')
+def test_LPParamStmt_string():
+ """ Test LPParamStmt.__str__()
+ """
+ stmt = {'param': 'LP', 'lp': 'D'}
+ lp = LPParamStmt.from_dict(stmt)
+ assert_equal(str(lp), '<Level Polarity: dark>')
+
+ stmt = {'param': 'LP', 'lp': 'C'}
+ lp = LPParamStmt.from_dict(stmt)
+ assert_equal(str(lp), '<Level Polarity: clear>')
+
+
+def test_AMParamStmt_factory():
+ name = 'DONUTVAR'
+ macro = (
+'''0 Test Macro. *
+1,1,1.5,0,0*
+20,1,0.9,0,0.45,12,0.45,0*
+21,1,6.8,1.2,3.4,0.6,0*
+22,1,6.8,1.2,0,0,0*
+4,1,4,0.1,0.1,0.5,0.1,0.5,0.5,0.1,0.5,0.1,0.1,0*
+5,1,8,0,0,8,0*
+6,0,0,5,0.5,0.5,2,0.1,6,0*
+7,0,0,7,6,0.2,0*
+8,THIS IS AN UNSUPPORTED PRIMITIVE*
+''')
+ s = AMParamStmt.from_dict({'param': 'AM', 'name': name, 'macro': macro})
+ s.build()
+ assert_equal(len(s.primitives), 10)
+ assert_true(isinstance(s.primitives[0], AMCommentPrimitive))
+ assert_true(isinstance(s.primitives[1], AMCirclePrimitive))
+ assert_true(isinstance(s.primitives[2], AMVectorLinePrimitive))
+ assert_true(isinstance(s.primitives[3], AMCenterLinePrimitive))
+ assert_true(isinstance(s.primitives[4], AMLowerLeftLinePrimitive))
+ assert_true(isinstance(s.primitives[5], AMOutlinePrimitive))
+ assert_true(isinstance(s.primitives[6], AMPolygonPrimitive))
+ assert_true(isinstance(s.primitives[7], AMMoirePrimitive))
+ assert_true(isinstance(s.primitives[8], AMThermalPrimitive))
+ assert_true(isinstance(s.primitives[9], AMUnsupportPrimitive))
+
+
+def testAMParamStmt_conversion():
+ name = 'POLYGON'
+ macro = '5,1,8,25.4,25.4,25.4,0*'
+ s = AMParamStmt.from_dict({'param': 'AM', 'name': name, 'macro': macro})
+
+ s.build()
+ s.units = 'metric'
+
+ # No effect
+ s.to_metric()
+ assert_equal(s.primitives[0].position, (25.4, 25.4))
+ assert_equal(s.primitives[0].diameter, 25.4)
+
+ s.to_inch()
+ assert_equal(s.units, 'inch')
+ assert_equal(s.primitives[0].position, (1., 1.))
+ assert_equal(s.primitives[0].diameter, 1.)
+
+ # No effect
+ s.to_inch()
+ assert_equal(s.primitives[0].position, (1., 1.))
+ assert_equal(s.primitives[0].diameter, 1.)
+
+ macro = '5,1,8,1,1,1,0*'
+ s = AMParamStmt.from_dict({'param': 'AM', 'name': name, 'macro': macro})
+ s.build()
+ s.units = 'inch'
+
+ # No effect
+ s.to_inch()
+ assert_equal(s.primitives[0].position, (1., 1.))
+ assert_equal(s.primitives[0].diameter, 1.)
+
+ s.to_metric()
+ assert_equal(s.units, 'metric')
+ assert_equal(s.primitives[0].position, (25.4, 25.4))
+ assert_equal(s.primitives[0].diameter, 25.4)
+
+ # No effect
+ s.to_metric()
+ assert_equal(s.primitives[0].position, (25.4, 25.4))
+ assert_equal(s.primitives[0].diameter, 25.4)
+
+
+def test_AMParamStmt_dump():
+ name = 'POLYGON'
+ macro = '5,1,8,25.4,25.4,25.4,0.0'
+ s = AMParamStmt.from_dict({'param': 'AM', 'name': name, 'macro': macro})
+ s.build()
+ assert_equal(s.to_gerber(), '%AMPOLYGON*5,1,8,25.4,25.4,25.4,0.0*%')
+
+ s = AMParamStmt.from_dict({'param': 'AM', 'name': 'OC8', 'macro': '5,1,8,0,0,1.08239X$1,22.5'})
+ s.build()
+ assert_equal(s.to_gerber(), '%AMOC8*5,1,8,0,0,1.08239X$1,22.5*%')
+
+
+def test_AMParamStmt_string():
+ name = 'POLYGON'
+ macro = '5,1,8,25.4,25.4,25.4,0*'
+ s = AMParamStmt.from_dict({'param': 'AM', 'name': name, 'macro': macro})
+ s.build()
+ assert_equal(str(s), '<Aperture Macro POLYGON: 5,1,8,25.4,25.4,25.4,0*>')
+
+
+def test_ASParamStmt_factory():
+ stmt = {'param': 'AS', 'mode': 'AXBY'}
+ s = ASParamStmt.from_dict(stmt)
+ assert_equal(s.param, 'AS')
+ assert_equal(s.mode, 'AXBY')
+
+
+def test_ASParamStmt_dump():
+ stmt = {'param': 'AS', 'mode': 'AXBY'}
+ s = ASParamStmt.from_dict(stmt)
+ assert_equal(s.to_gerber(), '%ASAXBY*%')
+
+
+def test_ASParamStmt_string():
+ stmt = {'param': 'AS', 'mode': 'AXBY'}
+ s = ASParamStmt.from_dict(stmt)
+ assert_equal(str(s), '<Axis Select: AXBY>')
+
+
def test_INParamStmt_factory():
""" Test INParamStmt factory
"""
@@ -178,6 +526,7 @@ def test_INParamStmt_factory():
inp = INParamStmt.from_dict(stmt)
assert_equal(inp.name, 'test')
+
def test_INParamStmt_dump():
""" Test INParamStmt to_gerber()
"""
@@ -186,6 +535,12 @@ def test_INParamStmt_dump():
assert_equal(inp.to_gerber(), '%INtest*%')
+def test_INParamStmt_string():
+ stmt = {'param': 'IN', 'name': 'test'}
+ inp = INParamStmt.from_dict(stmt)
+ assert_equal(str(inp), '<Image Name: test>')
+
+
def test_LNParamStmt_factory():
""" Test LNParamStmt factory
"""
@@ -193,6 +548,7 @@ def test_LNParamStmt_factory():
lnp = LNParamStmt.from_dict(stmt)
assert_equal(lnp.name, 'test')
+
def test_LNParamStmt_dump():
""" Test LNParamStmt to_gerber()
"""
@@ -200,6 +556,13 @@ def test_LNParamStmt_dump():
lnp = LNParamStmt.from_dict(stmt)
assert_equal(lnp.to_gerber(), '%LNtest*%')
+
+def test_LNParamStmt_string():
+ stmt = {'param': 'LN', 'name': 'test'}
+ lnp = LNParamStmt.from_dict(stmt)
+ assert_equal(str(lnp), '<Level Name: test>')
+
+
def test_comment_stmt():
""" Test comment statement
"""
@@ -207,6 +570,7 @@ def test_comment_stmt():
assert_equal(stmt.type, 'COMMENT')
assert_equal(stmt.comment, 'A comment')
+
def test_comment_stmt_dump():
""" Test CommentStmt to_gerber()
"""
@@ -214,12 +578,18 @@ def test_comment_stmt_dump():
assert_equal(stmt.to_gerber(), 'G04A comment*')
+def test_comment_stmt_string():
+ stmt = CommentStmt('A comment')
+ assert_equal(str(stmt), '<Comment: A comment>')
+
+
def test_eofstmt():
""" Test EofStmt
"""
stmt = EofStmt()
assert_equal(stmt.type, 'EOF')
+
def test_eofstmt_dump():
""" Test EofStmt to_gerber()
"""
@@ -227,6 +597,10 @@ def test_eofstmt_dump():
assert_equal(stmt.to_gerber(), 'M02*')
+def test_eofstmt_string():
+ assert_equal(str(EofStmt()), '<EOF Statement>')
+
+
def test_quadmodestmt_factory():
""" Test QuadrantModeStmt.from_gerber()
"""
@@ -239,6 +613,7 @@ def test_quadmodestmt_factory():
stmt = QuadrantModeStmt.from_gerber(line)
assert_equal(stmt.mode, 'multi-quadrant')
+
def test_quadmodestmt_validation():
""" Test QuadrantModeStmt input validation
"""
@@ -301,3 +676,275 @@ def test_unknownstmt_dump():
stmt = UnknownStmt(line)
assert_equal(stmt.to_gerber(), line)
+
+def test_statement_string():
+ """ Test Statement.__str__()
+ """
+ stmt = Statement('PARAM')
+ assert_in('type=PARAM', str(stmt))
+ stmt.test = 'PASS'
+ assert_in('test=PASS', str(stmt))
+ assert_in('type=PARAM', str(stmt))
+
+
+def test_ADParamStmt_factory():
+ """ Test ADParamStmt factory
+ """
+ stmt = {'param': 'AD', 'd': 0, 'shape': 'C'}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(ad.d, 0)
+ assert_equal(ad.shape, 'C')
+
+ stmt = {'param': 'AD', 'd': 1, 'shape': 'R'}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(ad.d, 1)
+ assert_equal(ad.shape, 'R')
+
+ stmt = {'param': 'AD', 'd': 1, 'shape': 'C', "modifiers": "1.42"}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(ad.d, 1)
+ assert_equal(ad.shape, 'C')
+ assert_equal(ad.modifiers, [(1.42,)])
+
+ stmt = {'param': 'AD', 'd': 1, 'shape': 'C', "modifiers": "1.42X"}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(ad.d, 1)
+ assert_equal(ad.shape, 'C')
+ assert_equal(ad.modifiers, [(1.42,)])
+
+ stmt = {'param': 'AD', 'd': 1, 'shape': 'R', "modifiers": "1.42X1.24"}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(ad.d, 1)
+ assert_equal(ad.shape, 'R')
+ assert_equal(ad.modifiers, [(1.42, 1.24)])
+
+
+def test_ADParamStmt_conversion():
+ stmt = {'param': 'AD', 'd': 0, 'shape': 'C',
+ 'modifiers': '25.4X25.4,25.4X25.4'}
+ ad = ADParamStmt.from_dict(stmt)
+ ad.units = 'metric'
+
+ # No effect
+ ad.to_metric()
+ assert_equal(ad.modifiers[0], (25.4, 25.4))
+ assert_equal(ad.modifiers[1], (25.4, 25.4))
+
+ ad.to_inch()
+ assert_equal(ad.units, 'inch')
+ assert_equal(ad.modifiers[0], (1., 1.))
+ assert_equal(ad.modifiers[1], (1., 1.))
+
+ # No effect
+ ad.to_inch()
+ assert_equal(ad.modifiers[0], (1., 1.))
+ assert_equal(ad.modifiers[1], (1., 1.))
+
+ stmt = {'param': 'AD', 'd': 0, 'shape': 'C', 'modifiers': '1X1,1X1'}
+ ad = ADParamStmt.from_dict(stmt)
+ ad.units = 'inch'
+
+ # No effect
+ ad.to_inch()
+ assert_equal(ad.modifiers[0], (1., 1.))
+ assert_equal(ad.modifiers[1], (1., 1.))
+
+ ad.to_metric()
+ assert_equal(ad.modifiers[0], (25.4, 25.4))
+ assert_equal(ad.modifiers[1], (25.4, 25.4))
+
+ # No effect
+ ad.to_metric()
+ assert_equal(ad.modifiers[0], (25.4, 25.4))
+ assert_equal(ad.modifiers[1], (25.4, 25.4))
+
+
+def test_ADParamStmt_dump():
+ stmt = {'param': 'AD', 'd': 0, 'shape': 'C'}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(ad.to_gerber(), '%ADD0C*%')
+ stmt = {'param': 'AD', 'd': 0, 'shape': 'C', 'modifiers': '1X1,1X1'}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(ad.to_gerber(), '%ADD0C,1X1,1X1*%')
+
+
+def test_ADPamramStmt_string():
+ stmt = {'param': 'AD', 'd': 0, 'shape': 'C'}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(str(ad), '<Aperture Definition: 0: circle>')
+
+ stmt = {'param': 'AD', 'd': 0, 'shape': 'R'}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(str(ad), '<Aperture Definition: 0: rectangle>')
+
+ stmt = {'param': 'AD', 'd': 0, 'shape': 'O'}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(str(ad), '<Aperture Definition: 0: obround>')
+
+ stmt = {'param': 'AD', 'd': 0, 'shape': 'test'}
+ ad = ADParamStmt.from_dict(stmt)
+ assert_equal(str(ad), '<Aperture Definition: 0: test>')
+
+
+def test_MIParamStmt_factory():
+ stmt = {'param': 'MI', 'a': 1, 'b': 1}
+ mi = MIParamStmt.from_dict(stmt)
+ assert_equal(mi.a, 1)
+ assert_equal(mi.b, 1)
+
+
+def test_MIParamStmt_dump():
+ stmt = {'param': 'MI', 'a': 1, 'b': 1}
+ mi = MIParamStmt.from_dict(stmt)
+ assert_equal(mi.to_gerber(), '%MIA1B1*%')
+ stmt = {'param': 'MI', 'a': 1}
+ mi = MIParamStmt.from_dict(stmt)
+ assert_equal(mi.to_gerber(), '%MIA1B0*%')
+ stmt = {'param': 'MI', 'b': 1}
+ mi = MIParamStmt.from_dict(stmt)
+ assert_equal(mi.to_gerber(), '%MIA0B1*%')
+
+
+def test_MIParamStmt_string():
+ stmt = {'param': 'MI', 'a': 1, 'b': 1}
+ mi = MIParamStmt.from_dict(stmt)
+ assert_equal(str(mi), '<Image Mirror: A=1 B=1>')
+
+ stmt = {'param': 'MI', 'b': 1}
+ mi = MIParamStmt.from_dict(stmt)
+ assert_equal(str(mi), '<Image Mirror: A=0 B=1>')
+
+ stmt = {'param': 'MI', 'a': 1}
+ mi = MIParamStmt.from_dict(stmt)
+ assert_equal(str(mi), '<Image Mirror: A=1 B=0>')
+
+
+def test_coordstmt_ctor():
+ cs = CoordStmt('G04', 0.0, 0.1, 0.2, 0.3, 'D01', FileSettings())
+ assert_equal(cs.function, 'G04')
+ assert_equal(cs.x, 0.0)
+ assert_equal(cs.y, 0.1)
+ assert_equal(cs.i, 0.2)
+ assert_equal(cs.j, 0.3)
+ assert_equal(cs.op, 'D01')
+
+
+def test_coordstmt_factory():
+ stmt = {'function': 'G04', 'x': '0', 'y': '001',
+ 'i': '002', 'j': '003', 'op': 'D01'}
+ cs = CoordStmt.from_dict(stmt, FileSettings())
+ assert_equal(cs.function, 'G04')
+ assert_equal(cs.x, 0.0)
+ assert_equal(cs.y, 0.1)
+ assert_equal(cs.i, 0.2)
+ assert_equal(cs.j, 0.3)
+ assert_equal(cs.op, 'D01')
+
+
+def test_coordstmt_dump():
+ cs = CoordStmt('G04', 0.0, 0.1, 0.2, 0.3, 'D01', FileSettings())
+ assert_equal(cs.to_gerber(FileSettings()), 'G04X0Y001I002J003D01*')
+
+
+def test_coordstmt_conversion():
+ cs = CoordStmt('G71', 25.4, 25.4, 25.4, 25.4, 'D01', FileSettings())
+ cs.units = 'metric'
+
+ # No effect
+ cs.to_metric()
+ assert_equal(cs.x, 25.4)
+ assert_equal(cs.y, 25.4)
+ assert_equal(cs.i, 25.4)
+ assert_equal(cs.j, 25.4)
+ assert_equal(cs.function, 'G71')
+
+ cs.to_inch()
+ assert_equal(cs.units, 'inch')
+ assert_equal(cs.x, 1.)
+ assert_equal(cs.y, 1.)
+ assert_equal(cs.i, 1.)
+ assert_equal(cs.j, 1.)
+ assert_equal(cs.function, 'G70')
+
+ # No effect
+ cs.to_inch()
+ assert_equal(cs.x, 1.)
+ assert_equal(cs.y, 1.)
+ assert_equal(cs.i, 1.)
+ assert_equal(cs.j, 1.)
+ assert_equal(cs.function, 'G70')
+
+ cs = CoordStmt('G70', 1., 1., 1., 1., 'D01', FileSettings())
+ cs.units = 'inch'
+
+ # No effect
+ cs.to_inch()
+ assert_equal(cs.x, 1.)
+ assert_equal(cs.y, 1.)
+ assert_equal(cs.i, 1.)
+ assert_equal(cs.j, 1.)
+ assert_equal(cs.function, 'G70')
+
+ cs.to_metric()
+ assert_equal(cs.x, 25.4)
+ assert_equal(cs.y, 25.4)
+ assert_equal(cs.i, 25.4)
+ assert_equal(cs.j, 25.4)
+ assert_equal(cs.function, 'G71')
+
+ # No effect
+ cs.to_metric()
+ assert_equal(cs.x, 25.4)
+ assert_equal(cs.y, 25.4)
+ assert_equal(cs.i, 25.4)
+ assert_equal(cs.j, 25.4)
+ assert_equal(cs.function, 'G71')
+
+
+def test_coordstmt_offset():
+ c = CoordStmt('G71', 0, 0, 0, 0, 'D01', FileSettings())
+ c.offset(1, 0)
+ assert_equal(c.x, 1.)
+ assert_equal(c.y, 0.)
+ assert_equal(c.i, 1.)
+ assert_equal(c.j, 0.)
+ c.offset(0, 1)
+ assert_equal(c.x, 1.)
+ assert_equal(c.y, 1.)
+ assert_equal(c.i, 1.)
+ assert_equal(c.j, 1.)
+
+
+def test_coordstmt_string():
+ cs = CoordStmt('G04', 0, 1, 2, 3, 'D01', FileSettings())
+ assert_equal(str(cs),
+ '<Coordinate Statement: Fn: G04 X: 0 Y: 1 I: 2 J: 3 Op: Lights On>')
+ cs = CoordStmt('G04', None, None, None, None, 'D02', FileSettings())
+ assert_equal(str(cs), '<Coordinate Statement: Fn: G04 Op: Lights Off>')
+ cs = CoordStmt('G04', None, None, None, None, 'D03', FileSettings())
+ assert_equal(str(cs), '<Coordinate Statement: Fn: G04 Op: Flash>')
+ cs = CoordStmt('G04', None, None, None, None, 'TEST', FileSettings())
+ assert_equal(str(cs), '<Coordinate Statement: Fn: G04 Op: TEST>')
+
+
+def test_aperturestmt_ctor():
+ ast = ApertureStmt(3, False)
+ assert_equal(ast.d, 3)
+ assert_equal(ast.deprecated, False)
+ ast = ApertureStmt(4, True)
+ assert_equal(ast.d, 4)
+ assert_equal(ast.deprecated, True)
+ ast = ApertureStmt(4, 1)
+ assert_equal(ast.d, 4)
+ assert_equal(ast.deprecated, True)
+ ast = ApertureStmt(3)
+ assert_equal(ast.d, 3)
+ assert_equal(ast.deprecated, False)
+
+
+def test_aperturestmt_dump():
+ ast = ApertureStmt(3, False)
+ assert_equal(ast.to_gerber(), 'D3*')
+ ast = ApertureStmt(3, True)
+ assert_equal(ast.to_gerber(), 'G54D3*')
+ assert_equal(str(ast), '<Aperture: 3>')
diff --git a/gerber/tests/test_ipc356.py b/gerber/tests/test_ipc356.py
new file mode 100644
index 0000000..45bb01b
--- /dev/null
+++ b/gerber/tests/test_ipc356.py
@@ -0,0 +1,139 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Author: Hamilton Kibbe <ham@hamiltonkib.be>
+from ..ipc356 import *
+from ..cam import FileSettings
+from .tests import *
+
+import os
+
+IPC_D_356_FILE = os.path.join(os.path.dirname(__file__),
+ 'resources/ipc-d-356.ipc')
+
+
+def test_read():
+ ipcfile = read(IPC_D_356_FILE)
+ assert(isinstance(ipcfile, IPC_D_356))
+
+
+def test_parser():
+ ipcfile = read(IPC_D_356_FILE)
+ assert_equal(ipcfile.settings.units, 'inch')
+ assert_equal(ipcfile.settings.angle_units, 'degrees')
+ assert_equal(len(ipcfile.comments), 3)
+ assert_equal(len(ipcfile.parameters), 4)
+ assert_equal(len(ipcfile.test_records), 105)
+ assert_equal(len(ipcfile.components), 21)
+ assert_equal(len(ipcfile.vias), 14)
+ assert_equal(ipcfile.test_records[-1].net_name, 'A_REALLY_LONG_NET_NAME')
+ assert_equal(ipcfile.outlines[0].type, 'BOARD_EDGE')
+ assert_equal(set(ipcfile.outlines[0].points),
+ {(0., 0.), (2.25, 0.), (2.25, 1.5), (0., 1.5), (0.13, 0.024)})
+
+
+def test_comment():
+ c = IPC356_Comment('Layer Stackup:')
+ assert_equal(c.comment, 'Layer Stackup:')
+ c = IPC356_Comment.from_line('C Layer Stackup: ')
+ assert_equal(c.comment, 'Layer Stackup:')
+ assert_raises(ValueError, IPC356_Comment.from_line, 'P JOB')
+ assert_equal(str(c), '<IPC-D-356 Comment: Layer Stackup:>')
+
+
+def test_parameter():
+ p = IPC356_Parameter('VER', 'IPC-D-356A')
+ assert_equal(p.parameter, 'VER')
+ assert_equal(p.value, 'IPC-D-356A')
+ p = IPC356_Parameter.from_line('P VER IPC-D-356A ')
+ assert_equal(p.parameter, 'VER')
+ assert_equal(p.value, 'IPC-D-356A')
+ assert_raises(ValueError, IPC356_Parameter.from_line,
+ 'C Layer Stackup: ')
+ assert_equal(str(p), '<IPC-D-356 Parameter: VER=IPC-D-356A>')
+
+
+def test_eof():
+ e = IPC356_EndOfFile()
+ assert_equal(e.to_netlist(), '999')
+ assert_equal(str(e), '<IPC-D-356 EOF>')
+
+
+def test_outline():
+ type = 'BOARD_EDGE'
+ points = [(0.01, 0.01), (2., 2.), (4., 2.), (4., 6.)]
+ b = IPC356_Outline(type, points)
+ assert_equal(b.type, type)
+ assert_equal(b.points, points)
+ b = IPC356_Outline.from_line('389BOARD_EDGE X100Y100 X20000Y20000 X40000 Y60000',
+ FileSettings(units='inch'))
+ assert_equal(b.type, 'BOARD_EDGE')
+ assert_equal(b.points, points)
+
+
+def test_test_record():
+ assert_raises(ValueError, IPC356_TestRecord.from_line,
+ 'P JOB', FileSettings())
+ record_string = '317+5VDC VIA - D0150PA00X 006647Y 012900X0000 S3'
+ r = IPC356_TestRecord.from_line(record_string, FileSettings(units='inch'))
+ assert_equal(r.feature_type, 'through-hole')
+ assert_equal(r.net_name, '+5VDC')
+ assert_equal(r.id, 'VIA')
+ assert_almost_equal(r.hole_diameter, 0.015)
+ assert_true(r.plated)
+ assert_equal(r.access, 'both')
+ assert_almost_equal(r.x_coord, 0.6647)
+ assert_almost_equal(r.y_coord, 1.29)
+ assert_equal(r.rect_x, 0.)
+ assert_equal(r.soldermask_info, 'both')
+ r = IPC356_TestRecord.from_line(record_string, FileSettings(units='metric'))
+ assert_almost_equal(r.hole_diameter, 0.15)
+ assert_almost_equal(r.x_coord, 6.647)
+ assert_almost_equal(r.y_coord, 12.9)
+ assert_equal(r.rect_x, 0.)
+ assert_equal(str(r), '<IPC-D-356 +5VDC Test Record: through-hole>')
+
+ record_string = '327+3.3VDC R40 -1 PA01X 032100Y 007124X0236Y0315R180 S0'
+ r = IPC356_TestRecord.from_line(record_string, FileSettings(units='inch'))
+ assert_equal(r.feature_type, 'smt')
+ assert_equal(r.net_name, '+3.3VDC')
+ assert_equal(r.id, 'R40')
+ assert_equal(r.pin, '1')
+ assert_true(r.plated)
+ assert_equal(r.access, 'top')
+ assert_almost_equal(r.x_coord, 3.21)
+ assert_almost_equal(r.y_coord, 0.7124)
+ assert_almost_equal(r.rect_x, 0.0236)
+ assert_almost_equal(r.rect_y, 0.0315)
+ assert_equal(r.rect_rotation, 180)
+ assert_equal(r.soldermask_info, 'none')
+ r = IPC356_TestRecord.from_line(
+ record_string, FileSettings(units='metric'))
+ assert_almost_equal(r.x_coord, 32.1)
+ assert_almost_equal(r.y_coord, 7.124)
+ assert_almost_equal(r.rect_x, 0.236)
+ assert_almost_equal(r.rect_y, 0.315)
+
+ record_string = '317 J4 -M2 D0330PA00X 012447Y 008030X0000 S1'
+ r = IPC356_TestRecord.from_line(record_string, FileSettings(units='inch'))
+ assert_equal(r.feature_type, 'through-hole')
+ assert_equal(r.id, 'J4')
+ assert_equal(r.pin, 'M2')
+ assert_almost_equal(r.hole_diameter, 0.033)
+ assert_true(r.plated)
+ assert_equal(r.access, 'both')
+ assert_almost_equal(r.x_coord, 1.2447)
+ assert_almost_equal(r.y_coord, 0.8030)
+ assert_almost_equal(r.rect_x, 0.)
+ assert_equal(r.soldermask_info, 'primary side')
+
+ record_string = '317SCL COMMUNICATION-1 D 40PA00X 34000Y 20000X 600Y1200R270 '
+ r = IPC356_TestRecord.from_line(record_string, FileSettings(units='inch'))
+ assert_equal(r.feature_type, 'through-hole')
+ assert_equal(r.net_name, 'SCL')
+ assert_equal(r.id, 'COMMUNICATION')
+ assert_equal(r.pin, '1')
+ assert_almost_equal(r.hole_diameter, 0.004)
+ assert_true(r.plated)
+ assert_almost_equal(r.x_coord, 3.4)
+ assert_almost_equal(r.y_coord, 2.0)
diff --git a/gerber/tests/test_layers.py b/gerber/tests/test_layers.py
new file mode 100644
index 0000000..3f2bcfc
--- /dev/null
+++ b/gerber/tests/test_layers.py
@@ -0,0 +1,33 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Author: Hamilton Kibbe <ham@hamiltonkib.be>
+
+from .tests import *
+from ..layers import guess_layer_class, hints
+
+
+def test_guess_layer_class():
+ """ Test layer type inferred correctly from filename
+ """
+
+ # Add any specific test cases here (filename, layer_class)
+ test_vectors = [(None, 'unknown'), ('NCDRILL.TXT', 'unknown'),
+ ('example_board.gtl', 'top'),
+ ('exampmle_board.sst', 'topsilk'),
+ ('ipc-d-356.ipc', 'ipc_netlist'), ]
+
+ for hint in hints:
+ for ext in hint.ext:
+ assert_equal(hint.layer, guess_layer_class('board.{}'.format(ext)))
+ for name in hint.name:
+ assert_equal(hint.layer, guess_layer_class('{}.pho'.format(name)))
+
+ for filename, layer_class in test_vectors:
+ assert_equal(layer_class, guess_layer_class(filename))
+
+
+def test_sort_layers():
+ """ Test layer ordering
+ """
+ pass
diff --git a/gerber/tests/test_primitives.py b/gerber/tests/test_primitives.py
new file mode 100644
index 0000000..c49b558
--- /dev/null
+++ b/gerber/tests/test_primitives.py
@@ -0,0 +1,1270 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Author: Hamilton Kibbe <ham@hamiltonkib.be>
+from operator import add
+
+from ..primitives import *
+from .tests import *
+
+
+def test_primitive_smoketest():
+ p = Primitive()
+ try:
+ p.bounding_box
+ assert_false(True, 'should have thrown the exception')
+ except NotImplementedError:
+ pass
+ #assert_raises(NotImplementedError, p.bounding_box)
+
+ p.to_metric()
+ p.to_inch()
+ try:
+ p.offset(1, 1)
+ assert_false(True, 'should have thrown the exception')
+ except NotImplementedError:
+ pass
+
+
+def test_line_angle():
+ """ Test Line primitive angle calculation
+ """
+ cases = [((0, 0), (1, 0), math.radians(0)),
+ ((0, 0), (1, 1), math.radians(45)),
+ ((0, 0), (0, 1), math.radians(90)),
+ ((0, 0), (-1, 1), math.radians(135)),
+ ((0, 0), (-1, 0), math.radians(180)),
+ ((0, 0), (-1, -1), math.radians(225)),
+ ((0, 0), (0, -1), math.radians(270)),
+ ((0, 0), (1, -1), math.radians(315)), ]
+ for start, end, expected in cases:
+ l = Line(start, end, 0)
+ line_angle = (l.angle + 2 * math.pi) % (2 * math.pi)
+ assert_almost_equal(line_angle, expected)
+
+
+def test_line_bounds():
+ """ Test Line primitive bounding box calculation
+ """
+ cases = [((0, 0), (1, 1), ((-1, 2), (-1, 2))),
+ ((-1, -1), (1, 1), ((-2, 2), (-2, 2))),
+ ((1, 1), (-1, -1), ((-2, 2), (-2, 2))),
+ ((-1, 1), (1, -1), ((-2, 2), (-2, 2))), ]
+
+ c = Circle((0, 0), 2)
+ r = Rectangle((0, 0), 2, 2)
+ for shape in (c, r):
+ for start, end, expected in cases:
+ l = Line(start, end, shape)
+ assert_equal(l.bounding_box, expected)
+ # Test a non-square rectangle
+ r = Rectangle((0, 0), 3, 2)
+ cases = [((0, 0), (1, 1), ((-1.5, 2.5), (-1, 2))),
+ ((-1, -1), (1, 1), ((-2.5, 2.5), (-2, 2))),
+ ((1, 1), (-1, -1), ((-2.5, 2.5), (-2, 2))),
+ ((-1, 1), (1, -1), ((-2.5, 2.5), (-2, 2))), ]
+ for start, end, expected in cases:
+ l = Line(start, end, r)
+ assert_equal(l.bounding_box, expected)
+
+
+def test_line_vertices():
+ c = Circle((0, 0), 2)
+ l = Line((0, 0), (1, 1), c)
+ assert_equal(l.vertices, None)
+
+ # All 4 compass points, all 4 quadrants and the case where start == end
+ test_cases = [((0, 0), (1, 0), ((-1, -1), (-1, 1), (2, 1), (2, -1))),
+ ((0, 0), (1, 1), ((-1, -1), (-1, 1),
+ (0, 2), (2, 2), (2, 0), (1, -1))),
+ ((0, 0), (0, 1), ((-1, -1), (-1, 2), (1, 2), (1, -1))),
+ ((0, 0), (-1, 1), ((-1, -1), (-2, 0),
+ (-2, 2), (0, 2), (1, 1), (1, -1))),
+ ((0, 0), (-1, 0), ((-2, -1), (-2, 1), (1, 1), (1, -1))),
+ ((0, 0), (-1, -1), ((-2, -2), (1, -1),
+ (1, 1), (-1, 1), (-2, 0), (0, -2))),
+ ((0, 0), (0, -1), ((-1, -2), (-1, 1), (1, 1), (1, -2))),
+ ((0, 0), (1, -1), ((-1, -1), (0, -2),
+ (2, -2), (2, 0), (1, 1), (-1, 1))),
+ ((0, 0), (0, 0), ((-1, -1), (-1, 1), (1, 1), (1, -1))), ]
+ r = Rectangle((0, 0), 2, 2)
+
+ for start, end, vertices in test_cases:
+ l = Line(start, end, r)
+ assert_equal(set(vertices), set(l.vertices))
+
+
+def test_line_conversion():
+ c = Circle((0, 0), 25.4, units='metric')
+ l = Line((2.54, 25.4), (254.0, 2540.0), c, units='metric')
+
+ # No effect
+ l.to_metric()
+ assert_equal(l.start, (2.54, 25.4))
+ assert_equal(l.end, (254.0, 2540.0))
+ assert_equal(l.aperture.diameter, 25.4)
+
+ l.to_inch()
+ assert_equal(l.start, (0.1, 1.0))
+ assert_equal(l.end, (10.0, 100.0))
+ assert_equal(l.aperture.diameter, 1.0)
+
+ # No effect
+ l.to_inch()
+ assert_equal(l.start, (0.1, 1.0))
+ assert_equal(l.end, (10.0, 100.0))
+ assert_equal(l.aperture.diameter, 1.0)
+
+ c = Circle((0, 0), 1.0, units='inch')
+ l = Line((0.1, 1.0), (10.0, 100.0), c, units='inch')
+
+ # No effect
+ l.to_inch()
+ assert_equal(l.start, (0.1, 1.0))
+ assert_equal(l.end, (10.0, 100.0))
+ assert_equal(l.aperture.diameter, 1.0)
+
+ l.to_metric()
+ assert_equal(l.start, (2.54, 25.4))
+ assert_equal(l.end, (254.0, 2540.0))
+ assert_equal(l.aperture.diameter, 25.4)
+
+ # No effect
+ l.to_metric()
+ assert_equal(l.start, (2.54, 25.4))
+ assert_equal(l.end, (254.0, 2540.0))
+ assert_equal(l.aperture.diameter, 25.4)
+
+ r = Rectangle((0, 0), 25.4, 254.0, units='metric')
+ l = Line((2.54, 25.4), (254.0, 2540.0), r, units='metric')
+ l.to_inch()
+ assert_equal(l.start, (0.1, 1.0))
+ assert_equal(l.end, (10.0, 100.0))
+ assert_equal(l.aperture.width, 1.0)
+ assert_equal(l.aperture.height, 10.0)
+
+ r = Rectangle((0, 0), 1.0, 10.0, units='inch')
+ l = Line((0.1, 1.0), (10.0, 100.0), r, units='inch')
+ l.to_metric()
+ assert_equal(l.start, (2.54, 25.4))
+ assert_equal(l.end, (254.0, 2540.0))
+ assert_equal(l.aperture.width, 25.4)
+ assert_equal(l.aperture.height, 254.0)
+
+
+def test_line_offset():
+ c = Circle((0, 0), 1)
+ l = Line((0, 0), (1, 1), c)
+ l.offset(1, 0)
+ assert_equal(l.start, (1., 0.))
+ assert_equal(l.end, (2., 1.))
+ l.offset(0, 1)
+ assert_equal(l.start, (1., 1.))
+ assert_equal(l.end, (2., 2.))
+
+
+def test_arc_radius():
+ """ Test Arc primitive radius calculation
+ """
+ cases = [((-3, 4), (5, 0), (0, 0), 5),
+ ((0, 1), (1, 0), (0, 0), 1), ]
+
+ for start, end, center, radius in cases:
+ a = Arc(start, end, center, 'clockwise', 0, 'single-quadrant')
+ assert_equal(a.radius, radius)
+
+
+def test_arc_sweep_angle():
+ """ Test Arc primitive sweep angle calculation
+ """
+ cases = [((1, 0), (0, 1), (0, 0), 'counterclockwise', math.radians(90)),
+ ((1, 0), (0, 1), (0, 0), 'clockwise', math.radians(270)),
+ ((1, 0), (-1, 0), (0, 0), 'clockwise', math.radians(180)),
+ ((1, 0), (-1, 0), (0, 0), 'counterclockwise', math.radians(180)), ]
+
+ for start, end, center, direction, sweep in cases:
+ c = Circle((0,0), 1)
+ a = Arc(start, end, center, direction, c, 'single-quadrant')
+ assert_equal(a.sweep_angle, sweep)
+
+
+def test_arc_bounds():
+ """ Test Arc primitive bounding box calculation
+ """
+ cases = [((1, 0), (0, 1), (0, 0), 'clockwise', ((-1.5, 1.5), (-1.5, 1.5))),
+ ((1, 0), (0, 1), (0, 0), 'counterclockwise',
+ ((-0.5, 1.5), (-0.5, 1.5))),
+ # TODO: ADD MORE TEST CASES HERE
+ ]
+ for start, end, center, direction, bounds in cases:
+ c = Circle((0,0), 1)
+ a = Arc(start, end, center, direction, c, 'single-quadrant')
+ assert_equal(a.bounding_box, bounds)
+
+
+def test_arc_conversion():
+ c = Circle((0, 0), 25.4, units='metric')
+ a = Arc((2.54, 25.4), (254.0, 2540.0), (25400.0, 254000.0),
+ 'clockwise', c, 'single-quadrant', units='metric')
+
+ # No effect
+ a.to_metric()
+ assert_equal(a.start, (2.54, 25.4))
+ assert_equal(a.end, (254.0, 2540.0))
+ assert_equal(a.center, (25400.0, 254000.0))
+ assert_equal(a.aperture.diameter, 25.4)
+
+ a.to_inch()
+ assert_equal(a.start, (0.1, 1.0))
+ assert_equal(a.end, (10.0, 100.0))
+ assert_equal(a.center, (1000.0, 10000.0))
+ assert_equal(a.aperture.diameter, 1.0)
+
+ # no effect
+ a.to_inch()
+ assert_equal(a.start, (0.1, 1.0))
+ assert_equal(a.end, (10.0, 100.0))
+ assert_equal(a.center, (1000.0, 10000.0))
+ assert_equal(a.aperture.diameter, 1.0)
+
+ c = Circle((0, 0), 1.0, units='inch')
+ a = Arc((0.1, 1.0), (10.0, 100.0), (1000.0, 10000.0),
+ 'clockwise', c, 'single-quadrant', units='inch')
+ a.to_metric()
+ assert_equal(a.start, (2.54, 25.4))
+ assert_equal(a.end, (254.0, 2540.0))
+ assert_equal(a.center, (25400.0, 254000.0))
+ assert_equal(a.aperture.diameter, 25.4)
+
+
+def test_arc_offset():
+ c = Circle((0, 0), 1)
+ a = Arc((0, 0), (1, 1), (2, 2), 'clockwise', c, 'single-quadrant')
+ a.offset(1, 0)
+ assert_equal(a.start, (1., 0.))
+ assert_equal(a.end, (2., 1.))
+ assert_equal(a.center, (3., 2.))
+ a.offset(0, 1)
+ assert_equal(a.start, (1., 1.))
+ assert_equal(a.end, (2., 2.))
+ assert_equal(a.center, (3., 3.))
+
+
+def test_circle_radius():
+ """ Test Circle primitive radius calculation
+ """
+ c = Circle((1, 1), 2)
+ assert_equal(c.radius, 1)
+
+
+def test_circle_hole_radius():
+ """ Test Circle primitive hole radius calculation
+ """
+ c = Circle((1, 1), 4, 2)
+ assert_equal(c.hole_radius, 1)
+
+
+def test_circle_bounds():
+ """ Test Circle bounding box calculation
+ """
+ c = Circle((1, 1), 2)
+ assert_equal(c.bounding_box, ((0, 2), (0, 2)))
+
+
+def test_circle_conversion():
+ """Circle conversion of units"""
+ # Circle initially metric, no hole
+ c = Circle((2.54, 25.4), 254.0, units='metric')
+
+ c.to_metric() # shouldn't do antyhing
+ assert_equal(c.position, (2.54, 25.4))
+ assert_equal(c.diameter, 254.)
+ assert_equal(c.hole_diameter, None)
+
+ c.to_inch()
+ assert_equal(c.position, (0.1, 1.))
+ assert_equal(c.diameter, 10.)
+ assert_equal(c.hole_diameter, None)
+
+ # no effect
+ c.to_inch()
+ assert_equal(c.position, (0.1, 1.))
+ assert_equal(c.diameter, 10.)
+ assert_equal(c.hole_diameter, None)
+
+ # Circle initially metric, with hole
+ c = Circle((2.54, 25.4), 254.0, 127.0, units='metric')
+
+ c.to_metric() #shouldn't do antyhing
+ assert_equal(c.position, (2.54, 25.4))
+ assert_equal(c.diameter, 254.)
+ assert_equal(c.hole_diameter, 127.)
+
+ c.to_inch()
+ assert_equal(c.position, (0.1, 1.))
+ assert_equal(c.diameter, 10.)
+ assert_equal(c.hole_diameter, 5.)
+
+ # no effect
+ c.to_inch()
+ assert_equal(c.position, (0.1, 1.))
+ assert_equal(c.diameter, 10.)
+ assert_equal(c.hole_diameter, 5.)
+
+ # Circle initially inch, no hole
+ c = Circle((0.1, 1.0), 10.0, units='inch')
+ # No effect
+ c.to_inch()
+ assert_equal(c.position, (0.1, 1.))
+ assert_equal(c.diameter, 10.)
+ assert_equal(c.hole_diameter, None)
+
+ c.to_metric()
+ assert_equal(c.position, (2.54, 25.4))
+ assert_equal(c.diameter, 254.)
+ assert_equal(c.hole_diameter, None)
+
+ # no effect
+ c.to_metric()
+ assert_equal(c.position, (2.54, 25.4))
+ assert_equal(c.diameter, 254.)
+ assert_equal(c.hole_diameter, None)
+
+ c = Circle((0.1, 1.0), 10.0, 5.0, units='inch')
+ #No effect
+ c.to_inch()
+ assert_equal(c.position, (0.1, 1.))
+ assert_equal(c.diameter, 10.)
+ assert_equal(c.hole_diameter, 5.)
+
+ c.to_metric()
+ assert_equal(c.position, (2.54, 25.4))
+ assert_equal(c.diameter, 254.)
+ assert_equal(c.hole_diameter, 127.)
+
+ # no effect
+ c.to_metric()
+ assert_equal(c.position, (2.54, 25.4))
+ assert_equal(c.diameter, 254.)
+ assert_equal(c.hole_diameter, 127.)
+
+
+
+def test_circle_offset():
+ c = Circle((0, 0), 1)
+ c.offset(1, 0)
+ assert_equal(c.position, (1., 0.))
+ c.offset(0, 1)
+ assert_equal(c.position, (1., 1.))
+
+
+def test_ellipse_ctor():
+ """ Test ellipse creation
+ """
+ e = Ellipse((2, 2), 3, 2)
+ assert_equal(e.position, (2, 2))
+ assert_equal(e.width, 3)
+ assert_equal(e.height, 2)
+
+
+def test_ellipse_bounds():
+ """ Test ellipse bounding box calculation
+ """
+ e = Ellipse((2, 2), 4, 2)
+ assert_equal(e.bounding_box, ((0, 4), (1, 3)))
+ e = Ellipse((2, 2), 4, 2, rotation=90)
+ assert_equal(e.bounding_box, ((1, 3), (0, 4)))
+ e = Ellipse((2, 2), 4, 2, rotation=180)
+ assert_equal(e.bounding_box, ((0, 4), (1, 3)))
+ e = Ellipse((2, 2), 4, 2, rotation=270)
+ assert_equal(e.bounding_box, ((1, 3), (0, 4)))
+
+
+def test_ellipse_conversion():
+ e = Ellipse((2.54, 25.4), 254.0, 2540., units='metric')
+
+ # No effect
+ e.to_metric()
+ assert_equal(e.position, (2.54, 25.4))
+ assert_equal(e.width, 254.)
+ assert_equal(e.height, 2540.)
+
+ e.to_inch()
+ assert_equal(e.position, (0.1, 1.))
+ assert_equal(e.width, 10.)
+ assert_equal(e.height, 100.)
+
+ # No effect
+ e.to_inch()
+ assert_equal(e.position, (0.1, 1.))
+ assert_equal(e.width, 10.)
+ assert_equal(e.height, 100.)
+
+ e = Ellipse((0.1, 1.), 10.0, 100., units='inch')
+
+ # no effect
+ e.to_inch()
+ assert_equal(e.position, (0.1, 1.))
+ assert_equal(e.width, 10.)
+ assert_equal(e.height, 100.)
+
+ e.to_metric()
+ assert_equal(e.position, (2.54, 25.4))
+ assert_equal(e.width, 254.)
+ assert_equal(e.height, 2540.)
+
+ # No effect
+ e.to_metric()
+ assert_equal(e.position, (2.54, 25.4))
+ assert_equal(e.width, 254.)
+ assert_equal(e.height, 2540.)
+
+
+def test_ellipse_offset():
+ e = Ellipse((0, 0), 1, 2)
+ e.offset(1, 0)
+ assert_equal(e.position, (1., 0.))
+ e.offset(0, 1)
+ assert_equal(e.position, (1., 1.))
+
+
+def test_rectangle_ctor():
+ """ Test rectangle creation
+ """
+ test_cases = (((0, 0), 1, 1), ((0, 0), 1, 2), ((1, 1), 1, 2))
+ for pos, width, height in test_cases:
+ r = Rectangle(pos, width, height)
+ assert_equal(r.position, pos)
+ assert_equal(r.width, width)
+ assert_equal(r.height, height)
+
+def test_rectangle_hole_radius():
+ """ Test rectangle hole diameter calculation
+ """
+ r = Rectangle((0,0), 2, 2)
+ assert_equal(0, r.hole_radius)
+
+ r = Rectangle((0,0), 2, 2, 1)
+ assert_equal(0.5, r.hole_radius)
+
+
+
+def test_rectangle_bounds():
+ """ Test rectangle bounding box calculation
+ """
+ r = Rectangle((0, 0), 2, 2)
+ xbounds, ybounds = r.bounding_box
+ assert_array_almost_equal(xbounds, (-1, 1))
+ assert_array_almost_equal(ybounds, (-1, 1))
+ r = Rectangle((0, 0), 2, 2, rotation=45)
+ xbounds, ybounds = r.bounding_box
+ assert_array_almost_equal(xbounds, (-math.sqrt(2), math.sqrt(2)))
+ assert_array_almost_equal(ybounds, (-math.sqrt(2), math.sqrt(2)))
+
+
+def test_rectangle_conversion():
+ """Test converting rectangles between units"""
+
+ # Initially metric no hole
+ r = Rectangle((2.54, 25.4), 254.0, 2540.0, units='metric')
+
+ r.to_metric()
+ assert_equal(r.position, (2.54, 25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+
+ # Initially metric with hole
+ r = Rectangle((2.54, 25.4), 254.0, 2540.0, 127.0, units='metric')
+
+ r.to_metric()
+ assert_equal(r.position, (2.54,25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+ assert_equal(r.hole_diameter, 127.0)
+
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+ assert_equal(r.hole_diameter, 5.0)
+
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+ assert_equal(r.hole_diameter, 5.0)
+
+ # Initially inch, no hole
+ r = Rectangle((0.1, 1.0), 10.0, 100.0, units='inch')
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+
+ r.to_metric()
+ assert_equal(r.position, (2.54, 25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+
+ r.to_metric()
+ assert_equal(r.position, (2.54, 25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+
+ # Initially inch with hole
+ r = Rectangle((0.1, 1.0), 10.0, 100.0, 5.0, units='inch')
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+ assert_equal(r.hole_diameter, 5.0)
+
+ r.to_metric()
+ assert_equal(r.position, (2.54,25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+ assert_equal(r.hole_diameter, 127.0)
+
+ r.to_metric()
+ assert_equal(r.position, (2.54, 25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+ assert_equal(r.hole_diameter, 127.0)
+
+
+def test_rectangle_offset():
+ r = Rectangle((0, 0), 1, 2)
+ r.offset(1, 0)
+ assert_equal(r.position, (1., 0.))
+ r.offset(0, 1)
+ assert_equal(r.position, (1., 1.))
+
+
+def test_diamond_ctor():
+ """ Test diamond creation
+ """
+ test_cases = (((0, 0), 1, 1), ((0, 0), 1, 2), ((1, 1), 1, 2))
+ for pos, width, height in test_cases:
+ d = Diamond(pos, width, height)
+ assert_equal(d.position, pos)
+ assert_equal(d.width, width)
+ assert_equal(d.height, height)
+
+
+def test_diamond_bounds():
+ """ Test diamond bounding box calculation
+ """
+ d = Diamond((0, 0), 2, 2)
+ xbounds, ybounds = d.bounding_box
+ assert_array_almost_equal(xbounds, (-1, 1))
+ assert_array_almost_equal(ybounds, (-1, 1))
+ d = Diamond((0, 0), math.sqrt(2), math.sqrt(2), rotation=45)
+ xbounds, ybounds = d.bounding_box
+ assert_array_almost_equal(xbounds, (-1, 1))
+ assert_array_almost_equal(ybounds, (-1, 1))
+
+
+def test_diamond_conversion():
+ d = Diamond((2.54, 25.4), 254.0, 2540.0, units='metric')
+
+ d.to_metric()
+ assert_equal(d.position, (2.54, 25.4))
+ assert_equal(d.width, 254.0)
+ assert_equal(d.height, 2540.0)
+
+ d.to_inch()
+ assert_equal(d.position, (0.1, 1.0))
+ assert_equal(d.width, 10.0)
+ assert_equal(d.height, 100.0)
+
+ d.to_inch()
+ assert_equal(d.position, (0.1, 1.0))
+ assert_equal(d.width, 10.0)
+ assert_equal(d.height, 100.0)
+
+ d = Diamond((0.1, 1.0), 10.0, 100.0, units='inch')
+
+ d.to_inch()
+ assert_equal(d.position, (0.1, 1.0))
+ assert_equal(d.width, 10.0)
+ assert_equal(d.height, 100.0)
+
+ d.to_metric()
+ assert_equal(d.position, (2.54, 25.4))
+ assert_equal(d.width, 254.0)
+ assert_equal(d.height, 2540.0)
+
+ d.to_metric()
+ assert_equal(d.position, (2.54, 25.4))
+ assert_equal(d.width, 254.0)
+ assert_equal(d.height, 2540.0)
+
+
+def test_diamond_offset():
+ d = Diamond((0, 0), 1, 2)
+ d.offset(1, 0)
+ assert_equal(d.position, (1., 0.))
+ d.offset(0, 1)
+ assert_equal(d.position, (1., 1.))
+
+
+def test_chamfer_rectangle_ctor():
+ """ Test chamfer rectangle creation
+ """
+ test_cases = (((0, 0), 1, 1, 0.2, (True, True, False, False)),
+ ((0, 0), 1, 2, 0.3, (True, True, True, True)),
+ ((1, 1), 1, 2, 0.4, (False, False, False, False)))
+ for pos, width, height, chamfer, corners in test_cases:
+ r = ChamferRectangle(pos, width, height, chamfer, corners)
+ assert_equal(r.position, pos)
+ assert_equal(r.width, width)
+ assert_equal(r.height, height)
+ assert_equal(r.chamfer, chamfer)
+ assert_array_almost_equal(r.corners, corners)
+
+
+def test_chamfer_rectangle_bounds():
+ """ Test chamfer rectangle bounding box calculation
+ """
+ r = ChamferRectangle((0, 0), 2, 2, 0.2, (True, True, False, False))
+ xbounds, ybounds = r.bounding_box
+ assert_array_almost_equal(xbounds, (-1, 1))
+ assert_array_almost_equal(ybounds, (-1, 1))
+ r = ChamferRectangle(
+ (0, 0), 2, 2, 0.2, (True, True, False, False), rotation=45)
+ xbounds, ybounds = r.bounding_box
+ assert_array_almost_equal(xbounds, (-math.sqrt(2), math.sqrt(2)))
+ assert_array_almost_equal(ybounds, (-math.sqrt(2), math.sqrt(2)))
+
+
+def test_chamfer_rectangle_conversion():
+ r = ChamferRectangle((2.54, 25.4), 254.0, 2540.0, 0.254,
+ (True, True, False, False), units='metric')
+
+ r.to_metric()
+ assert_equal(r.position, (2.54, 25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+ assert_equal(r.chamfer, 0.254)
+
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+ assert_equal(r.chamfer, 0.01)
+
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+ assert_equal(r.chamfer, 0.01)
+
+ r = ChamferRectangle((0.1, 1.0), 10.0, 100.0, 0.01,
+ (True, True, False, False), units='inch')
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+ assert_equal(r.chamfer, 0.01)
+
+ r.to_metric()
+ assert_equal(r.position, (2.54, 25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+ assert_equal(r.chamfer, 0.254)
+
+ r.to_metric()
+ assert_equal(r.position, (2.54, 25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+ assert_equal(r.chamfer, 0.254)
+
+
+def test_chamfer_rectangle_offset():
+ r = ChamferRectangle((0, 0), 1, 2, 0.01, (True, True, False, False))
+ r.offset(1, 0)
+ assert_equal(r.position, (1., 0.))
+ r.offset(0, 1)
+ assert_equal(r.position, (1., 1.))
+
+
+def test_round_rectangle_ctor():
+ """ Test round rectangle creation
+ """
+ test_cases = (((0, 0), 1, 1, 0.2, (True, True, False, False)),
+ ((0, 0), 1, 2, 0.3, (True, True, True, True)),
+ ((1, 1), 1, 2, 0.4, (False, False, False, False)))
+ for pos, width, height, radius, corners in test_cases:
+ r = RoundRectangle(pos, width, height, radius, corners)
+ assert_equal(r.position, pos)
+ assert_equal(r.width, width)
+ assert_equal(r.height, height)
+ assert_equal(r.radius, radius)
+ assert_array_almost_equal(r.corners, corners)
+
+
+def test_round_rectangle_bounds():
+ """ Test round rectangle bounding box calculation
+ """
+ r = RoundRectangle((0, 0), 2, 2, 0.2, (True, True, False, False))
+ xbounds, ybounds = r.bounding_box
+ assert_array_almost_equal(xbounds, (-1, 1))
+ assert_array_almost_equal(ybounds, (-1, 1))
+ r = RoundRectangle((0, 0), 2, 2, 0.2,
+ (True, True, False, False), rotation=45)
+ xbounds, ybounds = r.bounding_box
+ assert_array_almost_equal(xbounds, (-math.sqrt(2), math.sqrt(2)))
+ assert_array_almost_equal(ybounds, (-math.sqrt(2), math.sqrt(2)))
+
+
+def test_round_rectangle_conversion():
+ r = RoundRectangle((2.54, 25.4), 254.0, 2540.0, 0.254,
+ (True, True, False, False), units='metric')
+
+ r.to_metric()
+ assert_equal(r.position, (2.54, 25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+ assert_equal(r.radius, 0.254)
+
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+ assert_equal(r.radius, 0.01)
+
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+ assert_equal(r.radius, 0.01)
+
+ r = RoundRectangle((0.1, 1.0), 10.0, 100.0, 0.01,
+ (True, True, False, False), units='inch')
+
+ r.to_inch()
+ assert_equal(r.position, (0.1, 1.0))
+ assert_equal(r.width, 10.0)
+ assert_equal(r.height, 100.0)
+ assert_equal(r.radius, 0.01)
+
+ r.to_metric()
+ assert_equal(r.position, (2.54, 25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+ assert_equal(r.radius, 0.254)
+
+ r.to_metric()
+ assert_equal(r.position, (2.54, 25.4))
+ assert_equal(r.width, 254.0)
+ assert_equal(r.height, 2540.0)
+ assert_equal(r.radius, 0.254)
+
+
+def test_round_rectangle_offset():
+ r = RoundRectangle((0, 0), 1, 2, 0.01, (True, True, False, False))
+ r.offset(1, 0)
+ assert_equal(r.position, (1., 0.))
+ r.offset(0, 1)
+ assert_equal(r.position, (1., 1.))
+
+
+def test_obround_ctor():
+ """ Test obround creation
+ """
+ test_cases = (((0, 0), 1, 1),
+ ((0, 0), 1, 2),
+ ((1, 1), 1, 2))
+ for pos, width, height in test_cases:
+ o = Obround(pos, width, height)
+ assert_equal(o.position, pos)
+ assert_equal(o.width, width)
+ assert_equal(o.height, height)
+
+
+def test_obround_bounds():
+ """ Test obround bounding box calculation
+ """
+ o = Obround((2, 2), 2, 4)
+ xbounds, ybounds = o.bounding_box
+ assert_array_almost_equal(xbounds, (1, 3))
+ assert_array_almost_equal(ybounds, (0, 4))
+ o = Obround((2, 2), 4, 2)
+ xbounds, ybounds = o.bounding_box
+ assert_array_almost_equal(xbounds, (0, 4))
+ assert_array_almost_equal(ybounds, (1, 3))
+
+
+def test_obround_orientation():
+ o = Obround((0, 0), 2, 1)
+ assert_equal(o.orientation, 'horizontal')
+ o = Obround((0, 0), 1, 2)
+ assert_equal(o.orientation, 'vertical')
+
+
+def test_obround_subshapes():
+ o = Obround((0, 0), 1, 4)
+ ss = o.subshapes
+ assert_array_almost_equal(ss['rectangle'].position, (0, 0))
+ assert_array_almost_equal(ss['circle1'].position, (0, 1.5))
+ assert_array_almost_equal(ss['circle2'].position, (0, -1.5))
+ o = Obround((0, 0), 4, 1)
+ ss = o.subshapes
+ assert_array_almost_equal(ss['rectangle'].position, (0, 0))
+ assert_array_almost_equal(ss['circle1'].position, (1.5, 0))
+ assert_array_almost_equal(ss['circle2'].position, (-1.5, 0))
+
+
+def test_obround_conversion():
+ o = Obround((2.54, 25.4), 254.0, 2540.0, units='metric')
+
+ # No effect
+ o.to_metric()
+ assert_equal(o.position, (2.54, 25.4))
+ assert_equal(o.width, 254.0)
+ assert_equal(o.height, 2540.0)
+
+ o.to_inch()
+ assert_equal(o.position, (0.1, 1.0))
+ assert_equal(o.width, 10.0)
+ assert_equal(o.height, 100.0)
+
+ # No effect
+ o.to_inch()
+ assert_equal(o.position, (0.1, 1.0))
+ assert_equal(o.width, 10.0)
+ assert_equal(o.height, 100.0)
+
+ o = Obround((0.1, 1.0), 10.0, 100.0, units='inch')
+
+ # No effect
+ o.to_inch()
+ assert_equal(o.position, (0.1, 1.0))
+ assert_equal(o.width, 10.0)
+ assert_equal(o.height, 100.0)
+
+ o.to_metric()
+ assert_equal(o.position, (2.54, 25.4))
+ assert_equal(o.width, 254.0)
+ assert_equal(o.height, 2540.0)
+
+ # No effect
+ o.to_metric()
+ assert_equal(o.position, (2.54, 25.4))
+ assert_equal(o.width, 254.0)
+ assert_equal(o.height, 2540.0)
+
+
+def test_obround_offset():
+ o = Obround((0, 0), 1, 2)
+ o.offset(1, 0)
+ assert_equal(o.position, (1., 0.))
+ o.offset(0, 1)
+ assert_equal(o.position, (1., 1.))
+
+
+def test_polygon_ctor():
+ """ Test polygon creation
+ """
+ test_cases = (((0, 0), 3, 5, 0),
+ ((0, 0), 5, 6, 0),
+ ((1, 1), 7, 7, 45))
+ for pos, sides, radius, hole_diameter in test_cases:
+ p = Polygon(pos, sides, radius, hole_diameter)
+ assert_equal(p.position, pos)
+ assert_equal(p.sides, sides)
+ assert_equal(p.radius, radius)
+ assert_equal(p.hole_diameter, hole_diameter)
+
+
+
+def test_polygon_bounds():
+ """ Test polygon bounding box calculation
+ """
+ p = Polygon((2, 2), 3, 2, 0)
+ xbounds, ybounds = p.bounding_box
+ assert_array_almost_equal(xbounds, (0, 4))
+ assert_array_almost_equal(ybounds, (0, 4))
+ p = Polygon((2, 2), 3, 4, 0)
+ xbounds, ybounds = p.bounding_box
+ assert_array_almost_equal(xbounds, (-2, 6))
+ assert_array_almost_equal(ybounds, (-2, 6))
+
+
+def test_polygon_conversion():
+ p = Polygon((2.54, 25.4), 3, 254.0, 0, units='metric')
+
+ # No effect
+ p.to_metric()
+ assert_equal(p.position, (2.54, 25.4))
+ assert_equal(p.radius, 254.0)
+
+ p.to_inch()
+ assert_equal(p.position, (0.1, 1.0))
+ assert_equal(p.radius, 10.0)
+
+ # No effect
+ p.to_inch()
+ assert_equal(p.position, (0.1, 1.0))
+ assert_equal(p.radius, 10.0)
+
+ p = Polygon((0.1, 1.0), 3, 10.0, 0, units='inch')
+
+ # No effect
+ p.to_inch()
+ assert_equal(p.position, (0.1, 1.0))
+ assert_equal(p.radius, 10.0)
+
+ p.to_metric()
+ assert_equal(p.position, (2.54, 25.4))
+ assert_equal(p.radius, 254.0)
+
+ # No effect
+ p.to_metric()
+ assert_equal(p.position, (2.54, 25.4))
+ assert_equal(p.radius, 254.0)
+
+
+def test_polygon_offset():
+ p = Polygon((0, 0), 5, 10, 0)
+ p.offset(1, 0)
+ assert_equal(p.position, (1., 0.))
+ p.offset(0, 1)
+ assert_equal(p.position, (1., 1.))
+
+
+def test_region_ctor():
+ """ Test Region creation
+ """
+ apt = Circle((0, 0), 0)
+ lines = (Line((0, 0), (1, 0), apt), Line((1, 0), (1, 1), apt),
+ Line((1, 1), (0, 1), apt), Line((0, 1), (0, 0), apt))
+ points = ((0, 0), (1, 0), (1, 1), (0, 1))
+ r = Region(lines)
+ for i, p in enumerate(lines):
+ assert_equal(r.primitives[i], p)
+
+
+def test_region_bounds():
+ """ Test region bounding box calculation
+ """
+ apt = Circle((0, 0), 0)
+ lines = (Line((0, 0), (1, 0), apt), Line((1, 0), (1, 1), apt),
+ Line((1, 1), (0, 1), apt), Line((0, 1), (0, 0), apt))
+ r = Region(lines)
+ xbounds, ybounds = r.bounding_box
+ assert_array_almost_equal(xbounds, (0, 1))
+ assert_array_almost_equal(ybounds, (0, 1))
+
+
+def test_region_offset():
+ apt = Circle((0, 0), 0)
+ lines = (Line((0, 0), (1, 0), apt), Line((1, 0), (1, 1), apt),
+ Line((1, 1), (0, 1), apt), Line((0, 1), (0, 0), apt))
+ r = Region(lines)
+ xlim, ylim = r.bounding_box
+ r.offset(0, 1)
+ new_xlim, new_ylim = r.bounding_box
+ assert_array_almost_equal(new_xlim, xlim)
+ assert_array_almost_equal(new_ylim, tuple([y + 1 for y in ylim]))
+
+
+def test_round_butterfly_ctor():
+ """ Test round butterfly creation
+ """
+ test_cases = (((0, 0), 3), ((0, 0), 5), ((1, 1), 7))
+ for pos, diameter in test_cases:
+ b = RoundButterfly(pos, diameter)
+ assert_equal(b.position, pos)
+ assert_equal(b.diameter, diameter)
+ assert_equal(b.radius, diameter / 2.)
+
+
+def test_round_butterfly_ctor_validation():
+ """ Test RoundButterfly argument validation
+ """
+ assert_raises(TypeError, RoundButterfly, 3, 5)
+ assert_raises(TypeError, RoundButterfly, (3, 4, 5), 5)
+
+
+def test_round_butterfly_conversion():
+ b = RoundButterfly((2.54, 25.4), 254.0, units='metric')
+
+ # No Effect
+ b.to_metric()
+ assert_equal(b.position, (2.54, 25.4))
+ assert_equal(b.diameter, (254.0))
+
+ b.to_inch()
+ assert_equal(b.position, (0.1, 1.0))
+ assert_equal(b.diameter, 10.0)
+
+ # No effect
+ b.to_inch()
+ assert_equal(b.position, (0.1, 1.0))
+ assert_equal(b.diameter, 10.0)
+
+ b = RoundButterfly((0.1, 1.0), 10.0, units='inch')
+
+ # No effect
+ b.to_inch()
+ assert_equal(b.position, (0.1, 1.0))
+ assert_equal(b.diameter, 10.0)
+
+ b.to_metric()
+ assert_equal(b.position, (2.54, 25.4))
+ assert_equal(b.diameter, (254.0))
+
+ # No Effect
+ b.to_metric()
+ assert_equal(b.position, (2.54, 25.4))
+ assert_equal(b.diameter, (254.0))
+
+
+def test_round_butterfly_offset():
+ b = RoundButterfly((0, 0), 1)
+ b.offset(1, 0)
+ assert_equal(b.position, (1., 0.))
+ b.offset(0, 1)
+ assert_equal(b.position, (1., 1.))
+
+
+def test_round_butterfly_bounds():
+ """ Test RoundButterfly bounding box calculation
+ """
+ b = RoundButterfly((0, 0), 2)
+ xbounds, ybounds = b.bounding_box
+ assert_array_almost_equal(xbounds, (-1, 1))
+ assert_array_almost_equal(ybounds, (-1, 1))
+
+
+def test_square_butterfly_ctor():
+ """ Test SquareButterfly creation
+ """
+ test_cases = (((0, 0), 3), ((0, 0), 5), ((1, 1), 7))
+ for pos, side in test_cases:
+ b = SquareButterfly(pos, side)
+ assert_equal(b.position, pos)
+ assert_equal(b.side, side)
+
+
+def test_square_butterfly_ctor_validation():
+ """ Test SquareButterfly argument validation
+ """
+ assert_raises(TypeError, SquareButterfly, 3, 5)
+ assert_raises(TypeError, SquareButterfly, (3, 4, 5), 5)
+
+
+def test_square_butterfly_bounds():
+ """ Test SquareButterfly bounding box calculation
+ """
+ b = SquareButterfly((0, 0), 2)
+ xbounds, ybounds = b.bounding_box
+ assert_array_almost_equal(xbounds, (-1, 1))
+ assert_array_almost_equal(ybounds, (-1, 1))
+
+
+def test_squarebutterfly_conversion():
+ b = SquareButterfly((2.54, 25.4), 254.0, units='metric')
+
+ # No effect
+ b.to_metric()
+ assert_equal(b.position, (2.54, 25.4))
+ assert_equal(b.side, (254.0))
+
+ b.to_inch()
+ assert_equal(b.position, (0.1, 1.0))
+ assert_equal(b.side, 10.0)
+
+ # No effect
+ b.to_inch()
+ assert_equal(b.position, (0.1, 1.0))
+ assert_equal(b.side, 10.0)
+
+ b = SquareButterfly((0.1, 1.0), 10.0, units='inch')
+
+ # No effect
+ b.to_inch()
+ assert_equal(b.position, (0.1, 1.0))
+ assert_equal(b.side, 10.0)
+
+ b.to_metric()
+ assert_equal(b.position, (2.54, 25.4))
+ assert_equal(b.side, (254.0))
+
+ # No effect
+ b.to_metric()
+ assert_equal(b.position, (2.54, 25.4))
+ assert_equal(b.side, (254.0))
+
+
+def test_square_butterfly_offset():
+ b = SquareButterfly((0, 0), 1)
+ b.offset(1, 0)
+ assert_equal(b.position, (1., 0.))
+ b.offset(0, 1)
+ assert_equal(b.position, (1., 1.))
+
+
+def test_donut_ctor():
+ """ Test Donut primitive creation
+ """
+ test_cases = (((0, 0), 'round', 3, 5), ((0, 0), 'square', 5, 7),
+ ((1, 1), 'hexagon', 7, 9), ((2, 2), 'octagon', 9, 11))
+ for pos, shape, in_d, out_d in test_cases:
+ d = Donut(pos, shape, in_d, out_d)
+ assert_equal(d.position, pos)
+ assert_equal(d.shape, shape)
+ assert_equal(d.inner_diameter, in_d)
+ assert_equal(d.outer_diameter, out_d)
+
+
+def test_donut_ctor_validation():
+ assert_raises(TypeError, Donut, 3, 'round', 5, 7)
+ assert_raises(TypeError, Donut, (3, 4, 5), 'round', 5, 7)
+ assert_raises(ValueError, Donut, (0, 0), 'triangle', 3, 5)
+ assert_raises(ValueError, Donut, (0, 0), 'round', 5, 3)
+
+
+def test_donut_bounds():
+ d = Donut((0, 0), 'round', 0.0, 2.0)
+ xbounds, ybounds = d.bounding_box
+ assert_equal(xbounds, (-1., 1.))
+ assert_equal(ybounds, (-1., 1.))
+
+
+def test_donut_conversion():
+ d = Donut((2.54, 25.4), 'round', 254.0, 2540.0, units='metric')
+
+ # No effect
+ d.to_metric()
+ assert_equal(d.position, (2.54, 25.4))
+ assert_equal(d.inner_diameter, 254.0)
+ assert_equal(d.outer_diameter, 2540.0)
+
+ d.to_inch()
+ assert_equal(d.position, (0.1, 1.0))
+ assert_equal(d.inner_diameter, 10.0)
+ assert_equal(d.outer_diameter, 100.0)
+
+ # No effect
+ d.to_inch()
+ assert_equal(d.position, (0.1, 1.0))
+ assert_equal(d.inner_diameter, 10.0)
+ assert_equal(d.outer_diameter, 100.0)
+
+ d = Donut((0.1, 1.0), 'round', 10.0, 100.0, units='inch')
+
+ # No effect
+ d.to_inch()
+ assert_equal(d.position, (0.1, 1.0))
+ assert_equal(d.inner_diameter, 10.0)
+ assert_equal(d.outer_diameter, 100.0)
+
+ d.to_metric()
+ assert_equal(d.position, (2.54, 25.4))
+ assert_equal(d.inner_diameter, 254.0)
+ assert_equal(d.outer_diameter, 2540.0)
+
+ # No effect
+ d.to_metric()
+ assert_equal(d.position, (2.54, 25.4))
+ assert_equal(d.inner_diameter, 254.0)
+ assert_equal(d.outer_diameter, 2540.0)
+
+
+def test_donut_offset():
+ d = Donut((0, 0), 'round', 1, 10)
+ d.offset(1, 0)
+ assert_equal(d.position, (1., 0.))
+ d.offset(0, 1)
+ assert_equal(d.position, (1., 1.))
+
+
+def test_drill_ctor():
+ """ Test drill primitive creation
+ """
+ test_cases = (((0, 0), 2), ((1, 1), 3), ((2, 2), 5))
+ for position, diameter in test_cases:
+ d = Drill(position, diameter, None)
+ assert_equal(d.position, position)
+ assert_equal(d.diameter, diameter)
+ assert_equal(d.radius, diameter / 2.)
+
+
+def test_drill_ctor_validation():
+ """ Test drill argument validation
+ """
+ assert_raises(TypeError, Drill, 3, 5, None)
+ assert_raises(TypeError, Drill, (3,4,5), 5, None)
+
+
+def test_drill_bounds():
+ d = Drill((0, 0), 2, None)
+ xbounds, ybounds = d.bounding_box
+ assert_array_almost_equal(xbounds, (-1, 1))
+ assert_array_almost_equal(ybounds, (-1, 1))
+ d = Drill((1, 2), 2, None)
+ xbounds, ybounds = d.bounding_box
+ assert_array_almost_equal(xbounds, (0, 2))
+ assert_array_almost_equal(ybounds, (1, 3))
+
+
+def test_drill_conversion():
+ d = Drill((2.54, 25.4), 254., None, units='metric')
+
+ # No effect
+ d.to_metric()
+ assert_equal(d.position, (2.54, 25.4))
+ assert_equal(d.diameter, 254.0)
+
+ d.to_inch()
+ assert_equal(d.position, (0.1, 1.0))
+ assert_equal(d.diameter, 10.0)
+
+ # No effect
+ d.to_inch()
+ assert_equal(d.position, (0.1, 1.0))
+ assert_equal(d.diameter, 10.0)
+
+ d = Drill((0.1, 1.0), 10., None, units='inch')
+
+ # No effect
+ d.to_inch()
+ assert_equal(d.position, (0.1, 1.0))
+ assert_equal(d.diameter, 10.0)
+
+ d.to_metric()
+ assert_equal(d.position, (2.54, 25.4))
+ assert_equal(d.diameter, 254.0)
+
+ # No effect
+ d.to_metric()
+ assert_equal(d.position, (2.54, 25.4))
+ assert_equal(d.diameter, 254.0)
+
+
+def test_drill_offset():
+ d = Drill((0, 0), 1., None)
+ d.offset(1, 0)
+ assert_equal(d.position, (1., 0.))
+ d.offset(0, 1)
+ assert_equal(d.position, (1., 1.))
+
+
+def test_drill_equality():
+ d = Drill((2.54, 25.4), 254., None)
+ d1 = Drill((2.54, 25.4), 254., None)
+ assert_equal(d, d1)
+ d1 = Drill((2.54, 25.4), 254.2, None)
+ assert_not_equal(d, d1)
diff --git a/gerber/tests/test_rs274x.py b/gerber/tests/test_rs274x.py
index f66a09e..d5acfe8 100644
--- a/gerber/tests/test_rs274x.py
+++ b/gerber/tests/test_rs274x.py
@@ -2,15 +2,55 @@
# -*- coding: utf-8 -*-
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
+import os
+
from ..rs274x import read, GerberFile
-from tests import *
+from .tests import *
-import os
TOP_COPPER_FILE = os.path.join(os.path.dirname(__file__),
- 'resources/top_copper.GTL')
+ 'resources/top_copper.GTL')
+
+MULTILINE_READ_FILE = os.path.join(os.path.dirname(__file__),
+ 'resources/multiline_read.ger')
def test_read():
top_copper = read(TOP_COPPER_FILE)
assert(isinstance(top_copper, GerberFile))
+
+
+def test_multiline_read():
+ multiline = read(MULTILINE_READ_FILE)
+ assert(isinstance(multiline, GerberFile))
+ assert_equal(10, len(multiline.statements))
+
+
+def test_comments_parameter():
+ top_copper = read(TOP_COPPER_FILE)
+ assert_equal(top_copper.comments[0], 'This is a comment,:')
+
+
+def test_size_parameter():
+ top_copper = read(TOP_COPPER_FILE)
+ size = top_copper.size
+ assert_almost_equal(size[0], 2.256900, 6)
+ assert_almost_equal(size[1], 1.500000, 6)
+
+
+def test_conversion():
+ import copy
+ top_copper = read(TOP_COPPER_FILE)
+ assert_equal(top_copper.units, 'inch')
+ top_copper_inch = copy.deepcopy(top_copper)
+ top_copper.to_metric()
+ for statement in top_copper_inch.statements:
+ statement.to_metric()
+ for primitive in top_copper_inch.primitives:
+ primitive.to_metric()
+ assert_equal(top_copper.units, 'metric')
+ for i, m in zip(top_copper.statements, top_copper_inch.statements):
+ assert_equal(i, m)
+
+ for i, m in zip(top_copper.primitives, top_copper_inch.primitives):
+ assert_equal(i, m)
diff --git a/gerber/tests/test_rs274x_backend.py b/gerber/tests/test_rs274x_backend.py
new file mode 100644
index 0000000..89512f0
--- /dev/null
+++ b/gerber/tests/test_rs274x_backend.py
@@ -0,0 +1,185 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Author: Garret Fick <garret@ficksworkshop.com>
+import io
+import os
+
+from ..render.rs274x_backend import Rs274xContext
+from ..rs274x import read
+from .tests import *
+
+def test_render_two_boxes():
+ """Umaco exapmle of two boxes"""
+ _test_render('resources/example_two_square_boxes.gbr', 'golden/example_two_square_boxes.gbr')
+
+
+def _test_render_single_quadrant():
+ """Umaco exapmle of a single quadrant arc"""
+
+ # TODO there is probably a bug here
+ _test_render('resources/example_single_quadrant.gbr', 'golden/example_single_quadrant.gbr')
+
+
+def _test_render_simple_contour():
+ """Umaco exapmle of a simple arrow-shaped contour"""
+ _test_render('resources/example_simple_contour.gbr', 'golden/example_simple_contour.gbr')
+
+
+def _test_render_single_contour_1():
+ """Umaco example of a single contour
+
+ The resulting image for this test is used by other tests because they must generate the same output."""
+ _test_render('resources/example_single_contour_1.gbr', 'golden/example_single_contour.gbr')
+
+
+def _test_render_single_contour_2():
+ """Umaco exapmle of a single contour, alternate contour end order
+
+ The resulting image for this test is used by other tests because they must generate the same output."""
+ _test_render('resources/example_single_contour_2.gbr', 'golden/example_single_contour.gbr')
+
+
+def _test_render_single_contour_3():
+ """Umaco exapmle of a single contour with extra line"""
+ _test_render('resources/example_single_contour_3.gbr', 'golden/example_single_contour_3.gbr')
+
+
+def _test_render_not_overlapping_contour():
+ """Umaco example of D02 staring a second contour"""
+ _test_render('resources/example_not_overlapping_contour.gbr', 'golden/example_not_overlapping_contour.gbr')
+
+
+def _test_render_not_overlapping_touching():
+ """Umaco example of D02 staring a second contour"""
+ _test_render('resources/example_not_overlapping_touching.gbr', 'golden/example_not_overlapping_touching.gbr')
+
+
+def _test_render_overlapping_touching():
+ """Umaco example of D02 staring a second contour"""
+ _test_render('resources/example_overlapping_touching.gbr', 'golden/example_overlapping_touching.gbr')
+
+
+def _test_render_overlapping_contour():
+ """Umaco example of D02 staring a second contour"""
+ _test_render('resources/example_overlapping_contour.gbr', 'golden/example_overlapping_contour.gbr')
+
+
+def _DISABLED_test_render_level_holes():
+ """Umaco example of using multiple levels to create multiple holes"""
+
+ # TODO This is clearly rendering wrong. I'm temporarily checking this in because there are more
+ # rendering fixes in the related repository that may resolve these.
+ _test_render('resources/example_level_holes.gbr', 'golden/example_overlapping_contour.gbr')
+
+
+def _DISABLED_test_render_cutin():
+ """Umaco example of using a cutin"""
+
+ # TODO This is clearly rendering wrong.
+ _test_render('resources/example_cutin.gbr', 'golden/example_cutin.gbr')
+
+
+def _test_render_fully_coincident():
+ """Umaco example of coincident lines rendering two contours"""
+
+ _test_render('resources/example_fully_coincident.gbr', 'golden/example_fully_coincident.gbr')
+
+
+def _test_render_coincident_hole():
+ """Umaco example of coincident lines rendering a hole in the contour"""
+
+ _test_render('resources/example_coincident_hole.gbr', 'golden/example_coincident_hole.gbr')
+
+
+def _test_render_cutin_multiple():
+ """Umaco example of a region with multiple cutins"""
+
+ _test_render('resources/example_cutin_multiple.gbr', 'golden/example_cutin_multiple.gbr')
+
+
+def _test_flash_circle():
+ """Umaco example a simple circular flash with and without a hole"""
+
+ _test_render('resources/example_flash_circle.gbr', 'golden/example_flash_circle.gbr')
+
+
+def _test_flash_rectangle():
+ """Umaco example a simple rectangular flash with and without a hole"""
+
+ _test_render('resources/example_flash_rectangle.gbr', 'golden/example_flash_rectangle.gbr')
+
+
+def _test_flash_obround():
+ """Umaco example a simple obround flash with and without a hole"""
+
+ _test_render('resources/example_flash_obround.gbr', 'golden/example_flash_obround.gbr')
+
+
+def _test_flash_polygon():
+ """Umaco example a simple polygon flash with and without a hole"""
+
+ _test_render('resources/example_flash_polygon.gbr', 'golden/example_flash_polygon.gbr')
+
+
+def _test_holes_dont_clear():
+ """Umaco example that an aperture with a hole does not clear the area"""
+
+ _test_render('resources/example_holes_dont_clear.gbr', 'golden/example_holes_dont_clear.gbr')
+
+
+def _test_render_am_exposure_modifier():
+ """Umaco example that an aperture macro with a hole does not clear the area"""
+
+ _test_render('resources/example_am_exposure_modifier.gbr', 'golden/example_am_exposure_modifier.gbr')
+
+
+def _resolve_path(path):
+ return os.path.join(os.path.dirname(__file__),
+ path)
+
+
+def _test_render(gerber_path, png_expected_path, create_output_path = None):
+ """Render the gerber file and compare to the expected PNG output.
+
+ Parameters
+ ----------
+ gerber_path : string
+ Path to Gerber file to open
+ png_expected_path : string
+ Path to the PNG file to compare to
+ create_output : string|None
+ If not None, write the generated PNG to the specified path.
+ This is primarily to help with
+ """
+
+ gerber_path = _resolve_path(gerber_path)
+ png_expected_path = _resolve_path(png_expected_path)
+ if create_output_path:
+ create_output_path = _resolve_path(create_output_path)
+
+ gerber = read(gerber_path)
+
+ # Create GBR output from the input file
+ ctx = Rs274xContext(gerber.settings)
+ gerber.render(ctx)
+
+ actual_contents = ctx.dump()
+
+ # If we want to write the file bytes, do it now. This happens
+ if create_output_path:
+ with open(create_output_path, 'wb') as out_file:
+ out_file.write(actual_contents.getvalue())
+ # Creating the output is dangerous - it could overwrite the expected result.
+ # So if we are creating the output, we make the test fail on purpose so you
+ # won't forget to disable this
+ assert_false(True, 'Test created the output %s. This needs to be disabled to make sure the test behaves correctly' % (create_output_path,))
+
+ # Read the expected PNG file
+
+ with open(png_expected_path, 'r') as expected_file:
+ expected_contents = expected_file.read()
+
+ assert_equal(expected_contents, actual_contents.getvalue())
+
+ return gerber
diff --git a/gerber/tests/test_utils.py b/gerber/tests/test_utils.py
index 001a32f..35f6f47 100644
--- a/gerber/tests/test_utils.py
+++ b/gerber/tests/test_utils.py
@@ -3,8 +3,8 @@
# Author: Hamilton Kibbe <ham@hamiltonkib.be>
-from .tests import assert_equal
-from ..utils import decimal_string, parse_gerber_value, write_gerber_value
+from .tests import assert_equal, assert_raises
+from ..utils import *
def test_zero_suppression():
@@ -19,10 +19,11 @@ def test_zero_suppression():
('1000', 0.01), ('10000', 0.1), ('100000', 1.0),
('1000000', 10.0), ('-1', -0.00001), ('-10', -0.0001),
('-100', -0.001), ('-1000', -0.01), ('-10000', -0.1),
- ('-100000', -1.0), ('-1000000', -10.0), ]
+ ('-100000', -1.0), ('-1000000', -10.0),
+ ('0', 0.0)]
for string, value in test_cases:
- assert(value == parse_gerber_value(string, fmt, zero_suppression))
- assert(string == write_gerber_value(value, fmt, zero_suppression))
+ assert_equal(value, parse_gerber_value(string, fmt, zero_suppression))
+ assert_equal(string, write_gerber_value(value, fmt, zero_suppression))
# Test trailing zero suppression
zero_suppression = 'trailing'
@@ -30,10 +31,14 @@ def test_zero_suppression():
('00001', 0.001), ('000001', 0.0001),
('0000001', 0.00001), ('-1', -10.0), ('-01', -1.0),
('-001', -0.1), ('-0001', -0.01), ('-00001', -0.001),
- ('-000001', -0.0001), ('-0000001', -0.00001)]
+ ('-000001', -0.0001), ('-0000001', -0.00001),
+ ('0', 0.0)]
for string, value in test_cases:
- assert(value == parse_gerber_value(string, fmt, zero_suppression))
- assert(string == write_gerber_value(value, fmt, zero_suppression))
+ assert_equal(value, parse_gerber_value(string, fmt, zero_suppression))
+ assert_equal(string, write_gerber_value(value, fmt, zero_suppression))
+
+ assert_equal(write_gerber_value(0.000000001, fmt, 'leading'), '0')
+ assert_equal(write_gerber_value(0.000000001, fmt, 'trailing'), '0')
def test_format():
@@ -46,10 +51,11 @@ def test_format():
((2, 1), '1', 0.1), ((2, 7), '-1', -0.0000001),
((2, 6), '-1', -0.000001), ((2, 5), '-1', -0.00001),
((2, 4), '-1', -0.0001), ((2, 3), '-1', -0.001),
- ((2, 2), '-1', -0.01), ((2, 1), '-1', -0.1), ]
+ ((2, 2), '-1', -0.01), ((2, 1), '-1', -0.1),
+ ((2, 6), '0', 0)]
for fmt, string, value in test_cases:
- assert(value == parse_gerber_value(string, fmt, zero_suppression))
- assert(string == write_gerber_value(value, fmt, zero_suppression))
+ assert_equal(value, parse_gerber_value(string, fmt, zero_suppression))
+ assert_equal(string, write_gerber_value(value, fmt, zero_suppression))
zero_suppression = 'trailing'
test_cases = [((6, 5), '1', 100000.0), ((5, 5), '1', 10000.0),
@@ -57,10 +63,11 @@ def test_format():
((2, 5), '1', 10.0), ((1, 5), '1', 1.0),
((6, 5), '-1', -100000.0), ((5, 5), '-1', -10000.0),
((4, 5), '-1', -1000.0), ((3, 5), '-1', -100.0),
- ((2, 5), '-1', -10.0), ((1, 5), '-1', -1.0), ]
+ ((2, 5), '-1', -10.0), ((1, 5), '-1', -1.0),
+ ((2, 5), '0', 0)]
for fmt, string, value in test_cases:
- assert(value == parse_gerber_value(string, fmt, zero_suppression))
- assert(string == write_gerber_value(value, fmt, zero_suppression))
+ assert_equal(value, parse_gerber_value(string, fmt, zero_suppression))
+ assert_equal(string, write_gerber_value(value, fmt, zero_suppression))
def test_decimal_truncation():
@@ -69,8 +76,8 @@ def test_decimal_truncation():
value = 1.123456789
for x in range(10):
result = decimal_string(value, precision=x)
- calculated = '1.' + ''.join(str(y) for y in range(1,x+1))
- assert(result == calculated)
+ calculated = '1.' + ''.join(str(y) for y in range(1, x + 1))
+ assert_equal(result, calculated)
def test_decimal_padding():
@@ -81,3 +88,42 @@ def test_decimal_padding():
assert_equal(decimal_string(value, precision=4, padding=True), '1.1230')
assert_equal(decimal_string(value, precision=5, padding=True), '1.12300')
assert_equal(decimal_string(value, precision=6, padding=True), '1.123000')
+ assert_equal(decimal_string(0, precision=6, padding=True), '0.000000')
+
+
+def test_parse_format_validation():
+ """ Test parse_gerber_value() format validation
+ """
+ assert_raises(ValueError, parse_gerber_value, '00001111', (7, 5))
+ assert_raises(ValueError, parse_gerber_value, '00001111', (5, 8))
+ assert_raises(ValueError, parse_gerber_value, '00001111', (13, 1))
+
+
+def test_write_format_validation():
+ """ Test write_gerber_value() format validation
+ """
+ assert_raises(ValueError, write_gerber_value, 69.0, (7, 5))
+ assert_raises(ValueError, write_gerber_value, 69.0, (5, 8))
+ assert_raises(ValueError, write_gerber_value, 69.0, (13, 1))
+
+
+def test_detect_format_with_short_file():
+ """ Verify file format detection works with short files
+ """
+ assert_equal('unknown', detect_file_format('gerber/tests/__init__.py'))
+
+
+def test_validate_coordinates():
+ assert_raises(TypeError, validate_coordinates, 3)
+ assert_raises(TypeError, validate_coordinates, 3.1)
+ assert_raises(TypeError, validate_coordinates, '14')
+ assert_raises(TypeError, validate_coordinates, (0,))
+ assert_raises(TypeError, validate_coordinates, (0, 1, 2))
+ assert_raises(TypeError, validate_coordinates, (0, 'string'))
+
+
+def test_convex_hull():
+ points = [(0, 0), (1, 0), (1, 1), (0.5, 0.5), (0, 1), (0, 0)]
+ expected = [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)]
+ assert_equal(set(convex_hull(points)), set(expected))
+ \ No newline at end of file
diff --git a/gerber/tests/tests.py b/gerber/tests/tests.py
index 29b7899..ac08208 100644
--- a/gerber/tests/tests.py
+++ b/gerber/tests/tests.py
@@ -7,6 +7,7 @@ from nose.tools import assert_in
from nose.tools import assert_not_in
from nose.tools import assert_equal
from nose.tools import assert_not_equal
+from nose.tools import assert_almost_equal
from nose.tools import assert_true
from nose.tools import assert_false
from nose.tools import assert_raises
@@ -14,5 +15,11 @@ from nose.tools import raises
from nose import with_setup
__all__ = ['assert_in', 'assert_not_in', 'assert_equal', 'assert_not_equal',
- 'assert_true', 'assert_false', 'assert_raises', 'raises',
- 'with_setup' ]
+ 'assert_almost_equal', 'assert_array_almost_equal', 'assert_true',
+ 'assert_false', 'assert_raises', 'raises', 'with_setup']
+
+
+def assert_array_almost_equal(arr1, arr2, decimal=6):
+ assert_equal(len(arr1), len(arr2))
+ for i in range(len(arr1)):
+ assert_almost_equal(arr1[i], arr2[i], decimal)