From 94bf54279937b5dc4b649bd5a8e0c1d72b18a34f Mon Sep 17 00:00:00 2001 From: Ian Date: Wed, 20 Feb 2019 15:01:16 -0500 Subject: [PATCH] #34 gcode algo closes #34 algorithm that creates a gcode from a path unittest for the algorithm --- pcbdevice/gcode/GcodeCreator.py | 97 ++++++++++++++++++++++ pcbdevice/{utils => gcode}/path.py | 0 pcbdevice/models/Coordinates.py | 6 ++ pcbdevice/tests/gcode/test_gcodeCreator.py | 93 +++++++++++++++++++++ 4 files changed, 196 insertions(+) create mode 100644 pcbdevice/gcode/GcodeCreator.py rename pcbdevice/{utils => gcode}/path.py (100%) create mode 100644 pcbdevice/tests/gcode/test_gcodeCreator.py diff --git a/pcbdevice/gcode/GcodeCreator.py b/pcbdevice/gcode/GcodeCreator.py new file mode 100644 index 0000000..e7778d5 --- /dev/null +++ b/pcbdevice/gcode/GcodeCreator.py @@ -0,0 +1,97 @@ +from pcbdevice.models.Coordinates import Coordinate + + +def findEndOfLine(image, direction, line, column, sequence): + """ + Start from a pixel and finds the end of a line of pixel in the direction specified + :param image: image the sequence is created from + :param direction: direction to go to find the end of line + :param line: line index of the pixel to apply the function + :param column: column index of the pixel to apply the function + :param sequence: list of coordinates to append the end of line coordinates + :return: + """ + + distance = 0 + + if direction == 0: + while (line - distance) >= 0 and image[line - distance][column] == 2: + image[line - distance][column] = 3 + distance += 1 + sequence.append(Coordinate(column, line - (distance - 1))) + image[line - (distance-1)][column] = 2 + + elif direction == 1: + while (column + distance) < len(image[line]) and image[line][column + distance] == 2: + image[line][column + distance] = 3 + distance += 1 + sequence.append(Coordinate(column + (distance - 1), line)) + image[line][column + (distance-1)] = 2 + + elif direction == 2: + while (line + distance) < len(image) and image[line + distance][column] == 2: + image[line + distance][column] = 3 + distance += 1 + sequence.append(Coordinate(column, line + (distance - 1))) + image[line + (distance-1)][column] = 2 + + elif direction == 3: + while (column - distance) >= 0 and image[line][column - distance] == 2: + image[line][column - distance] = 3 + distance += 1 + sequence.append(Coordinate(column - (distance - 1), line)) + image[line][column - (distance-1)] = 2 + + elif direction == -1: + image[line][column] = 3 + + return distance + + +def findDirection(image, line, column): + """ + Looks for a nearby pixel to choose a direction to start a line + :param image: image the sequence is created from + :param line: line index of the pixel to apply the function + :param column: column index of the pixel to apply the function + :return: direction of a nearby pixel, up = 0, right = 1, down = 2, left = 3, no pixel = -1. priorities is this order + """ + + if line != 0: + if image[line-1][column] == 2: + return 0 + + if column != (len(image[0]) - 1): + if image[line][column+1] == 2: + return 1 + + if line != (len(image)-1): + if image[line+1][column] == 2: + return 2 + + if column != 0: + if image[line][column-1] == 2: + return 3 + + return -1 + + +def createSequence(image): + + width = len(image[0]) + height = len(image) + sequence = [] + + for line in range(height): + for column in range(width): + + if image[line][column] == 2: + sequence.append(Coordinate(-1, -1)) + sequence.append(Coordinate(column, line)) + direction = 4 + while direction > -1: + x, y = sequence[-1].getX(), sequence[-1].getY() + direction = findDirection(image, y, x) + findEndOfLine(image, direction, y, x, sequence) + + return sequence diff --git a/pcbdevice/utils/path.py b/pcbdevice/gcode/path.py similarity index 100% rename from pcbdevice/utils/path.py rename to pcbdevice/gcode/path.py diff --git a/pcbdevice/models/Coordinates.py b/pcbdevice/models/Coordinates.py index 1d9728e..23233cc 100644 --- a/pcbdevice/models/Coordinates.py +++ b/pcbdevice/models/Coordinates.py @@ -5,6 +5,12 @@ class Coordinate: def __init__(self, x = -1, y = -1): self._x = x self._y = y + + def __eq__(self, other): + return self.getX() == other.getX() and self.getY() == other.getY() + + def __ne__(self, other): + return not self.__eq__(other) def setX(self, x): self._x = x diff --git a/pcbdevice/tests/gcode/test_gcodeCreator.py b/pcbdevice/tests/gcode/test_gcodeCreator.py new file mode 100644 index 0000000..d964f4e --- /dev/null +++ b/pcbdevice/tests/gcode/test_gcodeCreator.py @@ -0,0 +1,93 @@ +from unittest import TestCase + +from pcbdevice.gcode.GcodeCreator import createSequence, findDirection, findEndOfLine +from pcbdevice.models.Coordinates import Coordinate + + +class TestGcodeCreator(TestCase): + + + def imageTest(self): + return [[0, 2, 0, 0, 0, 0, 0], + [0, 2, 0, 0, 0, 0, 0], + [0, 2, 0, 0, 2, 2, 0], + [0, 2, 2, 0, 0, 2, 0], + [0, 0, 2, 0, 0, 2, 0], + [0, 0, 2, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0]] + + expectedSequence = [Coordinate(-1, -1), + Coordinate(1, 0), + Coordinate(1, 3), + Coordinate(2, 3), + Coordinate(2, 5), + Coordinate(-1, -1), + Coordinate(4, 2), + Coordinate(5, 2), + Coordinate(5, 4)] + + def imageTestDots(self): + return [[0, 0, 0, 2], + [0, 2, 0, 0], + [0, 0, 0, 0], + [0, 0, 2, 0]] + + expectedSequenceDots = [Coordinate(-1, -1), + Coordinate(3, 0), + Coordinate(-1, -1), + Coordinate(1, 1), + Coordinate(-1, -1), + Coordinate(2, 3)] + + def imageTestEmpty(self): + return [[0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0]] + + expectedSequenceEmpty = [] + + def imageTestFull(self): + return [[2, 2, 2, 2], + [2, 2, 2, 2], + [2, 2, 2, 2], + [2, 2, 2, 2]] + + expectedSequenceFull = [Coordinate(-1, -1), + Coordinate(0, 0), + Coordinate(3, 0), + Coordinate(3, 3), + Coordinate(0, 3), + Coordinate(0, 1), + Coordinate(2, 1), + Coordinate(2, 2), + Coordinate(1, 2)] + + + def test_createSequence(self): + + self.assertEqual(createSequence(self.imageTest()), self.expectedSequence) + self.assertEqual(createSequence(self.imageTestDots()), self.expectedSequenceDots) + self.assertEqual(createSequence(self.imageTestEmpty()), self.expectedSequenceEmpty) + self.assertEqual(createSequence(self.imageTestFull()), self.expectedSequenceFull) + + def test_findDirection(self): + + self.assertEqual(findDirection(self.imageTest(), 1, 1), 0) + self.assertEqual(findDirection(self.imageTest(), 2, 4), 1) + self.assertEqual(findDirection(self.imageTest(), 1, 4), 2) + self.assertEqual(findDirection(self.imageTest(), 3, 3), 3) + self.assertEqual(findDirection(self.imageTest(), 5, 4), -1) + + def test_findEndOfLine(self): + + sequenceTest = [] + + self.assertEqual(findEndOfLine(self.imageTest(), 2, 0, 1, sequenceTest), 4) + self.assertEqual(findEndOfLine(self.imageTest(), 1, 3, 1, sequenceTest), 2) + self.assertEqual(findEndOfLine(self.imageTest(), 0, 5, 2, sequenceTest), 3) + self.assertEqual(findEndOfLine(self.imageTest(), 3, 0, 1, sequenceTest), 1) + self.assertEqual(findEndOfLine(self.imageTestFull(), 1, 1, 1, sequenceTest), 3) + self.assertEqual(findEndOfLine(self.imageTestFull(), 0, 1, 1, sequenceTest), 2) + +