kopia lustrzana https://github.com/brendabell/knittingtools
commit
f428eb04bc
|
@ -6,8 +6,9 @@ import time
|
|||
import traceback
|
||||
|
||||
from modules.pcgenerator import PCGenerator
|
||||
from modules.pcgenerator import calibrate
|
||||
|
||||
def pcgenerator_get(handler):
|
||||
def pcgenerator_get(handler, logger):
|
||||
|
||||
f = open("{}/../templates/{}".format(
|
||||
os.path.dirname(os.path.realpath(__file__)),
|
||||
|
@ -38,46 +39,56 @@ def pcgenerator_get(handler):
|
|||
finally:
|
||||
f.close()
|
||||
|
||||
def pcgenerator_post(handler):
|
||||
def pcgenerator_post(handler, logger):
|
||||
|
||||
try:
|
||||
ctype, pdict = cgi.parse_header(handler.headers.getheader('Content-Type'))
|
||||
if ctype == 'multipart/form-data':
|
||||
query=cgi.parse_multipart(handler.rfile, pdict)
|
||||
|
||||
upfilecontent = query.get('upfile')
|
||||
if len(upfilecontent[0]) > 4000:
|
||||
handler.send_response(302)
|
||||
handler.send_header('Content-type', 'text/html')
|
||||
handler.end_headers()
|
||||
handler.wfile.write("Sorry. Your file cannot exceed 2500 bytes!")
|
||||
calibrate_only = query.get('test', [''])[0] == 'test'
|
||||
|
||||
result = None
|
||||
filename_template = None
|
||||
convert_to_png = False
|
||||
|
||||
if calibrate_only:
|
||||
result = calibrate()
|
||||
filename_template = 'attachment; filename="calibrate-{}.{}"'
|
||||
else:
|
||||
machine_type = query.get('machine')
|
||||
vert_repeat = query.get('vert')
|
||||
convert_to_png = query.get('png', [''])[0] == 'png'
|
||||
|
||||
generator = PCGenerator(
|
||||
handler,
|
||||
upfilecontent[0],
|
||||
machine_type[0],
|
||||
int(vert_repeat[0]))
|
||||
result = generator.generate()
|
||||
|
||||
handler.send_response(200)
|
||||
filename_template = 'attachment; filename="punchcard-{}.{}"'
|
||||
|
||||
if convert_to_png:
|
||||
result = cairosvg.svg2png(bytestring=result)
|
||||
handler.send_header('Content-type', 'image/png')
|
||||
handler.send_header('Content-Disposition', filename_template.format(int(time.time()), "png"))
|
||||
upfilecontent = query.get('upfile')
|
||||
if len(upfilecontent[0]) > 4000:
|
||||
handler.send_response(302)
|
||||
handler.send_header('Content-type', 'text/html')
|
||||
handler.end_headers()
|
||||
handler.wfile.write("Sorry. Your file cannot exceed 2500 bytes!")
|
||||
else:
|
||||
handler.send_header('Content-type', 'image/svg+xml')
|
||||
handler.send_header('Content-Disposition', filename_template.format(int(time.time()), "svg"))
|
||||
machine_type = query.get('machine')
|
||||
vert_repeat = query.get('vert')
|
||||
convert_to_png = query.get('png', [''])[0] == 'png'
|
||||
|
||||
handler.end_headers()
|
||||
handler.wfile.write(result)
|
||||
generator = PCGenerator(
|
||||
handler,
|
||||
upfilecontent[0],
|
||||
machine_type[0],
|
||||
int(vert_repeat[0]))
|
||||
result = generator.generate()
|
||||
filename_template = 'attachment; filename="punchcard-{}.{}"'
|
||||
|
||||
return
|
||||
handler.send_response(200)
|
||||
|
||||
if convert_to_png:
|
||||
result = cairosvg.svg2png(bytestring=result)
|
||||
handler.send_header('Content-type', 'image/png')
|
||||
handler.send_header('Content-Disposition', filename_template.format(int(time.time()), "png"))
|
||||
else:
|
||||
handler.send_header('Content-type', 'image/svg+xml')
|
||||
handler.send_header('Content-Disposition', filename_template.format(int(time.time()), "svg"))
|
||||
|
||||
handler.end_headers()
|
||||
handler.wfile.write(result)
|
||||
|
||||
return
|
||||
|
||||
except ValueError as e:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
|
@ -114,7 +125,7 @@ def pcgenerator_post(handler):
|
|||
"It will be helpful if you include the pattern you uploaded to help me "
|
||||
"diagnose the issue.")
|
||||
|
||||
def calculator_get(handler):
|
||||
def calculator_get(handler, logger):
|
||||
|
||||
f = open("{}/../templates/{}".format(
|
||||
os.path.dirname(os.path.realpath(__file__)),
|
||||
|
@ -145,7 +156,7 @@ def calculator_get(handler):
|
|||
finally:
|
||||
f.close()
|
||||
|
||||
def index_get(handler):
|
||||
def index_get(handler, logger):
|
||||
f = open("{}/../templates/{}".format(
|
||||
os.path.dirname(os.path.realpath(__file__)),
|
||||
"index.html"))
|
||||
|
|
|
@ -8,12 +8,12 @@ specs = {
|
|||
'blank_rows': 2,
|
||||
'row_height': 5.0,
|
||||
'stitch_width': 9.0,
|
||||
'pattern_hole_radius': 3.5,
|
||||
'pattern_hole_diameter': 3.5,
|
||||
'pattern_hole_xoffset': 22.5,
|
||||
'clip_hole_radius': 3.5,
|
||||
'clip_hole_diameter': 3.5,
|
||||
'clip_hole_xoffset': 5.0,
|
||||
'clip_hole_yoffset': 5.0,
|
||||
'tractor_hole_radius': 3.0,
|
||||
'tractor_hole_diameter': 3.0,
|
||||
'tractor_hole_xoffset': 12.5,
|
||||
'tractor_hole_yoffset': 2.5,
|
||||
'stitches': 12,
|
||||
|
@ -24,12 +24,12 @@ specs = {
|
|||
'blank_rows': 2,
|
||||
'row_height': 5.0,
|
||||
'stitch_width': 6.0,
|
||||
'pattern_hole_radius': 3.5,
|
||||
'pattern_hole_diameter': 3.5,
|
||||
'pattern_hole_xoffset': 17.5,
|
||||
'clip_hole_radius': 3.5,
|
||||
'clip_hole_diameter': 3.5,
|
||||
'clip_hole_xoffset': 5.0,
|
||||
'clip_hole_yoffset': 5.0,
|
||||
'tractor_hole_radius': 3.0,
|
||||
'tractor_hole_diameter': 3.0,
|
||||
'tractor_hole_xoffset': 12.5,
|
||||
'tractor_hole_yoffset': 2.5,
|
||||
'stitches': 18,
|
||||
|
@ -40,12 +40,12 @@ specs = {
|
|||
'blank_rows': 2,
|
||||
'row_height': 5.0,
|
||||
'stitch_width': 4.5,
|
||||
'pattern_hole_radius': 3.5,
|
||||
'pattern_hole_diameter': 3.5,
|
||||
'pattern_hole_xoffset': 17.5,
|
||||
'clip_hole_radius': 3.5,
|
||||
'clip_hole_diameter': 3.5,
|
||||
'clip_hole_xoffset': 5.0,
|
||||
'clip_hole_yoffset': 5.0,
|
||||
'tractor_hole_radius': 3.0,
|
||||
'tractor_hole_diameter': 3.0,
|
||||
'tractor_hole_xoffset': 12.0,
|
||||
'tractor_hole_yoffset': 2.5,
|
||||
'stitches': 24,
|
||||
|
@ -56,12 +56,12 @@ specs = {
|
|||
'blank_rows': 3,
|
||||
'row_height': (100.0 / 19.0),
|
||||
'stitch_width': 5.0,
|
||||
'pattern_hole_radius': 4.0,
|
||||
'pattern_hole_xoffset': 22.0,
|
||||
'clip_hole_radius': 3.5,
|
||||
'pattern_hole_diameter': 3.5,
|
||||
'pattern_hole_xoffset': 22.25,
|
||||
'clip_hole_diameter': 3.5,
|
||||
'clip_hole_xoffset': 2.0,
|
||||
'clip_hole_yoffset': 5.5,
|
||||
'tractor_hole_radius': 3.0,
|
||||
'tractor_hole_diameter': 3.0,
|
||||
'tractor_hole_xoffset': 12.5,
|
||||
'tractor_hole_yoffset': 5.5,
|
||||
'stitches': 40,
|
||||
|
@ -70,6 +70,25 @@ specs = {
|
|||
}
|
||||
|
||||
|
||||
def calibrate():
|
||||
|
||||
diagram = svgwrite.Drawing(
|
||||
"calibrate.svg",
|
||||
size=(
|
||||
'100mm',
|
||||
'100mm'),
|
||||
viewBox=(
|
||||
'0 0 100 100'),
|
||||
preserveAspectRatio='none')
|
||||
diagram.add(
|
||||
diagram.polygon(
|
||||
[(10,10), (90,10), (90,90), (10,90), (10,10)],
|
||||
fill='white',
|
||||
stroke='red',
|
||||
stroke_width=.1))
|
||||
return '<?xml version="1.0" encoding="UTF-8" standalone="no"?>{}'.format(diagram.tostring())
|
||||
|
||||
|
||||
class Layout:
|
||||
|
||||
def __init__(self, machine_id, stitches, rows, horz_repeat, vert_repeat):
|
||||
|
@ -86,14 +105,14 @@ class Layout:
|
|||
# width of one stitch on the card in mm
|
||||
self.stitch_width = specs[machine_id]['stitch_width']
|
||||
|
||||
# radius of a pattern hole in mm
|
||||
self.pattern_hole_radius = specs[machine_id]['pattern_hole_radius']
|
||||
# diameter of a pattern hole in mm
|
||||
self.pattern_hole_diameter = specs[machine_id]['pattern_hole_diameter']
|
||||
|
||||
# offset of the first pattern hole from the left edge of the card in mm
|
||||
self.pattern_hole_xoffset = specs[machine_id]['pattern_hole_xoffset']
|
||||
|
||||
# radius of a clip hole in mm
|
||||
self.clip_hole_radius = specs[machine_id]['clip_hole_radius']
|
||||
# diameter of a clip hole in mm
|
||||
self.clip_hole_diameter = specs[machine_id]['clip_hole_diameter']
|
||||
|
||||
# offset of a clip hole from the left/right edge of the card in mm
|
||||
self.clip_hole_xoffset = specs[machine_id]['clip_hole_xoffset']
|
||||
|
@ -101,8 +120,8 @@ class Layout:
|
|||
# offset of a clip hole from the top/bottom edges of the card in mm
|
||||
self.clip_hole_yoffset = specs[machine_id]['clip_hole_yoffset']
|
||||
|
||||
# radius of a tractor hole in mm
|
||||
self.tractor_hole_radius = specs[machine_id]['tractor_hole_radius']
|
||||
# diameter of a tractor hole in mm
|
||||
self.tractor_hole_diameter = specs[machine_id]['tractor_hole_diameter']
|
||||
|
||||
# offset of a tractor hole from the left/right edge of the card in mm
|
||||
self.tractor_hole_xoffset = specs[machine_id]['tractor_hole_xoffset']
|
||||
|
@ -182,14 +201,14 @@ class PCGenerator:
|
|||
yoffset = (self.layout.blank_rows * self.layout.row_height) + (self.layout.row_height / 2)
|
||||
for row_repeat in range(self.layout.vert_repeat):
|
||||
for rows in range(self.layout.card_rows):
|
||||
xoffset = self.layout.pattern_hole_xoffset + (self.layout.pattern_hole_radius / 2)
|
||||
xoffset = self.layout.pattern_hole_xoffset + (self.layout.pattern_hole_diameter / 2)
|
||||
for stitch_repeat in range(self.layout.horz_repeat):
|
||||
for stitches in range(self.layout.card_stitches):
|
||||
if lines[rows][stitches].upper() == 'X':
|
||||
objects.append(diagram.circle(
|
||||
center=(xoffset, yoffset),
|
||||
fill='white',
|
||||
r = (self.layout.pattern_hole_radius / 2),
|
||||
r = (self.layout.pattern_hole_diameter / 2),
|
||||
stroke='black',
|
||||
stroke_width=.1))
|
||||
xoffset += self.layout.stitch_width
|
||||
|
@ -200,13 +219,13 @@ class PCGenerator:
|
|||
# blank rows at top
|
||||
yoffset = self.layout.row_height / 2
|
||||
for rows in range(self.layout.blank_rows):
|
||||
xoffset = self.layout.pattern_hole_xoffset + (self.layout.pattern_hole_radius / 2)
|
||||
xoffset = self.layout.pattern_hole_xoffset + (self.layout.pattern_hole_diameter / 2)
|
||||
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.pattern_hole_radius / 2),
|
||||
r = (self.layout.pattern_hole_diameter / 2),
|
||||
stroke='black',
|
||||
stroke_width=.1))
|
||||
xoffset += self.layout.stitch_width
|
||||
|
@ -215,13 +234,13 @@ class PCGenerator:
|
|||
# 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 + (self.layout.pattern_hole_radius / 2)
|
||||
xoffset = self.layout.pattern_hole_xoffset + (self.layout.pattern_hole_diameter / 2)
|
||||
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.pattern_hole_radius / 2),
|
||||
r = (self.layout.pattern_hole_diameter / 2),
|
||||
stroke='black',
|
||||
stroke_width=.1))
|
||||
xoffset += self.layout.stitch_width
|
||||
|
@ -234,7 +253,7 @@ class PCGenerator:
|
|||
objects,
|
||||
self.layout.clip_hole_xoffset,
|
||||
self.layout.clip_hole_yoffset,
|
||||
self.layout.clip_hole_radius)
|
||||
self.layout.clip_hole_diameter)
|
||||
|
||||
def draw_tractor_holes(self, diagram, objects):
|
||||
|
||||
|
@ -243,11 +262,11 @@ class PCGenerator:
|
|||
objects,
|
||||
self.layout.tractor_hole_xoffset,
|
||||
self.layout.tractor_hole_yoffset,
|
||||
self.layout.tractor_hole_radius)
|
||||
self.layout.tractor_hole_diameter)
|
||||
|
||||
def draw_side_holes(self, diagram, objects, xoffset, yoffset, radius):
|
||||
def draw_side_holes(self, diagram, objects, xoffset, yoffset, diameter):
|
||||
|
||||
left_xoffset = xoffset + (radius / 2)
|
||||
left_xoffset = xoffset + (diameter / 2)
|
||||
right_xoffset = self.layout.card_width - left_xoffset
|
||||
|
||||
while yoffset < self.layout.card_height:
|
||||
|
@ -255,21 +274,21 @@ class PCGenerator:
|
|||
objects.append(diagram.circle(
|
||||
center=(left_xoffset, yoffset),
|
||||
fill='white',
|
||||
r = (radius / 2),
|
||||
r = (diameter / 2),
|
||||
stroke='black',
|
||||
stroke_width=.1))
|
||||
# holes on right
|
||||
objects.append(diagram.circle(
|
||||
center=(right_xoffset, yoffset),
|
||||
fill='white',
|
||||
r = (radius / 2),
|
||||
r = (diameter / 2),
|
||||
stroke='black',
|
||||
stroke_width=.1))
|
||||
yoffset += self.layout.row_height
|
||||
|
||||
def get_card_shape(self):
|
||||
|
||||
corner_radius = self.layout.corner_offset + 1
|
||||
corner_diameter = self.layout.corner_offset + 1
|
||||
|
||||
# a------------------b
|
||||
# p c
|
||||
|
@ -283,16 +302,16 @@ class PCGenerator:
|
|||
# k h
|
||||
# j------------------i
|
||||
|
||||
a = (corner_radius, 0)
|
||||
b = (self.layout.card_width - corner_radius, 0)
|
||||
a = (corner_diameter, 0)
|
||||
b = (self.layout.card_width - corner_diameter, 0)
|
||||
c = (self.layout.card_width - self.layout.corner_offset, 1)
|
||||
d = (self.layout.card_width - self.layout.corner_offset, 20)
|
||||
e = (self.layout.card_width, 22)
|
||||
f = (self.layout.card_width, self.layout.card_height - 22)
|
||||
g = (self.layout.card_width - self.layout.corner_offset, self.layout.card_height - 20)
|
||||
h = (self.layout.card_width - self.layout.corner_offset, self.layout.card_height - 1)
|
||||
i = (self.layout.card_width - corner_radius, self.layout.card_height)
|
||||
j = (corner_radius, self.layout.card_height)
|
||||
i = (self.layout.card_width - corner_diameter, self.layout.card_height)
|
||||
j = (corner_diameter, self.layout.card_height)
|
||||
k = ( self.layout.corner_offset, self.layout.card_height - 1)
|
||||
l = ( self.layout.corner_offset, self.layout.card_height - 20)
|
||||
m = (0, self.layout.card_height - 22)
|
||||
|
|
|
@ -55,7 +55,7 @@ class MyHandler(BaseHTTPRequestHandler):
|
|||
self.handle_not_found()
|
||||
return
|
||||
|
||||
actions['get'](self)
|
||||
actions['get'](self, logger)
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
self.log_error("%s %s\n" % (
|
||||
|
@ -72,7 +72,7 @@ class MyHandler(BaseHTTPRequestHandler):
|
|||
self.handle_not_found()
|
||||
return
|
||||
|
||||
actions['post'](self)
|
||||
actions['post'](self, logger)
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
self.log_error("%s %s\n" % (
|
||||
|
|
|
@ -72,9 +72,12 @@
|
|||
<script>y.value=vert.value;</script></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="test-align:right">Convert to PNG image:</td>
|
||||
<td style="text-align:right">Convert to PNG image:</td>
|
||||
<td><input type="checkbox" name="png" value="png"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align;right">Calibrate Only:</td>
|
||||
<td><input type="checkbox" name="test" value="test"></td>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="2"><input type="submit" value="Upload"></td>
|
||||
|
@ -116,6 +119,10 @@
|
|||
|
||||
<p>Silhouette users have reported issues importing SVG files or having to resize the SVG in Inkscape before importing. If you have trouble with the SVG file, try checking the Convert To PNG button to see if that gives you a better result.
|
||||
|
||||
<p>Depending on the software you use to view or cut the image, what you see on your screen may or may not be sized properly. If you'd like to calibrate your viewing or cutting software, check the Calibrate Only checkbox and click Upload. That will generate a 100x100mm diagram with a red square. Determine the steps necessary to make your software display or print the square so it's exactly 80x80mm. Then use those same steps to calibrate your software for the generated punchcards.
|
||||
|
||||
<p>If both Convert To PNG and Calibrate Only are checked, the downloaded calibration image will be converted to a PNG image.
|
||||
|
||||
<h2>Bugs & Disclaimers</h2>
|
||||
<p>This program has only been tested using Sure Cuts A Lot on a Pazzles Creative Mighty. YMMV!
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
||||
-xxx--xx-xx-xx--xxx--xxx--xx-xx-xx--xxx-
|
||||
x---xx--x--x--xx---xx---xx--x--x--xx---x
|
|
@ -17,3 +17,4 @@ text_file.close()
|
|||
png_file = open("{}.png".format(machine), "w")
|
||||
cairosvg.svg2png(bytestring=result,write_to=png_file)
|
||||
png_file.close()
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue