koch linie problem

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Antworten
lukas.s
Beiträge: 17
Registriert: Do 19. Mai 2011, 15:45

koch linie problem

Beitrag von lukas.s »

hallo,

ich bin gerade dabei einen kochlinien generator zu schreiben, nur leider komm ich bei einem problem nicht weiter.

ich vermute es liegt an meinen mangelnden fähigkeiten was geometrie angeht. wäre super wenn einer von euch mir kurz auf die sprünge helfen kann.

anscheinend berechne ich den punkt D (die neue spitze) nicht richtig,...

hier mal der code:

Code: Alles auswählen

...
type
  { TExtendedPoint }
  TExtendedPoint = record
    X, Y: Extended;
  end;
...
 
...
procedure TForm1.kochLinie(iterationstiefe: Integer; A, B: TExtendedPoint; myCanvas: TCanvas);
var
  C, D, E: TExtendedPoint;
  alpha, laenge: Extended;
begin
  if iterationstiefe > 0 then
  begin
    alpha:=arctan((B.X-A.X)/(B.Y-A.Y))+pi/3;
    C.X:=A.X+((B.X-A.X)/3);
    C.Y:=A.Y+((B.Y-A.Y)/3);
    E.X:=A.X+(2*(B.X-A.X)/3);
    E.Y:=A.Y+(2*(B.Y-A.Y)/3);
    laenge:=-1*sqrt((C.X-A.X)*(C.X-A.X) + (C.Y-A.Y)*(C.Y-A.Y));
    D.X:=C.X+cos(alpha)*laenge;
    D.Y:=C.Y+sin(alpha)*laenge;
 
 
    kochLinie(iterationstiefe-1, A, C, myCanvas);
    kochLinie(iterationstiefe-1, C, D, myCanvas);
    kochLinie(iterationstiefe-1, D, E, myCanvas);
    kochLinie(iterationstiefe-1, E, B, myCanvas);
  end
  else
  begin
    myCanvas.Line(Round(A.X), Round(A.Y), Round(B.X), Round(B.Y));
  end;
end;
 
...

A und B sind die beiden endpunkte der linie,
C der +60° knick
D der -120° knick
und
E der 2te +60° knick

in etwa so sollte es aussehen:

Code: Alles auswählen

.              D
.            /   \
.           /     \
.A--------C         E---------B
.


und in etwa so sieht es leider aus:

Code: Alles auswählen

.               D
.             /  |
.            /   |
.A--------C       E---------B
.



zur koch kurve: http://de.wikipedia.org/wiki/Koch-Kurve

vielen dank schon im vorraus!!
lgl

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: koch linie problem

Beitrag von Heinrich Wolf »

Hallo,

Code: Alles auswählen

...
type
{ TExtendedPoint }
TExtendedPoint = record
X, Y: Extended;
end;
...
 
...
procedure TForm1.kochLinie(iterationstiefe: Integer; A, B: TExtendedPoint; myCanvas: TCanvas);
var
C, D, E: TExtendedPoint;
alpha, laenge: Extended;
begin
if iterationstiefe > 0 then
begin
alpha:=arctan((B.X-A.X)/(B.Y-A.Y))+pi/3; // Hier musst Du x mit y vertauschen, wenn ich nicht irre.
C.X:=A.X+((B.X-A.X)/3);
C.Y:=A.Y+((B.Y-A.Y)/3);
E.X:=A.X+(2*(B.X-A.X)/3);
E.Y:=A.Y+(2*(B.Y-A.Y)/3);
laenge:=-1*sqrt((C.X-A.X)*(C.X-A.X) + (C.Y-A.Y)*(C.Y-A.Y));
// Das Minus hast Du wohl spendiert, weil y im Canvas nach unten zeigt. Ich würde es aus mathematischer Logik bei Line() einbauen.
D.X:=C.X+cos(alpha)*laenge;
D.Y:=C.Y+sin(alpha)*laenge;
 
 
kochLinie(iterationstiefe-1, A, C, myCanvas);
kochLinie(iterationstiefe-1, C, D, myCanvas);
kochLinie(iterationstiefe-1, D, E, myCanvas);
kochLinie(iterationstiefe-1, E, B, myCanvas);
end
else
begin
myCanvas.Line(Round(A.X), Round(A.Y), Round(B.X), Round(B.Y));
end;
end;
 
