SS 1998 - Fachhochschule Köln
Fachbereich Nachrichtentechnik
Dr. Matthias Groß

Praktikum Datenverarbeitung - 5. Arbeitsblatt

Abgabetermin für alle: Montag ...... 1998 im DV-Labor

Bei dieser Programmieraufgabe geht es um die Verwendung von Strukturen zur Datenhaltung und die Verwendung von Grafik. Außerdem soll die Zusammenarbeit bei einem größeren Programmierprojekt geübt werden, da hier eine Aufteilung der in Teilaufgaben sehr gut möglich ist.

Es ist ein Simulator für ein Planetarium (in 2-D (Dimensionen) oder alternativ etwas schwieriger, aber informativer in 3-D) zu entwerfen. Diese Aufgabe ist in 2 Teile mit jeweils unterschiedlichen Anforderungen unterteilt. Der erste Teil beschäftigt sich mit der Datenerfassung und anschließender Berechnung, der zweite Teil mit der grafischen Ausgabe der Daten auf den Bildschirm. Die gemeinsame Schnittstelle beider Programmteile ist ein Vektor mit den Koordinaten der einzelnen Himmelskörper im System.

Das Problem: Es soll ein Sonnensystem wie z.B. das unserige oder eine beliebige andere Konstellation von Himmelskörpern, das sich aufgrund der Newton'schen Mechanik entwickelt, simuliert werden. Hierbei gehen wir von einem einfachen Modell aus, welches in Zeitschritten t>0 jeweils die neuen Positionen aller Körper aufgrund der aktuellen Daten berechnet und auf dem Bildschirm anzeigt (Man wähle ohne Beschränkung der Allgemeinheit t=1). Die für einen Himmelskörper entscheidenden Größen sind die Ortskoordinate x=(x1, x2, x3), der Geschwindigkeitsvektor v=(v1, v2, v3), der Beschleunigungsvektor a=(a1, a2, a3) und die Masse m. Für die grafische Darstellung sind evtl. noch Größe in Pixeln und Farbe des Objekts zu speichern. Die Geschwindigkeits- und Ortsänderung ergibt sich aufgrund der bekannten Bewegungsgleichungen. Die Beschleunigung und alle weiteren Größen von Objekt i durch den Objekt j ergeben sich nach den folgenden Regeln: (i und j bezeichnen den i-ten und j-ten Vektor, n={1,2,3} ist der Index an den einzelnen Komponenten.

mj aij = -mi aji = g mi mj / <xi-xj,xi-xj>   (xi-xj) / <xi-xj,xi-xj>1/2

aij ist die Beschleunigung, die der Körper j durch Körper i erfährt.

(xi-xj) / <xi-xj,xi-xj>1/2 ist der normierte Vektor, in dessen Richtung die Beschleunigung aij wirkt.

g mi / <xi-xj,xi-xj> ist somit der Betrag der Beschleunigung. Nach dem Superpositionsprinzip ergibt sich somit

vj(tk+1) = vj(tk)+(a1j + ... + aij + ... + aAnzPlanet j) (tk+1-tk) und

xj(tk+1) = xj(tk)+vj (tk+1-tk) für jeden Zeitschritt tk+1-tk=1.

Hierbei ist die verallgemeinerte Gravitationskonstante g geeignet zu wählen. Weiteres ist bei Bedarf allgemeinen Physikbüchern zu entnehmen.

Technische Vorgehensweise: Um dieses Problem in C zu lösen, sollte man folgende Dinge berücksichtigen: Es gibt insgesamt n viele Körper (n läßt sich sinnvoll beschränken), zu denen jeweils die gleichen Informationen in einer Struktur zu speichern sind. Aus diesem Vektor mit struct's lassen sich nun alle für das Programm relevanten Dinge ableiten. Es ist zu beachten, daß sich in jedem Zeitschritt alle neuen Werte aus den alten ergeben. Um vollständig zu funktionieren, muß es eine Routine geben, die die notwendigen Startinformationen abfragt oder automatisch generiert, eine Routine, die die in einem Zeittakt ti-1-ti auftretenden Änderungen berechnet und schließlich eine Routine, die die grafische Ausgabe der berechneten Werte übernimmt, wobei hier evtl auf alte Werte zurückgegriffen werden muß, um die alten Positionen zu löschen. Das umfassende Hauptprogramm muß nun noch die Zeit t ablaufen lassen und die entsprechenden Unterprogramme in korrekt gesteuerter Form aufrufen.

Eine Beispielstruktur zur Speicherung eines Objektes und Beispielprototypen für die zu entwerfenden Funktionen wären:

