1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
#!/usr/bin/env python3
#coding:utf-8
# Author: mozman
# Purpose: svg examples
# Created: 08.09.2010
# Copyright (C) 2010, Manfred Moitzi
# License: MIT License
try:
import svgwrite
except ImportError:
# if svgwrite is not 'installed' append parent dir of __file__ to sys.path
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
import math
import svgwrite
def koch_snowflake(name):
# Koch Snowflake and Sierpinski Triangle combination fractal using recursion
# ActiveState Recipe 577156
# Created by FB36 on Sat, 27 Mar 2010 (MIT)
# http://code.activestate.com/recipes/577156-koch-snowflake-and-sierpinski-triangle-combination/
def tf (x0, y0, x1, y1, x2, y2):
a = math.hypot(x1 - x0, y1 - y0)
b = math.hypot(x2 - x1, y2 - y1)
c = math.hypot(x0 - x2, y0 - y2)
if (a < stop_val) or (b < stop_val) or (c < stop_val):
return
x3 = (x0 + x1) / 2
y3 = (y0 + y1) / 2
x4 = (x1 + x2) / 2
y4 = (y1 + y2) / 2
x5 = (x2 + x0) / 2
y5 = (y2 + y0) / 2
points = [(x3, y3), (x4, y4), (x5, y5)]
# append new polygon to snowflake element
snowflake.add(dwg.polygon(points))
tf(x0, y0, x3, y3, x5, y5)
tf(x3, y3, x1, y1, x4, y4)
tf(x5, y5, x4, y4, x2, y2)
def sf (ax, ay, bx, by):
f = math.hypot(bx - ax, by - ay)
if f < 1.:
return
f3 = f / 3
cs = (bx - ax) / f
sn = (by - ay) / f
cx = ax + cs * f3
cy = ay + sn * f3
h = f3 * math.sqrt(3) / 2
dx = (ax + bx) / 2 + sn * h
dy = (ay + by) / 2 - cs * h
ex = bx - cs * f3
ey = by - sn * f3
tf(cx, cy, dx, dy, ex, ey)
sf(ax, ay, cx, cy)
sf(cx, cy, dx, dy)
sf(dx, dy, ex, ey)
sf(ex, ey, bx, by)
# const values
stop_val = 8.
imgx = 512
imgy = 512
# create a new drawing
dwg = svgwrite.Drawing(name, (imgx, imgy), profile='tiny', debug=True)
# create a new <g /> element, we will insert the snowflake by the <use /> element
# here we set stroke, fill and stroke-width for all subelements
# attention: 'stroke-width' is not a valid Python identifier, so use 'stroke_witdth'
# underlines '_' will be converted to dashes '-', this is true for all svg-keyword-attributes
# if no 'id' is given ( like dwg.g(id="sflake") ), an automatic generated 'id' will be generated
snowflake = dwg.g(stroke="blue", fill="rgb(90%,90%,100%)", stroke_width=0.25)
# add the <g /> element to the <defs /> element of the drawing
dwg.defs.add(snowflake)
mx2 = imgx / 2
my2 = imgy / 2
r = my2
a = 2 * math.pi / 3
for k in range(3):
x0 = mx2 + r * math.cos(a * k)
y0 = my2 + r * math.sin(a * k)
x1 = mx2 + r * math.cos(a * (k + 1))
y1 = my2 + r * math.sin(a * (k + 1))
sf(x0, y0, x1, y1)
x2 = mx2 + r * math.cos(a)
y2 = my2 + r * math.sin(a)
tf(x0, y0, x1, y1, x2, y2)
# create an <use /> element
use_snowflake = dwg.use(snowflake)
# you can transform each <use /> element
# use_snowflake.rotate(15, center=(imgx/2, imgy/2))
# insert snowflake by the <use /> element
dwg.add(use_snowflake)
# and save the drawing
dwg.save()
if __name__ == '__main__':
koch_snowflake("koch_snowflake.svg")
|