...


Heiner

Tut mir leid, dass das Einrücken verloren gegangen ist! Ich hab erst Antworten, dann Zitieren geklickt und nicht gleich Zitieren. Das ist ein Bug im Forum.

lukas.s
Beiträge: 17
Registriert: Do 19. Mai 2011, 15:45

Re: koch linie problem

Beitrag von lukas.s »

hallo,

vielen dank!!!

ich war am verzweifeln ;)

jetzt funktioniert es ersmal (dacht ich zumindest) aber ab der dritten iterationstufe schleicht sich ein fehler ein.

das ergebnis sieht erstmal so aus (wie das bild im anhang)

ich werde versuchen den fehler noch zu finden, falls es jemand aus dem stehgreif wissen sollte woran das liegt wäre ich natürlich wieder für einen tip sehr dankbar.

lgl

EDIT:
anstatt 2mal der ersten wollte ich natürlich einmal die 0te und einmal die erste ins bild einfügen,... :roll:
Dateianhänge
koch_fehler.png

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: koch linie problem

Beitrag von Heinrich Wolf »

lukas.s hat geschrieben:jetzt funktioniert es ersmal (dacht ich zumindest) aber ab der dritten iterationstufe schleicht sich ein fehler ein.

das ergebnis sieht erstmal so aus (wie das bild im anhang)

Das Problem liegt nochmal beim arctan. Du musst arctan2 verwenden, weil arctan nur einen halben und nicht den ganzen Kreis abdeckt. Schau Dir bitte die Übergabeparameter genau an. x und y werden separat übergeben, nicht verwechseln! Du musst nicht teilen. Damit hast Du auch kein Problem mit Division durch 0 mehr.

Heiner

lukas.s
Beiträge: 17
Registriert: Do 19. Mai 2011, 15:45

Re: koch linie problem

Beitrag von lukas.s »

Heinrich Wolf hat geschrieben:
lukas.s hat geschrieben:jetzt funktioniert es ersmal (dacht ich zumindest) aber ab der dritten iterationstufe schleicht sich ein fehler ein.

das ergebnis sieht erstmal so aus (wie das bild im anhang)

Das Problem liegt nochmal beim arctan. Du musst arctan2 verwenden, weil arctan nur einen halben und nicht den ganzen Kreis abdeckt. Schau Dir bitte die Übergabeparameter genau an. x und y werden separat übergeben, nicht verwechseln! Du musst nicht teilen. Damit hast Du auch kein Problem mit Division durch 0 mehr.

Heiner


ok, danke nochmals für den tipp!
mein ansatz ging eh in die gleiche richtung,...
ich wollte es einfach mit abfrage erledigen, habe nicht gewusst, dass es eine arctan2 funktion gibt welche den richtigen radianten liefert! DANKE.

für alle die es vielleicht auch iwann mal brauchen ist hier nochmal der funktionierende code:

Code: Alles auswählen

procedure TForm1.kochLinie(iterationstiefe: Integer; A, B: TExtendedPoint; myCanvas: TCanvas);
var
  C, D, E: TExtendedPoint;
  alpha, laenge: Extended;
