Universität Stuttgart 6W X GL H Q DU ESabine Knapp plattformunabhängiges HLEin Programm zur Linienglättung in Java W D P Betreuer: Dipl.-Ing. Michael Glemser Prüfer: Prof. Dr.-Ing. Dieter Fritsch Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Vorwort Diese Studienarbeit wurde im Rahmen des Studiums der Geodäsie und Geoinformatik am Institut für Photogrammetrie an der Universität Stuttgart angefertigt. Auf diesem Weg möchte ich mich bei meinem Betreuer Herrn Dipl.-Ing. Michael Glemser für seine Unterstützung und Hilfe bedanken. Stuttgart, den 3. August 1998 Sabine Knapp Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp INHALTSVERZEICHNIS 0 ZUSAMMENFASSUNG ________________________________________________________ 1 1 EINLEITUNG_________________________________________________________________ 2 2 JAVA ________________________________________________________________________ 3 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 JAVA, EINE OBJEKTORIENTIERTE PROGRAMMIERSPRACHE ______________________________ 3 JAVA, EINE INTERPRETER-SPRACHE _______________________________________________ 5 JAVA, EINE EINFACHE SPRACHE __________________________________________________ 6 JAVA, EINE LEISTUNGSFÄHIGE SPRACHE ___________________________________________ 6 KLASSENBIBLIOTHEK __________________________________________________________ 7 OBJEKTORIENTIERTE PROGRAMMIERUNG __________________________________________ 8 NEGATIVE ASPEKTE DER PROGRAMMIERSPRACHE JAVA ______________________________ 12 ENTWICKLUNGSWERKZEUG UND PROGRAMMSTART _________________________________ 13 3 DOUGLAS/PEUKER ALGORITHMUS __________________________________________ 14 4 IMPLEMENTIERUNG ________________________________________________________ 16 4.1 NEU ENTWORFENE KLASSEN ___________________________________________________ 4.1.1 Klasse PunkteVektor zur Realisierung des Douglas/Peuker Algorithmuses __________ 4.1.2 Klassen DougPeuk und DougPeukErgebnis zur Generierung der grafischen Benutzeroberfläche_____________________________________________________________ 4.2 HIERARCHIE ________________________________________________________________ 4.3 MAIN-METHODE _____________________________________________________________ 4.4 PROGRAMMABLAUF __________________________________________________________ 4.5 FEHLERBEHANDLUNG _________________________________________________________ 4.6 TESTEN AUF VERSCHIEDENEN PLATTFORMEN ______________________________________ 4.6.1 Testdaten _____________________________________________________________ 4.6.2 Test auf PC unter Windows NT ____________________________________________ 4.6.3 Test auf Silicon Graphics-Workstation unter Unix _____________________________ 5 16 16 18 22 23 24 28 30 30 30 30 FAZIT ______________________________________________________________________ 33 LITERATURVERZEICHNIS _______________________________________________________ 34 ABBILDUNGSVERZEICHNIS ______________________________________________________ 35 ANHANG: QUELLTEXTE _________________________________________________________ 36 PUNKTEVEKTOR.JAVA _____________________________ DOUGPEUK.JAVA _________________________________ DOUGPEUKERGEBNIS.JAVA _________________________ FEHLERTEXT.JAVA________________________________ FEHLER! TEXTMARKE NICHT DEFINIERT. FEHLER! TEXTMARKE NICHT DEFINIERT. FEHLER! TEXTMARKE NICHT DEFINIERT. FEHLER! TEXTMARKE NICHT DEFINIERT. Hinweis: Die vorliegende Online-Version des Dokumentes enthält keinen Anhang. Bei Interesse wenden Sie sich bitte an [email protected]. Bitte denken Sie daran: Diese Arbeit ist zu zitieren als: Knapp, Sabine (1998): Ein plattformunabhängiges Programm zur Linienglättung in Java. Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart (unveröffentlicht). Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Zusammenfassung Im Mittelpunkt dieser Studienarbeit steht die Untersuchung der Programmiersprache Java. Java gilt als objektorientierte und plattformunabhängige Sprache. Diese Eigenschaften und weitere Besonderheiten von Java werden vorgestellt. Desweiteren wird auch auf den Inhalt der Klassenbibliothek und auf die Implementierung von Javas Grundkonzepten eingegangen. Als praktische Anwendung wurde der Douglas/Peuker Algorithmus zur Linienglättung objektorientiert formuliert und in Java implementiert. Die Ein- und Ausgabe sowie die Ergebnisse werden grafisch aufgearbeitet. Als abschließende Prüfung wurde das Programm auf unterschiedlichen Plattformen bzw. Betriebssystemen getestet. 1 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 0 Einleitung Die Entstehung der Programmiersprache Java geht auf James Goshing zurück. Als Java in den frühen Neunzigern zum ersten Mal vorgestellt wurde, hat die Internetwelt diese Programmiersprache begeistert aufgenommen. Ihr Einsatzbereich war zu Beginn fast ausschließlich dort angesiedelt. Durch eine tatkräftige Erweiterung um wichtige Programmelemente, die 1997 in der Java Version 1.1 realisiert wurde, begann sich die Programmiersprache Java auch auf die restliche Programmierwelt auszubreiten. Die Programmiersprache Java ist vorallem für Anwendungen geeignet, die auf verschiedene Plattformen in verschiedene Systeme übertragbar sein sollen. Dies ist innerhalb eines Betriebes oder ganz allgemein innerhalb einer vernetzten Umgebung vorteilhaft. Oft sind andere wichtige Programmpakete nur auf bestimmten Rechnern unter einem bestimmten Betriebssystem verfügbar, so daß unterschiedliche Hardwarekomponenten nicht zu umgehen sind. Als Beispiel einer solchen Anwendung, kann die Linienglättung genannt werden. Durch die große Bedeutung dieser Standardaufgabe bei die Generalisierung in der Digitalen Kartographie oder innerhalb von Geo-Informationssystemen (GIS), besteht der Bedarf, daß ein solches Verfahren in allen möglichen Systemen verfügbar ist. Eine einfache Übertragung der Anwendung im Netz, kann dann erreicht werden, wenn sie in plattformunabhängiger Form entwickelt wird. Sie steht dann als ausführbare Version zur Verwendung bereit. 2 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 1 JAVA Die Programmiersprache Java und die dazugehörigen umfangreichen Klassenbibliotheken bieten eine portable, interpretierende, leistungsfähige, einfache und objektorientierte Entwicklungsumgebung. Die Java-Umgebung ist für Programmieraufgaben geeignet, die von der Auflockerung von Web-Seiten bis zum Schreiben vollwertiger Anwendungssysteme reicht. Es sollen nun die Eigenschaften und Konzepte, die Klassenbibliothek sowie Programmierelemente der Programmiersprache Java vorgestellt und erläutert werden (vgl. [1],[3]). 1.1 Java, eine objektorientierte Programmiersprache Die vier zentralen Konzepte objektorientierter Programmierung sollen anhand von vier Fragen erklärt werden. (1) Was ist ein Objekt? Objekte sind der Schlüssel zum Verständnis der objektorientierten Technologie. Softwareobjekte sind den Objekten der realen Welt nachempfunden. Sie weisen einen Zustand und ein Verhalten auf. Dabei bewahrt es seinen Zustand in Variablen und implementiert sein Verhalten mit Methoden. Ein Objekt ist also ein Softwarebündel aus Variablen und damit zusammenhängenden Methoden. Alles, was ein Softwareobjekt weiß (Zustand) oder tun kann (Verhalten) wird innerhalb dieses Objekts durch Variablen und Methoden ausgedrückt. Das Verpacken von Variablen eines Objekts unter dem Schutz seiner Methoden nennt man Einkapselung. Unwesentliche Implementierungseinzelheiten werden verborgen. Die Vorteile der Einkapselung bestehen vorallem in der Modularität. Der Quelltext für ein Objekt kann unabhängig vom Quelltext für andere geschrieben und gepflegt werden. Zudem kann ein Objekt einfach im System weitergereicht werden. Durch das Verbergen von Informationen besitzt ein Objekt eine öffentliche Schnittstelle, über die andere Objekte mit ihm kommunizieren können. Allerdings kann das Objekt auch private Informationen und Methoden unterhalten, die jederzeit ohne Folgen für andere, von ihm abhängige Objekte geändert werden können. (2) Was sind Nachrichten? Durch das Zusammenwirken von Objekten kann ein höherer Grad an Funktionalität und ein komplexeres Verhalten erzielt werden. Die Kommunikation untereinander erfolgt über Nachrichten. Eine Nachricht besteht aus drei Komponenten: (a) dem Objekt, an das die Nachricht gerichtet ist (b) dem Namen der auszuführenden Methode (c) von der Methode benötigte Parameter Das Verhalten eines Objekts wird durch seine Methoden ausgedrückt. der Nachrichtenversand ist also, neben dem direkten Zugriff auf Variablen, für sämtliche möglichen Wechselwirkungen zwischen Objekten zuständig. 3 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Objekte brauchen nicht in demselben Prozeß und noch nicht einmal im selben Rechner angesiedelt zu sein, um Nachrichten untereinander zu versenden und zu empfangen. (3) Was sind Klassen? Ein Objekt ist eine Instanz oder Exemplar einer Klasse. Eine Klasse ist ein Bauplan oder ein Prototyp, der allen Objekten einer bestimmten Art gemeinsamen Variablen und Methoden definiert. Wenn eine Instanz einer Klasse erzeugt wird, wird ein Objekt dieses Typs erstellt und das System reserviert Speicher für die in dieser Klasse deklarierten Instanzvariablen. Klassen können sowohl Instanzvariablen und -methoden, als auch Klassenvariablen und -methoden enthalten. Eine Klasse ist nur ein Bauplan, erst eine Instanz der Klasse ist tatsächlich existent und benutzbar. Klassen besitzen den Vorzug der Wiederverwendbarkeit. Es können viele Obejekte der Klasse nach dem selben Bauplan als eine Instanz erzeugt werden. (4) Was ist Vererbung? Vererbung realisiert eine Hierarchie unter den Klassen. Es existieren darin Oberund Unterklassen. Jede Unterklasse erbt den Zustand der Oberklasse. Dabei können den aus ihrer Oberklassen geerbten Variablen und Methoden eigene hinzugefügt werden. Die geerbten Methoden können aber auch überschrieben werden. Die Klassenhierarchie kann so tief sein wie notwendig. Je weiter unten eine Klasse in der Hierarchie angesiedelt ist, desto spezialisierter ist in der Regel ihr Verhalten. Man unterscheidet einfache und multiple Vererbung. Bei einfacher Vererbung ist nur eine Oberklasse möglich, von der die Unterklasse Attribute erbt. Dagagen sind bei einer multiplen Vererbung mehrere Oberklassen erlaubt. Vorteilhaft an der Vererbung ist das Auftreten von allgemeinen und speziellen Eigenschaften. Unterklassen liefern, aufbauend auf den von der Oberklasse zur Verfügung gestellten allgemeineren Elementen, speziellere Verhaltensweisen. Die Wiederverwendbarkeit ist bei allgemeinen Eigenschaften größer als die von speziellen. Eine Oberklasse, die generische Verhaltensweisen zur Verfügung stellt, wird abstrakte Klasse genannt. Sie definiert das Verhalten der Klasse und kann es auch teilweise implementieren, doch viele Elemente in dieser Klasse können undefiniert bleiben oder werden nicht implementiert. Einzelheiten werden in Form von spezialisierten Unterklassen hinzugefügt. Das Prinzip der Generalsisierung erhöht die Wartbarkeit und Änderbarkeit. 4 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 1.2 Java, eine Interpreter-Sprache Java-Programm Abstraktion Die System-Klasse Portierung Laufzeitsystem Javas virtuelle Maschine JavaInterpreter Rechnerbetriebssystem Im Kern der Java-Laufzeitumgebung befindet sich Javas virtuelle Maschine, der JavaInterpreter und das Betriebssystem des Rechners. Das Laufzeitsystem stellt die aktuelle Laufzeitumgebung dar und ist eine Instanz der Klasse Runtime. Die aktuelle Laufzeitumgebung kann alles sein, von einer unter MacOS laufender Implementierung der virtuellen Maschine und des Java-Interpreters auf einem Macintosh, bis hin zur Windows 95 Implementierung auf einem PC. Runtime-Objekte stellen zwei Dienste bereit. Zuerst kommunizieren sie mit den Komponenten der Laufzeitumgebung und erhalten so Information und rufen Funktionen auf. Zweitens sind Runtime-Objekte die Schnittstelle zu systemabhängigen Teilen. Da die Runtime-Klasse eng mit der Implementierung des Java-Interpreters, der virtuellen Java-Maschine und dem Rechnerbetriebssystem verbunden ist, ist sie systemabhängig. Der Java-Compiler generiert nicht wie andere Compiler Maschinencode, sondern einen plattformunabhängigen Code, den Java-Bytecode, der vom Laufzeitsystem interpretiert werden kann. Der Bytecode steht in einer Klassendatei, die unabhängig von einem Browser ausführbar ist. Beim Starten eines Programms führt der Java-Interpreter den von der virtuellen Maschine übersetzten plattformunabhängigen Bytecode aus. Eine Linkphase ist praktisch nicht vorhanden, höchstens das Laden der Klassen kann als solches bezeichnet werden. 5 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Bei Java gibt es keine implementierungsabhängigen Aspekte in der Sprachspezifikation. Java definiert die Größe der primitiven Datentypen und ihr arithmetisches Verhalten selbst. 1.3 Java, eine einfache Sprache Bei der Entwicklung von Java war ein Ziel, diese Programmiersprache so zu gestalten, daß sie schnell und einfach zu erlernen ist. Deshalb gibt es relativ wenig Sprachkonstrukte. Diese sind aber sehr ähnlich zu bestehenden Programmiersprachen, vorallem C und C++. Um schlechten Programmierstil und somit die Gefahr von Fehlern zu bannen oder weil sie nicht notwendig sind, wurden viele Sprachelemente von C, C++ nicht übernommen. Java unterstützt die goto-Anweisung nicht und verwendet keine Headerfiles. Auch der Präprozessor fällt ganz weg. Da Java objektorientiert aufgebaut ist, wurden Konstrukte wie struct (Strukturen) und union (Varianten) nicht benötigt, statt dessen werden Klassen und Schnittstellen verwendet. Operatorenüberlagerung ist bei Java nicht möglich und auch auf multiple Vererbung wurde verzichtet. Dies ist bei C++ möglich. Als wichtigste Vereinfachung erweist sich die Beseitigung von Zeigern. Da Java keine Strukturen besitzt und Felder und Zeichenketten als Klassen realisiert hat, besteht auch gar keine Notwendigkeit für Zeiger. Außerdem wurde ein selbständiges Speichermanagement verwirklicht. Java übernimmt Referenzierung und Dereferenzierung der Objekte selbst. Sämtliche Java-Programme sind Klassen, dabei enthält eine dieser Klassen die mainMethode, die den Start eines Programmes einleitet. In Java gibt es keine globalen Variablen. Alle Variablen sind innerhalb einer bestimmten Klasse definiert und ihr zugeordnet. 1.4 Java, eine leistungsfähige Sprache Mit Java ist eine höchst zuverlässige und robuste Softwaregewinnung gewährleistet. Gewisse Programmierfehler werden von vornherein ausgeschlossen. Es gibt generell weniger Laufzeitfehler als bei C, da der Java-Compiler nicht so nachlässig und locker ist. Da Zeiger nicht vorhanden sind und ein anderer Zugang zu Feldern und Zeichenketten realisiert wurde, ist die Sprache weniger fehleranfällig für Speicherverletzungen. Die Sprache besitzt zudem eine „verteilte“ Natur, d.h. Java stellt Unterstützung zur Vernetzung zur Verfügung. Remote Files können genauso einfach gelesen werden wie lokale Files. Dabei ist Sicherheit ein wichtiger Aspekt. Java besitzt mehrere Schichten von Sicherheitskontrollen. Auf der untersten Stufe steht ein totales Verbot jeglichen Zugriffs auf Speicherplatz. In der zweiten Stufe wird der Bytecode vom Interpreter überprüft. Als zusätzlicher Schutz wird das sogenannte „Sandkasten“ Modell verwendet. Kritischer Code wird in einen „Sandkasten“ gestellt, wo er sicher spielen kann, ohne die reale Welt zu schädigen. Dabei gelten im „Sandkasten“ ganz bestimmte Regeln, die eingehalten werden müssen. Durch einen Security Manager werden diese Restriktionen überwacht. Bei sensiblen Operationen muß vor der Durchführung das „OK“ vom Security Manager gegeben werden. 6 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Als weiteres leistungsfähiges Merkmal besitzt Java sogenannte „Threads“. Ein „Thread“ wird manchmal auch als Ausführungskontext oder leichtgewichtiger Prozeß bezeichnet. Es ist ein einzelner sequentieller Ablauf oder Kontrollfluß innerhalb eines Prozesses. Man benützt Threads, um Aufgaben durchzuführen, die von anderen Aufgaben abgetrennt und nicht mit Operationen anderer Aufgaben überlagert sein sollen. Damit ist es also möglich, viele Dinge zur selben Zeit abzuwickeln. Dies verbessert die interaktive Performance grafischer Applikationen. Auch Animationen erfolgen über Threads. 1.5 Klassenbibliothek Java besitzt eine umfangreiche Klassenbibliothek. Sämtliche Klassen und Schnittstellen werden in 23 Paketen zusammengefaßt. Es sollen nun nur ein paar wichtige herausgegriffen und kurz erläutert werden. x java.applet: Ein Applet ist ein kleines einbettbares Java-Programm. Es ist so gestaltet, daß es mit Hilfe eines Webbrowsers ausgeführt werden kann. Somit steht ein Applet der gesamten Internetwelt zur Verfügung. x java.awt: Der abstrakte Fensterwerkzeugsatz bietet viele Standard-GUI-Komponenten wie Schaltflächen, Listen, Menüs und Textflächen an. Es enthält ebenfalls Container (z.B. Anwendungsfenster oder Menüleisten) und aufwendigere Komponenten wie z.B. ein Dialogfenster zum Öffnen und Sichern von Dateien. Wichtig innerhalb des Pakets ist die Graphics-Klasse. Sie definiert Methoden zur Darstellung von Linien und Texten und ermöglicht das Einbinden von Bildern. Die aus Component und MenuComponent abgeleiteten Unterklassen stellen GUIKomponenten bereit. Zusätzlich ist ein LayoutManager verfügbar. x java.awt.event: Dieses Paket definiert die Klassen und Schnittstellen zu Ereignisabwicklung innerhalb AWT-Klassen. Drei verschiedene Kategorien können grundsätzlich unterschieden werden: i Ereignisse ( Event): Sie werden von AWT-Klassen oder deren Komponenten erzeugt. i Zuhörer ( Listener): Ereigniszuhörer sind Schnittstellen, die von jedem Objekt implementiert werden müssen, das über eine bestimmtes Ereignis benachrichtigt werden will. i Adapter ( Adapter): Sie passen den Bedarf an Zuhörern der Anwendung an. Es müssen hierbei nicht alle Methoden der Schnittstelle des zugehörigen Listeners implementiert werden. 7 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp x x java.io: Dies ist ein sehr umfangreiches Paket, das verschiedene Möglichkeiten für die Einund Ausgabe anbietet. Man kann das Paket generell in Datenströme aufteilen, die einerseits für die Ein- und Ausgabe von Byteströmen (InputStream- und OutputStream-Klassen) und andererseits für die Ein- und Ausgabe von Zeichenströmen im ASCII-Format (Reader- und Writer-Klassen) zuständig sind. java.lang: In diesem Paket befinden sich die zentralen Java-Klassen. Hier ist die Klasse Object, die ultimative Oberklasse aller Java-Klassen, zu finden. Über die primitiven Datentypen wie z.B. double wurden Klassen gelegt, die nützliche Konvertierungen und andere Werkzeuge anbieten. Zeichenketten werden mit den Klassen String und Stringbuffer bearbeitet. Wichtig ist die Process-Klasse, die plattformunabhängige Schnittstellen zu plattformabhängigen Prozessen definiert, die an den Java-Interpreter weitergegeben werden. Zur Ausnahmen- und Fehlerbehandlung steht die Klasse Throwable zur Verfügung. Desweiteren sind hier die Klassen System, Runtime, Thread, Math und viele mehr untergebracht. x java.net: Eine leistungsfähige und flexible Klassensammlung für Netzwerkoperationen. x java.util: Hier steckt die Vector-Klasse, die Felder von Objekten verwaltet. Es sind noch mehr nützliche Werkzeuge hier verborgen wie z.B. Hashtable, Properties, Date, Calendar, Stack, usw. 1.6 Objektorientierte Programmierung Java ist von grundauf objektorientiert aufgebaut. Ausnahmen bilden nur numerische, Charakter- und boolsche Datentypen. Klassen sind die Basiseinheiten. Sämtliche JavaProgramme sind Klassen. Die Klasse Object in java.lang dient als Wurzel der Java Klassen Hierarchie. In diesem Kapitel soll nun gezeigt werden, wie das objektorientierte Konzept implementiert und genutzt werden kann. Dabei soll erläutert werden, wie Objekte erzeugt und gelöscht, Klassen, Unterklassen und Schnittstellen erzeugt und verwendet werden (vgl. [3]). x Objekte erzeugen Typ variablenname new Typ(); Diese Anweisung erzeugt ein neues Objekt Typ ( muß Klasse sein! ) und führt eigentlich drei Aktionen durch: Deklaration, Instantiierung und Initialisierung. i Objekt- bzw. Variablendeklaration: Variable variablenname wird erzeugt, die ein Objekt des Dartentyps Typ enthalten soll. 8 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp i Objektinstantiierung: Bereitstellung von Speicher für ein neues Objekt dieses Klassentyps mit new. Der new-Operator gibt eine Referenz auf das neu erzeugte Objekt zurück. i Objektinitialisierung: erfolgt durch Aufruf eines Konstruktors Typ(). Konstruktoren sind spezielle Methoden zur Initialisierung eines neuen Objekts dieses Typs. Konstruktoren tragen denselben Namen wie die Klasse. Java unterstützt das Überladen von Methodennamen, so daß eine Klasse eine beliebige Zahl gleichnamiger Konstruktoren besitzen kann. Sie können durch Anzahl und Typ ihrer Argumente unterschieden werden. x Variablen eines Objekts referenzieren objektReferenz.variable Um auf die Objektvariablen zuzugreifen, wird der Variablenname einfach an eine Objektreferenz mit einem dazwischengesetzten Punkt angehängt. x Methoden eines Objekts aufrufen objektReferenz.methodenName(argumentListe); oder objektReferenz.methodenName(); Um eine Methode eines Objekts aufzurufen, muß einfach der Methodenname an die Objektreferenz mit einem Punkt dazwischen angefügt werden. Mögliche Argumente können der Methode durch Klammern umschlossen übergeben werden. Methodenaufrufe werden an ein bestimmtes Objekt gerichtet, das auf die Anweisung reagiert. Dies wird auch als Objektnachricht bezeichnet. x Freigabe ungenutzter Objekte Explizit ist eine Freigabe von ungenutzten Objekten in Java nicht notwendig. Die Java-Laufzeitumgebung gibt Objekte selbst frei, wenn festgestellt wird, daß sie nicht länger benötigt werden. Dieser Prozeß ist als Speicherbereinigung bekannt. x Klassen erstellen [modifikatoren] class Klassenname [ extends Oberklassenname ] [ implements Schnittstellenname]{ datenfelddeklarationen methodendeklarationen } 9 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp i modifikatoren deklarieren, ob die Klasse öffentlich, endgültig oder abstrakt ist. public ( öffentlich): Klasse kann von Objekten außerhalb des aktuellen Paketes verwendet werden. abstract ( abstrakt): Klasse implementiert abstrakte Konzepte und kann nicht instantiiert werden. Nur von ihren Unterklassen können Objekte erzeugt werden. final ( endgültig): Klasse kann keine Unterklasse besitzen. i Klassenname legt den Namen der Klasse fest. i Oberklassenname ist der Name der Oberklasse von Klassenname. Wird für eine Klasse keine Oberklasse angegeben, wird dafür die in java.lang deklarierte Klasse Object angenommen. Die Klasse Klassenname erbt alle Datenfelder und Methoden der Oberklasse. i Schnittstellennamen ist eine durch Komma getrennte Liste von Schnittstellen, die von Klassenname implementiert werden. Eine Schnittstelle deklariert eine Menge von Methoden und Konstanten ohne Angabe von Implementierungen dafür. In einer Klassendeklaration sind nur das Schlüsselort class und der Klassenname erforderlich. Die anderen Elemente sind optional. Im Klassenrumpf sind zwei verschiedene Deklarationen möglich. Die Datenfelder einer Klasse repräsentieren den Zustand einer Klasse und ihre Methoden implementieren das Verhalten der Klasse. Datenfelder und Methoden werden als Attribute der Klasse bezeichnet. Der Zugriff auf Attribute wird mit Hilfe von Zugriffsangaben definiert. x Deklaration von Datenfeldern [zugriffsangaben] [static] [final] typ variablenname i zugriffsangaben definieren, welche anderen Klassen Zugriff auf die Variable haben (siehe Seite 11) i static zeigt an, daß die Variable eine Klassenvariable (siehe Seite 11) ist. i final zeigt an, daß die Variable eine Konstante ist. i typ bezeichnet den Klassentyp. i variablenname ist der Name der Variable. x Deklaration von Methoden [zugriffsangaben] [static] [abstract] [final] rückgabetyp methodenname ([parameterliste]) [throws ausnahmeliste] i zugriffsangaben definieren, welche anderen Klassen Zugriff auf die Methode haben i static zeigt an, daß die Variable eine Klassenvariable ist. i abstract bezeichnet Methoden ohne Implementierung und Instantiierung. i final zeigt an, daß die Variable eine Konstante ist. 10 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp i rückgabetyp deklariert den Datentyp des Wertes, den die Methode zurückgibt. i methodenname ist der Name der Methode und kann jeder gültige Bezeichner sein. i parameterliste definiert Anzahl und Typ der Argumente, die von der Methode gefordert werden. i ausnahmeliste: Wenn die Methode irgendwelche Ausnahmen auslösen kann, muß sie diese in der ausnahmeliste angeben. Eine Methode benötigt eine return-Anweisung für die Rückgabe eines Wertes. Nur beim Rückgabetyp void ist dies nicht notwendig. Eine Klasse darf eine Methode ihrer Oberklasse überschreiben und muß denselben Namen und Rückgabetyp und dieselbe Parameterliste aufweisen. Innerhalb von Methoden kann das Schlüsselwort this zum direkten Ansprechen der Klassenfelder des Objekts verwendet werden. Um Methoden oder Datenfelder der Oberklasse aufzurufen, muß das Schlüsselwort super benutzt werden. x Zugriffsangaben für Attribute private: protected: public: package: x Ein privates Attribut ist nur der Klasse zugänglich, in der es definiert ist. Zugriff wird der Klasse selbst, den Unterklassen und allen Klassen im selben Paket gewährt. Jede Klasse in jedem Paket hat Zugriff auf die öffentlichen Attribute einer Klasse. Diese Zugriffsebene erlaubt Klassen, die im selben Paket liegen und der Klasse selbst, den Zugriff auf deren Attribute. Unterschied: Instanzvariable - Klassenvariable Klassenvariablen werden mit dem Modifikator static deklariert. Das Laufzeitsystem legt Klassenvariablen einmal pro Klasse an, ganz unabhängig von der Anzahl der von dieser Klasse erzeugten Instanzen. Dagegen wird bei jeder Erzeugung einer Instanz der Klasse, eine Kopie von Instanzvariablen angelegt. x Unterschied: Instanzmethoden - Klassenmethoden Mit Methoden verhält es sich ähnlich wie mit Variablen. Klassen können Instanzmethoden und mit static definierte Klassenmethoden aufweisen. Instanzmethoden operieren auf den Instanzvariablen des aktuellen Objekts, können aber auch auf die Klassenvariablen zugreifen. Klassenmethoden können nicht auf die innerhalb der Klasse deklarierten Instanzvariablen zugreifen. solange sie nicht ein neues Objekt erzeugen und auf die Instanzvariablen über dieses Objekt zugreifen. Klassenmethoden für Klassen können ohne Instantiierung aufgerufen werden. 11 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 1.7 Negative Aspekte der Programmiersprache Java Es wurden genügend Vorteile von Java aufgezeigt. Gibt es auch Nachteile bei dieser Programmiersprache? Im Vergleich zu C, C++ verliert Java das Rennen in puncto Schnelligkeit. Wird Java aber bei interaktiven GUI- oder netzwerkbasierenden Anwendungen eingesetzt, so ist dies kein großer Nachteil, da sowieso Wartepausen entstehen. Zeitkritische Aspekte wurden innerhalb von Java in effizientem C-Code implementiert. Um ein rechenintensives Programm zu beschleunigen, können Programmteile in C oder C++ geschrieben und eingebettet werden. Java fällt insgesamt sicherlich in den mittleren Bereich eines Schnelligkeitsspektrums von Programmiersprachen. Desweiteren kann ich noch von meinen persönlichen Erfahrungen, als Anfänger in der Programmiersprache Java, berichten. Durch die umfangreiche Klassenbibliothek stehen natürlich sehr viel tolle Werkzeuge zur Verfügung. Was dabei zu Beginn vorallem schwer fällt, ist, sich einen Überblick zu verschaffen. Wo steht welche Klasse, die mir nun das Leben leichter macht? Welche Methode soll ich verwenden? Ist man aber in Java eingearbeitet, entwickelt man sicherlich eine gewisse Geübtheit in der Auswahl der zu verwendenden Klasse oder Methode. So kann ich eigentlich nicht von direkten Nachteilen sprechen. Generell denke ich, ist ein objektorientierter Ansatz einfach moderner und derzeit besser als ein nicht objektorientierter. Die Portabilität und Internetanbindung der Programmiersprache Java sprechen für sich. 12 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 1.8 Entwicklungswerkzeug und Programmstart Die Programme wurden auf einem Pentium®, 166 MHz unter dem Betriebsystem Windows 95, Version 4.0, entwickelt. Als Entwicklungswerkzeug wurde Java Development Kit (JDK), Version 1.1.6, installiert und verwendet. Der JDK stellt keine Entwicklungsumgebung bereit, sondern ist im KommandozeilenModus figuriert. Es handelt sich um Public Domain Software und eine aktuelle Version kann von der Web-Seite http://java.sun.com/products/JDK/CurrentRelease bezogen werden. Die Konkurrenz von Sun stellt selbstverständlich auch Entwicklungswerkzeuge für Java bereit. Microsoft bietet die Public Domain Software SDK für Java 3.0 an, zu finden unter: http://www.microsoft.com/java Desweiteren kann Visual J++, Version 1.1 von Microsoft kostenlos bezogen werden. http://www.microsoft.com/visualj/ Die aktuellste Version ist allerdings VJ++ 6.0. VJ++ ist integriert in die Entwicklungsumgebung des Microsoft Developer Studios. Die in einem einfachen Programm zur Textbearbeitung entwickelten Programme, werden im ASCII-Format mit der Dateinamenserweiterung .java abgespeichert. Übersetzen der Java-Quelltextdatei mit dem JDK: DOS Shell unter Windows 95: javac KlassenName.java Durch diesen Aufruf wird bei einer erfolgreichen Übersetzung die Klasse filename.class erzeugt. Die Klassendatei enthält Java-Bytecodes. Interpretieren bzw. Programmstart der Java-Anwendung mit dem JDK: DOS Shell unter Windows 95: java KlassenName Dabei enthält die Klasse Klassenname die main-Methode, um den Start des Programmes einzuleiten. 13 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 2 Douglas/Peuker Algorithmus Die Linienglättung spielt bei Generalisierungsproblemen in der Kartographie oder innerhalb eines Geo-Informationssystemen (GIS) eine große Rolle. Was genau ist unter Generalisierung zu verstehen? Definition Generalisierung (aus [4]): „Die Gesamtheit der bei der Erfassung oder kartograpischen Darstellung auftretende Generalisierungsvorgänge, mit denen, maßstabs- und themenbedingt, geometrisch, begrifflich und zeitlich die unwesentlichen Einzelheiten vernachlässigt werden und Wesentliches erhalten bleibt oder in übergeordnete Begriffe überführt wird.“ Dabei geht es im Wesentlichen darum, eine Karte in unterschiedlichen Formaten so darzustellen, daß sie lesbar bleibt. Das soll heißen, daß je nach Maßstab der Karte der Umfang der dargestellten Informationen optimal angepaßt werden soll. Man unterscheidet zwischen der Objektgeneralisierung und der kartograpischen Generalisierung. Bei der Objektgeneralisierung werden die Objekte selbst verändert, dabei wirken die Algorithmen auf die Semantik der raumbezogenen Daten. Dagegen wirkt sich die kartographische Generalisierung auf die kartographische Darstellung und somit auf die Geometrie der Objekte aus. Als Beispiel für eine rechnergestützte kartographische Generalisierung kann die Linienglättung genannt werden. Dabei unterscheidet man verschiedene Vorgehensweisen(siehe [4],[5]): x Verfahren, die die Nachbarschaft von Punkten betrachten Zum Beispiel werden über Abstand oder Pfeilhöhenbestimmung Punkte beseitigt, die eine Minimalgröße nicht überschreiten. x Sektionale Verfahren betrachten die weitere Umgebung Hierbei werden abschnittsweise Punkte entfernt, die einen vorgegebenen Abstand zu einer Kante nicht überschreiten, bis ein Punkt gefunden wird der dies nicht einhält. Danach wird von diesem Punkt beginnend weiter geglättet. x Globale Verfahren betrachten den ganzen Weg. Unter diese Kategorie fällt der Douglas/Peuker Algorithmus, der nachfolgend auf Seite 15 erläutert wird. x Approximationsverfahren Die Linie wird durch eine mathematische Funktion approximiert (z.B. Polynome, Splines,...). Bei dieser Methode werden die Punkte der Linie neu berechnet. Als einfachstes Beispiel kann die lineare Regression genannt werden. Dabei wird eine Linie z.B. mit der Douglas/Peuker Methode in Abschnitte segmentiert und für jeden Abschnitt eine ausgleichende Gerade berechnet. Die Regressionsgeraden werden dann zu einem neuen Linienzug zusammengesetzt. x Filterverfahren Durch eine Filterung im Frequenzbereich werden mit Hilfe von Tiefpaßfilter kleine Schwingungen beseitigt. 14 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Beim Douglas/Peuker Algorithmus, werden nach bestimmten Kriterien Linienstützpunkte ausgewählt oder ausgelassen. Die Linie wird als Ganzes betrachtet und die Form der Linie soll erhalten bleiben. Es handelt sich also um ein globales Verfahren. Der Algorithmus soll nun näher erläutert werden. Algorithmus der Linienglättung mit dem Douglas/Peuker Algorithmus: Der Anfangs- und Endpunkt der zu glättenden Linie, definieren eine gerade Linie. Zu dieser Linie werden sämtliche lotrechten Abstände der Zwischenpunkte berechnet. Sind alle Abstände kleiner als ein anzugebender Schwellwert, so werden die zugehörigen Zwischenpunkte bei diesem Grad der Generalisierung gelöscht. Gibt es dagegen größere Abstände, wird der Zwischenpunkt mit dem größten Abstand herangezogen und die Ausgangslinie Anfangspunkt - Endpunkt aufgeteilt in zwei Abschnitte: Anfangspunkt Zwischenpunkt und Zwischenpunkt - Endpunkt. Mit diesen zwei Abschnitten wird getrennt voneinander wie mit der Ausgangslinie gehandelt, solange bis alle unnötigen Zwischenpunkte gelöscht wurden. Es handelt sich hierbei um einen rekursiven Algorithmus. Der Schwellwert oder Glättungsparameter bestimmt die Dimension der Linienglättung. Ist er relativ groß, werden viele Punkte entfernt, ist er eher niedrig, bleiben die meisten Punkte erhalten. 15 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 3 Implementierung 3.1 Neu entworfene Klassen Die Implementierung unterteilt sich in zwei Gruppen. Die erste ist der eigentliche Douglas/Peuker Algorithmus mit den dazu notwendigen arithmetischen Operationen. Die zweite, aufwendigere Gruppe, umfaßt die Ausarbeitung einer grafischen Benutzeroberfläche zur Ein- und Ausgabe, sowie zur Visualisierung der Ergebnisse. 3.1.1 Klasse PunkteVektor zur Realisierung des Douglas/Peuker Algorithmuses In der Klasse PunkteVektor befinden sich alle notwendigen Methoden und Klassen zur Implementierung des Douglas/Peuker Algorithmus. Diese Klasse ist eine Unterklasse der Vector-Klasse, die sich im Java-Paket java.util befindet. Wie das programmtechnisch aussieht soll an ein kurzer Programmauszug zeigen: // // // public class PunkteVektor extends Vector { super(); Standardkonstruktor wird automatisch eingefügt super(parameterliste); für speziellen Konstruktor der Oberklasse Vector } Da man keinen bestimmten Konstruktor benötigt, kann auf die super-Anweisung verzichten. Standardmäßig wird die Zeile super(); eingefügt. Methoden der Oberklasse Vector werden vererbt und können genauso genutzt werden. Die von PunkteVektor aufgerufenen geerbten Methoden übernehmen das Feldmanagement und lauten: public public public public public final final final final final synchronized Object elementAt(int index) synchronized Object firstElement() int size() int indexOf(Object elem) synchronized void addElement(Object obj) Die Klasse PunkteVektor stellt folgende Methoden zur Verfügung: x Methoden für den Douglas/Peuker Algorithmus: public void glaettenVonBis (Object start, Object ende, double glaettPara) public Object getElementMaxAbstandZuLinie ( Object start, Object ende, double glaettPara ) public double getAbstandZuLinie ( Object start, Object ende, Object element) public double getDistanz ( Object p, Object q ) public void markiereZwischenElemente ( Object start, Object ende ) 16 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp x Methoden zur Verwendung bei der Visualisierung der Ergebnisse: public void visualisiereDougPeukErgebnis ( String InFile, double Border, PunkteVektor PVTrans ) public PunkteVektor transformiereFuerAusgabe () public double getxDim() public double getyDim() public double getxMin() public double getxMax() public double getyMin() public double getyMax() x Methoden zur Ein- und Ausgabe der Daten: public int schreibeAufDatei (String OutFile, boolean glaett) public int leseVonDatei (String InFile) Der Douglas/Peuker Algorithmus ist in der Methode GlaettenVonBis versteckt. Sie benötigt drei Eingabeparameter, das erste und letzte Element der Linie und den Glättungsparameter. Mit Hilfe der Methode getElementMaxAbstandZuLinie wird eine Nachricht an die Punkteliste geschickt: Hole mir den Punkt mit maximalem Abstand zur Geraden durch den Anfangs- und Endpunkt der Linie und einem größeren Abstand als der Glättungsparameter. Existiert ein solcher Punkt, so wird die Gerade in zwei Stücke geteilt. Das erste Stück läuft vom Anfangspunkt bis zum gefundenen Punkt, das zweite vom gefundenen Punkt bis zum Endpunkt. Mit diesen zwei Geraden soll nun genauso vorgegangen werden wie mit der Ausgangslinie. Dabei spielt der gefundene Punkt im ersten Teilstück die Rolle des Endpunktes, im zweiten Teilstück die Rolle des Startpunktes. Diese Technik wird Rekursion genannt, da sich die Methode selbst mit neuen Parametern aufruft. Existiert kein Punkt zwischen dem Anfangs- und Endpunkt der definierten Gerade, der obige Bedingung erfüllt, so werden die Zwischenpunkte markiert und fallen heraus. Auf die weiteren Methoden soll nicht näher eingegangen werden. Eine Beschreibung befindet sich im Quelltext der Klasse (siehe Anhang Seite Fehler! Textmarke nicht definiert.). Nur die Verwendung der Klasse Punkt muß noch erläutert werden. Die Oberklasse Vector stellt ein Feldmanagement für beliebige Objekte dar. In der Unterklasse PunkteVektor sollen diese Objekte Punkte sein. Da keine anderen Objekte vorkommen sollen, wurde die Klasse Punkt eingeführt. Sie ist geschützt, um keinen Zugriff von anderen Klassen zuzulassen. Sie ist speziell für die Klasse PunkteVektor kreiert und auch auf die Variablen soll außerhalb der Klasse PunkteVektor niemand direkt zugreifen, nur über die vorhandenen Methoden. Auszug aus der Klasse Punkt: protected class Punkt { protected String PunktNr; protected double x,y; protected boolean mark; // Punktnummer // x-,y-Koordinate // Markierung für Linienglättung // false: Punkt fällt heraus 17 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp // true: Punkt bleibt erhalten // Konstruktor 1 public Punkt (String PunktNr, double x, double y ) { this.PunktNr=PunktNr; this.x=x; this.y=y; this.mark=true; } // Konstruktor 2 public Punkt (String PunktNr, double x, double y, boolean mark) { this.PunktNr=PunktNr; this.x=x; this.y=y; this.mark=mark; } ... } Beim Einfügen eines neuen Elements in die Klasse PunkteVektor, wird ein Konstruktor der Klasse Punkt aufgerufen. Es gibt zwei unterschiedliche Konstruktoren. x Aufruf des Konstruktors 1: PVTrans.addElement(new Punkt(“Punkt Nr.2“,-1.2e-2,2.3e2)); Das Markierelement wird auf true gesetzt, das bedeutet, der Punkt bleibt bei der Glättung erhalten. Dies ist z.B. zu Beginn beim Einlesen der Daten sinnvoll. x Aufruf des Konstruktors 2: PVTrans.addElement(new Punkt(“Punkt Nr.1“,24.5,30.765,false)); Das Markierelement wird explizit auf false gesetzt, das bedeutet, der Punkt fällt bei der Glättung heraus. 3.1.2 Klassen DougPeuk und DougPeukErgebnis zur Generierung der grafischen Benutzeroberfläche Etwas aufwendiger gestaltete es sich, die grafische Oberfläche zu generieren. Die Boxen sind durchgehend Unterklassen der Klasse Frame. Mit Hilfe des GridBagLayouts wurde die Eingabebox (Abbildung 2) innerhalb der Klasse DougPeuk gestaltet. Dabei wird die Fläche in vier Zeilen und drei Spalten aufgeteilt, wobei den einzelnen oder mehreren Feldern Komponenten wie Label, Textfield oder Button zugeordnet werden können. Definition des Layouts der Eingabebox (Abbildung 2): // Layout this.setLayout(new GridBagLayout()); this.setBackground(Color.lightGray); this.setLocation(100,50); GridBagConstraints c = new GridBagConstraints(); 18 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp GridBagLayout ist der flexibelste Layoutverwalter des AWT. GridBagConstraints spezifizieren Größen- und Positionsangaben der Komponenten. Es soll nun die zweite Zeile der Eingabebox (Abbildung 2) definiert werden. Label lInFileName = new Label("Eingabedatei: tfInFileName = new TextField(15); Button bOpen = new Button("Öffnen"); bOpen.setActionCommand("OPEN"); bOpen.addActionListener(this); c.anchor=GridBagConstraints.WEST; c.gridwidth=1; c.gridx = 0; c.gridy = 1; this.add(lInFileName, c); c.gridx = 1; this.add(tfInFileName, c); c.gridx = 2; this.add(bOpen, c); "); // erste Spalte // zweite Zeile // zweite Spalte // dritte Spalte In der zweiten Zeile der Eingabebox (Abbildung 2) sollen eine Beschriftung (Label), ein Textfeld (TextField) und ein Knopf (Button) als Komponenten verfügbar sein. Dies erledigen die ersten drei Zeilen. Mit anchor wird die Ausrichtung der Komponenten definiert. Gridwidth gibt an wieviele Spalten für eine Komponente benutzt werden. Innerhalb des Gitters bewegt man sich mit den Variablen gridx und gridy. Der Nullpunkt liegt oben links. Mit add werden die Komponenten dem Fenster mit definiertem Layout c übergeben. Dem Button bOpen wurde ein ActionCommand und ein ActionListener zugeordnet. Bei Knopfdruck, wird ein Ereignis ( Event) ausgelöst, das vom Zuhörer ( Listener) registriert wird. Das Ereignis kann abgefragt werden und dementsprechend können Aktionen gestartet werden. public void actionPerformed (ActionEvent e) { // OK-Button: if (e.getActionCommand().equals("OK")) { ... } // OPEN-Button else if (e.getActionCommand().equals("OPEN")) { ... } // CANCEL-Button else if (e.getActionCommand().equals("CANCEL")) { ... } } // actionPerformed In der Ergebnisbox (Abbildung 5), die mit der Klasse DougPeukErgebnis realisiert wurde, sind gleich drei verschiedene AWT-Komponenten verwendet worden. Die Klasse Frame steht wieder als Oberklasse bereit. Neben verschiedenen Labels und Buttons, befindet sich in der Mitte der Box ein umrandeter Bereich mit einer Grafik im 19 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Innern. Diese selbst definierte Komponente, namens framedArea, kann dem Frame so zugeordnet werden: this.add(framedArea, c); Der umrahmte Bereich wird mit einem Panel erzeugt. Deshalb ist die Klasse framedArea eine Unterklasse von Panel. Die Zeichenfläche in der Mitte ist eine Unterklasse von Canvas und heißt DrawArea. Wichtig ist nun, für jede Komponente eine paint-Methode zu definieren bzw. zu überschreiben. Die paint-Methode wird vom System aufgerufen, sobald in der Box ein neues Darstellen ihres Inhalts verlangt wird. Das ist z.B. nötig, wenn die Box verschoben, deaktiviert und wieder aktiviert, „iconisiert“ und wieder „deiconisiert“ wird. Innerhalb der Klasse FramedArea soll der Rahmen gezeichnet werden, das geschieht so: public FramedArea(PunkteVektor PVTrans) { ... public void paint (Graphics g) { Dimension d=super.getSize(); g.setColor(getBackground()); g.draw3DRect(0,0,d.width-1,d.height-1,true); g.draw3DRect(3,3,d.width-7,d.height-7,false); } // paint } // FramedArea Die Originallinie und die geglättete Linie sollen innerhalb der Zeichenfläche erscheinen und deswegen ist die zugehörige paint-Methode innerhalb der DrawArea Klasse zu finden: class DrawArea extends Canvas { ... public void paint (Graphics g) { ... // geglättete Linie Punkt p=(Punkt)PVTrans.elementAt(0); int x = (int)(p.x); int y = (int)(p.y); g.setColor(textcolor); g.drawString( p.PunktNr, x+2, y-2 ); for (int i=1; i<PVTrans.size(); i++) { p=(Punkt)PVTrans.elementAt(i); if ((p=(Punkt)PVTrans.elementAt(i)).mark) { g.setColor(outline2); g.drawLine(x,y,(int)p.x,(int)p.y); x=(int)p.x; y=(int)p.y; } } // Original Linie ... } // paint } // DrawArea Für die Darstellung der Linien gibt es eine Methode, die selbständig die Koordinaten der Punkte in vernünftige Pixelkoordinaten eines bestimmten Bereichs innerhalb der 20 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Box transformiert. Sie heißt transformiereFuerAusgabe(250.Die Größe ist auf 250 Pixel festgelegt und kann in der DougPeuk-Klasse (siehe Seite Fehler! Textmarke nicht definiert.) verändert werden. In der Ergebnisbox (Abbildung 5) sind desweiteren zwei Ereignisse abzufangen. Bei Knopfdruck auf Ducken wird ein Druckjob angefordert und der Inhalt des Fensters gedruckt. Dies geschieht relativ einfach über Methoden, die Java anbietet. void print() { Toolkit toolkit = this.getToolkit(); PrintJob job = toolkit.getPrintJob(this,this.getTitle(), printprefs); if (job==null) return; Graphics g = job.getGraphics(); ... // drucke alle Komponenten des Frames this.printAll(g); // lösche Grafik g.dispose(); job.end(); } // print Zunächst muß hier ein Toolkit zur Verfügung gestellt werden. Über die Methode getPrintJob(...) wird das Standardfenster für einen Druckauftrag geöffnet. Übergeben wird das Fenster von dem der Dialog gestartet wird, um die Abhängigkeit des Fensters zu definieren. Zusätzlich kann eine Überschrift für das Fenster angegeben werden. Die Variable printprefs enthält die zuletzt angegebenen Druckervorgaben und ändert sie gegebenenfalls. Danach wird für den Druckauftrag eine Grafik erzeugt, indem sie alle Komponenten aus dem angegebenen Frame speichert und anschließend druckt. Diese Grafik wird anschließend gelöscht mit g.dispose() und der Druckauftrag beendet mit job.end(). Beispielhaft soll beim Aktivieren des Sichern-Knopfes erklärt werden, wie ein FileDialog aufgerufen wird: void save() { FileDialog f = new FileDialog (this, "Abspeichern der geglätteten Linie", FileDialog.SAVE); f.show(); String filename = f.getFile(); if (filename != null) { int i=PV.schreibeAufDatei(filename,true); } } // save Mit new FileDialog wird eine Instanz der Klasse FileDialog erzeugt (siehe Abbildung 8). Übergeben wird das Anwendungsfenster von dem das Dialogfenster aufgerufen wird, der Titel der Box und die Art des Dialogs. FileDialog.SAVE sagt aus, daß man eine Ausgabedatei zum Speichern wählen will. Möglich ist auch ein FileDialog.OPEN zum Öffnen einer Datei. Die Box wird mit f.show() sichtbar 21 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp gemacht. Der FileDialog f erhält beim Schließen des Dialogfensters Attribute, die abgefragt werden können. Hier interessiert der Dateiname, den man mit f.getFile() anfordert. Um ein Schließen der Boxen zu ermöglichen, wurde ein Adapter verwendet: this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {dispose();} }); Dies sollte einen kleinen Überblick über die Vorgehensweise des Programms DougPeuk geben. Nähere Beschreibungen aller Klassen und Methoden sind im Anhang zu finden. 3.2 Hierarchie In der Grafik werden die wichtigsten Klassen, die benutzt werden, in ihrer hierarchischen Ebene dargestellt. Die neu entworfenen Klassen sind mit grau hinterlegt. Bei den Klassen Component, Container und Graphics, handelt es sich um abstrakte Klassen. Writer BufferedWriter Reader BufferedReader Graphics GridBagLayout Vector PunkteVektor Object Label Component TextComponent TextField Canvas DrawArea Button Container Panel FramedArea Dialog FileDialog Frame DouPeuk Window DougPeukErgebnis FehlerText 22 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 3.3 main-Methode Wie schon eingangs erwähnt, umfaßt jede Java-Anwendung nur Klassen. Anfangspunkt einer Anwendung ist die Methode main, die in einer der Klassen der Anwendung definiert sein muß. Führt der Java-Interpreter eine Anwendung aus, ruft er zuerst die Methode main der betreffenden Klasse auf. Die Methode main ruft dann alle anderen für die Ausführung der Anwendung notwendigen Methoden auf. Die Klasse DougPeuk enthält die main-Methode, die den Start des Programmes einleitet. public static void main(String args[]) ... } { Der programmtechnische Ablauf gliedert sich in die Punkte: 1. Einlesen der Eingabedaten von Datei 2. Linienglättung 3. Ausgabe auf Datei Die Eingabedatei muß ein bestimmtes Format aufweisen. Am Beispiel der Testdaten soll dieses Format beschrieben werden. Abbildung 1: Eingabedatei Die Eingabedatei (Abbildung 1) ist im ASCII-Format zu beschreiben. In den Spalten 110 steht die Punktnummer des Punktes. Es folgen in den Spalten 11-20 der x-Wert und in den Spalten 21-Ende der Linie der y-Wert des Punktes. Das Ergebnis der Glättung wird visualisiert und kann gedruckt oder abgespeichert werden. Über die Eingabebox (Abbildung 2) können auch neue Eingabedaten bestimmt und eine erneute Glättung vorgenommen werden. Das Format der Ausgabedatei (Abbildung 8) entspricht dem Format der Eingabedatei. 23 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 3.4 Programmablauf In diesem Kapitel soll ein beispielhafter Programmablauf gezeigt werden. Aufgerufen wird die Klasse DougPeuk, um das Programm zu starten. Abbildung 2: Eingabebox In der Eingabebox (Abbildung 2) sind zwei Parameter anzugeben, der Eingabedateiname und der Glättungsparameter. Beider Eingabe des Dateinamens hat man zwei Möglichkeiten. Entweder man gibt den Dateinamen direkt in das Textfeld ein oder man öffnet durch drücken des Öffnen-Knopfes einen File-Dialog und wählt sich die entsprechende Datei aus. Der File-Dialog wird in Abbildung 3 dargestellt. Abbildung 3: File-Dialog-Box Hier kann jede beliebige Datei auf dem Rechner oder innerhalb des Netzwerks ausgewählt werden. Der Dateiname kann direkt eingegeben oder durch anklicken gekennzeichnet werden. Mit Öffnen wird der Dateiname in die Eingabebox (Abbildung 2) übernommen. 24 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Abbildung 4: Eingabebox mit Eingabewerten Der Glättungsparameter muß als zweiter Parameter angegeben werden. Es handelt sich hierbei um eine reelle Zahl, die Nachkommastellen werden nach einem Punkt angehängt. Sind nun beide Parameter korrekt angegeben, so wird mit Drücken des OKButtons der Douglas/Peuker Algorithmus gestartet und das Ergebnis in folgender Box (Abbildung 5) visualisiert. Abbildung 5: Ergebnisbox der Linienglättung In Abbildung 5 ist die Ausgangslinie in blau dargestellt. Die geglätteten Bereiche erscheinen rot. Die Koordinaten der Punkte der Linie werden vor Ausgabe auf dem Bildschirm in Pixelkoordinaten auf eine gleichbleibende Größe transformiert. Diese Größe ändert sich jedoch während des Programms nicht. Sie ist auf 250 Pixel festgelegt. Bei einer Veränderung der Fenstergröße, z.B. mit der Maus, kann ein Teil der Grafik verschwinden. 25 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Mit dem Knopf Drucken wird die Standard Druckbox (Abbildung 6) des Betriebssystems aufgerufen. Abbildung 6: Druckbox Sämtliche Einstellungen, die in dieser Box (Abbildung 6) verändert werden, bleiben bei einem weiteren Aufruf der Box erhalten. Mit OK wird der Druckvorgang gestartet. Abbildung 8: Box zum Sichern der Ergebnisse Wird in der Ergebnisbox (Abbildung 5) der Sichern-Knopf gedrückt, so wird ein FileDialog (Abbildung 8) gestartet. Es kann wieder der Dateiname direkt oder über Anklicken ausgewählt werden. Mit Speichern werden die Punkte der geglätteten Linie im ASCII-Format gespeichert (siehe Abbildung 8). 26 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Abbildung 8: Ergebnisdatei Hinweis: Auch mehrfaches Ausführen der Glättung ist möglich. Somit kann direkt am Bildschirm ein Vergleich der Ergebnisse stattfinden ( siehe Abbildung 9). Abbildung 9: Mehrfache Ausführung der Linienglättung 27 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 3.5 Fehlerbehandlung Methoden können Ausnahmen bzw. Fehler durch Bereitstellen einer Ausnahmebehandlung für den jeweiligen Ausnahmetyp abfangen. Dafür stehen die try/catch/finally-Blöcke zur Verfügung. Im try-Block werden die Anweisungen gehalten, die eventuell Ausnahmen auslösen. Mit einem catch-Block werden Ausnahmen abgefangen und Java-Anweisungen ausgeführt. Mit finally kann definiert werden, was auf jeden Fall durchgeführt werden soll, ob es Ausnahmen gibt oder nicht. Dies soll nun an einem Auszug aus der PunkteVektor Klasse verdeutlicht werden. public int leseVonDatei (String InFile) { BufferedReader br=null; try { ... } catch (FileNotFoundException fnfe) { String[] Texte = {"Datei '"+InFile+"' ist nicht vorhanden.", "Bitte andere Datei wählen"}; FehlerText fehler = new FehlerText(Texte); return -2; } catch (IOException io) { String [] Texte = {"Fehler '"+io+"' beim Lesen der Datei.", "Bitte Fehler beheben oder andere Datei wählen."}; FehlerText fehler = new FehlerText(Texte); return -3; } catch (NumberFormatException nfe) { String [] Texte = {"Daten der Datei '"+InFile+"' sind fehlerhaft.","Format einer Zeile: ","Punktnummer(Spalte 110), x-Wert(Spalte 11-20), y-Wert(Spalte 21-Zeilenende)", "Bitte Format anpassen oder andere Datei wählen."}; FehlerText fehler = new FehlerText(Texte); return -4; } finally { try { if (br!= null) br.close(); } catch (IOException io) { String [] Texte = {"Fehler '"+io+"' beim Schließen der Datei '"+InFile+"'.","Bitte Fehler beheben."}; FehlerText fehler = new FehlerText(Texte); return -5; } } return 0; } // leseVonDatei Es werden demnach verschiedene Fehler abgefangen. Der Name der Ausnahme muß dafür bekannt sein. 28 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Im Douglas/Peuker Programm werden Fehler in eine Infobox (siehe Abbildung 10) geschrieben, die angezeigt wird, sobald ein Fehler auftritt. Die Klasse heißt FehlerText und ist eine Unterklasse von Frame. Abgefangen werden folgende Fehler: i i i i i Weniger als zwei Punkte in der Datei FileNotFoundException: Datei nicht gefunden NumberFormatException: Falsches Format der Eingabedatei NumberFormatException: Falsches Format des Glättungsparameters IOException : Sonstige, bei der Ein- und Ausgabe, auftretenden Fehler Abbildung 10: Beispiel für Fehlerbox 29 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 3.6 Testen auf verschiedenen Plattformen Die Programme wurden auf einem PC unter Windows 95 entwickelt und in Bytecode übersetzt. Ein Programmablauf wurde in Kapitel 4.2 vorgestellt. Auf den Testplattformen muß die Java-Laufzeitumgebung und die in Bytecode übersetzten Klassendateien vorhanden sein. Es können direkt die unter Windows 95 übersetzten Dateien verwendet werden, ein neues Übersetzen ist nicht notwendig bzw. überflüssig. Zum Starten des Programms wird die Klasse DougPeuk aufgerufen. 3.6.1 Testdaten Die Eingabedatei lautet bsp3.txt und enthält zehn Punkte. Der Glättungsparameter wird mit 2.3 festgelegt. Abbildung 11: Eingabedatei Bsp3.txt 3.6.2 Test auf PC unter Windows NT Der Programmaufruf ist gleich wie unter Windows 95 (siehe Seite 13). Bei diesem Test ändert sich weder im Programmablauf noch im äußeren Erscheinungsbild der Boxen gegenüber der Windows 95 Darstellung etwas. 3.6.3 Test auf Silicon Graphics-Workstation unter Unix Das Programm konnte erfolgreich gestartet werden und lief einwandfrei. Interpretieren bzw. Programmstart der Java-Anwendung unter Unix: java KlassenName 30 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Die Boxen ändern sich in ihrer Darstellung gegenüber der Windows 95 Erscheinung. Java benützt immer die auf dem jeweiligen System gegebenen Standardfenster. So ist zum einen der Rahmen der Fenster auf jedem System verschieden gestaltet, zum anderen sind die Standardboxen für das Drucken und Datei auswählen voneinander abweichend realisiert worden. Der Inhalt der neu entworfenen Boxen wird gleich dargestellt (siehe Abbildung 12 und Abbildung 13). Abbildung 12: Eingabebox (Vergleich mit Abbildung 1) Abbildung 13: Ergebnisbox der Linienglättung (Vergleich mit Abbildung 5) 31 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Die Standardbox für einen File-Dialog ist in Unix anders verwirklicht worden. Es erscheint die in Abbildung 14 dargestellte Box. Abbildung 14: Box zum Sichern der Ergebnisse (Vergleich mit Abbildung 7) Auch die Druckerbox trägt ein anderes Erscheinungsbild. Abbildung 15: Druckbox (Vergleich mit Abbildung 6) Die Funktionalität beider Boxen (Abbildung 14 und Abbildung 15) entspricht der Funktionalität der Boxen von Windows 95 (Abbildung 6 und Abbildung 8). 32 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp 4 Fazit Die Tests dürfen als positiv bewertet werden. Java wird dem Anspruch einer portablen, plattformunabhängigen Programmiersprache gerecht. Dabei unterstützt ihr Aufbau die Konzepte der objektorientierten Programmierung. Man wird dazu gezwungen ein „Denken in Klassen“ an den Tag zu legen und die Algorithmen in den Klassen zu ordnen. Ist man erst mal eingearbeitet, so ist der Code recht leserlich. Es war interessant, mit Java zu arbeiten und ich denke, man kann Java als eine Sprache mit Zukunft bezeichnen. 33 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Literaturverzeichnis [1] [2] [3] [4] [5] Flanagan D. : JAVA in a Nutshell, A Desktop Quick Reference, 1997 Flanagan D. : JAVA Examples, A Tutorial Companion to Java in a Nutshell, 1997 Campione M. Walrath K.: Das Java Tutorial, Objetkorientierte Programmierung für das Internet, 1997 Illert A.: Digitale und Thematische Kartographie,Vorlesungsskript, SS 1996 Sester M.: GIS II, Vorlesungsskript, WS 1995 34 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Abbildungsverzeichnis Abbildung 1: Eingabedatei..............................................................................................23 Abbildung 2: Eingabebox ...............................................................................................24 Abbildung 3: File-Dialog-Box ........................................................................................24 Abbildung 4: Eingabebox mit Eingabewerten ................................................................25 Abbildung 5: Ergebnisbox der Linienglättung................................................................25 Abbildung 6: Druckbox...................................................................................................26 Abbildung 7: Box zum Sichern der Ergebnisse ..............................................................26 Abbildung 8: Ergebnisdatei.............................................................................................27 Abbildung 9: Mehrfache Ausführung der Linienglättung ..............................................27 Abbildung 10: Beispiel für Fehlerbox.............................................................................29 Abbildung 11: Eingabedatei Bsp3.txt .............................................................................30 Abbildung 12: Eingabebox (Vergleich mit Abbildung 1)...............................................31 Abbildung 13: Ergebnisbox der Linienglättung (Vergleich mit Abbildung 5)...............31 Abbildung 14: Box zum Sichern der Ergebnisse (Vergleich mit Abbildung 7) .............32 Abbildung 15: Druckbox (Vergleich mit Abbildung 6)..................................................32 35 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart Ein plattformunabhängiges Programm zur Linienglättung in Java - Sabine Knapp Anhang: Quelltexte Übersicht über die Programme: x DougPeuk.java enthält Hauptprogramm und Klasse DougPeuk und muß zum Starten des Programms aufgerufen werden mit: >java DougPeuk x DougPeukErgebnis.java enthält Klassen DougPeukErgebnis, FramedArea und DrawArea und dient zum Visualisieren des Ergebnisses x PunkteVektor.java enthält Klassen PunkteVektor und Punkt und dient zum Implementieren des Douglas/Peuker Algorithmus und zur Punkteverwaltung. 36 Studienarbeit am Institut für Photogrammetrie der Universität Stuttgart