diff --git a/.vscode/settings.json b/.vscode/settings.json
index 01ee7a8..2844c0e 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,8 @@
{
- "terminal.integrated.cwd": "${workspaceFolder}"
+ "terminal.integrated.cwd": "${workspaceFolder}",
+ "cSpell.words": [
+ "pyplot",
+ "xlabel",
+ "ylabel"
+ ]
}
\ No newline at end of file
diff --git a/convo.svg b/convo.svg
new file mode 100644
index 0000000..8057a21
--- /dev/null
+++ b/convo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/embroiderTurtle.py b/embroiderTurtle.py
new file mode 100644
index 0000000..dae4d45
--- /dev/null
+++ b/embroiderTurtle.py
@@ -0,0 +1,91 @@
+import matplotlib.pyplot as plt
+from math import pi, sin, cos, isnan
+
+DEGREES_TO_RADIANS = pi / 180
+
+
+def print_coords(coords):
+ for (x, y) in coords:
+ if isnan(x):
+ print("")
+ else:
+ print("({:.2f}, {:.2f})".format(x, y))
+
+
+def turtle_to_coords(turtle_program, turn_amount=45):
+ # The state variable tracks the current location and angle of the turtle.
+ # The turtle starts at (0, 0) facing up (90 degrees).
+ state = (0.0, 0.0, 90.0)
+
+ # Throughout the turtle's journey, we "yield" its location. These coordinate
+ # pairs become the path that plot_coords draws.
+ yield (0.0, 0.0)
+
+ # Loop over the program, one character at a time.
+ for command in turtle_program:
+ x, y, angle = state
+
+ if command in "Ff": # Move turtle forward
+ state = (
+ x - cos(angle * DEGREES_TO_RADIANS),
+ y + sin(angle * DEGREES_TO_RADIANS),
+ angle,
+ )
+
+ if command == "f":
+ # Insert a break in the path so that
+ # this line segment isn't drawn.
+ yield (float("nan"), float("nan"))
+
+ yield (state[0], state[1])
+
+ elif command == "+": # Turn turtle clockwise without moving
+ state = (x, y, angle + turn_amount)
+
+ elif command == "-": # Turn turtle counter-clockwise without moving
+ state = (x, y, angle - turn_amount)
+
+ # Note: We silently ignore unknown commands
+
+
+def plot_coords(coords, bare_plot=False):
+ if bare_plot:
+ # Turns off the axis markers.
+ plt.axis("off")
+ # Ensures equal aspect ratio.
+ plt.axes().set_aspect("equal", "datalim")
+ # Converts a list of coordinates into
+ # lists of X and Y values, respectively.
+ X, Y = zip(*coords)
+ # Draws the plot.
+ plt.plot(X, Y)
+
+
+def transform_sequence(sequence, transformations):
+ return "".join(transformations.get(c, c) for c in sequence)
+
+
+def transform_multiple(sequence, transformations, iterations):
+ for _ in range(iterations):
+ sequence = transform_sequence(sequence, transformations)
+ return sequence
+
+
+def hilbert():
+ return turtle_to_coords(
+ transform_multiple("L", {"L": "-RF+LFL+FR-", "R": "+LF-RFR-FL+"}, 5), 90
+ )
+
+
+if __name__ == "__main__":
+ plt.style.use("bmh") # Use some nicer default colors
+ plt.xlabel("x")
+ plt.ylabel("y")
+
+ plot_coords(
+ turtle_to_coords(
+ transform_multiple("L", {"L": "-RF+LFL+FR-", "R": "+LF-RFR-FL+"}, 5), 90
+ )
+ )
+
+ plt.show()
diff --git a/embryoid.py b/embryoid.py
index 97f3a0f..3259b68 100644
--- a/embryoid.py
+++ b/embryoid.py
@@ -22,8 +22,15 @@ class Embryoid:
def add_stitch_block(self, block):
self.pattern.add_block(block)
+ def block_from_coords(self, coords):
+ block = []
+ for coord in coords:
+ block.append((coord[0], coord[1]))
+ self.pattern.add_block(block, "teal")
+
def parse_svg(self, fname):
paths, attributes = svg2paths(fname)
+ print(paths)
print(attributes)
for path in paths:
block = []
@@ -43,15 +50,22 @@ def solid_block(x_len=100, y_len=100, num_stitches=20):
return stitches
-def parse(fname):
+def parse(fname, outname):
e = Embryoid()
e.parse_svg(INPUT_SVG + fname)
- e.save_svg("linger_longer.svg")
- e.save_pes("linger_longer.pes")
+ e.save_svg(outname + ".svg")
+ e.save_pes(outname + ".pes")
if __name__ == "__main__":
- parse("linger_longer_audioplot.svg")
+ from embroiderTurtle import hilbert
+
+ e = Embryoid()
+ e.block_from_coords([*hilbert()])
+ e.save_pes("hilbert.pes")
+ e.save_svg("hilbert.svg")
+ print(*hilbert())
+ # parse("convo.svg", "convo")
# e = Embryoid()
# e.add_stitch_block(solid_block())
# e.save_svg("block_test.svg")
diff --git a/hilbert.pes b/hilbert.pes
new file mode 100644
index 0000000..170dcd2
Binary files /dev/null and b/hilbert.pes differ
diff --git a/hilbert.svg b/hilbert.svg
new file mode 100644
index 0000000..dde125b
--- /dev/null
+++ b/hilbert.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/l-system.py b/l-system.py
new file mode 100644
index 0000000..d1ba05e
--- /dev/null
+++ b/l-system.py
@@ -0,0 +1,203 @@
+import pygame
+import math
+
+# other = variables
+# F,A = move n forward
+# G = move n forward without drawing a line
+# B = move n backwards
+# - = turn left by angle
+# + = turn right by angle
+# [ = push position and angle
+# ] = pop position and angle
+# a,b,c,d = color 1,2,3,4
+# 1-4 line size (std = 1)
+#
+
+rules = {}
+
+rules["F"] = "F-F++F-F"
+axiom = "F++F++F"
+angle = 60
+
+# rules['A'] = '+F-A-F+' # Sierpinsky
+# rules['F'] = '-A+F+A-'
+# axiom = 'A'
+# angle = 60
+
+# rules['F'] = 'F+F-F-F+F' # Koch curve 1
+# axiom = 'F'
+# angle = 60
+
+# rules['F'] = 'F+F--F+F' # Koch curve 2
+# axiom = 'F'
+# angle = 60
+
+# rules["X"] = "X+YF+" # Dragon curve
+# rules["Y"] = "-FX-Y"
+# axiom = "FX"
+# angle = 90
+
+# rules['X'] = 'F-[[X]+X]+F[+FX]-X' # Wheat
+# rules['F'] = 'FF'
+# axiom = 'X'
+# angle = 25
+
+# rules['F'] = 'a2FF-[c1-F+F+F]+[c1+F-F-F]' # Tree - colored
+# axiom = 'F'
+# angle = 23
+
+# rules['X'] = 'F-[[X]-1X]+2F-[+3FX]+1X' # Wheat
+# rules['F'] = 'X'
+# axiom = 'X'
+# angle = 25
+
+iterations = 7 # number of iterations
+step = 15 # step size / line length
+
+color1 = (105, 46, 26) # brown 1
+color2 = (201, 146, 127) # brown 2
+color3 = (101, 250, 52) # green
+color4 = (255, 255, 255) # white
+
+angleoffset = 90
+
+size = width, height = 10000, 10000 # display with/height
+pygame.init() # init display
+screen = pygame.Surface(size) # open screen
+
+# startpos = 100, height - 225
+# startpos = 50, height / 2 - 50
+startpos = width / 2, height / 2
+# startpos = 100, height / 2
+# startpos = 10,10
+
+
+def applyRule(input):
+ output = ""
+ for (
+ rule,
+ result,
+ ) in rules.items(): # applying the rule by checking the current char against it
+ if input == rule:
+ output = result # Rule 1
+ break
+ else:
+ output = input # else ( no rule set ) output = the current char -> no rule was applied
+ return output
+
+
+def processString(oldStr):
+ newstr = ""
+ for character in oldStr:
+ newstr = newstr + applyRule(character) # build the new string
+ return newstr
+
+
+def createSystem(numIters, axiom):
+ startString = axiom
+ endString = ""
+ for i in range(numIters): # iterate with appling the rules
+ print("Iteration: {0}".format(i))
+ endString = processString(startString)
+ startString = endString
+ return endString
+
+
+def polar_to_cart(theta, r, offx, offy):
+ x = r * math.cos(math.radians(theta))
+ y = r * math.sin(math.radians(theta))
+ return tuple([x + y for x, y in zip((int(x), int(y)), (offx, offy))])
+
+
+def cart_to_polar(x, y):
+ return (math.degrees(math.atan(y / x)), math.sqrt(math.pow(x, 2) + math.pow(y, 2)))
+
+
+def drawTree(input, oldpos):
+ a = 0 # angle
+ i = 0 # counter for processcalculation
+ processOld = 0 # old process
+ newpos = oldpos
+ num = [] # stack for the brackets
+ color = (255, 255, 255)
+ linesize = 1
+ xmax = 0
+ xmin = 0
+ ymax = 0
+ ymin = 0
+ for (
+ character
+ ) in input: # process for drawing the l-system by writing the string to the screen
+
+ i += 1 # print process in percent
+ process = i * 100 / len(input)
+ if not process == processOld:
+ print(process, "%")
+ processOld = process
+
+ if character == "A": # magic happens here
+ newpos = polar_to_cart(a + angleoffset, step, oldpos[0], oldpos[1])
+ pygame.draw.line(screen, color, oldpos, newpos, linesize)
+ oldpos = newpos
+ elif character == "F":
+ newpos = polar_to_cart(a + angleoffset, step, oldpos[0], oldpos[1])
+ pygame.draw.line(screen, color, oldpos, newpos, linesize)
+ oldpos = newpos
+ elif character == "B":
+ newpos = polar_to_cart(-a + angleoffset, -step, oldpos[0], oldpos[1])
+ pygame.draw.line(screen, color, oldpos, newpos, linesize)
+ oldpos = newpos
+ elif character == "G":
+ newpos = polar_to_cart(a + angleoffset, step, oldpos[0], oldpos[1])
+ oldpos = newpos
+ elif character == "a":
+ color = color1
+ elif character == "b":
+ color = color2
+ elif character == "c":
+ color = color3
+ elif character == "d":
+ color = color4
+ elif character == "1":
+ linesize = 1
+ elif character == "2":
+ linesize = 2
+ elif character == "3":
+ linesize = 3
+ elif character == "4":
+ linesize = 4
+ elif character == "+":
+ a += angle
+ elif character == "-":
+ a -= angle
+ elif character == "[":
+ num.append((oldpos, a))
+ elif character == "]":
+ oldpos, a = num.pop()
+ if xmax < oldpos[0] - width / 2:
+ xmax = oldpos[0] - width / 2
+ if xmin > oldpos[0] - width / 2:
+ xmin = oldpos[0] - width / 2
+ if ymax < oldpos[1] - height / 2:
+ ymax = oldpos[1] - height / 2
+ if ymin > oldpos[1] - height / 2:
+ ymin = oldpos[1] - height / 2
+ crop = pygame.Surface((abs(xmax - xmin) + 100, abs(ymax - ymin) + 100))
+ crop.blit(
+ screen,
+ (50, 50),
+ (xmin + width / 2, ymin + height / 2, xmax + width / 2, ymax + height / 2),
+ )
+ pygame.image.save(crop, "screenshot.png")
+
+
+if __name__ == "__main__":
+ # drawTree(createSystem(iterations, axiom), startpos)
+ tree = createSystem(iterations, axiom)
+ drawTree(tree, startpos)
+ # pygame.display.flip()
+ # pygame.image.save(screen, "screenshot.png")
+ # print "Finished"
+ while 1:
+ pass
+ exit() # uncommand
diff --git a/linger_longer.pes b/linger_longer.pes
new file mode 100644
index 0000000..18bf62b
Binary files /dev/null and b/linger_longer.pes differ
diff --git a/linger_longer.svg b/linger_longer.svg
new file mode 100644
index 0000000..c2d133e
--- /dev/null
+++ b/linger_longer.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tests_input/convo.svg b/tests_input/convo.svg
new file mode 100644
index 0000000..7efff38
--- /dev/null
+++ b/tests_input/convo.svg
@@ -0,0 +1,43 @@
+
+
diff --git a/tests_pes/convo.pes b/tests_pes/convo.pes
new file mode 100644
index 0000000..da19804
Binary files /dev/null and b/tests_pes/convo.pes differ