kopia lustrzana https://github.com/branchwelder/embryoid
Working on l-system embroideries
rodzic
b1d2bcb402
commit
989cbdbcba
|
@ -1,3 +1,8 @@
|
|||
{
|
||||
"terminal.integrated.cwd": "${workspaceFolder}"
|
||||
"terminal.integrated.cwd": "${workspaceFolder}",
|
||||
"cSpell.words": [
|
||||
"pyplot",
|
||||
"xlabel",
|
||||
"ylabel"
|
||||
]
|
||||
}
|
File diff suppressed because one or more lines are too long
Po Szerokość: | Wysokość: | Rozmiar: 21 KiB |
|
@ -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("<gap>")
|
||||
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()
|
22
embryoid.py
22
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")
|
||||
|
|
Plik binarny nie jest wyświetlany.
File diff suppressed because one or more lines are too long
Po Szerokość: | Wysokość: | Rozmiar: 12 KiB |
|
@ -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
|
Plik binarny nie jest wyświetlany.
File diff suppressed because one or more lines are too long
Po Szerokość: | Wysokość: | Rozmiar: 16 KiB |
File diff suppressed because one or more lines are too long
Po Szerokość: | Wysokość: | Rozmiar: 11 KiB |
Plik binarny nie jest wyświetlany.
Ładowanie…
Reference in New Issue