Skip to content

Instantly share code, notes, and snippets.

@PM2Ring
Created October 4, 2018 11:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PM2Ring/924b71c2c40728e7e1183de62b53a882 to your computer and use it in GitHub Desktop.
Save PM2Ring/924b71c2c40728e7e1183de62b53a882 to your computer and use it in GitHub Desktop.
Crocheted sphere pattern generator
#!/usr/bin/env python3
''' Crocheted sphere pattern generator.
Calculate the number of stitches per row in a crocheted sphere
of a given number of rows, and thence print a crochet pattern.
Original patterns from http://www.craftster.org/forum/index.php?topic=341241.0
Written by PM 2Ring 2011.10.20
Updated to Python 3.6 2018.10.03
Key:
Ch = chain
Sc = single crochet
inc = 2 single crochet in next stitch.
dec = single crochet decrease.
These are worked in spiral rounds.
'''
import sys
from math import sin, pi
from itertools import chain
intro = """
An ideal Crocheted Sphere pattern.
All stitches are single crochet, apart from the initial chain.
Ch = chain
Sc = single crochet
inc = 2 single crochet in next stitch.
dec = single crochet decrease.
These are worked in spiral rounds.
"""
def main(n):
""" Print an ideal crocheted sphere pattern """
print(intro)
#Account for null "rows" at the poles.
nn = n + 1
#Polar angle between each row
ang = pi / nn
#1st row is always == 6
equator = 6.0 / sin(ang)
head = 'Ch 2. 6 Sc in second Ch from hook.'
foot = (
'[dec] * 4. Fasten off. (4)\n'
'Weave loose end through each stitch '
'in the opening. Pull tightly to close.'
)
rowlengths = [int(0.55 + equator * sin(i * ang)) for i in range(nn)]
deltas = [0] + [j - k for j, k in zip(rowlengths[1:], rowlengths)]
print("Total number of rows =", n)
print("Total number of stitches =", sum(rowlengths[1:]) - 2)
print(f"Equator = {equator:.3f}\n")
for i in range(1, nn):
rowlen = rowlengths[i]
#First and last rows
if i == 1:
print(f"Row {i:2}: {head} ({rowlen})")
continue
elif i == n:
print(f"Row {i:2}: {foot}")
return
delta = deltas[i]
if delta > 0:
# Northern hemisphere, increasing
ch = 'inc'
k = rowlen - 2 * delta
elif delta < 0:
# Southern hemisphere, decreasing
ch = 'dec'
k = rowlen + delta
else:
# Equatorial band
print(f"Row {i:2}: even ({rowlen})")
continue
delta = abs(delta)
f = k / delta
# Fill the stitches buffer with the delta pattern
buff = [int(f * u) for u in range(delta + 1)]
buff = [u - v for u, v in zip(buff[1:], buff)]
# Rotate the end section to the front
buff = [buff[-1]] + buff[:-1]
# Halve the front section, and save the other
# half so it can be rotated back to the end
u = buff[0]
buff[0] = u // 2
sa = u - buff[0]
# Insert the 'inc' or 'dec' tokens. A token replaces a zero delta,
# and a token is inserted after a non-zero delta.
buff = list(chain.from_iterable((u, ch) if u else (ch,) for u in buff))
if sa:
# Append the the rotated half from the front section
buff.append(sa)
#Condense the pattern, if it repeats exactly
u = len(buff)
for k in range(1, u // 2):
if u % k == 0:
start = buff[:k]
m = u // k
if buff == start * m:
buff = start
break
else:
m = 1
buff = ', '.join([f"{u:2}" for u in buff])
if m > 1:
buff = f"[{buff}] * {m}"
print(f"Row {i:2}: {buff} ({rowlen})")
if __name__ == '__main__':
n = int(sys.argv[1]) if len(sys.argv) > 1 else 20
main(n)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment