kopia lustrzana https://github.com/brendabell/knittingtools
Initial commit
rodzic
89a0d64792
commit
f28473d42e
|
|
@ -0,0 +1 @@
|
|||
# intentionally empty
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
import cgi
|
||||
from os import curdir
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from modules.pcgenerator import PCGenerator
|
||||
|
||||
def pcgenerator_get(handler):
|
||||
|
||||
f = open("{}/templates/{}".format(
|
||||
curdir,
|
||||
"pcgenerator.html"))
|
||||
|
||||
try:
|
||||
handler.send_response(200)
|
||||
handler.send_header('Content-type', 'text/html')
|
||||
handler.end_headers()
|
||||
handler.wfile.write(f.read())
|
||||
|
||||
return
|
||||
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
handler.wfile.write(
|
||||
"<h1>Aw, snap! We seem to have a problem.</h1><p><b>")
|
||||
handler.wfile.write(
|
||||
repr(traceback.format_exception(exc_type, exc_value,exc_traceback)))
|
||||
handler.wfile.write(
|
||||
"</b><p>Please report this error via private message to "
|
||||
"<a href='http://www.ravelry.com/people/beebell'>beebell on Ravelry</a>. "
|
||||
"It will be helpful if you include the pattern you uploaded to help me "
|
||||
"diagnose the issue.")
|
||||
handler.log_error("%s", traceback.format_exception(exc_type, exc_value,exc_traceback))
|
||||
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def pcgenerator_post(handler):
|
||||
|
||||
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]) > 2500:
|
||||
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:
|
||||
horz_repeat = query.get('horz')
|
||||
vert_repeat = query.get('vert')
|
||||
cell_height = query.get('rowheight')
|
||||
cell_width = query.get('colwidth')
|
||||
generator = PCGenerator(
|
||||
upfilecontent[0],
|
||||
float(cell_height[0]),
|
||||
float(cell_width[0]),
|
||||
int(horz_repeat[0]),
|
||||
int(vert_repeat[0]))
|
||||
result = generator.generate()
|
||||
|
||||
handler.send_response(200)
|
||||
handler.send_header('Content-type', 'image/svg+xml')
|
||||
handler.send_header("Content-Disposition", "attachment; filename=punchcard.svg")
|
||||
handler.end_headers()
|
||||
handler.wfile.write(result)
|
||||
|
||||
return
|
||||
|
||||
except ValueError as e:
|
||||
handler.send_response(302)
|
||||
handler.send_header('Content-type', 'text/html')
|
||||
handler.end_headers()
|
||||
handler.wfile.write(
|
||||
"<h1>Aw, snap!</h1><p>")
|
||||
handler.wfile.write(e)
|
||||
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
handler.send_response(302)
|
||||
handler.send_header('Content-type', 'text/html')
|
||||
handler.end_headers()
|
||||
handler.wfile.write(
|
||||
"<h1>Aw, snap! We seem to have a problem.</h1><p><b>")
|
||||
handler.wfile.write(
|
||||
repr(traceback.format_exception(exc_type, exc_value,exc_traceback)))
|
||||
handler.wfile.write(
|
||||
"</b><p>Please report this error via private message to "
|
||||
"<a href='http://www.ravelry.com/people/beebell'>beebell on Ravelry</a>. "
|
||||
"It will be helpful if you include the pattern you uploaded to help me "
|
||||
"diagnose the issue.")
|
||||
handler.log_error("%s", traceback.format_exception(exc_type, exc_value,exc_traceback))
|
||||
|
||||
def calculator_get(handler):
|
||||
|
||||
f = open("{}/templates/{}".format(
|
||||
curdir,
|
||||
"calculator.html"))
|
||||
|
||||
try:
|
||||
handler.send_response(200)
|
||||
handler.send_header('Content-type', 'text/html')
|
||||
handler.end_headers()
|
||||
handler.wfile.write(f.read())
|
||||
|
||||
return
|
||||
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
handler.wfile.write(
|
||||
"<h1>Aw, snap! We seem to have a problem.</h1><p><b>")
|
||||
handler.wfile.write(
|
||||
repr(traceback.format_exception(exc_type, exc_value,exc_traceback)))
|
||||
handler.wfile.write(
|
||||
"</b><p>Please report this error via private message to "
|
||||
"<a href='http://www.ravelry.com/people/beebell'>beebell on Ravelry</a>. "
|
||||
"It will be helpful if you include the pattern you uploaded to help me "
|
||||
"diagnose the issue.")
|
||||
handler.log_error("%s", traceback.format_exception(exc_type, exc_value,exc_traceback))
|
||||
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def index_get(handler):
|
||||
f = open("{}/templates/{}".format(
|
||||
curdir,
|
||||
"index.html"))
|
||||
|
||||
try:
|
||||
handler.send_response(200)
|
||||
handler.send_header('Content-type', 'text/html')
|
||||
handler.end_headers()
|
||||
handler.wfile.write(f.read())
|
||||
|
||||
return
|
||||
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
handler.wfile.write(
|
||||
"<h1>Aw, snap! We seem to have a problem.</h1><p><b>")
|
||||
handler.wfile.write(
|
||||
repr(traceback.format_exception(exc_type, exc_value,exc_traceback)))
|
||||
handler.wfile.write(
|
||||
"</b><p>Please report this error via private message to "
|
||||
"<a href='http://www.ravelry.com/people/beebell'>beebell on Ravelry</a>. "
|
||||
"It will be helpful if you include the pattern you uploaded to help me "
|
||||
"diagnose the issue.")
|
||||
handler.log_error("%s", traceback.format_exception(exc_type, exc_value,exc_traceback))
|
||||
|
||||
finally:
|
||||
f.close()
|
||||
|
|
@ -0,0 +1 @@
|
|||
# intentionally empty
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
import svgwrite
|
||||
|
||||
# default values
|
||||
|
||||
# number of overlapping blank rows at the top of the card
|
||||
blank_rows = 2
|
||||
|
||||
# width of the side margin in mm
|
||||
side_margin = 17.0
|
||||
|
||||
# height of one row on the card in mm
|
||||
row_height = 5.0
|
||||
|
||||
# width of one stitch on the card in mm
|
||||
stitch_width = 4.5
|
||||
#stitch_width = 9.0
|
||||
|
||||
# radius of a pattern hole in mm
|
||||
pattern_hole_radius = 3.5
|
||||
|
||||
# radius of a clip hole in mm
|
||||
clip_hole_radius = 3.0
|
||||
|
||||
# radius of a sprocket hole in mm
|
||||
sprocket_hole_radius = 3.5
|
||||
|
||||
# drawing stroke width
|
||||
stroke_width='.1'
|
||||
|
||||
# fill color
|
||||
fill_color = 'white'
|
||||
|
||||
# stroke_color
|
||||
stroke_color = 'black'
|
||||
|
||||
card_width = 0
|
||||
card_height = 0
|
||||
card_rows = 0
|
||||
card_stitches = 0
|
||||
|
||||
class PCGenerator:
|
||||
|
||||
def __init__(self, data, cell_height, cell_width, horz_repeat, vert_repeat):
|
||||
global row_height
|
||||
global stitch_width
|
||||
|
||||
self.data = data.split()
|
||||
self.horz_repeat = horz_repeat
|
||||
self.vert_repeat = vert_repeat
|
||||
row_height = cell_height
|
||||
stitch_width = cell_width
|
||||
|
||||
def generate(self):
|
||||
global card_rows
|
||||
global card_stitches
|
||||
global card_width
|
||||
global card_height
|
||||
|
||||
card_rows = len(self.data)
|
||||
card_stitches = len(self.data[0])
|
||||
if card_rows > 200 or card_stitches > 30:
|
||||
raise ValueError(
|
||||
"Your pattern seems to exceed 200 rows and/or 30 stitches. "
|
||||
"Are you sure you uploaded the right text file?")
|
||||
|
||||
card_width = (side_margin * 2) + (card_stitches * self.horz_repeat * stitch_width)
|
||||
card_height = ((blank_rows * 2) + (card_rows * self.vert_repeat)) * row_height
|
||||
|
||||
diagram = self.create_card()
|
||||
|
||||
objects = []
|
||||
self.draw_pattern(diagram, self.data, objects)
|
||||
self.draw_blank_lines(diagram, objects)
|
||||
self.draw_clip_holes(diagram, objects)
|
||||
self.draw_sprocket_holes(diagram, objects)
|
||||
|
||||
# sort the list to optimize cutting
|
||||
sorted_objects = sorted(objects, key=lambda x: (float(x.attribs['cy']), float(x.attribs['cx'])))
|
||||
for i in sorted_objects:
|
||||
diagram.add(i)
|
||||
|
||||
return diagram.tostring()
|
||||
|
||||
def create_card(self):
|
||||
global card_width
|
||||
global card_height
|
||||
|
||||
diagram = svgwrite.Drawing(
|
||||
"punchcard.svg",
|
||||
size=(
|
||||
'{0}mm'.format(card_width),
|
||||
'{0}mm'.format(card_height)),
|
||||
viewBox=(
|
||||
'0 0 {0} {1}'.format(card_width, card_height)),
|
||||
preserveAspectRatio='none')
|
||||
|
||||
shape_points = [
|
||||
(2, 0),
|
||||
(card_width-2, 0),
|
||||
(card_width-1, 1),
|
||||
(card_width-1, 20),
|
||||
(card_width, 22),
|
||||
(card_width, card_height-22),
|
||||
(card_width-1, card_height-20),
|
||||
(card_width-1, card_height-1),
|
||||
(card_width-2, card_height),
|
||||
(2, card_height),
|
||||
(1, card_height-1),
|
||||
(1, card_height-20),
|
||||
(0, card_height-22),
|
||||
(0, 22),
|
||||
(1, 20),
|
||||
(1, 1)]
|
||||
diagram.add(diagram.polygon(
|
||||
points=shape_points,
|
||||
fill=fill_color,
|
||||
stroke=stroke_color,
|
||||
stroke_width=stroke_width))
|
||||
|
||||
return diagram
|
||||
|
||||
def draw_pattern(self, diagram, lines, objects):
|
||||
global card_rows
|
||||
global card_stitches
|
||||
global fill_color
|
||||
global pattern_hole_radius
|
||||
global row_color
|
||||
global row_height
|
||||
global side_margin
|
||||
global stitch_width
|
||||
global stroke_color
|
||||
global stroke_width
|
||||
|
||||
# main body of card
|
||||
yoffset = 10.0 + (row_height / 2)
|
||||
for row_repeat in range(self.vert_repeat):
|
||||
for rows in range(card_rows):
|
||||
xoffset = side_margin + (stitch_width / 2)
|
||||
for stitch_repeat in range(self.horz_repeat):
|
||||
for stitches in range(card_stitches):
|
||||
if lines[rows][stitches].upper() == 'X':
|
||||
objects.append(diagram.circle(
|
||||
center=(xoffset, yoffset),
|
||||
fill=fill_color,
|
||||
r = (pattern_hole_radius / 2),
|
||||
stroke=stroke_color,
|
||||
stroke_width=stroke_width))
|
||||
xoffset += stitch_width
|
||||
yoffset += row_height
|
||||
|
||||
def draw_blank_lines(self, diagram, objects):
|
||||
global blank_rows
|
||||
global card_stitches
|
||||
global fill_color
|
||||
global pattern_hole_radius
|
||||
global row_height
|
||||
global side_margin
|
||||
global stitch_width
|
||||
global stroke_color
|
||||
global stroke_width
|
||||
|
||||
# blank rows at top
|
||||
yoffset = row_height / 2
|
||||
for rows in range(blank_rows):
|
||||
xoffset = side_margin + (stitch_width / 2)
|
||||
for stitch_repeat in range(self.horz_repeat):
|
||||
for stitches in range(card_stitches):
|
||||
objects.append(diagram.circle(
|
||||
center=(xoffset, yoffset),
|
||||
fill=fill_color,
|
||||
r = (pattern_hole_radius / 2),
|
||||
stroke=stroke_color,
|
||||
stroke_width=stroke_width))
|
||||
xoffset += stitch_width
|
||||
yoffset += row_height
|
||||
|
||||
# blank rows at bottom
|
||||
yoffset = (card_height - (row_height * blank_rows)) + (row_height / 2)
|
||||
for rows in range(blank_rows):
|
||||
xoffset = side_margin + (stitch_width / 2)
|
||||
for stitch_repeat in range(self.horz_repeat):
|
||||
for stitches in range(card_stitches):
|
||||
objects.append(diagram.circle(
|
||||
center=(xoffset, yoffset),
|
||||
fill=fill_color,
|
||||
r = (pattern_hole_radius / 2),
|
||||
stroke=stroke_color,
|
||||
stroke_width=stroke_width))
|
||||
xoffset += stitch_width
|
||||
yoffset += row_height
|
||||
|
||||
def draw_clip_holes(self, diagram, objects):
|
||||
global card_height
|
||||
global clip_hole_radius
|
||||
global fill_color
|
||||
global row_height
|
||||
global side_margin
|
||||
global stitch_width
|
||||
global stroke_color
|
||||
global stroke_width
|
||||
|
||||
left_xoffset = side_margin + (stitch_width / 2) - 6.0
|
||||
right_xoffset = (card_width - side_margin - (stitch_width / 2)) + 6.0
|
||||
yoffset = row_height / 2
|
||||
|
||||
while yoffset < card_height:
|
||||
# clip holes on left
|
||||
objects.append(diagram.circle(
|
||||
center=(left_xoffset, yoffset),
|
||||
fill=fill_color,
|
||||
r = (clip_hole_radius / 2),
|
||||
stroke=stroke_color,
|
||||
stroke_width=stroke_width))
|
||||
# clip holes on right
|
||||
objects.append(diagram.circle(
|
||||
center=(right_xoffset, yoffset),
|
||||
fill=fill_color,
|
||||
r = (clip_hole_radius / 2),
|
||||
stroke=stroke_color,
|
||||
stroke_width=stroke_width))
|
||||
yoffset += row_height
|
||||
|
||||
def draw_sprocket_holes(self, diagram, objects):
|
||||
|
||||
left_xoffset = 6.5
|
||||
right_xoffset = card_width - 6.5
|
||||
yoffset = row_height
|
||||
for row_repeat in range(self.vert_repeat):
|
||||
for rows in range(((card_rows * self.vert_repeat) + (blank_rows * 2)) / 2):
|
||||
# sprocket holes on left
|
||||
objects.append(diagram.circle(
|
||||
center=(left_xoffset, yoffset),
|
||||
fill=fill_color,
|
||||
r = (sprocket_hole_radius / 2),
|
||||
stroke=stroke_color,
|
||||
stroke_width=stroke_width))
|
||||
# sprocket holes on left
|
||||
objects.append(diagram.circle(
|
||||
center=(right_xoffset, yoffset),
|
||||
fill=fill_color,
|
||||
r = (sprocket_hole_radius / 2),
|
||||
stroke=stroke_color,
|
||||
stroke_width=stroke_width))
|
||||
yoffset += (row_height * 2)
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
from BaseHTTPServer import BaseHTTPRequestHandler
|
||||
from BaseHTTPServer import HTTPServer
|
||||
|
||||
from handlers import actions
|
||||
|
||||
|
||||
pcgenerator_actions = {
|
||||
'get': actions.pcgenerator_get,
|
||||
'post': actions.pcgenerator_post }
|
||||
|
||||
calculator_actions = {
|
||||
'get': actions.calculator_get,
|
||||
'post': None
|
||||
}
|
||||
|
||||
index_actions = {
|
||||
'get': actions.index_get,
|
||||
'post': None
|
||||
}
|
||||
|
||||
template_map = {
|
||||
'/pcgenerator': pcgenerator_actions,
|
||||
'/pcgenerator/': pcgenerator_actions,
|
||||
'/calculator': calculator_actions,
|
||||
'/calculator/': calculator_actions,
|
||||
'/': index_actions,
|
||||
'/index': index_actions }
|
||||
|
||||
|
||||
class MyHandler(BaseHTTPRequestHandler):
|
||||
|
||||
def do_GET(self):
|
||||
print self.path
|
||||
actions = template_map.get(self.path, None)
|
||||
if actions is None:
|
||||
self.send_response(404)
|
||||
self.send_header('Content-type', 'text/html')
|
||||
self.end_headers()
|
||||
self.wfile.write('Not found!')
|
||||
|
||||
actions['get'](self)
|
||||
|
||||
def do_POST(self):
|
||||
print self.path
|
||||
actions = template_map.get(self.path, None)
|
||||
if actions is None:
|
||||
self.send_response(404)
|
||||
self.send_header('Content-type', 'text/html')
|
||||
self.end_headers()
|
||||
self.wfile.write('Not found!')
|
||||
|
||||
actions['post'](self)
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
server = HTTPServer(('', 8080), MyHandler)
|
||||
print 'started httpserver...'
|
||||
server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
print '^C received, shutting down server'
|
||||
except Exception:
|
||||
print sys.exc_info()[0]
|
||||
finally:
|
||||
server.socket.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
<!DOCTYPE HTML SYSTEM>
|
||||
<html>
|
||||
<head>
|
||||
<title>Knitting Gauge Calculator</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: arial, sans-serif;
|
||||
margin-top: 40px;
|
||||
margin-left: 10%;
|
||||
width: 80%;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: 1px solid #cccccc;
|
||||
text-align: center;
|
||||
padding: 8px;
|
||||
}
|
||||
.boxed {
|
||||
border: 1px solid gray;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Knitting Gauge Calculator</h1>
|
||||
<a href="/"><Back></a>
|
||||
<hr>
|
||||
|
||||
<p>This app will help you calculate stitches and rows when your gauge differs from the gauge specified on the pattern.
|
||||
<p>The forms are reactive. I.e., when you enter a value in any field, the other fields will automatically be adjusted for the value you entered. For example, if you enter inches in the "Imperial" column, the equivalent value in centimeters will automatically displayed in the "Metric" column.
|
||||
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
<b>How do I convert from centimeters to/from inches, meters to/from yards or grams to/from ounces?</b>
|
||||
<p>
|
||||
<form>
|
||||
<table class="boxed">
|
||||
<tr style="background-color:darkgray">
|
||||
<th style="width:400px">Conversion</th>
|
||||
<th style="width:150px">Metric</th>
|
||||
<th style-"width:150px">Imperial</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Centimeters & Inches</td>
|
||||
<td><input type="number" id="cm" oninput="inch.value = Math.round(cm.value * 0.393701 * 1000) / 1000;"><sup> a</sup></td>
|
||||
<td><input type="number" id="inch" oninput="cm.value = Math.round(inch.value * 2.54 * 1000) / 1000;"><sup> b</sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Meters & Yards</td>
|
||||
<td><input type="number" id="m" oninput="yd.value = Math.round(m.value * 1.093613 * 1000) / 1000;"><sup> c</sup></td>
|
||||
<td><input type="number" id="yd" oninput="m.value = Math.round(yd.value * 0.9144 * 1000) / 1000;"><sup> d</sup></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Grams & Ounces</td>
|
||||
<td><input type="number" id="gm" oninput="oz.value = Math.round(gm.value * 0.035274 * 1000) / 1000;"><sup> e</sup></td>
|
||||
<td><input type="number" id="oz" oninput="gm.value = Math.round(oz.value * 28.349523 * 1000) / 1000;"><sup> f</sup></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<p><b>How it's done:</b>
|
||||
<p style="margin-left: 40px;">a = b * 2.54
|
||||
<br>b = a * 0.393701
|
||||
<br>c = d * 0.9144
|
||||
<br>d = c * 1.093613
|
||||
<br>e = f * 28.349523
|
||||
<br>f = e * 0.035274
|
||||
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
<b>My pattern is written for one gauge, but I get a different gauge (rows or stitches) on my knitting machine. How do I calculate the number of stitches to cast on or the number of rows to knit to achieve the desired size?</b>
|
||||
<p>
|
||||
<form>
|
||||
|
||||
<table class="boxed">
|
||||
<tr style="background-color:darkgray">
|
||||
<th style="width:400px">Description</th>
|
||||
<th style="width:150px">Value</th>
|
||||
<tr>
|
||||
<td>Rows/stitches per 10cm/4" on the pattern<sup> a</sup></td>
|
||||
<td><input
|
||||
type="number"
|
||||
id="a"
|
||||
min="1.0"
|
||||
max="100.0"
|
||||
step="0.1"
|
||||
value="1.0"
|
||||
oninput="d.value = Math.round((b.value / a.value) * c.value)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Pattern rows/stitches<sup> b</sup></td>
|
||||
<td><input
|
||||
type="number"
|
||||
id="b"
|
||||
min="1.0"
|
||||
max="100.0"
|
||||
step="0.1"
|
||||
value="1.0"
|
||||
oninput="d.value = Math.round((b.value / a.value) * c.value)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rows/stitches per 10cm/4" on your knitting machine<sup> c</sup></td>
|
||||
<td><input
|
||||
type="number"
|
||||
id="c"
|
||||
min="1.0"
|
||||
max="100.0"
|
||||
step="0.1"
|
||||
value="1.0"
|
||||
oninput="d.value = Math.round((b.value / a.value) * c.value)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Equivalent rows/stitches on your knitting machine<sup> d</sup></td>
|
||||
<td><output
|
||||
name="d"
|
||||
for="a b c"
|
||||
value="1">
|
||||
</output></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
<p><b>How it's done:</b>
|
||||
<p style="margin-left: 40px">d = (b / a) * c
|
||||
<hr>
|
||||
<p>
|
||||
<b>How do I calculate the number of stitches to cast on or the number of rows to knit to achieve the desired width or length?</b>
|
||||
<p>
|
||||
<form>
|
||||
|
||||
<table class="boxed">
|
||||
<tr style="background-color:darkgray">
|
||||
<th style="width:400px">Description</th>
|
||||
<th style="width:150px">Metric (cm)</th>
|
||||
<th style="width:150px">Imperial (in)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rows/stitches per 10cm/4"<sup> a</sup></td>
|
||||
<td colspan="2"><input
|
||||
type="number"
|
||||
id="a"
|
||||
name="gauge"
|
||||
min="1.0"
|
||||
max="100.0"
|
||||
step="0.1"
|
||||
value="1.0"
|
||||
oninput="c1.value = Math.round(a.value / 10 * b1.value); c2.value = Math.round(a.value / 4 * b1.value);"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>desired width/length<sup> b</sup></td>
|
||||
<td><input
|
||||
type="number"
|
||||
id="b1"
|
||||
name="target_size"
|
||||
min="1.0"
|
||||
max="100.0"
|
||||
step="0.1"
|
||||
value="1.0"
|
||||
oninput="b2.value = Math.round(b1.value * 0.393701 * 1000) / 1000; c1.value = Math.round(a.value / 10 * b1.value); c2.value = Math.round(a.value / 4 * b2.value);"></td>
|
||||
<td><input
|
||||
type="number"
|
||||
id="b2"
|
||||
name="target_size"
|
||||
min="1.0"
|
||||
max="100.0"
|
||||
step="0.1"
|
||||
value="1.0"
|
||||
oninput="b1.value= Math.round(b2.value * 2.54 * 1000) / 1000; c1.value = Math.round(a.value / 10 * b1.value); c2.value = Math.round(a.value / 4 * b2.value);"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td># stitches to cast on or rows to knit<sup> c</sup></td>
|
||||
<td><output
|
||||
name="c1"
|
||||
for="a b1"
|
||||
value="1">
|
||||
</output></td>
|
||||
<td><output
|
||||
name="c2"
|
||||
for="a b2"
|
||||
value="1">
|
||||
</output></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
<p><b>How it's done:</b>
|
||||
<p style="margin-left: 40px">c = (a / 10) * b (in centimeters)
|
||||
<br>c = (a / 4) * b (in inches)
|
||||
|
||||
<hr>
|
||||
|
||||
<p><b>Quick Tips:</b>
|
||||
<p>After you compute the number of stitches or rows required for your gauge, consult the pattern to see if knitting a different size will produce the desired results.
|
||||
<p style="margin-left: 40px">For example, if the pattern instructs you to cast on 80 stitches for a size medium but your gauge requires you to cast on 90 stitches to achieve the same width, look at the pattern to see if the next larger size specifies a cast on that's closer to 90 stitches. Knitting a larger size at a smaller gauge (or smaller size at a larger gauge) may produce the same result.
|
||||
|
||||
<p>If you have questions or feedback, please contact <a href="http://www.ravelry.com/people/beebell">beebell on Ravelry</a> via private message.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE HTML SYSTEM>
|
||||
<html>
|
||||
<head>
|
||||
<title>Knitting Tools</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: arial, sans-serif;
|
||||
margin-top: 40px;
|
||||
margin-left: 10%;
|
||||
width: 80%;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: 1px solid #cccccc;
|
||||
text-align: right;
|
||||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Knitting Tools</h1>
|
||||
<hr>
|
||||
|
||||
<p><a href="/pcgenerator">Punchcard Generator</a>: Generate SVG files from text files for cutting punchcards on a die cutter
|
||||
<p><a href="/calculator">Knitting Calculator</a>: Perform a variety of calculations including unit and gauge conversions
|
||||
|
||||
<hr>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
<!DOCTYPE HTML SYSTEM>
|
||||
<html>
|
||||
<head>
|
||||
<title>PCGenerator</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: arial, sans-serif;
|
||||
margin-top: 40px;
|
||||
margin-left: 10%;
|
||||
width: 80%;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: None;
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Punchcard Generator</h1>
|
||||
<a href="/"><Back></a>
|
||||
<hr>
|
||||
|
||||
<p>This app will allow you to upload a small text file that contains your pattern represented as a sequence of rows with X's for punched holes and any other character except space for unpunched holes. The program will generate an SVG file that can be imported into the software you use to cut material with your die cutter.
|
||||
|
||||
<h2>TL;DR</h2>
|
||||
<ul>
|
||||
<li>Select the file to upload.</li>
|
||||
<li>Enter your punchcard row height and column width in millimeters.</li>
|
||||
<li>Enter horizontal and vertical repeats if you need them.</li>
|
||||
<li>Click the Upload button.</li>
|
||||
</ul>In a few seconds, you should see a dialog prompting you for where you want to save your file. If you need more detailed instructions, keep reading below.
|
||||
|
||||
<p>
|
||||
<form
|
||||
id="main"
|
||||
method="POST"
|
||||
enctype="multipart/form-data"
|
||||
action="/pcgenerator"
|
||||
onfocus="x.value=horz.value; y.value=vert.value"
|
||||
oninput="x.value=horz.value; y.value=vert.value">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td style="text-align:right">Select file to upload:<br> </td>
|
||||
<td colspan="2"><input type="file" name="upfile"><br><small>(maximum file size 2500 characters)<small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right">Height of 1 punchcard row (mm):</td>
|
||||
<td colspan="2"><input type="number" name="rowheight" min="1.0" max="10.0" step="0.1" value="5.0"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right">Width of 1 punchcard column (mm):</td>
|
||||
<td colspan="2"><input type="number" name="colwidth" min="1.0" max="10.0" step="0.1" value="4.5"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right"># Horizontal repeats (up to 12):</td>
|
||||
<td colspan="2"><input type="range" id="horz" name="horz" min="1" max="12" step="1" value="1">
|
||||
<output id="x" name="x" value="1"></output>
|
||||
<script>x.value=horz.value;</script></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right"># Vertical repeats (up to 12):</td>
|
||||
<td><input type="range" id="vert" name="vert" min="1" max="12" step="1" value="1">
|
||||
<output id="y" name="y" value="1"></output>
|
||||
<script>y.value=vert.value;</script></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="2"><input type="submit" value="Upload"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<br>
|
||||
|
||||
<br>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<h1>Instructions</h1>
|
||||
|
||||
<p>Both upper and lower case X's are supported. The total width in stitches is determined by the number of characters in the first row. For example, the following text file has 4 rows and 12 stitches:
|
||||
|
||||
<pre>
|
||||
x-----x-----
|
||||
-x-----x----
|
||||
--x-----x---
|
||||
---x-----x--
|
||||
</pre>
|
||||
|
||||
<p>By default, the generator will do 1 horizontal repeat and 1 vertical repeat. I.e., if your file contains 36 rows with 24 characters per row, the generated file will produce a 24 row x 36 stitch card. You can increase the width and/or length by adjusting the horizontal and/or vertical repeat before clicking the upload button.
|
||||
|
||||
<p>What this means is that you can design a simple 4x4 card and use repeats to make the card as wide or as long as it needs to be in order to work properly. For example, the following text file will generate a 24 row x 48 stitch card if you specify 6 for the horizontal repeat and 12 for the vertical repeat:
|
||||
|
||||
<pre>
|
||||
x-x-
|
||||
-x-x
|
||||
x-x-
|
||||
-x-x
|
||||
</pre>
|
||||
|
||||
<p>You'll need to specify the height and width of 1 row and 1 column on the punchcard. You can determine the correct values by measuring the size of the squares on a card that works with your knitting machine. If your card doesn't have squares, you can measure the distance between the centers of two adjacent holes. For reference:
|
||||
|
||||
<p>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Knitting Machine</th>
|
||||
<th style="text-align:center">Row Height<br>(mm)</th>
|
||||
<th style="text-align:center">Column Width<br>(mm)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Brother 24-Stitch Standard</td>
|
||||
<td style="text-align:center">5</td>
|
||||
<td style="text-align:center">4.5</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Brother 12-Stitch Bulky</td>
|
||||
<td style="text-align:center">5</td>
|
||||
<td style="text-align:center">9</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>The resulting SVG file can be imported into any application that understands SVG. You can also display the SVG in some browsers. Neither the text file or resulting SVG will be saved on this site. Be sure to keep them in a safe location so they don't get lost.
|
||||
|
||||
<p>This program has only been tested using Sure Cuts A Lot on a Pazzles Creative Mighty. YMMV!
|
||||
|
||||
<p>If you have questions or feedback, please contact <a href="http://www.ravelry.com/people/beebell">beebell on Ravelry</a> via private message.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Ładowanie…
Reference in New Issue