Seite 1 von 2
Sierpinski-Kurve
Verfasst: Sonntag 20. Januar 2008, 13:16
von BeneCrack
Hallo Leute.
Ich muss bis nächste Woche ein Programm schreiben mit dem man eine Sierpinski Kurve zeichnen kann. Nur leider ist es so schwer dass ichs einfach nicht hin bekomme. Ich hab unter Wikipedia (
http://de.wikipedia.org/wiki/Sierpi%C5%84ski-Kurve) nach geschaut wie das ganze funktionieren soll. Dort is auch schon ein Beispiel in Java geschrieben.
Also hoffentlich könnt ihr mir helfen.
Bis jetzt hab ich nur dass zusammengebracht:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import Image
import ImageDraw
import random
import sys
class SierpinskiKurve:
global dist0
dist0 = 128
global dist
dist = 128
bild = "Kurve.pdf"
groesse = (800, 800)
global image
image = Image.new("1", groesse, color=255)
level = 3
def lineRel(deltaX, deltaY):
zahler = 0
if zahler == 0:
xx = 2 * dist
yy = dist
zahler = 1
x = 2 * dist
y = dist
draw = ImageDraw.Draw(image)
draw.line ( (x, y) , x + deltaX, y + deltaY )
xx += deltaX
yy += deltaY
def sierpA (level):
if (level > 0):
sierpA(level-1)
lineRel(+dist,+dist)
sierpB(level-1)
lineRel(+2*dist,0)
sierpD(level-1)
lineRel(+dist,-dist)
sierpA(level-1)
def sierpB (level):
if (level > 0):
sierpB(level-1)
lineRel(-dist,+dist)
sierpC(level-1)
lineRel(0,+2*dist)
sierpA(level-1)
lineRel(+dist,+dist)
sierpB(level-1)
def sierpC (level):
if (level > 0):
sierpC(level-1)
lineRel(-dist,-dist)
sierpD(level-1)
lineRel(-2*dist,0)
sierpB(level-1)
lineRel(-dist,+dist)
sierpC(level-1)
def sierpD (level):
if (level > 0):
sierpD(level-1)
lineRel(+dist,-dist)
sierpA(level-1)
lineRel(0,-2*dist)
sierpC(level-1)
lineRel(-dist,-dist)
sierpD(level-1)
dist = dist0
for i in range(0,level):
dist /= 2
sierpA(level)
lineRel(+dist,+dist)
sierpB(level)
lineRel(-dist,+dist)
sierpC(level)
lineRel(-dist,-dist)
sierpD(level)
lineRel(+dist,-dist)
image.save(bild)
print 'saved as: %s' % bild
sg.show()
bild = SierpinskiKurve()
Danke
Edit (Leonidas): Nikolas hat recht - Thread verschoben.
Verfasst: Sonntag 20. Januar 2008, 14:10
von BlackJack
Du solltest mit dem Python-Tutorial aus der Dokumentation anfangen und erst einmal Python lernen. Dieser Quelltext funktioniert ja nun *überhaupt nicht*. Das ist im Grunde nicht einmal Python sondern etwas das so ähnlich aussieht.
Ich habe auch so ein bisschen das Gefühl Du hast einfach etwas zusammen geschrieben und nicht nachgedacht. `lineRel()` enthält zum Beispiel solchen "
WTF?"-Code.
Da `lineRel()` über Aufrufe hinweg die jeweils letzten Koordinaten verwenden muss, musst Du die Grundlagen bis einschliesslich Objektorientierung (OOP), also eigene Klassen, drauf haben, bevor Du Dich an diese Aufgabe wagst. Das OOP liesse sich auf das Zeichen beschränken, indem man die Zeichenfläche, in diesem Fall das `Image` und die `lineRel()`-Methode in einem Objekt unterbringt. Diese Klasse entspräche dann von der Funktion her der `SimpleGraphics` von der Wikipedia-Seite. Der Rest liesse sich dann mit einfachen Funktionen umsetzen.
Ein Bitmap-Bild würde man übrigens eher als PNG speichern. PDF macht da nicht soviel Sinn und ich weiss auch gar nicht, ob PIL das von Haus aus auf jeder Plattform kann.
Verfasst: Sonntag 20. Januar 2008, 15:02
von BeneCrack
Ich hab eh schon vorher ein Programm mit zwei Klassen geschrieben, nur da waren noch mehr Fehlermeldungen drinn wie vorher. Ich hab wirklich keine Ahnung wie ich das bis nächste Wochhe DO programmiren soll. Python hab ich eh schon gelern nur mit dem PIL kenn ich mich nicht so ganz aus. Und PIL kann eh Bilder in PDF speichern, dass muss ich ja auch in meiner Aufgabe machen.
Kann mir keiner eine ungefähre Lösung posten wie ich das bewähltigen soll?
Ich bitte um Hilfe.
Verfasst: Sonntag 20. Januar 2008, 15:34
von BlackJack
Eine ungefähre Lösung hast Du schon. Du musst jetzt nur noch verstehen was die tut und Python lernen. Deine Probleme haben wenig bis gar nichts mit PIL zu tun. Das sind ganz fundamentale Fehler die Python-Grundlagen betreffen.
PIL kann auch Bilder als PNG speichern. Das ist wirklich ein besseres Format als PDF für simple schwarz/weisse *Pixel*-Grafiken.
Dir hier eine Lösung zu präsentieren ist keine Hilfe, weil Du dadurch nicht lernst wie man es selber macht.
Fang mit einzelnen Komponenten an und teste diese. Zum Beispiel erst einmal eine Klasse für die Grafik und entwickle dann Stück für Stück entweder eine Klasse oder eine Funktion welche die Sierpinski-Kurve zeichnet. Dabei sollte jeder Zwischenschritt fehlerfrei ausführbar sein. Ein dermassen fehlerbehafteter Quelltext, wie Du ihn im ersten Beitrag gezeigt hast, in ein funktionsfähiges Programm um zu wandeln, bringt nur Frust.
Verfasst: Sonntag 20. Januar 2008, 16:23
von Nikolas
Der Witz von Serpinksi ist doch die Rekursitivät. Und du schreibst nur was für die drei untersten Stufen...
schau dir mal die turtle-sprache an. Da ist diese Figur in unter 20 Zeilen wunderbar lösbar.
Verfasst: Sonntag 20. Januar 2008, 18:32
von BeneCrack
Hab wieder alles neue bearbeitet aber es kommen noch immer Fehlermeldungen und ich hab keine Ahneung wie ich es ausbessern soll oder woran es liegt könnt ihr mir bitte sagen was ich besser machen kann. BITTE
Hier ist der Source:
Code: Alles auswählen
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import Image
import ImageDraw
class SimpleGraphics:
groesse = (800, 800)
im = Image.new("1", groesse, color=255)
xx = 0
yy = 0
goToXY(x, y):
xx = x
yy = y
getImage():
return im
lineRel(deltaX, deltaY):
draw = ImageDraw.Draw(im)
draw.line((xx, yy), fill=128)
x += deltaX; y += deltaY;
class SierpinskiKurve:
dist0 = 128;
dist = 128;
level = 3
bild = "bild.bmp"
def sierpA (level):
if (level > 0):
sierpA(level-1)
SimpleGraphics.lineRel(+dist,+dist)
sierpB(level-1)
SimpleGraphics.lineRel(+2*dist,0)
sierpD(level-1)
SimpleGraphics.lineRel(+dist,-dist)
sierpA(level-1)
def sierpB (level):
if (level > 0):
sierpB(level-1)
SimpleGraphics.lineRel(-dist,+dist)
sierpC(level-1)
SimpleGraphics.lineRel(0,+2*dist)
sierpA(level-1)
SimpleGraphics.lineRel(+dist,+dist)
sierpB(level-1)
def sierpC (level):
if (level > 0):
sierpC(level-1)
SimpleGraphics.lineRel(-dist,-dist)
sierpD(level-1)
SimpleGraphics.lineRel(-2*dist,0)
sierpB(level-1)
SimpleGraphics.lineRel(-dist,+dist)
sierpC(level-1)
def sierpD (level):
if (level > 0):
sierpD(level-1)
SimpleGraphics.lineRel(+dist,-dist)
sierpA(level-1)
SimpleGraphics.lineRel(0,-2*dist)
sierpC(level-1)
SimpleGraphics.lineRel(-dist,-dist)
sierpD(level-1)
dist = dist0
for i in range(0,level):
dist /= 2
sierpA(level)
lineRel(+dist,+dist)
sierpB(level)
lineRel(-dist,+dist)
sierpC(level)
lineRel(-dist,-dist)
sierpD(level)
lineRel(+dist,-dist)
image = SimpleGraphics.getImage()
image.save(bild)
print 'saved as: %s' % bild
image.show()
Verfasst: Sonntag 20. Januar 2008, 18:35
von Leonidas
In den Zeilen 14, 18 und 21 fehlen die ``def``s. Ließ dir ein Tutorial zu OOP in Python durch, das was du machst wirst du nicht durch zusammenhacken von *irgendwas* lösen können.
Verfasst: Sonntag 20. Januar 2008, 18:37
von Nikolas
Vielleicht wäre der Thread auch besser bei den allgemeinen Fragen und nicht bei den ShowCases aufgehoben.
Verfasst: Sonntag 20. Januar 2008, 19:18
von BlackJack
@BeneCrack: Du musst die Hilfe aber auch annehmen. Nochmal: Python bis einschliesslich OOP lernen, dann das Programm Stückchen für Stückchen implementieren und immer testen statt einen grossen Quelltext zu schreiben, der vor Fehlern nur so strotzt.
Bevor Du nicht halbwegs sicher mit Klassen und Objekten umgehen kannst, brauchst Du mit der Aufgabe gar nicht erst anfangen.
Verfasst: Montag 21. Januar 2008, 19:30
von BlackJack
Das Programm von der Wikipediaseite in
FreeBASIC umgesetzt:
http://paste.pocoo.org/show/22789/
Die Funktionen habe ich durch "Steuerdaten" ersetzt. Würde ich bei einer Python-Lösung auch machen.
Verfasst: Montag 21. Januar 2008, 19:48
von SonGuko
wennde einen einfachen code für die sirpinskikurve haben willst, kann ich dir nur die seite von meinem infolehrer empfehlen ^^
http://www.g-ymnasium.de/?option=com_co ... &Itemid=55
Verfasst: Montag 21. Januar 2008, 20:21
von BeneCrack
OK, danke Leute, aber ich hab mich entschieden es selber zu machen und hab ma ein paar Tutorials angschaut. Ich hab es "besser" gemacht aber da kommt bei mir so eine Fehlermeldung in Zeile 21:
IndentationError: unindent does not match any outer indentation level
Code: Alles auswählen
class Sierpinski:
def __init__(self, size):
self.image = Image.new('1', size, color = 255)
self.draw = ImageDraw.Draw(self.image)
def save(self, filename):
self.image.save(filename)
print 'saved as: %s' % filename
return True
def show(self):
self.image.show()
return True
class SierKurve(Sierpinski):
thisX = 0
thisY = 0
def __init__(self, size):
Sierpinski.__init__(self, size)
def goToXY(self, x, y):
SierKurve.thisX = x
SierKurve.thisY = y
def lineRel(self, deltaX, deltaY):
c = canvas.canvas()
c.stroke(path.line(SierKurve.thisX, SierKurve.thisY, deltaX, deltaY))
SierKurve.thisX += deltaX
SierKurve.thisY += deltaY
class SierpinskiKurve(Sierpinski, SierKurve):
dist = 128
dist0 = 128
def __init__(self, size):
SierKurve.__init__(self, size)
def generate(self, level):
SierKurve.dist = SierKurve.dist0
for i in range(0,level):
SierKurve.dist /= 2
self.goToXY(2*SierpinskiKurve.dist,SierpinskiKurve.dist);
self.sierpA(level)
self.lineRel(+SierpinskiKurve.dist,+SierpinskiKurve.dist)
self.sierpB(level)
self.lineRel(-SierpinskiKurve.dist,+SierpinskiKurve.dist)
self.sierpC(level)
self.lineRel(-SierpinskiKurve.dist,-SierpinskiKurve.dist)
self.sierpD(level)
self.lineRel(+SierpinskiKurve.dist,-SierpinskiKurve.dist)
def sierpA (self, level):
if (level > 0):
self.sierpA(level-1)
self.lineRel(+SierpinskiKurve.dist,+SierpinskiKurve.dist)
self.sierpB(level-1)
self.lineRel(+2*SierpinskiKurve.dist,0)
self.sierpD(level-1)
self.lineRel(+SierpinskiKurve.dist,-SierpinskiKurve.dist)
self.sierpA(level-1)
def sierpB (self, level):
if (level > 0):
self.sierpB(level-1)
self.lineRel(-SierpinskiKurve.dist,+SierpinskiKurve.dist)
self.sierpC(level-1)
self.lineRel(0,+2*SierpinskiKurve.dist)
self.sierpA(level-1)
self.lineRel(+SierpinskiKurve.dist,+SierpinskiKurve.dist)
self.sierpB(level-1)
def sierpC (self, level):
if (level > 0):
self.sierpC(level-1)
self.lineRel(-SierpinskiKurve.dist,-SierpinskiKurve.dist)
self.sierpD(level-1)
self.lineRel(-2*SierpinskiKurve.dist,0)
self.sierpB(level-1)
self.lineRel(-SierpinskiKurve.dist,+SierpinskiKurve.dist)
self.sierpC(level-1)
def sierpD (self, level):
if (level > 0):
self.sierpD(level-1)
self.lineRel(+SierpinskiKurve.dist,-SierpinskiKurve.dist)
self.sierpA(level-1)
self.lineRel(0,-2*SierpinskiKurve.dist)
self.sierpC(level-1)
self.lineRel(-SierpinskiKurve.dist,-SierpinskiKurve.dist)
self.sierpD(level-1)
Könnt Ihr mir bitte sagen was das für ein Fehler ist, weil meines wissents hab ich da nichts falsch.
Verfasst: Montag 21. Januar 2008, 20:22
von BeneCrack
Sorry in Zeile 22.
Verfasst: Montag 21. Januar 2008, 21:32
von Nikolas
Da muss nicht unbedingt was falsch sein, könnte vlll auch am editor liegen. Lösch die zwei Zeilen kurz und schreib sei neu, oder schieb sie ganz nach links und rücke neu ein.
Warum hast du eigentlich immer noch das Sierpinkisky A bis D ? Da Ändern sich doch nur ein paar Faktoren, die du auch als argumente übergeben kannst.
Verfasst: Montag 21. Januar 2008, 21:38
von CM
Oder, ganz allgemein: Du hast eine Fehlermeldung? Wie lautet sie denn? Wie geht Dein Skript an der Stelle?
Verfasst: Montag 21. Januar 2008, 21:43
von Nikolas
Hat er doch geschrieben: Es war ein IndentFehler, daher macht sein Skript gar nichts, wenn der Fehler kommt

Verfasst: Dienstag 22. Januar 2008, 06:18
von BeneCrack
Hallo
Diese SierpA - B Funktionen hab ich desswegen weil ich diese Aufgabe
rekursiv lösen muss.

Verfasst: Dienstag 22. Januar 2008, 06:23
von BeneCrack
Ich hab jetzt die Zeile neu geschrieben (ganz links und dann eingerückt) und es kommt noch immer dieser Fehler.
Verfasst: Dienstag 22. Januar 2008, 08:32
von CM
Hoi,
ah, erst habe ich übersehen, wo der Fehler liegt. Aber schau doch mal auf die Position der 'def's, die dahinter folgen. Na? Liegen die alle an derselben Stelle? Am besten nimmst Du einen Editor, der Dir bei der Einrückung hilft. Wie schon gesagt: Wenn Du Tabs und Leerzeichen gemischt hast, kannst Du solche Fehler auch provozieren. Gute Editoren zeigen auf Wunsch auch an, ob Tabs oder Leerzeichen vorliegen und machen auch Korrekturen.
Gruß,
Christian
Verfasst: Dienstag 22. Januar 2008, 09:46
von BlackJack
@BeneCrack: Rekursiv lösen heisst nicht, dass man *vier* Funktionen braucht, das geht auch mit einer. Siehe das
BASIC-Beispiel. Die Regeln kann man auch in eine Datenstruktur stecken. Dann lässt sich der gleiche Code dazu nutzen mit anderen Regeln auch andere Kurven zu zeichnen.
Die Klassenaufteilung ist übrigens unsinnig. Am Ende landet doch alles in einer Klasse, warum sind das also drei "verschiedene"? Der Inhalt von `Sierpinski` und `SierKurve` sollte eine Klasse sein. Und da die nichts mit Sierpinski im besonderen zu tun hat, wäre ein allgemeinerer Name angebracht. `Canvas` zum Beispiel. Die unbedingten ``return True`` am Ende von `save()` und `show()` sind überflüssig und sollten weg fallen.
Dann sind die letzten Koordinaten Klassenattribute, wo sie besser Instanzattribute sein sollten. Auf `dist` und `dist0` sollte man auch besser über `self` zugreifen. Und wenn das Klassenkonstanten sein sollten, wäre komplette Grossschreibung der Namen eine gute Idee, um das deutlicher zu machen.
Der Inhalt von `SierpinskiKurve` braucht nicht in einer Klasse zu stecken. Hier reichen ganz normale Funktionen.