Auf geht's, Ihr feigen Hunde!

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • RE: Auf geht's, Ihr feigen Hunde!

    Ok, dann traue ich mich mal. Der Code ist nicht perfekt, es ist eigentlich nur der Anfang, aber in der letzten und in der nächsten Zeit habe ich irre viel in der Schule zu tun (LateinSA heute, EnglischSA Montag, dann noch PhysikSA und ChemieSA...)

    Also, mein Code beschränkt sich zur Zeit auf eine Klasse, genauer eine Subklasse von NSView. Ich hoffe, er ist nicht zu unleserlich und ich hoffe, dass ihr nichts gegen mein Lieblingsspielzeug, den Precompiler habt. Hier ist der Code:

    Quellcode

    1. #import <AppKit/AppKit.h>
    2. #import <CoreGraphics/CoreGraphics.h>
    3. @interface AppleMan : NSView
    4. {
    5. double zoom_faktor;
    6. float imageHeight, imageWidth;
    7. unsigned short iterationen;
    8. NSPoint center;
    9. NSBitmapImageRep *imageRep;
    10. }
    11. - (void)getColor:(struct PointColor*)anColor forPoint:(NSPoint)point;
    12. - (NSImageRep*)fraktRep;@end
    Alles anzeigen
    und die Implementation-Datei:

    Quellcode

    1. #import "AppleMan.h"
    2. #define BLACK {0x00, 0xff, 0xff}
    3. #define NEW_POOL NSAutoreleasePool *anAutoreleasePool = [[NSAutoreleasePool alloc] init]
    4. #define DEL_POOL [anAutoreleasePool release]
    5. #define KOMMENTAR 0
    6. #define TEST 0
    7. #define NSLOG 1
    8. struct PointColor {
    9. unsigned char red;
    10. unsigned char blue;
    11. unsigned char green;
    12. };
    13. struct ComplexNumber {
    14. long double real;
    15. long double immaginaer;
    16. };
    17. @implementation AppleMan
    18. - (id)initWithFrame:(NSRect)frameRect
    19. {
    20. if ((self = [super initWithFrame:frameRect]) != nil) {
    21. zoom_faktor = 100.0;
    22. iterationen = 150;
    23. imageHeight = [self bounds].size.height, imageWidth = [self bounds].size.width;
    24. center = NSZeroPoint;
    25. center.x = -50.0;
    26. }
    27. return self;
    28. }
    29. - (void)awakeFromNib {
    30. [[self window] useOptimizedDrawing:YES];
    31. NEW_POOL;
    32. imageRep = [[self fraktRep] retain];
    33. DEL_POOL;
    34. }
    35. - (void)dealloc {
    36. [imageRep release];
    37. [super dealloc];
    38. }
    39. - (void)mouseDown:(NSEvent*)event {
    40. NSPoint mousePoint;
    41. imageHeight = [self bounds].size.height, imageWidth = [self bounds].size.width;
    42. mousePoint = [event locationInWindow];
    43. if ([event modifierFlags] & NSAlternateKeyMask) {
    44. if (zoom_faktor < 0.01) {
    45. NSBeep();
    46. }
    47. else
    48. zoom_faktor /= 2.0;
    49. }
    50. else {
    51. zoom_faktor *= 2.0;
    52. }
    53. [imageRep release];
    54. NEW_POOL;
    55. imageRep = [[self fraktRep] retain];
    56. DEL_POOL;
    57. [self setNeedsDisplay:YES];
    58. }
    59. - (void)drawRect:(NSRect)rect {
    60. NSRect imageRect;
    61. imageRect.size = [imageRep size];
    62. imageRect.origin = NSZeroPoint;
    63. [imageRep drawInRect:imageRect];
    64. }
    65. - (NSImageRep*)fraktRep {
    66. NSDate *zeit = [NSDate date];
    67. #if NSLOG
    68. NSLog(@"Beginn");
    69. #endif
    70. struct PointColor color = BLACK;
    71. int x, y;
    72. NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
    73. pixelsWide:imageWidth
    74. pixelsHigh:imageHeight
    75. bitsPerSample:8
    76. samplesPerPixel:3
    77. hasAlpha:NO
    78. isPlanar:NO
    79. colorSpaceName:NSDeviceRGBColorSpace
    80. bytesPerRow:0
    81. bitsPerPixel:0];
    82. unsigned char* pixels = [bitmap bitmapData];
    83. for (y = 0; y < imageHeight; y++) {
    84. for (x = 0; x < imageWidth; x++) {
    85. [self getColor:&color forPoint:NSMakePoint(x, y)];
    86. *pixels++ = color.red;
    87. *pixels++ = color.blue;
    88. *pixels++ = color.green;
    89. }
    90. }
    91. #if NSLOG
    92. NSLog(@"Zeit gebraucht: %f Sekunden bei Zoom: %f", [zeit timeIntervalSinceNow]*(-1), zoom_faktor);
    93. #endif
    94. return [bitmap autorelease];
    95. }
    96. - (void)getColor:(struct PointColor*)anColor forPoint:(NSPoint)point {
    97. int b;
    98. int genauigkeit = 50;
    99. struct ComplexNumber c, z, z1;
    100. double colorNum;
    101. struct PointColor result;
    102. c.real= (point.x - imageWidth/2.0 + center.x) / zoom_faktor;
    103. c.immaginaer = (point.y - imageHeight/2.0 + center.y) / zoom_faktor;
    104. if (zoom_faktor < 100)
    105. genauigkeit = 500.0/zoom_faktor; //You need this, because else the Area around the Figur will be black
    106. if ((c.real > -1.2) && (c.real < 0.3) && (c.immaginaer > -0.6) && (c.immaginaer < 0.6)) {
    107. /*Dieser Teil wird aufgerufen, um den Mittelpunkt des Mandelbrotes gleich Schwarz
    108. auszufüllen und nicht alles auszurechnen. Das ist zwar nicht mathematisch korrekt,
    109. bringt aber eine große Steigerung in der Performance, vor allem bei Zoom um 200 rum.
    110. Zum Teil ist dann das Berechnen von mehr Details schneller als von weniger.*/
    111. if ((c.real > -0.5) && (c.real < 0.25) && (c.immaginaer > -0.5) && (c.immaginaer < 0.5)) {
    112. result.red = 0x00;
    113. result.blue = 0x00;
    114. result.green = 0x00;
    115. *anColor = result;
    116. return;
    117. }
    118. else if ((c.real > - 1.15) && (c.real < -0.84) && (c.immaginaer > -0.2) && (c.immaginaer < 0.2)) {
    119. result.red = 0x00;
    120. result.blue = 0x00;
    121. result.green = 0x00;
    122. *anColor = result;
    123. return;
    124. }
    125. }
    126. z1.real = 0.0;
    127. z1.immaginaer = 0.0;
    128. for (b = 0; (b < iterationen) && !(abs(z1.real) > genauigkeit || abs(z1.immaginaer) > genauigkeit); b++) {
    129. z.real = z1.real;
    130. z.immaginaer = z1.immaginaer;
    131. z1.real = z.real * z.real - z.immaginaer * z.immaginaer + c.real;
    132. z1.immaginaer = 2 * z.real * z.immaginaer + c.immaginaer;
    133. }
    134. if (b == 150) {
    135. result.red = 0x00;
    136. result.green = 0x00;
    137. result.blue = 0x00;
    138. *anColor = result;
    139. return;
    140. }
    141. colorNum = 1.0 - (b % 50) / 50.0;
    142. result.red = (unsigned)256 * colorNum;
    143. result.green = (unsigned)256 * colorNum;
    144. result.blue = (unsigned)256 * colorNum;
    145. *anColor = result;
    146. }
    147. - (BOOL)isOpaque {
    148. return YES;
    149. }
    150. @end
    Alles anzeigen

    Das war es auch schon. Es gibt natürlich noch einige Fehler, aber das ist ja auch Sinn und Zweck des "Coding Contest".
    Folgende sind mir bekannt:
    Es ist egal, wohin man mit der Maus hinklickt, es ändert am Ergebniss nichts; es wird nämlich immer des gleiche Punkt in der Mitte Mittelpunkt bleiben, ein Klicken ändert nur den Zoomfaktor.
    Auch ist eine resizing der View noch nicht sinnvoll, da sie immer neu gezeichnet werden würde.
    Auch gibt es noch keine Farben innerhalb des Mandelbrotes.

    Und, was haltet ihr von meiner Arbeit? (Ach, wenn ihr euch wundert, wieso die Klasse AppleMan heißt, folgendes: Ich weiß nicht, wie eine Verniedlichung von Mann im Englischen gebildet wird...)
    There are 10 kinds of people in the world - those who understand binary
    and those who don't.
  • RE: Auf geht's, Ihr feigen Hunde!

    Original von Squart
    Ok, dann traue ich mich mal.


    Super! Ein mutiger hat sich gefunden ;-)

    Ist ja allerhand in dem Code drinn. Muß man sich erst mal in Ruhe anschauen. Aber könntest Du das vielleicht noch als Xcode Projekt hochladen? Dann hat man es etwas einfacher da durchzugehen.

    Ciao, t.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • ich kann das app nicht starten. ich bekomme folgende meldung:

    Quellcode

    1. [Session started at 2004-12-10 15:20:23 +0100.]
    2. dyld: /Users/sascha/Desktop/Apfelmann/build/Apfelmann.app/Contents/MacOS/Apfelmann bad CPU subtype in object file image: /Users/sascha/Desktop/Apfelmann/build/Apfelmann.app/Contents/MacOS/Apfelmann
    3. Executable “Apfelmann” has exited due to signal 5 (SIGTRAP).


    sascha
  • Tschuldiggung...

    ...ich glaube, da habe ich unter anderem an den Compilereinstellungen etwas rumgespielt (auf den G5 optimiert,etc.). Habe jetzt noch mal ein neues Projekt angelegt und ein kleines bisschen aufgeräumt, ich hoffe, dass man es jetzt compilieren kann.
    There are 10 kinds of people in the world - those who understand binary
    and those who don't.
  • Also, ich lass jetzt gleich mal was los zu dem Beispiel von Squart.
    Konnte mir bis jetzt nur den geposteten Code anschauen.

    Zwei Dinge sind mir aufgefallen, wahrscheinlich, weil ich das so gemacht habe.

    Zeile 101: das NSMakeRect koennte man weg optimieren indem man vorher ein Rect anlegt und nur noch die Location des Rects aendert, dann braucht nicht jedesmal ein neues erzeugt werden.

    Zeile 128 - 148: wenn eine man sich den letzten Iterationwert merkt, und es kommt beim naechsten mal der selbe raus, braucht die Farbe nicht neu gesetzt werden, fuer grosse Flaechen mit der gleichen Farbe bringt das einiges.


    so long.
  • RE: Auf geht's, Ihr feigen Hunde!

    Danke Squart. Mit einem Xcode Projekt läßt sich umfangreicherer Code einfach besser durchgehen.

    Ich poste jetzt einfach mal meine Version dagegen.

    Ist im Laufe der Zeit etwas im Funktionsumfang angewachsen, und ich bin gerade zu faul, um das entsprechend der ursprünglichen Zielsetzung jetzt wieder für eine Demo runterzubrechen. Hoffe, daß ist ok.

    Die Goodies:

    - Farbe.
    - Wertebereich und maximale Iteration können per Hand eingegeben werden.
    - Inkrementelle Darstellung während der Berechnung.
    - Zoom in einen Auswahlbereich mit der Maus.
    - Das Fractal läßt sich als tiff abspeichern.

    Zur Darstellung wird ein CGImage verwendet. Der Code ist Stellenweise etwas konfus und nicht ganz sauber programmiert... Seht selbst.

    t.

    PS: Die Optimierungseinstellungen -zerolink -O0 und -mtune=970 -mcpu=970 etc. machen zusammen nicht allzuviel Sinn, aber um den G5 beneide ich Dich schon...
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • RE: Auf geht's, Ihr feigen Hunde!

    Original von tsunamix
    ...PS: Die Optimierungseinstellungen -zerolink -O0 und -mtune=970 -mcpu=970 etc. machen zusammen nicht allzuviel Sinn, aber um den G5 beneide ich Dich schon...
    Jepp, die für den G5-Spezifischen Optimiungseinstellungen habe ich wieder verworfen, als ich die Performance auf einem alten (alten) iMac mit 400 Mhz testen wollte. Aber auf dem habe ich es nicht compiliert, sondern nur getestet. Deshalb dachte ich, es liegt vielleicht daran, da dies meine ersten wirklichen Erfahrungen mit den Compilereinstellungen waren.
    There are 10 kinds of people in the world - those who understand binary
    and those who don't.
  • RE: Auf geht's, Ihr feigen Hunde!

    Habe es mir eben angeschaut:
    Wahnsinn. Ich muss mir nachher noch den Code anschauen (hab jetzt kaum Zeit). Schade dass es verzerrt ist, aber das ist auch das Einzige, was ich bemängeln kann. Das geht ja super flott und ausserdem noch mit diesem stück für Stück Zeichen-Effekt - super!
    There are 10 kinds of people in the world - those who understand binary
    and those who don't.
  • RE: Auf geht's, Ihr feigen Hunde!

    Also hier ist auch meine Version. Sie unterscheidet sich weniger von den euren, aber ich habe noch Sachen wie Bindings verwendet. Features sind kaum mehr drin, aber irgendwann hatte ich dann einfach aufgehört. Zu verbessern wäre noch:

    - die Performance der Berechnungen
    - die Zuweisungen der Farben (_sehr_ langsam das ganze)
    - optimierung der speicherung der farben
    - eine zoom-out funktion
    - speichern-funktionen für shoots und koordinatensetups

    Viel spaß beim zerreißen ;)

    max
  • RE: Auf geht's, Ihr feigen Hunde!

    Ich hatte die Diskussion nach den ersten Vorstellungen auch lebhafter erwartet. Aber ich bin ja selber bisher mit Komentaren zu anderen Lösungen auch schweigsam gewesen.

    Das liegt hauptsächlich daran, daß es doch recht mühsam ist, sich erst mal durch den Code anderer Leute zu friemeln, um ihn einigermaßen zu verstehen, besonders da da ja schon einiges an Features drin ist. Wenn mal selber gerade frisch am schreiben ist, ist es viel einfacher zu verstehen, was man wo warum macht.

    Zu MAX' Version kann ich aber schon mal mehr allgemein als en detail ein bißchen Senf dazu geben:

    Die Performance scheint mir gar nicht mal so schlecht zu sein. Ich hätte CGDrawRect als 'Pixelierungsmethode' schlechter erwartet.

    Performancetechnisch fallen mir ein paar Nickerigkeiten ein. In der Funktion calculateImage machst Du zu oft zu viele malloc calls. Würde da nicht ein einzelner Speicherblock (1mal malloc) reichen? (Man müßte mal genau messen, wie teuer diese Aufrufe tatsächlich sind.) Die Referenzierung der Elemente in _pixels müßte dann natürlich anders aussehen und wohl über Offsets gehen. Außerdem hast Du da wohl ein Speicherleck. Das Array ist doch zweidimensional. Du sagst zwar free(_pixels), vergißt aber anscheinend die darin enthaltenen Elemente auch wieder zu löschen. Böse, böse ;-)

    Vom Prinzip her eigentlich ganz gut, die C-Kernfunktionen in ein anderes Modul auszulagern, wenn Du sie aber in das Modul MandelbrotView reinnimmst und sie als static deklarierst (denn nur da werden sie verwendet), dann kann der Kompiler bei höherem O-Flag entscheiden, sie inline zu nehmen, und damit evtl. eine Menge optimieren. In der iterate-Funktion würde ich eine do-while-Schleife vorziehen. Das spart zu mindest pro Funktionsaufruf eine Konditionsabfrage. Wäre mal interessant auszumessen, ob und wie der Unterschied dann wäre.

    Interessant ist der Ansatz Farben ohne komplette Neuberechnung der Mandelbrotmenge, bzw. der Iterationen, ändern zu können. Ich bin allerdings noch nicht ganz durchgestiegen, wie Du das im Detail genau machst.

    Das GUI ist auch schon ganz nett. Das mit der Farbauswahl gefällt mir (vom Prinzip). Hat mich bei meiner Weiterentwicklung inspiriert. Es stört mich allerdings, daß Du die Farbe für die Mandelbrotmenge nicht separat behandelst. Traditionell ist das Apfelmännchen schwarz. Sollte es m.M. zumindest in der Grundeinstellung sein.

    So das waren jetzt ein paar erste Gedanken.

    t.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • Joo, das Teil von M.A.X. ist ja echt verdammt flott.
    Da kann ich bei weitem nicht mithalten.
    Ueberhaupt ist das ziemlich gelungen muss ich sagen.

    Hier ist nun meine Version auch mal. Mein erster Kontakt mit Mac und Graphik-Programmierung. Ich hab mich beschraekt auf CoreGraphics (muesste doch dann Quartz sein, oder? ).
    Und hier male ich auch nur Rechtecke, bearbeite also keine Pixeldaten. Alleine daher sollte es schonmal langsamer sein.
    Den Zoom muss man ueber x Inc und y Inc eingeben, wobei hier ein Wert gereicht haette, der sollte ja immer fuer beide gleich sein.
    Bin damit aber noch nicht ganz zufriden, weil das Bild immer woanders hin verschwindet, wenn ich andere Eingaben mache.
    Farbe hab ich auch keine, wobei das nicht so tragisch ist, in grau gefaellt mir das eigentlich doch ganz gut.

    Naja, schauts Euch an.
  • Ich sagte ja, ich hab eingfach irgendwann aufgehört ;)

    Aber danke für das Lob. Ich hatte den Code ausgelagert mit der option, ihn vielleicht in Assembler neu zu schreiben - müsste man sehen, inwiefern das sinnvoll ist. Das mit den farben ist recht einfach. Ich hab einfach die werte für die Pixel aufgehoben und dann in einer funktion diese so umgerechnet, dass man sie in ne BitmapRep schreiben kann. Mir gefällt an dem Projekt so einiges nicht, aber man muss ja nicht nur schlecht reden. Besonders stolz bin ich ja auf die Tatsache, dass meine Zeichenroutine immer versucht, linien zu zeichen und nicht 10* das selbe pixel hintereinander :D

    Zu asrael: Also du hast ja auch die Idee umgesetzt, die komplexe Zahl als struct zu beschreiben. Allerdings hätte ich an deiner Stelle versucht, besser durchzuhalten und auch die berechnungen in pure-C zu schrieben. Auch sind diese separat ausgelagerten Methoden bei den Berechnungen selber eher schlecht als recht, weil man halt immer so viele aufrufe hat. Ein aggressives hardcoden wäre hier sicherlich das schnellere. Sonst ist es sehr nett. Das interface ist ein bissel verwürscht, aber sonst für das erste Projekt... Hehe, einwas muss ich noch anbringen: vielleicht würdest du besser fahren, wenn du die ganzen vielen Ints lieber in ein Dictionary packst, da hättest du nicht so viele variablen und auch nicht so viel accessoren. Zu berechnung kann man sie dann ja auslesen :)

    Max
  • MandelBiX (asrael)

    Hier mein Senf:

    Wirklich der 'lesbarste' Code bisher. Kompliment. Man kann ohne große Konzentrationsanforderungen drüberschauen und den Code sofort verstehen.

    Die Datei ComplexValue finde ich richtig originell. Freilich nicht besonders performant, aber die Iterationsformel wird so schön verständlich in kleine Einheiten aufgeteilt.

    Mit der mayRedraw-Variable schießt Du Dir leider ins eigene Knie. Minimire mal _nach_ der Berechnung das Fenster ins Dock und hol's dann wieder zurück. Bluescreen. Das Appfelmännchen ist futsch. Ohne, daß sich etwas geändert hätte. Das gleiche passiert natürlich beim resizen des views (nur daß sich da Werte ändern.)
    Das Verhalten ließe sich umgehen, wenn Du in ein Image zeichnest. Das Image kann dann soz. gecached werden und bei Bedarf im View dargestellt werden.

    Statt mit den real und imaginär Wertebereichen (x_min, x_max, y_min y_max) jeweils mit einem Minimum und dem Inkrement zu arbeiten, halte ich nicht für besonders glücklich, zumindest nicht aus Sicht der Benutzerfreundlichkeit. Üblich ist das nicht. Die Inkremente können doch in der Zeichenmethode berechnet werden. Dann besteht natürlich die Gefahr, daß die Darstellung verzerrt... Vielleicht sollte man dem User die Wahl lassen, ob er 'Verzerrung' in Kauf nimmt od. nicht. Muß diesem Punkt wohl für meinen Code auch noch mal überdenken...

    Die Userwerte in ein Dict zu packen, wie MAX vorgeschlagen hat, halte ich nicht für besonders sinnvol oder hilfreich. Mit den Einzelnen Accessoren ist der Code doch leichter nachzuvollziehen. Und bei den paar Werten macht eventuelle Einsparung von ein bißchen Schreibarbeit den Kohl auch nicht fett.

    Ach ja, wie ich schon mal sagte, traditionell ist das Apfelmännchen schwarz. In weiß mag ich es persönlich ja überhaupt nicht..

    t.

    BTW: NSLog(@"... initialition ..."); ähem! Auch das ist originell ;-)
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • RE: MandelBiX (asrael)

    Original von tsunamix
    Die Userwerte in ein Dict zu packen, wie MAX vorgeschlagen hat, halte ich nicht für besonders sinnvol oder hilfreich. Mit den Einzelnen Accessoren ist der Code doch leichter nachzuvollziehen. Und bei den paar Werten macht eventuelle Einsparung von ein bißchen Schreibarbeit den Kohl auch nicht fett.

    Das sehe ich anders. Stell dir mal vor, du baust noch 50 weitere Parameter ein. Willst du wirklich für jeden einzelnen nen accessor schreiben? Außerdem wäre mit einem Dict auch das Binden des Interfaces ein bissel übersichtlicher. Ich finde es besser, alles in einem dict zu speichern (also wenn man z.b. viele zahlen hat), dann kann man über keys drauf zugreifen und muss nur ein objekt übergeben, wenn man alle parameter z.b. an eine separate engine übergeben will...

    Max