begin
  if iterationstiefe > 0 then
  begin
 
    alpha:=arctan2((B.Y-A.Y), (B.X-A.X))+pi/3;
    C.X:=A.X+((B.X-A.X)/3);
    C.Y:=A.Y+((B.Y-A.Y)/3);
    E.X:=A.X+(2*(B.X-A.X)/3);
    E.Y:=A.Y+(2*(B.Y-A.Y)/3);
    laenge:=sqrt((C.X-A.X)*(C.X-A.X) + (C.Y-A.Y)*(C.Y-A.Y));
    D.X:=C.X+cos(alpha)*laenge;
    D.Y:=C.Y+sin(alpha)*laenge;
 
    kochLinie(iterationstiefe-1, A, C, myCanvas);
    kochLinie(iterationstiefe-1, C, D, myCanvas);
    kochLinie(iterationstiefe-1, D, E, myCanvas);
    kochLinie(iterationstiefe-1, E, B, myCanvas);
 
  end
  else
  begin
    myCanvas.Line(Round(A.X), myCanvas.Height-Round(A.Y), Round(B.X), myCanvas.Height-Round(B.Y));
  end;
end;

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: koch linie problem

Beitrag von Heinrich Wolf »

Das macht Spaß, solche rekursiven Kurven zu malen. Hier noch ein paar Anregungen.

Heiner
Dateianhänge
Hilbert Kurven
Hilbert Kurven
hilbert.png (4.93 KiB) 1914 mal betrachtet
w.png
w.png (5.82 KiB) 1925 mal betrachtet
Herz.png
Herz.png (7.2 KiB) 1925 mal betrachtet
Sierpinski Kurven
Sierpinski Kurven
sierpinski.png (7.28 KiB) 1925 mal betrachtet
Zuletzt geändert von Heinrich Wolf am So 26. Aug 2012, 11:53, insgesamt 1-mal geändert.

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: koch linie problem

Beitrag von Heinrich Wolf »

Code: Alles auswählen

procedure TForm1.kochLinie(iterationstiefe: Integer; A, B: TExtendedPoint; myCanvas: TCanvas);
var
  C, D, E: TExtendedPoint;
  alpha, laenge: Extended;
begin
  if iterationstiefe > 0 then
  begin
 
    alpha:=arctan2((B.Y-A.Y), (B.X-A.X))+pi/3;
    C.X:=A.X+((B.X-A.X)/3);
    C.Y:=A.Y+((B.Y-A.Y)/3);
    E.X:=A.X+(2*(B.X-A.X)/3);
    E.Y:=A.Y+(2*(B.Y-A.Y)/3);
    //laenge:=sqrt((C.X-A.X)*(C.X-A.X) + (C.Y-A.Y)*(C.Y-A.Y)); Es gibt auch eine sqr Funktion
    laenge:=sqrt(sqr(C.X-A.X) + sqr(C.Y-A.Y));
    D.X:=C.X+cos(alpha)*laenge;
    D.Y:=C.Y+sin(alpha)*laenge;
 
    kochLinie(iterationstiefe-1, A, C, myCanvas);
    kochLinie(iterationstiefe-1, C, D, myCanvas);
    kochLinie(iterationstiefe-1, D, E, myCanvas);
    kochLinie(iterationstiefe-1, E, B, myCanvas);
 
  end
  else
  begin
    myCanvas.Line(Round(A.X), myCanvas.Height-Round(A.Y), Round(B.X), myCanvas.Height-Round(B.Y));
  end;
end;

lukas.s
Beiträge: 17
Registriert: Do 19. Mai 2011, 15:45

Re: koch linie problem

Beitrag von lukas.s »

Heinrich Wolf hat geschrieben:Das macht Spaß, solche rekursiven Kurven zu malen. Hier noch ein paar Anregungen.

Heiner

das ist wahr!

ich hänge mal mein kleines projekt an.

ein paar sachen hab ich schon, z.b. sierpinski dreieck, kochkurve, drachenkurve (naja, eigentlich erst die 3)
aber es sollen mehr werden.

vielen dank für deine hilfe!

lgl
Dateianhänge
fraktal.zip
(4.08 MiB) 92-mal heruntergeladen

Antworten