\documentclass[11pt,a4paper]{article}
\usepackage[ansinew]{inputenc}
\usepackage[margin=2.5cm,nohead]{geometry}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{wasysym}
\usepackage{ngerman,latexsym,alltt,graphicx,textcomp}
\usepackage[bookmarks, colorlinks=false, pdftitle={MRT I Praktikumsprotokoll}, pdfauthor={Fabian Kurz, http://fkurz.net/}, pdfsubject={C Praktikum}, pdfkeywords={TU Dresden, Praktikum, Mikrorechentechnik}, linkbordercolor={1 1 1}]{hyperref}
\date{16. Dezember 2004}
\author{Gruppe 63:\\Fabian~Kurz, Alexander~Eder\\Stephan~Stiebitz, Phillip~Burker}
\title{Praktikumsprotokoll -- Mikrorechentechnik I\\Versuch "`C-Programmierung"'}
\begin{document}
\setlength{\parindent}{0pt}
\setcounter{secnumdepth}{4}
\maketitle
\tableofcontents
\newpage
\section{Aufgabenstellung}

Zur numerischen Untersuchung von Fraktalen, insbesondere der \emph{Julia-Menge} und der \emph{Mandelbrotmenge}, soll ein Rechenprogramm entworfen und implementiert werden.
Für die Iterationsformel
\begin{equation}
z_{i+1} = c + {z_i}^2, \qquad z_i,\, z_{i+1},\, c \in \mathbb C
\end{equation}
mit $z_i = x_i + jy_i$, und $c = a + jb$ soll geprüft werden, nach wie vielen Iterationen $i$ die komplexe Zahl $z_i$ ein vorgegebenes Gebiet $G$ (z.B. einen Kreis) verläßt. Jeder Zahl $i$, für die $z_i$ das vorgegebene Gebiet verläßt, soll eine Farbe zugeordnet werden. Wenn sich $z_i$ für $i > i_{max}$ immer noch in diesem Gebiet befindet, wird die Iteration abgebrochen und diesem Punkt die Farbe schwarz zugeordnet.

Führt man nun diese Iteration für jeden Punkt auf der komplexen Zahlenebene aus, entstehen fraktale geometrische Figuren, die man bei Variation von
\begin{itemize}
\item $c$ als Mandelbrotmenge (nach dem französischen Mathematiker Beno\^it B. Mandelbrot, diese Menge wird wegen ihres Aussehens auch "`Apfelmännchen"' genannt)
\item $z_i$ als Julia-Menge (nach dem französischen Mathematiker Gaston Maurice Julia) 
\end{itemize}
bezeichnet.

\subsection{Die Mandelbrotmenge}
Da bei der Mandelbrotmenge $c$ variiert und die Anfangsbedingung $z_0 = 0\ $ lautet, ergibt sich (bei ausreichend hohem $i_{max}$ und einem hinreichend kleinem Gebiet $G$) das typische Erscheinungsbild wie in Abb.~1 dargestellt.
\begin{figure}[h]
\begin{minipage}[t]{7.2cm}
\centering \includegraphics[width=6cm]{1}
\caption{Typisches Erscheinungsbild der Mandelbrotmenge in der komplexen Ebene (aus \href{http://de.wikipedia.org/wiki/Fraktal}{Wikipedia})}
\end{minipage}
\hfill
\begin{minipage}[t]{7.2cm}
\centering \includegraphics[width=6cm]{2}
\caption{Ausgewählte Erscheinungsbilder der Julia-Menge mit entsprechenden Werten von $c$ (aus \href{http://de.wikipedia.org/wiki/Julia-Menge}{Wikipedia})}
\end{minipage}
\end{figure}

\subsection{Die Julia-Menge}

Die sich bei der Julia-Menge ergebenen Fraktale kommen in wesentlich vielfältigeren Formen daher, da hier der gewählte Wert für $c$ einen entscheidenen Einfluß auf das Iterationsverhalten der Reihe hat. In Abb.~2 sind exemplarisch einige Formen mit den dazugehörigen komplexen Werten von $c$ dargestellt, im Gegensatz zur Darstellung der Mandelbrotmenge in Abb.~1 wird hier nur der Rand der Menge dargestellt.


\section{Entwurf und Implementierung}

\subsection{Mathematische Grundlagen}

Die Berechnung der Iterationsfolgewerte nach (1) erfolgt nach den bekannten Rechenregeln für komplexe Zahlen:
\begin{align*}
z_{i+1} &= c + {z_i}^2 = a + ib + (x_i + iy_i)^2 = a + ib + {x_i}^2 - {y_i}^2\\
        &= (a + {x_i}^2 - {y_i}^2) + i(b + 2x_iy_i)
\end{align*}
Da die Programmiersprache C keinen Datentyp für komplexe Zahlen kennt und somit auch nicht mit ihnen rechnen kann, wurde ein eigener Datentyp eingeführt, welcher in 2.2.1 näher beschrieben wird. Die Berechnung der Iterationswerte im Programm erfolgt getrennt für den Real- und Imaginärteil: 
\begin{align}
\mathrm{Re}\,(z_{i+1}) &= a + {x_i}^2 - {y_i}^2\\
\mathrm{Im}\,(z_{i+1}) &= i(b + 2x_iy_i)
\end{align}
Um zu ermitteln ob die Reihe sich noch innerhalb des Gebietes $G$ (Kreis mit Radius $r$) befindet, wird nach dem Satz von Pythagoras die Entfernung vom Anfangspunkt $c = a +ib$ bei der Mandelbrotmenge bzw. $z_0 =  x_0 + iy_0$ bei der Julia-Menge ermittelt.
\begin{equation}
d = \sqrt{(a - x_i)^2 + (b - y_i)^2} \qquad \text {bzw.} \qquad d = \sqrt{(x_0-x_i)^2 + (y_0 - y_i)^2}
\end{equation}

\subsection{Datenstrukturen}

\subsubsection{Datentyp für komplexe Zahlen: \texttt{tComplex}}

Der Datentyp \texttt{tComplex} ist eine Struktur (\texttt{struct}) aus zwei \texttt{double}-Werten zur Aufnahme des Real- und Imaginärteils einer komplexen Zahl. 

\bigskip

Typendefinition:

\smallskip

\hrule
\begin{verbatim}
struct tComplex {         // Struktur zur Beschreibung komplexer Zahlen
  double r;               // Realteil
  double i;               // Imaginärteil
};
\end{verbatim}
\hrule

\bigskip

\subsubsection{Datentyp zum Speichern der Fraktalparameter: \texttt{tParam}}

Die benötigten Parameter zur Berechnung der Fraktale werden in der Struktur \texttt{tParam} gespeichert. Sie enthält das Quadrat des Radius \texttt{R} des Iterationsgebietes $G$ vom Typ \texttt{int} (durch Angabe des Quadrates erspart man das Ziehen der Wurzel bei der Berechnung der Entfernung nach (4)), die maximale Iterationsanzahl \texttt{imax} vom Typ \texttt{int}, den Fraktaltyp \texttt{ftype} vom Typ \texttt{tFracttyp} (2.2.3) sowie die Grenzwerte \texttt{xmin}, \texttt{xmax}, \texttt{ymin}, \texttt{ymax} des Gebietes der komplexen Ebene auf dem die Berechnungen durchgeführt werden sollen, jeweils vom Typ \texttt{float}.

\bigskip

Typendefinition:
\smallskip
\hrule
\begin{verbatim}
struct tParam {           // Parameterstruktur
  int         R;          // Quadrat des Radius des Gebietes G
  int         imax;       // maximale Anzahl der Iterationen
  tFracttyp   ftype;      // Fraktaltyp, Apfel/Julia
  double      xmin;       // Minmaler Realteil des Analysegebietes
  double      xmax;       // Maximaler Realteil des Analysegebietes
  double      ymin;       // Minmaler Im-Teil des Analysegebietes
  double      ymax;       // Maximaler Im-Teil des Analysegebietes
};
\end{verbatim}
\hrule


\subsubsection{Datentyp zur Angabe des Fraktaltyps: \texttt{tFracttyp}}

Die Typendefinition für \texttt{tFracttyp} ist eine Enumeration der möglichen Fraktaltypen, also der Julia-Menge und der Mandelbrotmenge (Apfelmännchen). Ein separater Typ ist für diesen Zweck eigentlich nicht nötig (man könnte beispielsweise einen Integerwert mit 1 für die Julia-Menge, 0 für das Apfelmännchen belegen), jedoch gewinnt man dadurch im weiteren Verlauf des Programms an Übersichtlichkeit.

\bigskip

Typendefinition:

\smallskip

\hrule
\begin{verbatim}
typedef enum {  Apfel,       // Apfelmännchen
                Julia        // Juliamenge
             } tFracttyp;
\end{verbatim}
\hrule

\bigskip

\subsubsection{Datentyp für die Farbpalette: \texttt{tColor}}

Der Typ \texttt{tColor} ist eine Enumeration, in welcher den ersten 16 Farbwerten der VGA Farbpalette entsprechende Bezeichnungen \texttt{black}, \texttt{blue}, \ldots zugeordnet werden.

\bigskip

Typendefinition:

\smallskip

\hrule
\begin{verbatim}
typedef enum {  black,         /*   0 schwarz         */
                blue,          /*   1 blau            */
                green,         /*   2 grün            */
                cyan,          /*   3 cyan            */
                red,           /*   4 rot             */
                magenta,       /*   5 violett         */
                brown,         /*   6 braun           */
                white,         /*   7 weiß            */
                gray,          /*   8 grau            */
                lightblue,     /*   9 hellblau        */
                lightgreen,    /*  10 hellgrün        */
                lightcyan,     /*  11 hellcyan        */
                lightred,      /*  12 hellrot         */
                lightmagenta,  /*  13 hellviolett     */
                lightyellow,   /*  14 gelb            */
                brightwhite    /*  15 intensivweiß    */
              } tColor;
\end{verbatim}
\hrule
\smallskip

\subsection{Programmstruktur}

Das Programm wurde in vier Programmmodule geteilt, \texttt{V3\_MAIN}, \texttt{V3\_DIALO}, \texttt{V3\_GRAPH}, \texttt{V3\_FRAKT}. Diese bestehen jeweils aus einer Headerdatei (\texttt{*.h}) als Schnittstelle zum Rest des Programms (außer der Hauptdatei, \texttt{V3\_MAIN}), welche Definitionen von Datentypen und die Funktionsköpfe enthält und einer Implementierungsdatei (\texttt{*.c}), welche den Quelltext der zu implementierenden Funktionen enthält.

Die Trennung der einzenen Programmteile dient dazu den Code übersichtlich zu halten, bestimmte Teile einfacher wiederverwendbar zu machen und die Wartbarkeit des Programms zu erhöhen.

Im Folgenden werden die vier Programmmodule im Detail beschrieben.

\subsubsection{Das Hauptmodul: \texttt{V3\_MAIN}}

Im Hauptmodul befindet sich nur die \texttt{main}-Funktion mit den eingebundenen Programmmodulen. Hier wird eine Variable vom Typ \texttt{tParam} vereinbart und mit bestimmten Werten initialisiert, $z_0$ und $c$ werden vereinbart und initialisiert und danach eine Schleife ausgeführt, in der der eigentliche Programmablauf stattfindet:

\begin{itemize}
\item Abfrage der Fraktal-Parameter (\texttt{V3\_DIALO}) 
\item Initialisierung der Grafik (\texttt{V3\_GRAPH})
\item Berechnung und Ausgabe des Fraktals (\texttt{V3\_FRAKT})
\item Bildschirm löschen
\item Abbruchbedingung abfragen
\end{itemize}


\subsubsection{Parameter-Eingabedialog: \texttt{V3\_DIALO}}

Zum Verändern der am Anfang des Hauptmoduls festgelegten Parameter zur Berechnung des Fraktals wird die Funktion \texttt{ParamDialog} im Modul \texttt{V3\_DIALO} aufgerufen. Der Funktion werden Pointer auf die Struktur zur Speicherung der Fraktalparameter vom Typ \texttt{tParam} und auf die komplexe Zahl \texttt{c} vom Typ \texttt{tComplex} übergeben. Dessen Werte werden in dieser Funktion nacheinander abgefragt, auf Sinnfreiheit überprüft und bei nichtvorhandensein derselben sogar gespeichert.   

Die Verwendung von Pointern ist hier die elegantest Methode zur Veränderung der Parameterwerte. Man hätte sie auch als \texttt{extern} Variablen definieren können und dann in \texttt{ParamDialog} ändern können, jedoch fördert dies nicht gerade die Übersichtlichkeit und Wartbarkeit des Codes.


\subsubsection{Grafik-Routinen: \texttt{V3\_GRAPH}}

Die Initialisierung der graphischen Schnittstelle besteht im Wesentlichen aus schnittstellenspezifischen Befehlen, die nichts mit ANSI C zu tun haben.

Der programmtechnisch interessante Teil dieses Moduls ist die Bildung der Parameter zur Umrechnung der Eingabewerte zwischen \texttt{ymin} und \texttt{ymax} bzw. \texttt{xmin} und \texttt{xmax} auf die entsprechenden Punkte des Bildschirms. Dabei ist sowohl das gegebene Intervall in $x$-  und $y$-Richtung auf die Abmessungen des Bildschirms zu strecken/stauchen als auch die $y$-Koordinate "`umzudrehen"', da der Koordinatenursprung $(0/0)$ des Bildschirms in der oberen linken Ecke liegt und die positive $y$-Achse nach unten zeigt, im Gegensatz zum kartesischen Koordinatensystem bzw. der Gaußschen Zahlenebene, welche es abzubilden gilt.

Letztendlich enthält dieses Modul die Funktion \texttt{SetPoint}, der die Variablen \texttt{x} und \texttt{y} vom Typ \texttt{double} und die Farbe \texttt{color} vom Typ \texttt{tColor}

\subsubsection{Fraktalberechnung: \texttt{V3\_FRAKT}}

Die eigentliche Berechnung der Iterationsfolge nach (1) bis (4) findet im Programmodul \texttt{V3\_FRAKT} statt. 


Die Funktion \texttt{GetItera} erhält als Eingabewerte zwei komplexe Zahlen $z$ und $c$ sowie eine Parameterstruktur vom Typ \texttt{tParam} und gibt als Rückgabewert die Anzahl der Iterationen bis zum Verlassen des in \texttt{tParam} festgelegten Gebietes zurück.
Dies wird durch eine \texttt{while}-Schleife realisiert, die solange ausgeführt wird, wie der Abstand des aktuellen Wertes $z_{i+1}$ noch innerhalb des Radius $r = \sqrt{R}$ liegt \emph{und} die aktuelle Iterationsanzahl noch unter der maximalen Iterationsanzahl \texttt{imax} aus der Parameterstruktur liegt.


Die Funktion  \texttt{GetColorValue} ermittelt aus dem Verhältnis der Iterationen zur maximalen Anzahl von Iterationen einen Farbwert. Für die maximale Anzahl der Iterationen wird die Farbe schwarz festgelegt, die restlichen Werte werden in der Folge der Standard-VGA-Palette belegt. Da im konkreten Fall nur 16 Farben darstellbar sind, wird hier mit Modulo 16 gearbeitet, so daß sich die Farben nachdem die Palette durchlaufen ist wiederholen.

Die genaue Farbe ist im Prinzip auch unwichtig. Wesentlich ist, daß in der ausgegebene Grafik erkennbar ist, daß es in der Fraktalgrafik bestimmte Zonen gibt, in denen das Iterationsverhalten der Reihe gleich ist.

Letztendlich enthält das Programmmodul \texttt{V3\_FRAKT} noch die Funktion zur eigentlichen Erzeugung der Fraktalgrafik, \texttt{Fraktal}. 

Als Parameter werden zwei komplexe Zahlen $c$ und $z$ und eine Parameterstruktur vom Typ \texttt{tParam} übergeben. In der Funktion wird nun für alle Punkte des in der Parameterstruktur angegebenen Gebietes der komplexen Ebene das Iterationsverhalten untersucht und ein entsprechender Farbpunkt auf dem Display ausgegeben. Dazu kommen zwei \texttt{for}-Schleifen zum Einsatz, die den Bereich in $x$-Richtung in 640, in $y$-Richtung in 480 Schritten durchlaufen. Die Schrittweite ergibt sich folglich aus
\begin{equation}
s_x = \frac{x_{\mathrm{max}}-x_{\mathrm{min}}}{640} \qquad \text{bzw.} \qquad
s_y = \frac{y_{\mathrm{max}}-y_{\mathrm{min}}}{480}.
\end{equation}
Damit wird erreicht, daß der verfügbare Bildschirmbereich Pixel für Pixel ausgefüllt wird; es sich also keine Lücken oder Überlappungen (je nach Wertebereich von $x_{\mathrm{min}}/x_{\mathrm{max}}$ und $y_{\mathrm{min}}/y_{\mathrm{max}}$) ergeben.

Innerhalb dieser Schleifen wird für jeden Punkt die Anzahl der Iterationen berechnet, danach die passende Farbe dazu berechnet und letztendlich der Farbpunkt auf dem Display dargestellt.

Bevor die Berechnung der Iterationsanzahl erfolgen kann, muss jedoch noch abhängig davon, ob eine Julia-Menge oder eine Mandelbrotmenge erzeugt werden soll, der variable Parameter bestimmt werden. Bei der Julia-Menge wird $z$ variiert, bei der Mandelbrotmenge $c$.


\subsection{Programmstruktur und Ablauf}

\begin{figure}[h]
\begin{center}
\begin{picture}(400,115)
\multiput(0,0)(150,0){3}{
\multiput(0,0)(100,0){2}{\line(0,1){45}}
\multiput(0,0)(0,45){2}{\line(1,0){100}}
\put(0,30){\line(1,0){100}}
}
\multiput(150,70)(0,40){2}{\line(1,0){100}}
\multiput(150,70)(100,0){2}{\line(0,1){40}}
\put(175,087){\texttt{V3\_MAIN.C}}
\put(172,34){\texttt{V3\_FRAKT.H}}
\put(22,34){\texttt{V3\_GRAPH.H}}
\put(322,34){\texttt{V3\_DIALO.H}}
\put(172,12){\texttt{V3\_FRAKT.C}}
\put(22,12){\texttt{V3\_GRAPH.C}}
\put(322,12){\texttt{V3\_DIALO.C}}
\put(200,45){\vector(0,1){25}}
\put(50,45){\line(0,1){12.5}}
\put(50,57.5){\line(1,0){125}}
\put(175,57.5){\vector(0,1){12.5}}
\put(350,45){\line(0,1){12.5}}
\put(350,57.5){\line(-1,0){125}}
\put(225,57.5){\vector(0,1){12.5}}
\end{picture}
\end{center}
\caption{Strukturdiagramm}
\end{figure}
\clearpage

Die Programmstruktur ist in Abb.~3, der Übersichtlichkeit halber ohne die eingebundenen Standardbibliotheken, dargestellt. Abb.~4 zeigt das Ablaufdiagramm des Programms als Flußdiagramm. Auch hier wurde sich auf das Wesentliche beschränkt um das Diagramm lesbar zu halten. Manchmal wurden mehrere Schritte, auch wenn sie im Programm in unterschiedlichen Funktionen implementiert wurden, in einzelne Boxen zusammengefasst. 



\begin{figure}
\begin{picture}(410,450)

\put(150,440){\oval(50,20)}
\put(138,437){Start}
\multiput(150,430)(0,-40){3}{\vector(0,-1){20}}
\multiput(100,390)(100,0){2}{\line(0,1){20}}
\multiput(100,390)(0,20){2}{\line(1,0){100}}
\put(118,397){Initialisierung}
\multiput(100,350)(100,0){2}{\line(0,1){20}}
\multiput(100,350)(0,20){2}{\line(1,0){100}}
\put(111,357){Parameterdialog}
\multiput(150,330)(-30,-30){2}{\line(1,-1){30}}
\multiput(150,330)(30,-30){2}{\line(-1,-1){30}}
\put(135,304){Werte}
\put(139,288){OK?}
\put(180,300){\line(1,0){40}}
\put(220,300){\line(0,1){60}}
\put(220,360){\vector(-1,0){20}}
\put(185,305){nein}
\put(155,260){ja}
\multiput(150,270)(0,-50){2}{\vector(0,-1){20}}
\multiput(100,220)(100,0){2}{\line(0,1){30}}
\multiput(100,220)(0,30){2}{\line(1,0){100}}
\put(118,237){Initialisierung}
\put(124,225){der Grafik}
\multiput(80,122)(140,0){2}{\line(0,1){78}}
\multiput(80,122)(0,78){2}{\line(1,0){140}}
\put(101,187){Fraktaltyp festlegen,}
\put(88,175){nächsten Punkt ermitteln,}
\put(97,163){Iterationen berechnen,}
\put(102,151){Farbwert berechnen,}
\put(99,139){Punkt auf Bildschirm}
\put(126,127){ausgeben.}
\put(150,122){\vector(0,-1){22}}
\multiput(150,100)(-30,-30){2}{\line(1,-1){30}}
\multiput(150,100)(30,-30){2}{\line(-1,-1){30}}
\put(135,074){Grafik}
\put(136,60){fertig?}
\put(150,40){\line(0,-1){20}}
\put(150,20){\line(-1,0){90}}
\put(60,20){\line(0,1){190}}
\put(60,210){\vector(1,0){90}}
\put(155,30){nein}
\put(185,75){ja}
\put(180,70){\line(1,0){120}}
\put(300,70){\vector(0,1){75}}
\multiput(250,145)(100,0){2}{\line(0,1){30}}
\multiput(250,145)(0,30){2}{\line(1,0){100}}
\put(270,163){Warten auf}
\put(263,150){Tastatureingabe}
\put(300,175){\vector(0,1){45}}
\multiput(250,220)(100,0){2}{\line(0,1){30}}
\multiput(250,220)(0,30){2}{\line(1,0){100}}
\put(257,237){Bildschirmausgabe}
\put(284,225){löschen}
\put(300,250){\vector(0,1){100}}
\multiput(300,410)(-30,-30){2}{\line(1,-1){30}}
\multiput(300,410)(30,-30){2}{\line(-1,-1){30}}
\put(300,410){\vector(0,1){20}}
\put(300,440){\oval(50,20)}
\put(288,437){Ende}
\put(282,377){Weiter?}
\put(270,380){\vector(-1,0){120}}
\put(255,385){ja}
\put(305,415){nein}
\end{picture}
\caption{Ablaufdiagramm}
\end{figure}



\section{Probleme}

Die Praktikumsaufgabe bereitete keine größeren Schwierigkeiten und konnte dank der guten Vorbereitung durch die Vorlesung sowie die bereitgestellten Unterlagen problemlos gelöst werden. Als zusätzliche Referenz wurde das Buch "`Programmieren in C"' von Kernigham und Ritchie benutzt.

Im Praktikum fiel auf, daß die Funktion zum Anfragen neuer Fraktalparameter (\texttt{ParamDialog} unabhängig vom Fraktaltyp immer die Werte für eine komplexe Zahl $c$ abfragt, obwohl diese nur bei der Julia-Menge benötigt wird (bei der Mandelbrotmenge wird $c$ variiert).

\newpage
\appendix
\section{Anhang \texttt{V3\_MAIN}}
\subsection{Implementierungsdatei \texttt{V3\_MAIN.C}}
\begin{verbatim}
/* Datei v3_main.c                         */
/* Fabian Kurz, 13.12.2004                 */

#include "v3_frakt.h"
#include "v3_graph.h"
#include "v3_dialo.h"
#include <conio.h>       /* getch */
#include <stdio.h>       /* printf */
 
void main () 
{ 
  /*--- Variablendeklaration -----------------------------------------------*/
  int a;                  
  double d; 
  int abbruch; 
 
  /*--- Initialwerte für Fraktalberechnung ---------------------------------*/
 
  tParam p;                 // Variable Parameter von tParam
  parameter.R     =  4;     // initialisieren...
  parameter.imax  = 75; 
  parameter.ftype = Julia;
  parameter.xmin  = -2;
  parameter.xmax  =  2;
  parameter.ymin  = -2;
  parameter.ymax  =  2;


  /*--- Initialwerte zur Fraktalanalyse ------------------------------------*/

  tComplex c;                // komplexe Zahlen c und z
  tComplex z;

  c.r = 0.4;                 // Initialisierung derselben
  c.i = 0.4;
  z.r = 0;
  z.i = 0;

  /*--- Parameterdialog und gegf. Fraktalberechnung ------------------------*/

do {
ParamDialog(&p, &c);                   // Parameterdialog

InitGraph(p.xmin,p.xmax,p.ymin,p.ymax);
 Fraktal(c,z,p);                       // Fraktalberechnung
 a = getch();                          // Auf Tastatureigabe warten bevor:
CloseGraph();                          // der Bildschirm gelöscht wird

do {                                   // Schleife für Abbruchbedingung
    printf("Weiter? (j/n)\n");
    a = getch();                       // Einlesen von a 
   } while (!(a == 'j' || a == 'n'));  // nochmal, wenn a nicht j oder n ist

  abbruch = 0;                         // abbruchbedingung auf 0 = falsch 
  if (a == 'n') abbruch = 1;           // falls nicht weitergemacht werden 
                                       // soll, abbruch auf 1 setzten
} while (abbruch == 0);                // bei abbruch = 1 ist hier schluß.

} /* v3_main.c */
\end{verbatim}

\section{Anhang \texttt{V3\_DIALO}}

\subsection{Headerdatei \texttt{V3\_DIALO.H}}

\begin{verbatim}
/* Datei: v3_dialo.h              */
/* Fabian Kurz, 13.12.2004        */

#ifndef __dialog
#define __dialog

#include "v3_frakt.h" /* tParam */


/*--- Modifikation und Test Analyseparameter -------------------------------*/

int ParamDialog(tParam *p, tComplex *c);

#endif

/* v3_dialo.h */
\end{verbatim}


\subsection{Implementierungsdatei \texttt{V3\_DIALO.C}}

\begin{verbatim}
/* Datei: v3_dialo.c                */
/* Fabian Kurz, 13. Dezember 2004   */
  
#include "v3_dialo.h"
#include <stdio.h>      /* printf  */
#include <stdlib.h>     /* strtod  */
#include <conio.h>      /* getch   */


/*--- Double-Zahl von der Tastatur lesen -----------------------------------*/

void InputDouble (double *value)
{
  char *endptr;
  char s[80];           /* Charakter-String                          */
                        /* ab [0] Inhalt, wenn <Enter> dann s[0]=0x0 */
  gets(s);              /* String von Tastatur lesen                 */
  if (s[0]!=0) *value=strtod (s, &endptr);     /* konvertieren       */
                        /* bei Eingabe von <Enter> bleibt der        */
                        /* bisherige Wert "value" unver~Dndert !      */
};


/*--- Int-Zahl von der Tastatur lesen --------------------------------------*/

void InputInt (int *value)
{
  char s[80];           /* Charakter-String                          */
                        /* ab [0] Inhalt, wenn <Enter> dann s[0]=0x0 */
  gets(s);              /* String von Tastatur lesen                 */
  if (s[0]!=0) *value=atoi (s);
                        /* bei Eingabe von <Enter> bleibt der        */
                        /* bisherige Wert "value" unverändert !      */
};

/*--- Parameterdialog und -test --------------------------------------------*/
/* Die benötigten Werte der Struktur p und eine komplexe Zahl werden ein    */
/* gelesen und auf Sinnfreiheit überprüft                                   */

int ParamDialog(tParam *p, tComplex *c)     // Es werden Pointer auf die Struk-
                                            // tur und die komplexe Zahl über-  
{                                           // geben..
char s[80];     
char *s2;
tParam pa;                   // Hier werden die Originalwerte
tComplex cm;                 // zwischengespeichert, bei Korrekturen benötigt
int j=0;
pa = *p;                     // Zwischenspeichern / Sichern
cm = *c;

do {                         // Anfang der Überprüfungsschleife
  printf("Bitte geben Sie das r^2 des Gebietes an: (%d)\n", p->R);
  InputInt(&pa.R);           // Wert einlesen und speichern
} while (pa.R < 1);          // Überprüfe ob r < 1, wenn ja wiederholen
p->R = pa.R;                 // Erfolgreich überprüft -> Wert übernehmen 

do {
printf("Bitte geben Sie die maximalen Iterationsschritte an: (%d)\n", p->imax);
  InputInt(&pa.imax);
} while (pa.imax < 1);
p->imax = pa.imax;           // Überprüfe ob imax < 1, wenn ja wiederholen

do {
  printf("Bitte geben Sie x_min (%f) ein\n", p->xmin);
  InputDouble(&pa.xmin);
} while (pa.xmin > 100 || pa.xmin < -100);    // prüfe ob xmin zwischen -100
p->xmin = pa.xmin;                            // und 100, wenn nicht wieder
                                              // holen

do {
  printf("Bitte geben Sie x_max (%f) ein\n", p->xmax);
  InputDouble(&pa.xmax);
} while (pa.xmax <= pa.xmin || pa.xmax > 100); // prüfe ob xmax > xmin und
p->xmax = pa.xmax;                             // xmax < 100

do {
  printf("Bitte geben Sie y_min (%f) ein\n", p->ymin);
  InputDouble(&pa.ymin);                         // dito, siehe xmin
} while (pa.ymin > 100 || pa.ymin < -100);
p->ymin = pa.ymin;

do {
  printf("Bitte geben Sie y_max: (%f) ein\n", p->ymax);
  InputDouble(&pa.ymax);                         // dito, siehe xmax
} while (pa.ymax <= pa.ymin || pa.ymax > 100);
p->ymax = pa.ymax;

do {
  j = (p->ftype == Julia) ? 1 : 0;       // j ist 1 bei Juliamenge, 0 sonst
  printf("Bitte waehlen Sie: Juliamenge (1) oder Apfelmaennchen (0)? 
                         (%s)\n", s2=(p->ftype == Julia) ? "Julia" : "Apfel");
 gets(s);                                // Einlesen des neuen Wertes (0/1)
 if (s[0]!=0) j=atoi (s);                // Setzten von j auf neuen Wert
} while (!(j==1 || j==0));               // Überprüfung ob 1 oder 0
p->ftype = (j == 1) ? Julia : Apfel;     // Speichern des neuen ftypes

printf("Bitte geben Sie Re(c) an (%f)\n", cm.r);
InputDouble(&cm.r);                      // Hier keine Überprüfung, strtod
c->r = cm.r;                             // regelt das; alle x \in R erlaubt


printf("Bitte geben Sie Im(c) an (%f)\n", cm.i);
InputDouble(&cm.i);                      // dito
c->i = cm.i;

return 1;                                // 1 zurückgeben, da auf jeden Fall
                                         // erfolgreich, wenn bis hier gekommen
}

/* v3_dialo.c */
\end{verbatim}

\section{Anhang \texttt{V3\_GRAPH}}

\subsection{Headerdatei \texttt{V3\_GRAPH.H}}

\begin{verbatim}
/* Datei: v3_graph.h            */
/* Fabian Kurz, 13.12.2004      */

#ifndef __graph
#define __graph

#include <graphics.h>

/*----- Typdefinitionen ----------------------------------------------------*/

typedef enum {  black,         /*   0 schwarz         */
                blue,          /*   1 blau            */
                green,         /*   2 grün            */
                cyan,          /*   3 cyan            */
                red,           /*   4 rot             */
                magenta,       /*   5 violett         */
                brown,         /*   6 braun           */
                white,         /*   7 weiß            */
                gray,          /*   8 grau            */
                lightblue,     /*   9 hellblau        */
                lightgreen,    /*  10 hellgrün        */
                lightcyan,     /*  11 hellcyan        */
                lightred,      /*  12 hellrot         */
                lightmagenta,  /*  13 hellviolett     */
                lightyellow,   /*  14 gelb            */
                brightwhite    /*  15 intensivweiß    */
              } tColor;

/*--- Grafik initialisieren und schließen ----------------------------------*/

void InitGraph (double Xmin,
                double Xmax,
                double Ymin,
                double Ymax);

void CloseGraph (void);


/*--- Grafikpunkt setzen ---------------------------------------------------*/

void SetPoint (double x, double y, tColor color);

#endif

/* v3_graph.h */
\end{verbatim}

\subsection{Implementierungsdatei \texttt{V3\_GRAPH.C}}

\begin{verbatim}
/* Datei: v3_graph.c             */
/* Fabian Kurz, 13. Dec 2004     */

#include <stdio.h>     /* printf */
#include <conio.h>     /* getch  */
#include <stdlib.h>    /* exit   */
#include "v3_graph.h"

/*----- Definitionen -------------------------------------------------------*/

static int      ixmax, iymax;   /* max. Integerwerte    */
static double   xmax,  ymax;    /* max. Realwerte       */
static double   xmin,  ymin;
static double   ax,bx,ay,by;    /* Umrechungsparameter  */

/*--- Grafik initialisieren ------------------------------------------------*/

void InitGraph (double Xmin,        /* Maximale Realwerte */
                double Xmax,
                double Ymin,
                double Ymax)
{
  int gdriver;
  int gmode;
  int errorcode;

  gdriver   = DETECT;                            /* request autodetection  */
  errorcode = registerbgidriver (EGAVGA_driver); /* register a driver      */
  if (errorcode < 0) {                           /* report any error       */
    printf ("Graphics error: %s\n", grapherrormsg(errorcode));
    printf ("Press any key to halt..\n");
    getch  ();
    exit   (1);                                  /* terminate w/error code */
  }

  initgraph (&gdriver, &gmode, "");              /* initialize graph mode  */
  errorcode = graphresult();                     /* read result of init    */
  if (errorcode != grOk) {                       /* an error occurred      */
    printf ("Graphics error: %s\n", grapherrormsg(errorcode));
    printf ("Press any key to halt...\n");
    getch  ();
    exit   (1);                                  /* return with error code */
  }
  ixmax = getmaxx();                             /* max. Abmaße Bildschirm */
  iymax = getmaxy();
  xmin  = Xmin; xmax  = Xmax;                    /* Zuweisung Init-Param.  */
  ymin  = Ymin; ymax  = Ymax;
  ax    = ixmax/(xmax-xmin);                     /* ix = ax*x + bx         */
  bx    =-ixmax*xmin/(xmax-xmin);
  ay    =-iymax/(ymax-ymin);                     /* iy = ay*y + by         */
  by    = iymax*ymax/(ymax-ymin);

}; /* InitGraph */


/*--- Farbpunkt setzen -----------------------------------------------------*/

void SetPoint (double x, double y, tColor color)
{ 
  int ix  = x*ax+bx;         // Ermittle Position auf Bildschirm
  int iy  = y*ay+by;         
  int icol= (int) (color);   // Konvertierung von tColor nach integer 
  putpixel(ix,iy,icol);      // Setzten des Pixels
};

/*--- Grafik schließen -----------------------------------------------------*/

void CloseGraph() { closegraph(); }; /* der Symmetrie wegen ! */

/* v3_graph.c */
\end{verbatim}

\section{Anhang \texttt{V3\_FRAKT}}

\subsection{Headerdatei \texttt{V3\_FRAKT.H}}

\begin{verbatim}
/* Datei: v3_frakt.h            */
/* Fabian Kurz, 13.12.2004       */

#ifndef __frakt
#define __frakt

/*--- Datentypvereinbarungen -----------------------------------------------*/

typedef enum {  Apfel,       // Apfelmännchen
                Julia        // Juliamenge
             } tFracttyp;

struct tParam {           // Parameterstruktur
  int         R;          // Quadrat des Radius des Gebietes G
  int         imax;       // maximale Anzahl der Iterationen
  tFracttyp   ftype;      // Fraktaltyp, Apfel/Julia
  double      xmin;       // Minmaler Realteil des Analysegebietes
  double      xmax;       // Maximaler Realteil des Analysegebietes
  double      ymin;       // Minmaler Im-Teil des Analysegebietes
  double      ymax;       // Maximaler Im-Teil des Analysegebietes
};

struct tComplex {         // Struktur zur Beschreibung komplexer Zahlen
  double r;               // Realteil
  double i;               // Imaginärteil
};

/*--- Fraktal analysieren und grafisch darstellen --------------------------*/

int GetItera (tComplex c, tComplex z, tParam param);

void Fraktal(tComplex c, tComplex z, tParam p);

#endif

/* v3_frakt.h */
\end{verbatim}

\subsection{Implementierungsdatei \texttt{V3\_FRAKT.C}}

\begin{verbatim}
/* Datei: v3_frakt.c                              */
/* Autor Fabian Kurz, Datum 13-Dec-2004           */

#include "v3_frakt.h"
#include "v3_graph.h"
#include <math.h>
#include <stdio.h>

/*--- interne Funktion zur Bildung des Quadrats einer float-Zahl -----------*/

float quad (float a)
{
return a*a;
}

/*--- Interne Funktion: Analyse der Iterationsanzahl -----------------------*/
/*    Gibt die Anzahl der Iterationen zurück, bei der die Folge mit den     */
/*    gegebenen Parametern den vorgegebenen Radius verläßt                  */

int GetItera (tComplex c, tComplex z, tParam param)
{
int i = 0;        // Anzahl der benötigten Iterationen
tComplex alt;     // Ursprünglicher Wert wird hier gespeichert
tComplex z2;      // Arbeitswert

alt.r = z.r;      // Ursprungswert, von dem die Entfernung
alt.i = z.i;      // gemessen wird

while( ((quad(z.r-alt.r)+quad(z.i-alt.i)) < param.R) && (i < param.imax))
{                         // solange der maximale Radius und die maximale
                          // Iterationsanzahl nicht erreicht sind....
 z2  = z;                 // retten, da zwischenzeitlich vermurkst wird
 z.r = c.r + quad(z.r) - quad(z.i);   // Realteil fuer zi+1
 z.i = c.i + 2*z2.r*z2.i;             // Imaginärteil berechnen 
 i++;                                 // Iterationsschritt erhoehen
}

 return i;        // Rückgabewert i (Anzahl der Iterationen)
}
/*--- Interne Funktion: Farbwert bestimmen ---------------------------------*/

tColor GetColorValue (int i, int imax)
{
int a;
if (i==imax) a = 0;     // Wenn maximale Iterationszahl erreicht wurde, 
                        // also G nicht verlassen wird: schwarz
else {
a = imax/i;             // bei i = imax  1, bei i = 1  imax
a = (a % 16)+1;         // "aufteilen" auf 16 Farben
}
return (tColor) a;      // Farbe vom Typ tColor zurückgeben 
}

/*--- Fraktal-Figur analysieren und zeichnen -------------------------------*/

void Fraktal(tComplex c, tComplex z, tParam p)
{
double x=p.xmin;                // Arbeitswert für Re(z) = x
double y=p.ymin;                // Arbeitswert für Im(z) = y
int it;                         // Iterationszähler
tColor f;                       // Farbwert 

for (x=p.xmin;x<p.xmax;x+=(p.xmax-p.xmin)/640) { // xmin->xmax in 640 schritten
  for (y=p.ymin;y < p.ymax;y+=(p.ymax-p.ymin)/480) {  //ymin->ymax " 480 "
   if (p.ftype == Apfel) {         // Überprüfen ob Apfelmännchen oder ..
     c.r = x;       // Apfel: Variation von c
     c.i = y;
    }
    else {                         // etwa doch die Juliamenge
      z.r = x;      // Julia: Variation von z                  
      z.i = y;
    }

    it = GetItera(c,z,p);          // Finde Iterationsschritte heraus

    f = GetColorValue(it, p.imax); // ermittle Farbe aus it und imax

    SetPoint(x,y,f);               // Setze Farbpunkt an entsprechender Stelle
   }
 }
}

/* v3_frakt.c */
\end{verbatim}



\end{document}