#define MAXPLANETS 50    /* Definiert die symbolische Konstante */

typedef struct sPlanet { /* Struktur fuer einen Planeten      */
  double Ort[3];         /* Die Ortskoordinate zur Zeit t     */
  double Geschw[3];      /* Die Geschwindigkeit zur Zeit t    */
  double Besch[3];       /* Die Beschleunigung zur Zeit t     */
  double Masse;          /* Die Masse des Planeten            */
  int    Radius;         /* Der Radius in Pixeln zum Zeichnen */
  int    Farbe;          /* Die Farbe zum Zeichnen            */
} Planet;

Planet System[MAXPLANETS];  /* Das Sonnensystem               */

int PlanetenAnz;            /* Menge der Objekte im System    */

void SystemInit(Planet *Sys, int n);

/* Initialisiert per Abfrage oder automatisch das System mit n Objekten */

void SystemNextStep(Planet *Sys, int n, double dt);

/* Fuehrt den naechsten Zeitschritt aus */

void SystemPlot(Planet *Sys, int n);

/* Stellt das Sytem grafisch auf dem Bildschirm dar */ 

Bei dieser Aufgabe ist es sinnvoll die Arbeit aufzuteilen, nachdem man gemeinsame alle notwendigen Strukturen festgelegt hat. Der eine entwickelt zunächst die grafischen Routinen, die andere die Berechnungen. (Die Routinen lassen sich unabhängig voneinander entwickeln und testen, wenn auf gemeinsame Strukturen zugegriffen wird.) Derjenige, der zuerst fertig wird ist, sollte dann ein Hauptprogramm zur Integration beider Teile entwickeln. Bei der Bildschirmausgabe sollte die Ausgabe von Momentaufnahmen und die von Bewegungsbahnen (aus Punkten) möglich sein. Zu dem Programm ist eine kurze Bedienungsanleitung zu entwerfen, die zur Abgabe dazugehört.

Bei der Programmierung der Grafik ist auf die Online-Hilfe von Borland-C und die Informationen aus der Vorlesung zurückzugreifen.

Eine gute Koordination und vorherige Absprache bei der Aufgabenverteilung sind für ein zügiges Arbeiten sehr wichtig. Gerade hier gilt: Erst planen, dann programmieren.

Beim Testen des Programms ist darauf zu achten, die Startwerte geeignet zu wählen und geeignete Perspektive für die Darstellung zu wählen. (Probieren!)

Grafik unter Borland-C:

Unter Borland C existiert eine komplette Unterstützung für die Darstellung von hochauflösender Grafik unter DOS. Dieses integrierte Programmpaket heißt BGI (Borland Graphics Interface) und wird durch das Einbinden der Header-Datei <graphics.h> in den entsprechenden C-Programmen aktiviert. Das eigentliche Zeichnen erfolgt nach dem Öffnen des Grafikbildschirms. Nach Beendigung des Zeichnens muß man wieder zurück in den Textmodus schalten, um mit Textausgaben fortzusetzen. Das folgende kurze Beispielprogramm soll die Handhabung erläutern:

#include <graphics.h>

...

/* Routine zum Initialisieren des Grafikbildschirms */

int setgraph(void)          /* Initialisiert das BGI-Grafiksystem */
{
  int graphdriver = DETECT, graphmode, errorcode;
  initgraph(&graphdriver, &graphmode, "c:\\run\\tcpp\\bgi")
                             /* Der Pfad muss auf die BGI-Treiber zeigen (*.bgi)
                                ACHTUNG: \\ steht fuer einen \ unter C            */
  errorcode = graphresult();
  return (errorcode != grOK);
}

/* Anwendung im Hauptprogramm */

...

if (setgraph())
{
  printf("Dieses Programm benoetigt EGA oder VGA-Grafik. Programm wird nun beendet!");
  exit(1);                   /* Fehlermeldung 1 an DOS weitergeben */
}

maxx = getmaxx();            /* Maximale Grafikkoordinaten holen.     */ 
maxy = getmaxy(); 
setcolor(WHITE);             /* Mal-Farbe setzen                      */
line(0, 0, maxx, maxy);      /* Diagonale ueber den Bildschirm ziehen */
putpixel(5,5,WHITE);         /* Einen weissen Punkt bei 5,5 setzen    */

...                          /* Weiter zeichnen */

getch();                     /* Auf eine Taste warten */
closegraph();                /* Grafiksystem beenden  */

FH-Köln zurück zurück vor WWW-Wais whois mail Hilfe


Seite zuletzt aktualisiert am 25.04.1998 von Matthias Groß. Diese Seite ist Teil des WWW-Dienstes der FH-Köln, Germany.