Fraktal mit Spirograph in Python
Einführung
Spirographenspielzeug, mit dem komplexe Muster aus Plastikzahnrädern und Farbstiften hergestellt werden. Ein Fraktal ist eine Kurve, die unter Verwendung eines wiederkehrenden Musters entwickelt wird, das sich in geringem Maßstab unendlich wiederholt. Fraktale werden zur Modellierung von Strukturen (wie Schneeflocken) oder zur Beschreibung teilweise chaotischer Phänomene verwendet.
Mit dem Spirographen können verschiedene Fraktale gezeichnet werden. Einige von ihnen sind unten angegeben
Sie können benice-equation-blogspot.in besuchen, um mehr Fraktale mit der parametrischen Gleichung zu entwerfen. Einige von ihnen sind unten angegeben
Mathematik hinter dem Vorhang
Dies sind die beiden parametrischen Gleichungen zur Bildung eines Spirographen-Fraktals. Um diese Gleichungen zu verstehen, müssen Sie eine verallgemeinerte Spirograph-Figur betrachten.
Für den Mathematik-Teil können Sie sich auf das Wiki beziehen, obwohl ich hier versuchen werde, ein wenig von dieser Mathematik kurz zu erklären. Wenn wir uns für die Mathematik interessieren, können Sie die angegebenen Links überprüfen. Ab sofort können diese verschiedenen Kurven mithilfe einer parametrischen Gleichung gezeichnet werden. Wenn Sie einige Werte dieser Gleichung variieren, können Sie verschiedene Fraktale erhalten. Hier ist also die parametrische Gleichung:
wo,
R ist ein Skalierungsparameter und hat keinen Einfluss auf die Struktur des Spirographen.
und,
Versuchen wir nun, dies in Code zu implementieren.
import
random, argparse
import
math
import
turtle
from
PIL
import
Image
from
datetime
import
datetime
from
fractions
import
gcd
class
Spiro:
def
__init__(
self
, xc, yc, col, R, r, l):
self
.t
=
turtle.Turtle()
self
.t.shape(
'turtle'
)
self
.step
=
5
self
.drawingComplete
=
False
self
.setparams(xc, yc, col, R, r, l)
self
.restart()
def
setparams(
self
, xc, yc, col, R, r, l):
self
.xc
=
xc
self
.yc
=
yc
self
.R
=
int
(R)
self
.r
=
int
(r)
self
.l
=
l
self
.col
=
col
gcdVal
=
gcd(
self
.r,
self
.R)
self
.nRot
=
self
.r
/
/
gcdVal
self
.k
=
r
/
float
(R)
self
.t.color(
*
col)
self
.a
=
0
def
restart(
self
):
self
.drawingComplete
=
False
self
.t.showturtle()
self
.t.up()
R, k, l
=
self
.R,
self
.k,
self
.l
a
=
0.0
x
=
R
*
((
1
-
k)
*
math.cos(a)
+
l
*
k
*
math.cos((
1
-
k)
*
a
/
k))
y
=
R
*
((
1
-
k)
*
math.sin(a)
-
l
*
k
*
math.sin((
1
-
k)
*
a
/
k))
self
.t.setpos(
self
.xc
+
x,
self
.yc
+
y)
self
.t.down()
def
draw(
self
):
R, k, l
=
self
.R,
self
.k,
self
.l
for
i
in
range
(
0
,
360
*
self
.nRot
+
1
,
self
.step):
a
=
math.radians(i)
x
=
R
*
((
1
-
k)
*
math.cos(a)
+
l
*
k
*
math.cos((
1
-
k)
*
a
/
k))
y
=
R
*
((
1
-
k)
*
math.sin(a)
-
l
*
k
*
math.sin((
1
-
k)
*
a
/
k))
self
.t.setpos(
self
.xc
+
x,
self
.yc
+
y)
self
.t.hideturtle()
def
update(
self
):
if
self
.drawingComplete:
return
self
.a
+
=
self
.step
R, k, l
=
self
.R,
self
.k,
self
.l
a
=
math.radians(
self
.a)
x
=
self
.R
*
((
1
-
k)
*
math.cos(a)
+
l
*
k
*
math.cos((
1
-
k)
*
a
/
k))
y
=
self
.R
*
((
1
-
k)
*
math.sin(a)
-
l
*
k
*
math.sin((
1
-
k)
*
a
/
k))
self
.t.setpos(
self
.xc
+
x,
self
.yc
+
y)
if
self
.a >
=
360
*
self
.nRot:
self
.drawingComplete
=
True
self
.t.hideturtle()
def
clear(
self
):
self
.t.clear()
class
SpiroAnimator:
def
__init__(
self
, N):
self
.deltaT
=
10
self
.width
=
turtle.window_width()
self
.height
=
turtle.window_height()
self
.spiros
=
[]
for
i
in
range
(N):
rparams
=
self
.genRandomParams()
spiro
=
Spiro(
*
rparams)
self
.spiros.append(spiro)
turtle.ontimer(
self
.update,
self
.deltaT)
def
restart(
self
):
for
spiro
in
self
.spiros:
spiro.clear()
rparams
=
self
.genRandomParams()
spiro.setparams(
*
rparams)
spiro.restart()
def
genRandomParams(
self
):
width, height
=
self
.width,
self
.height
R
=
random.randint(
50
,
min
(width, height)
/
/
2
)
r
=
random.randint(
10
,
9
*
R
/
/
10
)
l
=
random.uniform(
0.1
,
0.9
)
xc
=
random.randint(
-
width
/
/
2
, width
/
/
2
)
yc
=
random.randint(
-
height
/
/
2
, height
/
/
2
)
col
=
(random.random(),
random.random(),
random.random())
return
(xc, yc, col, R, r, l)
def
update(
self
):
nComplete
=
0
for
spiro
in
self
.spiros:
spiro.update()
if
spiro.drawingComplete:
nComplete
+
=
1
if
nComplete
=
=
len
(
self
.spiros):
self
.restart()
turtle.ontimer(
self
.update,
self
.deltaT)
def
toggleTurtles(
self
):
for
spiro
in
self
.spiros:
if
spiro.t.isvisible():
spiro.t.hideturtle()
else
:
spiro.t.showturtle()
def
saveDrawing():
turtle.hideturtle()
dateStr
=
(datetime.now()).strftime(
"%d%b%Y-%H%M%S"
)
fileName
=
'spiro-'
+
dateStr
(
'saving drawing to %s.eps/png'
%
fileName)
canvas
=
turtle.getcanvas()
canvas.postscript(
file
=
fileName
+
'.eps'
)
img
=
Image.
open
(fileName
+
'.eps'
)
img.save(fileName
+
'.png'
,
'png'
)
turtle.showturtle()
def
main():
(
'generating spirograph...'
)
descStr
=
parser
=
argparse.ArgumentParser(description
=
descStr)
parser.add_argument(
'--sparams'
, nargs
=
3
, dest
=
'sparams'
, required
=
False
,
help
=
"The three arguments in sparams: R, r, l."
)
args
=
parser.parse_args()
turtle.setup(width
=
0.8
)
turtle.shape(
'turtle'
)
turtle.title(
"Spirographs!"
)
turtle.onkey(saveDrawing,
"s"
)
turtle.listen()
turtle.hideturtle()
if
args.sparams:
params
=
[
float
(x)
for
x
in
args.sparams]
col
=
(
0.0
,
0.0
,
0.0
)
spiro
=
Spiro(
0
,
0
, col,
*
params)
spiro.draw()
else
:
spiroAnim
=
SpiroAnimator(
4
)
turtle.onkey(spiroAnim.toggleTurtles,
"t"
)
turtle.onkey(spiroAnim.restart,
"space"
)
turtle.mainloop()
if
__name__
=
=
'__main__'
:
main()
Ausgabe:
Das obige Programm zeichnet 4 verschiedene Arten von Spirograph-Fraktalen, versucht andere Fraktale zu generieren und lädt dann Ihre Github-Links in den Kommentar hoch. Ich helfe Ihnen gerne weiter, wenn ein Fehler auftritt.
Dieser Artikel wurde von Subhajit Saha verfasst . Wenn Ihnen GeeksforGeeks gefällt und Sie einen Beitrag leisten möchten, können Sie auch einen Artikel mit Contrib.geeksforgeeks.org schreiben oder Ihren Artikel an Contribute@geeksforgeeks.org senden . Sehen Sie sich Ihren Artikel auf der GeeksforGeeks-Hauptseite an und helfen Sie anderen Geeks.
Bitte schreiben Sie Kommentare, wenn Sie etwas Falsches finden oder weitere Informationen zu dem oben diskutierten Thema teilen möchten.