From 30c219d6b215828af0bcecd3895bf9aefff5214c Mon Sep 17 00:00:00 2001 From: Marc-Antoine Lafreniere Date: Sun, 17 Mar 2019 20:00:03 -0400 Subject: [PATCH 1/2] #42 Run the c++ code to convert PBM binary to ascii Run the converter if the image is in binary --- pcbdevice/gcode/GcodeBuilder.py | 1 + pcbdevice/main.py | 22 +++- pcbdevice/resources/input/square.pbm | 23 ---- .../resources/pathoutput/test100x100.csv | 100 ------------------ pcbdevice/tests/gcode/test_listToGcode.py | 2 +- pcbdevice/utils/convertiseur.exe | Bin 0 -> 68605 bytes 6 files changed, 20 insertions(+), 128 deletions(-) delete mode 100644 pcbdevice/resources/input/square.pbm delete mode 100644 pcbdevice/resources/pathoutput/test100x100.csv create mode 100644 pcbdevice/utils/convertiseur.exe diff --git a/pcbdevice/gcode/GcodeBuilder.py b/pcbdevice/gcode/GcodeBuilder.py index 603bc16..06f0e17 100644 --- a/pcbdevice/gcode/GcodeBuilder.py +++ b/pcbdevice/gcode/GcodeBuilder.py @@ -30,5 +30,6 @@ def listToGCode(listIndex, pHeight, pWidth): # FOOTER gcodeCommand.append('\nG0 Z0') gcodeCommand.append('G28') + gcodeCommand.append('M18') return gcodeCommand \ No newline at end of file diff --git a/pcbdevice/main.py b/pcbdevice/main.py index 9959568..38eaa16 100644 --- a/pcbdevice/main.py +++ b/pcbdevice/main.py @@ -6,10 +6,12 @@ from pcbdevice.gcode.GcodeCreator import createSequence from pcbdevice.gcode.path import path from pcbdevice.utils.FileUtils import FileUtils import argparse +import subprocess if __name__ == "__main__": parser = argparse.ArgumentParser(prog = 'main.py') parser.add_argument('-i', required = True, help = 'PCB image path') + parser.add_argument('--ascii', required = False, dest='imgTypeisAscii', action = 'store_true', help = 'If the image is in ascii(True) or binary(False)') parser.add_argument('-o', required = True, help = 'Gcode output path') parser.add_argument('-wi', required = True, type = int, help = 'Width of the PCB') parser.add_argument('-he', required = True, type = int, help = 'Height of the PCB') @@ -17,12 +19,24 @@ if __name__ == "__main__": parser.add_argument('-u', required = False, help = 'PCB dimension unit') args = parser.parse_args() - matrix, height, width = FileUtils.pbmToMatrix(args.i) + converterPath = '.\\pcbdevice\\utils\\convertiseur.exe' + asciiPbmPath = '.\\pcbdevice\\resources\\output\\pcbImageAscii.pbm' + + unitValue = 'mm' + isAscii = args.imgTypeisAscii + + if isAscii: + asciiPbmPath = args.i + + if not isAscii: + subprocess.check_call([converterPath, args.i, asciiPbmPath]) + + matrix, height, width = FileUtils.pbmToMatrix(asciiPbmPath) if args.u: - pxHeight, pxWidth = FileUtils.getPixelSize(height, width, args.he, args.wi, unit = args.u) - else: - pxHeight, pxWidth = FileUtils.getPixelSize(height, width, args.he, args.wi) + unitValue = args.u + + pxHeight, pxWidth = FileUtils.getPixelSize(height, width, args.he, args.wi, unit = unitValue) if pxHeight > pxWidth: rTool = int(math.ceil(args.t * pxHeight)) diff --git a/pcbdevice/resources/input/square.pbm b/pcbdevice/resources/input/square.pbm deleted file mode 100644 index 8b34f1c..0000000 --- a/pcbdevice/resources/input/square.pbm +++ /dev/null @@ -1,23 +0,0 @@ -P1 -# Bob -20 20 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 -0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 -0 0 2 0 1 1 1 1 1 1 1 1 1 1 1 1 0 2 0 0 -0 0 2 0 1 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 -0 0 2 0 1 0 2 2 2 2 2 2 2 2 0 1 0 2 0 0 -0 0 2 0 1 0 2 0 0 0 0 0 0 2 0 1 0 2 0 0 -0 0 2 0 1 0 2 0 0 0 0 0 0 2 0 1 0 2 0 0 -0 0 2 0 1 0 2 0 0 0 0 0 0 2 0 1 0 2 0 0 -0 0 2 0 1 0 2 0 0 0 0 0 0 2 0 1 0 2 0 0 -0 0 2 0 1 0 2 0 0 0 0 0 0 2 0 1 0 2 0 0 -0 0 2 0 1 0 2 0 0 0 0 0 0 2 0 1 0 2 0 0 -0 0 2 0 1 0 2 0 0 0 0 0 0 2 0 1 0 2 0 0 -0 0 2 0 1 0 2 0 0 0 0 0 0 2 0 1 0 2 0 0 -0 0 2 0 1 0 2 0 0 0 0 0 0 2 0 1 0 2 0 0 -0 0 2 0 1 0 2 2 2 2 2 2 2 2 0 1 0 2 0 0 -0 0 2 0 1 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 -0 0 2 0 1 1 1 1 1 1 1 1 1 1 1 1 0 2 0 0 -0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 -0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 diff --git a/pcbdevice/resources/pathoutput/test100x100.csv b/pcbdevice/resources/pathoutput/test100x100.csv deleted file mode 100644 index 1b35427..0000000 --- a/pcbdevice/resources/pathoutput/test100x100.csv +++ /dev/null @@ -1,100 +0,0 @@ -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 1 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 1 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 1 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 1 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 1 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 2 2 2 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 2 2 2 2 0 0 0 2 2 2 0 0 0 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 1 1 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2 2 2 2 2 0 0 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 2 2 0 0 0 2 2 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 2 2 0 0 0 0 0 1 1 0 0 0 0 2 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 1 0 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 1 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 2 2 2 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 1 0 0 0 0 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 1 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 1 1 0 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 2 0 0 0 0 0 0 2 2 0 0 0 0 1 1 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 2 2 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 2 2 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/pcbdevice/tests/gcode/test_listToGcode.py b/pcbdevice/tests/gcode/test_listToGcode.py index 3ca9a51..b09429b 100644 --- a/pcbdevice/tests/gcode/test_listToGcode.py +++ b/pcbdevice/tests/gcode/test_listToGcode.py @@ -52,7 +52,7 @@ class TestListToGCode(TestCase): def getExpected(coords, ySize, xSize): header = ['G28', 'G90\n'] - footer = ['\nG0 Z0', 'G28'] + footer = ['\nG0 Z0', 'G28', 'M18'] content = ['G0 X' + str(round(xSize * coords[0].getX(), 2)) + ' Y' + str(round(ySize * coords[0].getY(), 2)), 'G0 Z3', diff --git a/pcbdevice/utils/convertiseur.exe b/pcbdevice/utils/convertiseur.exe new file mode 100644 index 0000000000000000000000000000000000000000..fdba465c59c04f15e23e518845870d4e684e7616 GIT binary patch literal 68605 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 ljaV-UWV>;2(a Date: Mon, 18 Mar 2019 15:26:24 -0400 Subject: [PATCH 2/2] # 32 unit tests for path function closes #32 --- pcbdevice/gcode/path.py | 45 +++++--- pcbdevice/tests/gcode/test_path.py | 174 +++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 18 deletions(-) create mode 100644 pcbdevice/tests/gcode/test_path.py diff --git a/pcbdevice/gcode/path.py b/pcbdevice/gcode/path.py index ce8f1c4..53ed7c1 100644 --- a/pcbdevice/gcode/path.py +++ b/pcbdevice/gcode/path.py @@ -11,15 +11,19 @@ def scanHorizontal(image, rTool): for line in range(height): for column in range(width): - if image[line][column] == 1 and image[line][column - 1] != 1: - for px in range(2 * rTool + 1): - if image[line - rTool + px][column - rTool] == 0: - image[line - rTool + px][column - rTool] = 2 + if column > 0: + if image[line][column] == 1 and image[line][column - 1] != 1: + for px in range(2 * rTool + 1): + if column - rTool >= 0 and 0 <= line - rTool + px < height: + if image[line - rTool + px][column - rTool] == 0: + image[line - rTool + px][column - rTool] = 2 - if image[line][column] == 1 and image[line][column + 1] != 1: - for px in range(2 * rTool + 1): - if image[line - rTool + px][column + rTool] == 0: - image[line - rTool + px][column + rTool] = 2 + if column < width - 1: + if image[line][column] == 1 and image[line][column + 1] != 1: + for px in range(2 * rTool + 1): + if column + rTool < width and 0 <= line - rTool + px < height: + if image[line - rTool + px][column + rTool] == 0: + image[line - rTool + px][column + rTool] = 2 return image @@ -37,15 +41,19 @@ def scanVertical(image, rTool): for line in range(height): for column in range(width): - if image[line][column] == 1 and image[line - 1][column] != 1: - for px in range(2 * rTool + 1): - if image[line - rTool][column - rTool + px] == 0: - image[line - rTool][column - rTool + px] = 2 + if line > 0: + if image[line][column] == 1 and image[line - 1][column] != 1: + for px in range(2 * rTool + 1): + if line - rTool >= 0 and 0 <= column - rTool + px < width: + if image[line - rTool][column - rTool + px] == 0: + image[line - rTool][column - rTool + px] = 2 - if image[line][column] == 1 and image[line + 1][column] != 1: - for px in range(2 * rTool + 1): - if image[line + rTool][column - rTool + px] == 0: - image[line + rTool][column - rTool + px] = 2 + if line < height - 1: + if image[line][column] == 1 and image[line + 1][column] != 1: + for px in range(2 * rTool + 1): + if line + rTool < height and 0 <= column - rTool + px < width: + if image[line + rTool][column - rTool + px] == 0: + image[line + rTool][column - rTool + px] = 2 return image @@ -65,8 +73,9 @@ def twoRemoving(image, rTool): if image[line][column] == 1: for pixelx in range(1, 2 * rTool): for pixely in range(1, 2*rTool): - if image[line - rTool + pixelx][column - rTool + pixely] == 2: - image[line - rTool + pixelx][column - rTool + pixely] = 0 + if 0 <= line - rTool + pixelx < height and 0 <= column - rTool + pixely < width: + if image[line - rTool + pixelx][column - rTool + pixely] == 2: + image[line - rTool + pixelx][column - rTool + pixely] = 0 print("image width = " + str(width)) print("image height = " + str(height)) diff --git a/pcbdevice/tests/gcode/test_path.py b/pcbdevice/tests/gcode/test_path.py new file mode 100644 index 0000000..5ff8817 --- /dev/null +++ b/pcbdevice/tests/gcode/test_path.py @@ -0,0 +1,174 @@ +from unittest import TestCase + +from pcbdevice.gcode.path import scanHorizontal, scanVertical, twoRemoving + + +class TestPath(TestCase): + + #inputs + def imageTest(self): + return [[0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0]] + + def imageTestMulti(self): + return [[0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 1, 0, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 1, 0, 0]] + + def imageTestHOut(self): + return [[0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0]] + + def imageTestVOut(self): + return [[0, 0, 0], + [0, 0, 0], + [0, 0, 0], + [0, 1, 0], + [0, 0, 0], + [0, 0, 0], + [0, 0, 0]] + + def imageTest2(self): + return [[0, 0, 0, 0, 0, 0, 0], + [0, 2, 2, 2, 2, 2, 0], + [0, 2, 2, 2, 2, 2, 0], + [0, 2, 2, 1, 2, 2, 0], + [0, 2, 2, 2, 2, 2, 0], + [0, 2, 2, 2, 2, 2, 0], + [0, 0, 0, 0, 0, 0, 0]] + + def imageTestMulti2(self): + return [[2, 2, 2, 2, 2, 2, 2], + [2, 2, 2, 2, 2, 2, 2], + [2, 1, 2, 2, 1, 2, 2], + [2, 2, 2, 1, 2, 2, 2], + [2, 2, 2, 2, 2, 2, 2], + [2, 2, 2, 2, 2, 2, 2], + [2, 2, 2, 2, 1, 2, 2]] + + + #horizontal results + def imageResultHr2(self): + return [[0, 0, 0, 0, 0, 0, 0], + [0, 2, 0, 0, 0, 2, 0], + [0, 2, 0, 0, 0, 2, 0], + [0, 2, 0, 1, 0, 2, 0], + [0, 2, 0, 0, 0, 2, 0], + [0, 2, 0, 0, 0, 2, 0], + [0, 0, 0, 0, 0, 0, 0]] + + def imageResultHr3(self): + return [[2, 0, 0, 0, 0, 0, 2], + [2, 0, 0, 0, 0, 0, 2], + [2, 0, 0, 0, 0, 0, 2], + [2, 0, 0, 1, 0, 0, 2], + [2, 0, 0, 0, 0, 0, 2], + [2, 0, 0, 0, 0, 0, 2], + [2, 0, 0, 0, 0, 0, 2]] + + def imageResultHOut(self): + return [[0, 2, 0, 0, 0, 2, 0], + [0, 2, 0, 1, 0, 2, 0], + [0, 2, 0, 0, 0, 2, 0]] + + def imageResultMultiH(self): + return [[0, 0, 2, 2, 0, 0, 2], + [0, 2, 2, 2, 0, 2, 2], + [0, 1, 2, 2, 1, 2, 2], + [0, 2, 2, 1, 0, 2, 2], + [0, 2, 2, 2, 0, 2, 2], + [0, 2, 2, 0, 0, 2, 2], + [0, 0, 2, 0, 1, 0, 2]] + + + #vertical results + def imageResultVr2(self): + return [[0, 0, 0, 0, 0, 0, 0], + [0, 2, 2, 2, 2, 2, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 2, 2, 2, 2, 2, 0], + [0, 0, 0, 0, 0, 0, 0]] + + def imageResultVr3(self): + return [[2, 2, 2, 2, 2, 2, 2], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0], + [2, 2, 2, 2, 2, 2, 2]] + + def imageResultVOut(self): + return [[0, 0, 0], + [2, 2, 2], + [0, 0, 0], + [0, 1, 0], + [0, 0, 0], + [2, 2, 2], + [0, 0, 0]] + + def imageResultMultiV(self): + return [[2, 2, 2, 2, 2, 2, 2], + [0, 2, 2, 2, 2, 2, 0], + [0, 1, 0, 0, 1, 0, 0], + [0, 0, 0, 1, 0, 0, 0], + [2, 2, 2, 2, 2, 2, 2], + [0, 2, 2, 2, 2, 2, 0], + [0, 0, 0, 0, 1, 0, 0]] + + #two results + + def imageResult2(self): + return [[0, 0, 0, 0, 0, 0, 0], + [0, 2, 2, 2, 2, 2, 0], + [0, 2, 0, 0, 0, 2, 0], + [0, 2, 0, 1, 0, 2, 0], + [0, 2, 0, 0, 0, 2, 0], + [0, 2, 2, 2, 2, 2, 0], + [0, 0, 0, 0, 0, 0, 0]] + + def imageResultMulti2(self): + return [[2, 2, 2, 2, 2, 2, 2], + [0, 0, 0, 0, 0, 0, 2], + [0, 1, 0, 0, 1, 0, 2], + [0, 0, 0, 1, 0, 0, 2], + [2, 2, 0, 0, 0, 2, 2], + [2, 2, 2, 0, 0, 0, 2], + [2, 2, 2, 0, 1, 0, 2]] + + + + def test_hori(self): + + self.assertEqual(scanHorizontal(self.imageTest(), 2), self.imageResultHr2()) + self.assertEqual(scanHorizontal(self.imageTest(), 3), self.imageResultHr3()) + self.assertEqual(scanHorizontal(self.imageTestHOut(), 2), self.imageResultHOut()) + self.assertEqual(scanHorizontal(self.imageTest(), 4), self.imageTest()) + self.assertEqual(scanHorizontal(self.imageTestMulti(), 2), self.imageResultMultiH()) + + def test_vert(self): + + self.assertEqual(scanVertical(self.imageTest(), 2), self.imageResultVr2()) + self.assertEqual(scanVertical(self.imageTest(), 3), self.imageResultVr3()) + self.assertEqual(scanVertical(self.imageTestVOut(), 2), self.imageResultVOut()) + self.assertEqual(scanVertical(self.imageTest(), 4), self.imageTest()) + self.assertEqual(scanVertical(self.imageTestMulti(), 2), self.imageResultMultiV()) + + def test_two(self): + + self.assertEqual(twoRemoving(self.imageTest2(), 2), self.imageResult2()) + self.assertEqual(twoRemoving(self.imageTest2(), 3), self.imageTest()) + self.assertEqual(twoRemoving(self.imageTest2(), 7), self.imageTest()) + self.assertEqual(twoRemoving(self.imageTestMulti2(), 2), self.imageResultMulti2())