Problem beim Lösen einer Aufgabe [Fraktale]
lima-city → Forum → Programmiersprachen → C/C++ und D
algorithmus
aufruf
auszug
berechnen
bestimmte schranke
break
code
double
ergebnis
eventuelle hilfen
formel
komplexe zahlen
leitung
message
multiplikation
pos
position
punkt
vektor
zahl
-
Hi,
vor kurzem habe ich eine Aufgabe bekommen, es geht um Fraktale. Ich hab hier mal den Auszug aus dem Skript:
http://zyclop.zy.funpic.de/member/Skript_Aufgaben_PP_Teil3b_20061111.pdf
und hier mal meinen ersten Lösungsansatz:
#include <stdio.h> #include <stdlib.h> #include <math.h> int main(int argc, char *argv[]) { double z,c,x,y; z = 0; x = 1.5; y = 1.0; while(z < 2) { c = sqrt((x*x)+(y*y)); z = (z*z)+c; printf(\"\\n%f\",z); } getch(); }
Ich steh irgendwie auf der Leitung und hab keine Ahnung, was ich machen muss
es geht ausschließlich um den Algorithmus, die grafische Ausgabe ist erst mal unwichtig.
die zahlen für x und y habe ich mal so aus einer Beispiel Rechnung aus dem Unterricht übernommen.
Hier die Formel für komplexe Zahlen, für den Fall das sie einer nicht kennt:
z = x+j*y bzw. z = a+j*b
|z| = sqrt((x*x)+(y*y)) bzw. |z| = sqrt((a*a)+(b*b))
Ich danke schon mal für eventuelle Hilfen ^^
---zyclop
Beitrag geändert: 8.1.2008 9:03:42 von zyclop -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Hallo,
die Mandelbrotmenge ist nach deinem Skript definiert als die Menge der komplexen Zahlen c für die die Folge
z_n+1 = z_n^2 + c
mit z_0 = 0
konvergiert.
Da man nicht unendlich viele Folgenglieder berechnen kann, sagt man: 1. \"Wenn eine bestimmte Schranke (in deinem Fall 2) überschritten wird, bereche die Iteration ab und liefere das Ergebnis: Der Punkt gehört nicht zur Mandelbrotmenge\"
2. \"Wenn eine Anzahl von Iterationen erreicht wurden und liefere das Ergebnis: Der Punkt gehört zur Mandelbrotmenge\"
Punkt 2 fehlt bei dir.
Dann hast du die Formel
z_n+1 = z_n^2 + c
das sind komplexe Zahlen, du musst also schon die Rechenregeln für komplexe Zahlen benutzen!!!
Ich schreibe die komplexe Zahlen jetzt mal als Zahlenpaar:
z = x + iy = (x,y)
Addition: (x,y) + (u,v) = (x + u, y + v) [wie Vektoren]
Multiplikation: (x,y) * (u,v) = (u x - v y, v x + u y)
Sei z = (z_x, z_y) und c = (c_x, c_y)
dann haben wir:
(ungetestet).z_x = 0; z_y = 0; c_x = 1.5; c_y = 1.0; while (sqrt(z_x * z_x + z_y * z_y) < 2) { //das kann man optimieren zu z_x * z_x + z_y * z_y < 4 x = z_x * z_x - z_y * z_y; z_y = 2 * z_x * z_y; z_x = x + c_x; z_y = z_y + c_y; printf(...) }
du solltest noch eine Abbruchbedingung einfügen, z. B. dass er die Schleife nur 300 mal durchläuft. Sonst hast du eine Endlosschleife, wenn der Punkt zur Mandelbrotmenge gehört!!!
Beitrag geändert: 9.1.2008 22:40:37 von cga -
also ich hab den Algorithmus voll funktionsfähig und getestet... So ist es auch gemeint vom Lehrer:
/* fract.h */ int fract(double x0, double y0) { double x,y,z,tmpx; int j = 0; x = x0; y = y0; while((x*x + y*y) < 4 && j < 255) { tmpx = ((x*x)-(y*y))+x0; y = (2*x*y)+y0; x = tmpx; j++; } return j; }
/* draw.h */ void draw(HWND hwnd, RECT rect) { HDC hdc = GetDC(hwnd); int x,y,j,iterationen; double x0,y0; COLORREF col[256]; for(j = 0; j < 256; j++) { col[j] = RGB(j+20,(int)(j*0.8)+20,(int)(j*0.2)+20); } col[255] = RGB(0,0,0); for(y = 1; y < rect.bottom; y++) { for(x = 1; x < rect.right; x++) { //x0 = ((double) ((x+190)*3) / (double) (rect.right-rect.left)) - 2; //mit verschiebung //x0 = ((double) (x*3*0.5) / (double) (rect.right-rect.left)) - 2; //mit zoom x0 = ((double) (x*3) / (double) (rect.right-rect.left)) - 2; y0 = ((double) (y*2) / (double) (rect.bottom-rect.top)) - 1; iterationen = fract(x0,y0); SetPixel(hdc, x, y, col[iterationen]); } } ReleaseDC(hwnd, hdc); }
Soooo jetzt hab ich noch das problem, dass bei einem Linksklick reingezoomt werden soll und bei einem Rechtsklick raus... So sieht meine FensterProzedur gerade aus:
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { RECT rect; PAINTSTRUCT ps; POINT pos; switch (message) /* handle the messages */ { case WM_DESTROY: PostQuitMessage (0); /* send a WM_QUIT to the message queue */ break; case WM_PAINT: GetClientRect(hwnd, &rect); BeginPaint(hwnd, &ps); draw(hwnd, rect); EndPaint(hwnd, &ps); break; case WM_LBUTTONUP: GetCursorPos(&pos); // Hier weiß ich nicht wie ich den Zoom // und die Maus-Position an WM_Paint übergebe break; default: /* for messages that we don\'t deal with */ return DefWindowProc (hwnd, message, wParam, lParam); } return 0; }
Wenn ich bei \"case WM_LBUTTONUP\" die draw-Funktion aufrufe überschreib er mir mein neuerstelltes Bild sofort wieder wegen \"WM_PAINT\" und ich hab wieder den Ursprung!
Beitrag geändert: 9.1.2008 21:11:23 von zyclop -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage