From 7e3c1e469487dc2c7bc5f76c370b7642a9e340a0 Mon Sep 17 00:00:00 2001 From: Brenda Bell Date: Fri, 22 Dec 2017 01:11:09 -0500 Subject: [PATCH] Refactored machine configs; added 4.5mm Jac-40 --- .gitignore | 2 + data/12-stitch-br-sr.json | 19 ++++ data/18-stitch-mk70.json | 19 ++++ data/24-stitch-br-sr.json | 19 ++++ data/30-stitch-km.json | 19 ++++ data/40-stitch-deco.json | 19 ++++ data/40-stitch-jac-4_5.json | 19 ++++ data/json-template.txt | 19 ++++ modules/pcgenerator.py | 204 +++++++++++------------------------- sandbox/calibrate.py | 21 ++++ sandbox/test-geometry.py | 55 ++++++++++ templates/pcgenerator.html | 11 +- test/test.py | 15 +-- 13 files changed, 287 insertions(+), 154 deletions(-) create mode 100644 data/12-stitch-br-sr.json create mode 100644 data/18-stitch-mk70.json create mode 100644 data/24-stitch-br-sr.json create mode 100644 data/30-stitch-km.json create mode 100644 data/40-stitch-deco.json create mode 100644 data/40-stitch-jac-4_5.json create mode 100644 data/json-template.txt create mode 100644 sandbox/calibrate.py create mode 100644 sandbox/test-geometry.py diff --git a/.gitignore b/.gitignore index fbfa7d1..1e5f98a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ **/*.pyc +**/*.svg +**/*.png diff --git a/data/12-stitch-br-sr.json b/data/12-stitch-br-sr.json new file mode 100644 index 0000000..80c7533 --- /dev/null +++ b/data/12-stitch-br-sr.json @@ -0,0 +1,19 @@ +{ + "card_width": 142.0, + "stitches": 12, + "row_height": 5.0, + "stitch_width": 9.0, + "pattern_hole_diameter": 3.5, + "pattern_hole_xoffset": 24.25, + "pattern_hole_yoffset": 12.5, + "clip_hole_diameter": 3.5, + "clip_hole_xoffset": 6.75, + "clip_hole_yoffset": 5.0, + "tractor_hole_diameter": 3.0, + "tractor_hole_xoffset": 14.0, + "tractor_hole_yoffset": 2.5, + "overlapping_rows": 2, + "overlapping_row_xoffset": 24.25, + "overlapping_row_yoffset": 2.5, + "corner_offset": 2.0 +} diff --git a/data/18-stitch-mk70.json b/data/18-stitch-mk70.json new file mode 100644 index 0000000..c87442c --- /dev/null +++ b/data/18-stitch-mk70.json @@ -0,0 +1,19 @@ +{ + "card_width": 142.0, + "stitches": 18, + "row_height": 5.0, + "stitch_width": 6.0, + "pattern_hole_diameter": 3.5, + "pattern_hole_xoffset": 19.25, + "pattern_hole_yoffset": 12.5, + "clip_hole_diameter": 3.5, + "clip_hole_xoffset": 6.75, + "clip_hole_yoffset": 5.0, + "tractor_hole_diameter": 3.0, + "tractor_hole_xoffset": 14.0, + "tractor_hole_yoffset": 2.5, + "overlapping_rows": 2, + "overlapping_row_xoffset": 19.25, + "overlapping_row_yoffset": 2.5, + "corner_offset": 2.0 +} diff --git a/data/24-stitch-br-sr.json b/data/24-stitch-br-sr.json new file mode 100644 index 0000000..216ed90 --- /dev/null +++ b/data/24-stitch-br-sr.json @@ -0,0 +1,19 @@ +{ + "card_width": 142.0, + "stitches": 24, + "row_height": 5.0, + "stitch_width": 4.5, + "pattern_hole_diameter": 3.5, + "pattern_hole_xoffset": 19.25, + "pattern_hole_yoffset": 12.5, + "clip_hole_diameter": 3.5, + "clip_hole_xoffset": 6.75, + "clip_hole_yoffset": 5.0, + "tractor_hole_diameter": 3.0, + "tractor_hole_xoffset": 13.5, + "tractor_hole_yoffset": 2.5, + "overlapping_rows": 2, + "overlapping_row_xoffset": 19.25, + "overlapping_row_yoffset": 2.5, + "corner_offset": 2.0 +} diff --git a/data/30-stitch-km.json b/data/30-stitch-km.json new file mode 100644 index 0000000..5c6ae76 --- /dev/null +++ b/data/30-stitch-km.json @@ -0,0 +1,19 @@ +{ + "card_width": 142.0, + "stitches": 30, + "row_height": 5.0, + "stitch_width": 3.6, + "pattern_hole_diameter": 2.7, + "pattern_hole_xoffset": 18.85, + "pattern_hole_yoffset": 12.5, + "clip_hole_diameter": 3.5, + "clip_hole_xoffset": 6.75, + "clip_hole_yoffset": 5.0, + "tractor_hole_diameter": 3.0, + "tractor_hole_xoffset": 13.5, + "tractor_hole_yoffset": 2.5, + "overlapping_rows": 2, + "overlapping_row_xoffset": 18.85, + "overlapping_row_yoffset": 2.5, + "corner_offset": 2.0 +} diff --git a/data/40-stitch-deco.json b/data/40-stitch-deco.json new file mode 100644 index 0000000..47e8c84 --- /dev/null +++ b/data/40-stitch-deco.json @@ -0,0 +1,19 @@ +{ + "card_width": 243.0, + "stitches": 40, + "row_height": 5.25, + "stitch_width": 5.0, + "pattern_hole_diameter": 3.7, + "pattern_hole_xoffset": 24.0, + "pattern_hole_yoffset": 18.375, + "clip_hole_diameter": 3.5, + "clip_hole_xoffset": 3.75, + "clip_hole_yoffset": 5.5, + "tractor_hole_diameter": 3.0, + "tractor_hole_xoffset": 14.0, + "tractor_hole_yoffset": 5.5, + "overlapping_rows": 3, + "overlapping_row_xoffset": 24.0, + "overlapping_row_yoffset": 2.625, + "corner_offset": 0.0 +} diff --git a/data/40-stitch-jac-4_5.json b/data/40-stitch-jac-4_5.json new file mode 100644 index 0000000..c913b7b --- /dev/null +++ b/data/40-stitch-jac-4_5.json @@ -0,0 +1,19 @@ +{ + "card_width": 223.5, + "stitches": 40, + "row_height": 5.25, + "stitch_width": 4.5, + "pattern_hole_diameter": 3.0, + "pattern_hole_xoffset": 24.0, + "pattern_hole_yoffset": 28.875, + "clip_hole_diameter": 0.0, + "clip_hole_xoffset": 0.0, + "clip_hole_yoffset": 0.0, + "tractor_hole_diameter": 2.5, + "tractor_hole_xoffset": 4.5, + "tractor_hole_yoffset": 0.0, + "overlapping_rows": 0, + "overlapping_row_xoffset": 0.0, + "overlapping_row_yoffset": 0.0, + "corner_offset": 0.0 +} diff --git a/data/json-template.txt b/data/json-template.txt new file mode 100644 index 0000000..721038b --- /dev/null +++ b/data/json-template.txt @@ -0,0 +1,19 @@ +{ + "card_width": # total width of the cut card + "stitches": # stitches per row + "row_height": # height of one row on the card in mm + "stitch_width": # width of one stitch on the card in mm + "pattern_hole_diameter": # diameter of a pattern hole in mm + "pattern_hole_xoffset": # offset of the first pattern hole from the left edge of the card in mm + "pattern_hole_yoffset": # offset of the first pattern hole from the top edge of the card in mm + "clip_hole_diameter": # diameter of a clip hole in mm + "clip_hole_xoffset": # offset of a clip hole from the left/right edge of the card in mm + "clip_hole_yoffset": # offset of a clip hole from the top/bottom edges of the card in mm + "tractor_hole_diameter": # diameter of a tractor hole in mm + "tractor_hole_xoffset": # offset of a tractor hole from the left/right edge of the card in mm + "tractor_hole_yoffset": # offset of a tractor hole from the top/bottom edge of the card in mm + "overlapping_rows": # number of overlapping punched rows at the top/bottom of the card + "overlapping_row_xoffset": # offset of the first overlapping hole from the left edge of the card in mm + "overlapping_row_yoffset": # offset of the first overlapping hole from the top/bottom edges of the card in mm + "corner_offset": # offset of the card corners +} diff --git a/modules/pcgenerator.py b/modules/pcgenerator.py index 38e8361..9cca49b 100644 --- a/modules/pcgenerator.py +++ b/modules/pcgenerator.py @@ -1,109 +1,8 @@ import svgwrite +import json -# machine specs -specs = { - '12-stitch-br-sr': { - # total width of the cut card - 'card_width': 142, - # number of overlapping blank rows at the top of the card - 'blank_rows': 2, - # height of one row on the card in mm - 'row_height': 5.0, - # width of one stitch on the card in mm - 'stitch_width': 9.0, - # diameter of a pattern hole in mm - 'pattern_hole_diameter': 3.5, - # diameter of the overlapping pattern holes in mm - 'overlap_hole_diameter': 3.5, - # offset of the first pattern hole from the left edge of the card in mm - 'pattern_hole_xoffset': 22.5 + (3.5 / 2), - # diameter of a clip hole in mm - 'clip_hole_diameter': 3.5, - # offset of a clip hole from the left/right edge of the card in mm - 'clip_hole_xoffset': 5.0 + (3.5 / 2), - # offset of a clip hole from the top/bottom edges of the card in mm - 'clip_hole_yoffset': 5.0, - # diameter of a tractor hole in mm - 'tractor_hole_diameter': 3.0, - # offset of a tractor hole from the left/right edge of the card in mm - 'tractor_hole_xoffset': 12.5 + (3.0 / 2), - # offset of a tractor hole from the top/bottom edge of the card in mm - 'tractor_hole_yoffset': 2.5, - # stitches per row - 'stitches': 12, - # offset of the card corners - 'corner_offset': 2, - }, - '18-stitch-mk70': { - 'card_width': 142, - 'blank_rows': 2, - 'row_height': 5.0, - 'stitch_width': 6.0, - 'pattern_hole_diameter': 3.5, - 'overlap_hole_diameter': 3.5, - 'pattern_hole_xoffset': 17.5 + (3.5 / 2), - 'clip_hole_diameter': 3.5, - 'clip_hole_xoffset': 5.0 + (3.5 / 2), - 'clip_hole_yoffset': 5.0, - 'tractor_hole_diameter': 3.0, - 'tractor_hole_xoffset': 12.5 + (3.0 / 2), - 'tractor_hole_yoffset': 2.5, - 'stitches': 18, - 'corner_offset': 2, - }, - '24-stitch-br-sr': { - 'card_width': 142, - 'blank_rows': 2, - 'row_height': 5.0, - 'stitch_width': 4.5, - 'pattern_hole_diameter': 3.5, - 'overlap_hole_diameter': 3.5, - 'pattern_hole_xoffset': 17.5 + (3.5 / 2), - 'clip_hole_diameter': 3.5, - 'clip_hole_xoffset': 5.0 + (3.5 / 2), - 'clip_hole_yoffset': 5.0, - 'tractor_hole_diameter': 3.0, - 'tractor_hole_xoffset': 12.0 + (3.0 / 2), - 'tractor_hole_yoffset': 2.5, - 'stitches': 24, - 'corner_offset': 2, - }, - '30-stitch-km': { - 'card_width': 142, - 'blank_rows': 2, - 'row_height': 5.0, - 'stitch_width': 3.6, - 'pattern_hole_diameter': 2.7, - 'overlap_hole_diameter': 2.7, - 'pattern_hole_xoffset': 17.5 + (2.7 / 2), - 'clip_hole_diameter': 3.5, - 'clip_hole_xoffset': 5.0 + (3.5 / 2), - 'clip_hole_yoffset': 5.0, - 'tractor_hole_diameter': 3.0, - 'tractor_hole_xoffset': 12.0 + (3.0 / 2), - 'tractor_hole_yoffset': 2.5, - 'stitches': 30, - 'corner_offset': 2, - }, - '40-stitch-deco': { - 'card_width': 243, - 'blank_rows': 3, - 'row_height': (100.0 / 19.0), - 'stitch_width': 5.0, - 'pattern_hole_diameter': 3.7, - 'overlap_hole_diameter': 3.7, - 'pattern_hole_xoffset': 22.15 + (3.7 / 2), - 'clip_hole_diameter': 3.5, - 'clip_hole_xoffset': 2.0 + (3.5 / 2), - 'clip_hole_yoffset': 5.5, - 'tractor_hole_diameter': 3.0, - 'tractor_hole_xoffset': 12.5 + (3.0 / 2), - 'tractor_hole_yoffset': 5.5, - 'stitches': 40, - 'corner_offset': 0, - }, -} +machine_config = None def calibrate(): @@ -129,62 +28,80 @@ class Layout: def __init__(self, machine_id, stitches, rows, horz_repeat, vert_repeat, is_blank): - self.card_width = specs[machine_id]['card_width'] - self.blank_rows = specs[machine_id]['blank_rows'] - self.row_height = specs[machine_id]['row_height'] - self.stitch_width = specs[machine_id]['stitch_width'] - self.pattern_hole_diameter = specs[machine_id]['pattern_hole_diameter'] - self.overlap_hole_diameter = specs[machine_id]['overlap_hole_diameter'] - self.pattern_hole_xoffset = specs[machine_id]['pattern_hole_xoffset'] - self.clip_hole_diameter = specs[machine_id]['clip_hole_diameter'] - self.clip_hole_xoffset = specs[machine_id]['clip_hole_xoffset'] - self.clip_hole_yoffset = specs[machine_id]['clip_hole_yoffset'] - self.tractor_hole_diameter = specs[machine_id]['tractor_hole_diameter'] - self.tractor_hole_xoffset = specs[machine_id]['tractor_hole_xoffset'] - self.tractor_hole_yoffset = specs[machine_id]['tractor_hole_yoffset'] - self.corner_offset = specs[machine_id]['corner_offset'] + global machine_config + self.card_width = machine_config['card_width'] self.card_stitches = stitches + self.row_height = machine_config['row_height'] + self.stitch_width = machine_config['stitch_width'] + self.pattern_hole_diameter = machine_config['pattern_hole_diameter'] + self.pattern_hole_xoffset = machine_config['pattern_hole_xoffset'] + self.pattern_hole_yoffset = machine_config['pattern_hole_yoffset'] + self.clip_hole_diameter = machine_config['clip_hole_diameter'] + self.clip_hole_xoffset = machine_config['clip_hole_xoffset'] + self.clip_hole_yoffset = machine_config['clip_hole_yoffset'] + self.tractor_hole_diameter = machine_config['tractor_hole_diameter'] + self.tractor_hole_xoffset = machine_config['tractor_hole_xoffset'] + self.tractor_hole_yoffset = machine_config['tractor_hole_yoffset'] + self.overlapping_rows = machine_config['overlapping_rows'] + self.overlapping_row_xoffset = machine_config['overlapping_row_xoffset'] + self.overlapping_row_yoffset = machine_config['overlapping_row_yoffset'] + self.corner_offset = machine_config['corner_offset'] + self.card_rows = rows - if is_blank: - self.pattern_hole_diameter = .5 - - if self.card_rows > 200 or self.card_stitches > specs[machine_id]['stitches']: + if self.card_rows > 200 or self.card_stitches > machine_config['stitches']: raise ValueError( "Your pattern seems to exceed 200 rows and/or {} stitches. " - "Are you sure you uploaded the right text file?".format(specs[machine_id]['stitches'])) + "Are you sure you uploaded the right text file?".format(machine_config['stitches'])) self.horz_repeat = horz_repeat self.vert_repeat = vert_repeat + self.is_blank = is_blank - self.card_height = ((self.blank_rows * 2) + (self.card_rows * self.vert_repeat)) * self.row_height + self.card_height = (self.pattern_hole_yoffset * 2) + (((self.card_rows * self.vert_repeat) - 1) * self.row_height) class PCGenerator: def __init__(self, handler, data, machine_id, vert_repeat, is_blank = False): + global machine_config + self.handler = handler - self.data = data.split() + with open("data/{}.json".format(machine_id)) as json_config: + machine_config = json.loads(json_config.read()) + if is_blank: + self.data = ['x' * machine_config['stitches']] + else: + self.data = data.split() self.layout = Layout( machine_id, len(self.data[0]), len(self.data), - specs[machine_id]['stitches'] / len(self.data[0]), + machine_config['stitches'] / len(self.data[0]), vert_repeat, - is_blank - ) + is_blank) def generate(self): diagram = self.create_card() objects = [] + if (self.layout.overlapping_rows and + self.layout.overlapping_row_xoffset and + self.layout.overlapping_row_yoffset): + self.draw_overlapped_lines(diagram, objects) + if (self.layout.clip_hole_diameter and + self.layout.clip_hole_xoffset): + self.draw_clip_holes(diagram, objects) + if (self.layout.tractor_hole_diameter and + self.layout.tractor_hole_xoffset): + self.draw_tractor_holes(diagram, objects) + + if self.layout.is_blank: + self.layout.pattern_hole_diameter = .5 self.draw_pattern(diagram, self.data, objects) - self.draw_blank_lines(diagram, objects) - self.draw_clip_holes(diagram, objects) - self.draw_tractor_holes(diagram, objects) # sort the list to optimize cutting sorted_objects = sorted(objects, key=lambda x: (float(x.attribs['cy']), float(x.attribs['cx']))) @@ -215,7 +132,7 @@ class PCGenerator: def draw_pattern(self, diagram, lines, objects): # main body of card - yoffset = (self.layout.blank_rows * self.layout.row_height) + (self.layout.row_height / 2) + yoffset = self.layout.pattern_hole_yoffset for row_repeat in range(self.layout.vert_repeat): for rows in range(self.layout.card_rows): xoffset = self.layout.pattern_hole_xoffset @@ -231,37 +148,38 @@ class PCGenerator: xoffset += self.layout.stitch_width yoffset += self.layout.row_height - def draw_blank_lines(self, diagram, objects): + def draw_overlapped_lines(self, diagram, objects): - # blank rows at top - yoffset = self.layout.row_height / 2 - for rows in range(self.layout.blank_rows): - xoffset = self.layout.pattern_hole_xoffset + # overlapping rows at top + yoffset = self.layout.overlapping_row_yoffset + for rows in range(self.layout.overlapping_rows): + xoffset = self.layout.overlapping_row_xoffset for stitch_repeat in range(self.layout.horz_repeat): for stitches in range(self.layout.card_stitches): objects.append(diagram.circle( center=(xoffset, yoffset), fill='white', - r = (self.layout.overlap_hole_diameter / 2), + r = (self.layout.pattern_hole_diameter / 2), stroke='black', stroke_width=.1)) xoffset += self.layout.stitch_width yoffset += self.layout.row_height - # blank rows at bottom - yoffset = (self.layout.card_height - (self.layout.row_height * self.layout.blank_rows)) + (self.layout.row_height / 2) - for rows in range(self.layout.blank_rows): - xoffset = self.layout.pattern_hole_xoffset + # overlapping rows at bottom + # yoffset = (self.layout.card_height - (self.layout.row_height * self.layout.overlapping_rows)) + (self.layout.row_height / 2) + yoffset = self.layout.card_height - self.layout.overlapping_row_yoffset + for rows in range(self.layout.overlapping_rows): + xoffset = self.layout.overlapping_row_xoffset for stitch_repeat in range(self.layout.horz_repeat): for stitches in range(self.layout.card_stitches): objects.append(diagram.circle( center=(xoffset, yoffset), fill='white', - r = (self.layout.overlap_hole_diameter / 2), + r = (self.layout.pattern_hole_diameter / 2), stroke='black', stroke_width=.1)) xoffset += self.layout.stitch_width - yoffset += self.layout.row_height + yoffset -= self.layout.row_height def draw_clip_holes(self, diagram, objects): diff --git a/sandbox/calibrate.py b/sandbox/calibrate.py new file mode 100644 index 0000000..cf29851 --- /dev/null +++ b/sandbox/calibrate.py @@ -0,0 +1,21 @@ +import svgwrite + +diagram = svgwrite.Drawing( + "calibrate.svg", + size=('100mm', '100mm'), + viewBox=('0 0 100 100'), + preserveAspectRatio='none') + +diagram.add(diagram.polygon( + points=[(0,0),(100,0),(100,100),(0,100)], + fill='white', + stroke='black', + stroke_width=.1)) + +diagram.add(diagram.polygon( + points=[(10,10),(90,10),(90,90),(10,90)], + fill='white', + stroke='black', + stroke_width=.1)) + +print '{}'.format(diagram.tostring()) diff --git a/sandbox/test-geometry.py b/sandbox/test-geometry.py new file mode 100644 index 0000000..652dceb --- /dev/null +++ b/sandbox/test-geometry.py @@ -0,0 +1,55 @@ +import svgwrite + +tractor_hole_diameter = 2.5 +tractor_hole_xoffset = 4.5 +tractor_hole_yoffset = 0.0 +tractor_hole_yspacing = 5.25 + +pattern_hole_diameter = 3.0 +pattern_hole_xoffset = 24.0 +pattern_hole_yoffset = 23.5 +pattern_hole_xspacing = 4.5 +pattern_hole_yspacing = 5.25 + +diagram = svgwrite.Drawing( + "test.svg", + size=('200mm', '220mm'), + viewBox=('0 0 200 220'), + preserveAspectRatio='none') + +diagram.add(diagram.polygon( + points=[(10,10),(190,10),(190,210),(10,210),(10,10)], + fill='white', + stroke='black', + stroke_width=.1)) + +x = 10 + tractor_hole_xoffset +y = 10 + tractor_hole_yoffset +for i in range(30): + fill='green' if i == 0 else 'white' + diagram.add( + diagram.circle( + center=(x,y), + fill=fill, + r = (tractor_hole_diameter / 2), + stroke='black', + stroke_width=.1)) + y = y + tractor_hole_yspacing + +x = 10 + pattern_hole_xoffset +for i in range(30): + fill='red' if i == 0 else 'white' + y = 10 + pattern_hole_yoffset + for j in range(30): + fill2='blue' if j == 0 else fill + diagram.add( + diagram.circle( + center=(x,y), + fill=fill2, + r = (pattern_hole_diameter / 2), + stroke='black', + stroke_width=.1)) + y = y + pattern_hole_yspacing + x = x + pattern_hole_xspacing + +print '{}'.format(diagram.tostring()) diff --git a/templates/pcgenerator.html b/templates/pcgenerator.html index bb18000..33857b8 100644 --- a/templates/pcgenerator.html +++ b/templates/pcgenerator.html @@ -57,11 +57,12 @@ Select machine type:
  diff --git a/test/test.py b/test/test.py index d6f1af8..49efd22 100644 --- a/test/test.py +++ b/test/test.py @@ -4,13 +4,16 @@ from modules.pcgenerator import PCGenerator import cairosvg #pattern='--x---\n--xxxx\n-xxxx-\nxxxx--\n---x--\n' +#pattern='xxxxx' pattern='xxxxx' -#machine = '12-stitch-br-sr' -#machine = '18-stitch-mk70' -#machine = '24-stitch-br-sr' -machine = '40-stitch-deco' -#machine = '30-stitch-km' -generator = PCGenerator(None, pattern, machine, 10, True) +# machine = '12-stitch-br-sr' +# machine = '18-stitch-mk70' +# machine = '24-stitch-br-sr' +# machine = '30-stitch-km' +# machine = '40-stitch-deco' +machine = '40-stitch-jac-4_5' +# generator = PCGenerator(None, pattern, machine, 20, True) +generator = PCGenerator(None, pattern, machine, 20, False) result = generator.generate() text_file = open("{}.svg".format(machine), "w") text_file.write(result)