This commit is contained in:
Michael Fogleman 2017-01-13 22:18:02 -05:00
parent 2daaf8ec93
commit 417d980a80
5 changed files with 239 additions and 3 deletions

42
examples/circles.py Normal file
View File

@ -0,0 +1,42 @@
import axi
import math
import random
def circle(cx, cy, r, n):
points = []
for i in range(n + 1):
a = 2 * math.pi * i / n
x = cx + math.cos(a) * r
y = cy + math.sin(a) * r
points.append((x, y))
return points
def random_points_on_circle(cx, cy, r, n):
result = []
a = random.random() * 2 * math.pi
da = 2 * math.pi / n
for i in range(n):
x = cx + math.cos(a) * r
y = cy + math.sin(a) * r
result.append((x, y))
a += da
return result
def add(x, y, r, paths):
if r < 1:
return
paths.append(circle(x, y, r, 90))
points = random_points_on_circle(x, y, r, 2)
for x, y in points:
add(x, y, r / 2, paths)
def main():
paths = []
add(0, 0, 64, paths)
drawing = axi.Drawing(paths).rotate_and_scale_to_fit(11, 8.5).sort_paths()
im = drawing.render()
im.write_to_png('out.png')
axi.draw(drawing)
if __name__ == '__main__':
main()

70
examples/field.py Normal file
View File

@ -0,0 +1,70 @@
import axi
import random
import time
from math import hypot, atan2, sin, cos, pi
class Model(object):
def __init__(self):
self.particles = []
def add(self, x, y, m=1.0):
self.particles.append((x, y, m))
def test(self, x, y):
dx = 0
dy = 0
for px, py, pm in self.particles:
d = hypot(x - px, y - py)
if abs(d) < 1e-8:
return (0, 0)
angle = atan2(y - py, x - px)
dx += pm * cos(angle) / d
dy += pm * sin(angle) / d
angle = atan2(dy, dx) + pi / 2
dx = cos(angle)
dy = sin(angle)
return (dx, dy)
def polygon(sides, d):
x = 0.5
y = 0.5
rotation = 0
angle = 2 * pi / sides
angles = [angle * i + rotation for i in range(sides)]
return [(x + cos(a) * d, y + sin(a) * d) for a in angles]
def create_path(model, scale, ox, oy, x, y, m, length):
result = []
n = int(length * 32)
f = float(length) / scale / n
for j in range(n):
result.append((ox + x * scale, oy + y * scale))
dx, dy = model.test(x, y)
x += dx * f * m
y += dy * f * m
if x < 0 or y < 0 or x > 1 or y > 1:
break
return result
def main():
# axi.reset()
# return
model = Model()
for x, y in polygon(5, 0.35):
model.add(x, y, 1)
model.add(0.5, 0.5, 0.1)
paths = []
for _ in range(500):
x = random.random()
y = random.random()
path = create_path(model, 8.5, 1.25, 0, x, y, -1, 3)
paths.append(path)
drawing = axi.Drawing(paths).sort_paths().simplify_paths(0.001)
axi.draw(drawing)
if __name__ == '__main__':
main()

View File

@ -1,7 +1,17 @@
import axi import axi
import math
import random import random
import time import time
def circle(cx, cy, radius, n, rotation):
points = []
for i in range(n + 1):
a = 2 * math.pi * i / n + rotation
x = cx + math.cos(a) * radius
y = cy + math.sin(a) * radius
points.append((x, y))
return points
def main(): def main():
d = axi.Device() d = axi.Device()
d.pen_up() d.pen_up()
@ -10,9 +20,20 @@ def main():
points = [] points = []
points.append((0, 0)) points.append((0, 0))
for i in range(10): for i in range(10):
x = random.random() * 11 while True:
y = random.random() * 8.5 x = random.random() * 11
points.append((x, y)) y = random.random() * 8.5
r = random.random() * 4
if x - r < 0 or x + r > 11:
continue
if y - r < 0 or y + r > 8.5:
continue
break
rotation = random.random() * 2 * math.pi
c = circle(x, y, r, 90, rotation)
if random.random() < 0.5:
c = list(reversed(c))
points.extend(c)
points.append((0, 0)) points.append((0, 0))
d.run_path(points) d.run_path(points)
d.wait() d.wait()

57
examples/poisson_disc.py Normal file
View File

@ -0,0 +1,57 @@
import random
from math import pi, sin, cos, hypot, floor
class Grid(object):
def __init__(self, r):
self.r = r
self.size = r / 2 ** 0.5
self.cells = {}
def points(self):
return self.cells.values()
def normalize(self, x, y):
i = int(floor(x / self.size))
j = int(floor(y / self.size))
return (i, j)
def nearby(self, x, y):
result = []
i, j = self.normalize(x, y)
for p in xrange(i - 2, i + 3):
for q in xrange(j - 2, j + 3):
if (p, q) in self.cells:
result.append(self.cells[(p, q)])
return result
def insert(self, x, y):
for bx, by in self.nearby(x, y):
if hypot(x - bx, y - by) < self.r:
return False
i, j = self.normalize(x, y)
self.cells[(i, j)] = (x, y)
return True
def poisson_disc(x1, y1, x2, y2, r, n):
x = x1 + (x2 - x1) / 2.0
y = y1 + (y2 - y1) / 2.0
active = [(x, y)]
grid = Grid(r)
grid.insert(x, y)
while active:
ax, ay = random.choice(active)
for i in xrange(n):
a = random.random() * 2 * pi
d = random.random() * r + r
x = ax + cos(a) * d
y = ay + sin(a) * d
if x < x1 or y < y1 or x > x2 or y > y2:
continue
if not grid.insert(x, y):
continue
active.append((x, y))
break
else:
active.remove((ax, ay))
return grid.points()

46
examples/stars.py Normal file
View File

@ -0,0 +1,46 @@
import axi
import math
import random
from axi.spatial import Index
from poisson_disc import poisson_disc
def perturb_points(points, deviation):
result = []
for x, y in points:
a = random.random() * 2 * math.pi
r = random.gauss(0, deviation)
x += math.cos(a) * r
y += math.sin(a) * r
result.append((x, y))
return result
def star(x, y, r):
sides = 5
a = random.random() * 2 * math.pi
angle = 2 * math.pi / sides
angles = [angle * i + a for i in range(sides)]
points = [(x + math.cos(a) * r, y + math.sin(a) * r) for a in angles]
points = perturb_points(points, 0.04)
points.append(points[0])
return points[0::2] + points[1::2]
def main():
points = poisson_disc(0, 0, 11, 8.5, 0.4, 64)
index = Index(points)
paths = []
for x1, y1 in points:
index.remove((x1, y1))
x2, y2 = index.nearest((x1, y1))
index.insert((x1, y1))
d = math.hypot(x2 - x1, y2 - y1)
paths.append(star(x1, y1, d / 2))
drawing = axi.Drawing(paths)
drawing = drawing.remove_paths_outside(11, 8.5)
drawing = drawing.sort_paths()
# im = drawing.render()
# im.write_to_png('out.png')
axi.draw(drawing)
if __name__ == '__main__':
main()