next up previous contents
Nächste Seite: 7. Resumée Aufwärts: Diplomarbeit Vorherige Seite: 5. Realisierung   Inhalt

Unterabschnitte

6. Anwendung

Die bisher möglichst allgemein gehaltene Implementation der Java-Grafikobjekte und der Transformationsklassen bildet eine Bibliothek von Java-Klassen zur Bearbeitung von in XML codierten zweidimensionalen Grafikobjekten. Diese FlashWeather-Bibliothek soll nun zur Erzeugung von Flash-Filmen aus den Wettervorhersagedaten des Deutschen Wetterdienstes angewendet werden.


6.1 Benötigte Hard- und Software

Benötigte Hardware

Die Erzeugung der Flash-Filme ist wenig prozessor- aber sehr speicherintensiv, wie die Testläufe in Abschnitt 6.4 zeigen werden. Dabei bestimmen der Umfang der Eingabedaten und die Konfiguration des Visualisierungsvorgangs, wieviel Speicher tatsächlich benötigt wird: je höher die Auflösung der Daten, desto höher der Speicherbedarf.

Neben den Java-Grafikobjekten ist vor allem die verwendete DOM-Technologie, die XML-Dateien als Objektbäume im Speicher hält, für den hohen Bedarf an Speicher verantwortlich. Denn jeder Punkt, der in einer XML-Datei als Tag definiert ist, erweitert den entsprechenden Dokumentobjektbaum um drei Node-Objekte (Punkt, x-Attribut, y-Attribut).

Für die Erzeugung eines 170 KB großen Flash-Films, der für ein Deutschland umfassendes Gebiet für jede volle Stunde eines Tages die Wetterdaten und im Hintergrund die Landesgrenze, Flüsse, Seen und Städte zeigt, werden 50 MB Arbeitsspeicher benötigt.

Benötigte Software

Da Sun Microsystems das Java Development Kit (JDK) für Linux, Solaris und Windows implementiert und es auf fast alle anderen Plattformen portiert wurde, ist kein spezielles Betriebssystem erforderlich. Die Verwendung der Java2D-API durch Saxess Wave setzt allerdings die Existenz einer grafischen Oberfläche (X11, Windows) voraus.

Folgende Software-Pakete werden für die Erzeugung von Flash-Filmen mit den FlashWeather-Klassen benötigt und sind kostenlos im Internet verfügbar (siehe Anhang A):

Bis auf das JDK handelt es sich bei den Software-Paketen lediglich um JAR-Dateien, die der CLASSPATH-Variablen der Laufzeitumgebung hinzugefügt werden müssen.

Für die Umwandlung von ESRI Shapefiles in MapML-Dateien werden zusätzlich benötigt:

Eventuell müssen C-Programm und Bibliothek für die aktuelle Plattform erst kompiliert werden. Makefiles erleichtern diesen Vorgang. Zur Ausführung von shp2mapml unter Linux muss die Umgebungsvariable LD_LIBRARY_PATH auf das Verzeichnis der Shared Library libshp.so verweisen, in der sich die shapefile-Bibliothek befindet.

6.2 Karten- und Wetterdaten

Der Einstieg in die Verwendung der FlashWeather-Klassen erfolgt über die Klasse BaseShapeDocument, die die Schnittstelle zwischen XML-Dokument und Java-Grafikobjekten herstellt (vgl. Abbildung 5.9). Je XML-Dokumenttyp ist eine individuelle Subklasse von BaseShapeDocument zu bilden, die die bisher abstrakten Methoden buildShapes und buildDocument implementiert.

6.2.1 MapDocument

Das Ausgabeformat des Lesemoduls für ESRI Shapefiles wurde MapML genannt, da es die Elemente einer Landkarte (Städte, Flüsse, Seen und Länderumrisse) in einer XML-Ausprägung speichert. Die Subklasse von BaseShapeDocument, die dieses XML-Format in Java-Grafikobjekte überführt und umgekehrt die Grafikobjekte wieder in einen Dokumentobjektbaum verwandelt, heißt deshalb MapDocument.

MapDocument stellt drei Konstruktoren zur Verfügung, die alle das Ziel haben, aus einer XML-Quelle die entsprechenden Java-Grafikobjekte zu erzeugen. Ein String wird als URI (Uniform Resource Identifier) interpretiert, ein InputSource-Objekt als Eingabestrom behandelt und ein Dokumentobjekt direkt verarbeitet.

import de.flashweather.io.shape.BaseShapeDocument;
import ...
public class MapDocument extends BaseShapeDocument {
    public MapDocument( String uri ) throws ... {
       this( new InputSource( uri ) );
    }
    public MapDocument( InputSource in ) throws ... {
       this( this.read( in ) );
    }
    public MapDocument( Document doc ) {
       this.shape = this.buildShapes( doc ); 
    }
 
Die Methode read stammt aus der Superklasse und erstellt mit Hilfe eines validierenden DOM-Parsers einen Dokumentobjektbaum aus den Daten des Eingabestroms. Danach ist sichergestellt, dass das ursprüngliche XML-Dokument seine Dokumenttyp-Definition (DTD) erfüllt und ein gültiges Dokument ist. Seine Struktur und die verwendeten Tagnamen entsprechen den Angaben in der DTD.

Die Methode buildShapes in Quellcode 6.1 geht deshalb davon aus, dass das Argument ein gültiges Dokument liefert und überprüft nur noch den Namen des Dokumenttyps auf ,,map``. Die weiteren Anweisungen setzen nun die in der MapML-DTD definierte Struktur des Dokuments voraus. (Insofern sollte der dritte Konstruktor stets nur mit einem Dokumentobjektbaum als Argument aufgerufen werden, den ein validierender XML-Parser erstellt hat.)

protected Shape buildShapes( Document doc ) throws DOMException {

  String docname = doc.getDoctype().getName();
  if ( docname.compareTo("map") != 0 )        // check doctype
     throw new DOMException( ... );

  ShapeSet.XML_TAG = "map";                   // start new set of shapes
  ShapeSet shapeset = new ShapeSet();

  Element root   = doc.getDocumentElement();  // get root element
  String maptype = root.getAttribute("type"); // store maptype attribute
  shapeset.setAttribute("type", maptype );

  NodeList pnodes = root.getChildNodes();     // process all child nodes
  for (int i=0; i<pnodes.getLength(); i++) {  // of "map" root element

    Node pnode = pnodes.item( i );            // found a "part" element?
    if ( ( pnode.getNodeType() != Node.ELEMENT_NODE ) ||
         ( pnode.getNodeName().compareTo("part") != 0 ) ) {
      shapeset.addInfoNode( pnode );  continue;
    }
                                              // found a "part" element
    Element shapeelement = (Element) pnode;   // -> build shape
    String type = shapeelement.getAttribute("type");
    if ( type.compareTo("point") == 0 )
      shapeset.addShape( new PointShape( shapeelement ) );
    else if ( type.compareTo("line") == 0 )
      shapeset.addShape( new LineShape( shapeelement ) );
    else if ( type.compareTo("polygon") == 0 )
      shapeset.addShape( new PolygonShape( shapeelement ) );
  }
  return shapeset;
}

Quellcode 6.1: Methode buildShapes der Klasse MapDocument

 

protected Document buildDocument( Shape shape ) {

  DocumentImpl doc = new DocumentImpl();      // create new document 
  DocumentType doctype = 
    doc.createDocumentType("MapML",null,"map.dtd");
  doc.appendChild( doctype );                 // append doctype element

  shape.serialize( doc );                     // serialize shapes
  return doc;
}

Quellcode 6.2: Methode buildDocument der Klasse MapDocument

Im weiteren Verlauf erzeugt die Methode ein ShapeSet-Objekt und verarbeitet alle Elemente des MapML-Dokuments. Jedes part-Element wird entsprechend dem Wert seines Attributs ,,type`` als PointShape-, LineShape- oder PolygonShape-Objekt in den ShapeSet eingefügt. Alle Tags, die nicht den Namen ,,part`` haben, werden als Info-Knoten für die spätere Ausgabe aufbewahrt.

Das Gegenstück, die Umwandlung der Shape-Objekte in einen MapML-Objektbaum, implementiert die Methode buildDocument in Quellcode 6.2. Sie verwendet die Klasse DocumentImpl (Apaches Implementation des Document-Interface) als neues Dokumentobjekt, definiert den Dokumenttyp des Dokuments und ruft die serialize-Methode des ShapeSet-Objekts auf. Da der ShapeSet alle Grafikobjekte bzw. Kartenelemente enthält und als Container die serialize-Methode an seine Elemente weiterreicht, erstellen die Java-Grafikobjekte auf diese Weise selbstständig den Dokumentobjektbaum.

6.2.2 WeatherDocument

Eine zweite Subklasse von BaseShapeDocument wird für die Wetterdaten des DWD benötigt. Da es sich um Wetterprognosedaten handelt, heißt sie WeatherDocument.

Die Implementation der bisher abstrakten Methoden buildShapes und buildDocument ist analog zur Klasse MapDocument durchzuführen. Einen gravierenden Unterschied zwischen beiden Klassen stellt lediglich das Ausgangsformat der Eingabedaten dar. Die Kartendaten können von MapDocument nur verarbeitet werden, wenn sie im MapML-Format vorliegen. Die Wetterprognosedaten des DWD befinden sich im Gegensatz dazu in GRIB-Dateien, die zwar über das in Abschnitt 5.3.2 vorgestellte Lesemodul ausgelesen werden können, jedoch anschließend durch ein GribRecord- bzw. GridShape-Objekt repräsentiert werden.

Dieser Unterschied hat zur Folge, dass in der Klasse WeatherDocument ein weiterer Konstrukor implementiert werden muss, der die Eingabedaten in Form eines GribRecord-Objekts erhält. Quellcode 6.3 zeigt den neuen Konstruktor, der die eigentlichen Rasterdaten ermittelt und das GridShape-Objekt mit weiteren Attributen versieht.

public WeatherDocument( GribRecord grib ) {

  // configure GridPoint classes
  GridPoint.XML_TAG    = "point";
        
  // get grid of weather data as GridShape object
  this.shape = grib.getGridShape();

  // set attributes of GridShape
  this.shape.setAttribute("type",  grib.getType() );
  this.shape.setAttribute("label", grib.getDescription() );
  this.shape.setAttribute("unit",  grib.getUnit() );
  this.shape.setAttribute("level", grib.getLevel() );

  // add date and time as infonodes to GridShape
  this.shape.addInfoNode( ... );
  this.shape.addInfoNode( ... );
}

Quellcode 6.3: Konstruktor in der Klasse WeatherDocument

Um sicherzustellen, dass vor einem Aufruf der write-Methoden die Rasterdaten in Vektordaten umgewandelt wurden, wird außerdem die Methode modify aus BaseShapeDocument überschrieben (siehe Quellcode 6.4). Die neue Methode ruft die ursprüngliche modify-Methode der Superklasse auf und überprüft anschließend den Resultatwert. 

public void modify( ConfigDocument config ) throws ... {

  // configure two Shape classes
  PolygonShape.XML_TAG = "area";
  ShapeSet.XML_TAG     = "weather";

  // call metod of super class
  super.modify( config );

  // did not get a result shape?
  if ( this.shape == null )
    throw new IllegalStateException( ... );

  // did not get a ShapeSet as result? 
  // -> configuration is incorrect (<vectorize> missing?)
  if ( ! ( this.shape instanceof ShapeSet ) )  
    throw new IllegalStateException( ... );

  // add id attributes to shapes
  ShapeSet shapeset = (ShapeSet) this.shape;
  String shapesetid = shapeset.getAttribute("id");

  for (int i=0; i<shapeset.getLength(); i++)
    shapeset.getShape(i).setAttribute("id", shapesetid + "area" + (i+1));
}

Quellcode 6.4: Methode modify der Klasse WeatherDocument

Eine Vektorisierung der Rasterdaten ist notwendig, um eine Ausgabe der Wetterdaten im folgenden XML-Format zu ermöglichen, das den Namen WeatherML erhielt und die ermittelten Isoflächen speichert:

 
<weather id="..."                        Wetter-Dokument
          type="..."                     Typ/Code des Parameters
          label="..."                    Name des Parameters
          level="..."                    Höhen- oder Druckangabe
          unit="...">                    Name der Größeneinheit
     <date ... />                        Datum (Infoknoten)
     <time ... />                        Zeit (Infoknoten)
     <area id="..."                      eine Isofläche
           label="..."                   Beschriftung der Umrisslinie
           fill="...">                   Füllindex
         <point x=".." y=".." />         Punkt des Umrisses
         ...                             weitere Umrisspunkte
         <labelpoint x=".." y=".." />    Punkt für eine Beschriftung
         ...                             weitere Labelpunkte
     </area>                             Ende der Isofläche
     ...                                 weitere Isoflächen
</weather>                               Ende des Wetter-Dokuments
Das XML-Format WeatherML kann gegebenenfalls erneut von der Klasse WeatherDocument eingelesen und weiterverarbeitet werden. Es stellt das Pendant zu MapML dar und die Methoden buildShapes und buildDocument wurden entsprechend umgesetzt. Abbildung 6.1 stellt die möglichen Datenformate der Karten- und Wetterdaten während des Visualisierungsprozesses gegenüber.

Abbildung 6.1: Karten- und Wetterdatenformate


6.3 Erzeugung eines Wetterfilms

Nachdem nun zwei spezielle Subklassen von BaseShapeDocument zur Verfügung stehen, die für die Karten- und Wetterdaten die konkrete Schnittstelle zwischen XML-Datei und Java-Grafikobjekten bilden, fehlen für die Erzeugung der Wetterfilme nur noch wenige Komponenten: Für Karten- und Wetterdaten werden jeweils

benötigt. Die nächsten Abschnitte erstellen Schritt für Schritt den Flash-Wetterfilm.

6.3.1 Konfiguration

Wetterdaten

Die Konfigurationsdatei für die Transformationen der DWD-Wetterprognosedaten enthält die folgenden Angaben:

  1. Generalisierung des Rasters
    <generalize cols="3"  rows="3" />
    Fasst jeweils 3x3 Rasterpunkte zu einem einzelnen Punkt zusammen, um die Anzahl der Rasterpunkte und damit Auflösung der Daten zu verringern. Hier kann die Größe des resultierenden Flash-Films entschieden beeinflusst werden.

  2. Rotation des Gradnetzes
    <project    class="de.flashweather.graph2d.project.RotateGeoLLGrid" 
                type="rotategrid" 
                rotaxis1="y"  rotangle1="-57.5" 
                rotaxis2="z"  rotangle2="-10.0" />
    Rotiert das Netz der Längen- und Breitengrade um 57,5° um die y-Achse und um 10,0° um die z-Achse. Der Schnittpunkt von Äquator und Nullmeridian liegt dabei auf der x-Achse (vgl. Abbildung 4.11).

    Die Positionen der Rasterpunkte sind ursprünglich bezüglich eines rotierten Längen- und Breitengradnetzes definiert und werden in diesem Schritt zu geografischen Koordinaten konvertiert.

  3. Lambert-Projektion
    <project    class="de.flashweather.graph2d.project.Geo2Lambert" 
                type="azimuthal" 
                refx="10.0"  refy="50.0" />
    Projeziert alle Rasterpunkte (Punkte auf der Erdoberfläche) mit Hilfe der azimuthalen Lambert-Projektion in die Ebene.

  4. Skalierung mit Spiegelung
    <scale      xscale="+4200.0"  yscale="-4200.0" />
    Ein negativer Wert für die Skalierung in y-Richtung bewirkt eine vertikale Spiegelung des Rasters, die notwendig ist, da die geografischen Breitengrad-Koordinaten in Richtung des Nordpols (nach oben) ansteigen, die y-Koordinatenachse des Flash-Films aber nach unten zeigt. Betragsmäßig identische Skalierungswerte in x- und y-Richtung erhalten das Größenverhältnis von Breite zu Höhe.

  5. Verschiebung
    <translate xtranslate="380"  ytranslate="386" />
    Diese Anweisung verschiebt die Grafikobjekte nach rechts und unten, da sich der Ursprung des Flash-Films in der linken oberen Ecke befindet.

    Die Werte für Skalierung und Translation der Grafikobjekte können berechnet werden, werden aber am einfachsten durch Ausprobieren anhand der Hintergrundelemente ermittelt. Ist z.B. der Umriss von Deutschland korrekt in der Mitte des Flash-Films platziert worden, können bzw. müssen die Werte für die Wetterdaten übernommen werden.

  6. Clipping I
    <clip       class="de.flashweather.graph2d.clip.ClipperImpl"
                xmin="0"  xmax="800" 
                ymin="0"  ymax="600" />
    Ein Clipping der Rasterdaten verkleinert das Raster und verringert damit den Aufwand für die nachfolgende Vektorisierung. (Der Clipping-Algorithmus eliminiert prinzipiell alle Spalten und Zeilen des Rasters, die komplett außerhalb des Clipping-Fensters liegen. Jeweils eine nicht-sichtbare Zeile und Spalte an den Rändern des Clipping-Fensters wird jedoch verschont, damit das Raster immernoch die gesamte Fläche des Fensters bedeckt.)

  7. Vektorisierung
    <vectorize  class="de.flashweather.graph2d.vectorize.VectorizerImpl" 
                isovalues="0.1 0.3 0.5 0.7 0.9" 
                cutoutinternalpolygons="true" />
    Die Vektorisierung ist die einzige Transformation die für jeden Parametertyp der Wetterdaten unterschiedlich konfiguriert werden muss. Die Isowerte sind dem Wertebereich des Parameters entsprechend zu formulieren und das Ausschneiden der Polygonflächen hängt genauso wie die Beschriftung der Isoflächen von dem gewünschten Layout des Flash-Films ab.

    Das Beispiel stammt aus der Konfigurationsdatei für die Bewölkungsvorhersage, die den Grad der Bedeckung in Prozent angibt. Beschriftungspunkte werden nicht ermittelt.

  8. Clipping II
    <clip       class="de.flashweather.graph2d.clip.ClipperImpl"
                xmin="0"  xmax="800"
                ymin="0"  ymax="600" />
    Das zweite Clipping ist ein Polygon-Clipping und schneidet die aus den Rasterdaten erzeugten Vektorgrafikobjekte auf die gewünschte rechteckige Größe des Flash-Films zurecht. Die Transformation der Wetterdaten ist damit abgeschlossen.

Kartendaten

Die entsprechende Konfigurationsdatei für die Transformation der vorliegenden Kartendaten enthält nur die Punkte 3, 4, 5 und eventell Punkt 8. Eine Generalisierung (Punkt 1) ist genauso wie eine Vektorisierung (Punkt 7) nicht möglich, da die MapML-Daten bereits Vektorgrafikobjekte beschreiben. Eine Rotation des zugrundeliegenden Gradnetzes (Punkt 2) muss nicht durchgeführt werden, da die Definitionspunkte der Grafikobjekte bereits in geografischen Koordinaten angegeben sind. Das Clipping (Punkt 8) kann eventuell entfallen, wenn die Kartenelemente komplett übernommen werden sollen (z.B. gesamte Deutschlandkarte), es muss auf jeden Fall nur einmal durchgeführt werden.

6.3.2 XSLT-Stylesheet

Die Hauptaufgabe der Konfigurationsdatei ist es, die Wetter- und Kartendaten für die Visualisierung soweit vorzubereiten, dass die Grafikobjekte eines gewünschten Ausschnitts in Koordinatenangaben vorliegen, die direkt als Pixel eines Flash-Films verwendet werden können. Das XSLT-Stylesheet bestimmt nun noch:

Die Definition einer Stadt in MapML lautet z.B.
<map type="city">
     <part id="city1" type="point" label="Hamburg" category="1"> 
         <point x="9.9748" y="53.5358"/>
     </part>
</map>
und durchläuft die in Quellcode 6.5 genannten XSLT-Templates. Die tatsächliche SWFML-Ausgabe in diesem Ausschnitt der Datei map2swfml.xslt ist blau markiert.
<?xml-stylesheet type="text/xml"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <!-- movie and shape layout -->
    <xsl:variable name="moviewidth">800</xsl:variable>
    <xsl:variable name="movieheight">600</xsl:variable>
    <xsl:variable name="movierate">1</xsl:variable>
    <xsl:variable name="moviebgcolor">FFB0B0B0</xsl:variable> 
    <xsl:variable name="labeltextcolor">FF000000</xsl:variable>
    <xsl:variable name="labeltextsize">8</xsl:variable>

    <!-- rule for document root: start and end swfml -->
    <xsl:template match="map">
        <SWF rate="{$movierate}"     w="{$moviewidth}"
             color="{$moviebgcolor}" h="{$movieheight}">
            <xsl:apply-templates select="part" mode="defineshapes"/>
            <xsl:apply-templates select="part" mode="placeshapes"/>
        </SWF>
    </xsl:template>

    <!-- define all cities -->
    <xsl:template match="map[@type='city']/part" mode="defineshapes">
        <ellipse ID="{@id}" lc="FF000000" lw="1" color="FFFF0000"
                 x="}\{floor(point/@x) - 2\}\textcolor{blue}{" w="4"}
                 y="}\{floor(point/@y) - 2\}\textcolor{blue}{" h="4"/>}
        <text ID="{@id}label" color="{$labeltextcolor}"
              size="{$labeltextsize - @category}"
              x="{floor(point/@x) - $labeltextsize}"
              y="{floor(point/@y - $labeltextsize)}">
            <xsl:value-of select="@label"/>
        </text>
    </xsl:template> 

    <!-- rule for all points -->
    <xsl:template match="point">
        <point x="{floor(@x)}" y="{floor(@y)}"/>
    </xsl:template> 

    <!-- place city shapes -->
    <xsl:template match="map[@type='city']/part" mode="placeshapes">
        <PlaceObject ID="{@id}"      depth="3"/>
        <PlaceObject ID="{@id}label" depth="4"/>
    </xsl:template>

    ...

</xsl:stylesheet>

Quellcode 6.5: Ausschnitt aus map2swfml.xslt 

Der Aufbau der XSLT-Datei weather2swfml.xslt, die die Anweisungen für die Übersetzung einer WeatherML-Quelle nach SWFML enthält, ist nur unwesentlich komplizierter. Für jeden Parametertyp (Temperatur, Niederschlag, ...) ist den Isoflächen bzw. den daraus resultierenden Polygonen die dem Füllindex entsprechende Füllfarbe zuzuordnen. Die Anzahl der möglichen Füllfarben wird durch die Anzahl der Isowerte bestimmt, die während der Vektorisierung verwendet wurden.

6.3.3 Java-Applikation

Eine Applikation, die alle bisher entwickelten Komponenten verbindet und die Erzeugung einer SWFML-Datei aus einer MapML-, einer WeatherML- oder einer GRIB-Datei ermöglicht, setzt sich aus den folgenden Anweisungen zusammen:

  1. Die Erzeugung der Objekte für Wetter- und Kartendaten

    GribFile gribfile = new GribFile( Name der GRIB-Datei ); 
    GribRecord gribrec = gribfile.getRecord( Nummer des GRIB-Records ); 
    WeatherDocument doc = new WeatherDocument( gribrec );

    oder

    WeatherDocument doc = new WeatherDocument( Name der WeatherML-Datei );

    oder

    MapDocument doc = new MapDocument( Name der MapML-Datei );

  2. Die Erzeugung der Objekte der Konfigurationsdateien

    ConfigDocument config  = new ConfigDocument( Name der Konfigurationsdatei );
    FileInputStream xslt  = new FileInputStream( Dateiname des XSLT-Stylesheets );

  3. Die Erzeugung des Ausgabestreams

    FileOutputStream output = new FileOutputStream( Dateiname der Ausgabedatei );

  4. Die Transformation der Grafikobjekte

    doc.modify( config );

  5. Die Ausgabe der Grafikobjekte als XML-Datei

    doc.write( output );

    oder (mit Übersetzung der XML-Ausprägung)
     
    doc.write( xslt, output );

Ein Vertreter dieser Applikationen ist z.B. Grib2ml, das als Input eine GRIB-Datei erwartet. Quellcode 6.6 zeigt einen Ausschnitt des Programmcodes. Ein Aufruf erfolgt von der Kommandozeile mit den Parametern:
 
java Grib2ml gribfile recordnumber configfile outputfile


oder wie in Quellcode 6.6 mit der Übersetzung von WeatherML in eine andere XML-Ausprägung

java Grib2ml gribfile recordnumber configfile xsltfile outputfile
Der Befehl
java Grib2ml dwd_tmp_199912261500.grb 1 grib_dwd_tmp.configml \ 
             weather2swfml.xslt tmp15.swfml
verarbeitet die Temperaturprognose des DWD für den 26.12.1999 um 15 Uhr (Zeitzone: GMT) zu einer SWFML-Datei. Dabei wird eine Kontrollausgabe erzeugt, wie in Quellcode 6.7 aufgelistet.
// get GRIB record
GribFile grib = new GribFile( args[0] ); 
int recordnumber = Integer.parseInt( args[1] );
GribRecord gribrec = grib.getRecord( recordnumber );

// create WeatherDocument from GRIB record
WeatherDocument weather = new WeatherDocument( gribrec );

// read configuration and transform graphic objects
ConfigDocument config = new ConfigDocument( args[2] ); 
weather.modify( config );

// use XSLT stylesheet during output of graphic objects
FileInputStream xslt = new FileInputStream( args[3] );
OutputStream out = new FileOutputStream( args[4] );
weather.write( xslt, out );

Quellcode 6.6: Ausschnitt aus Grib2ml.java

Reading GRIB file information...

GRIB record:
    IS section:
        Grib Edition 1
        length: 117980 bytes
    PDS section:
        parameter: Temperature
        level: 2 m above ground
        time: 26.12.1999  16:0
        dec.scale: 0
        GDS exists
        BMS exists
    GDS section:
        Rotated LatLon Grid  (325x325)
        lon: -12.5 to 7.75  (dx 0.062)
        lat: 3.25 to -17.0  (dy -0.063)
        south pole: lon 10.0 lat -32.5
        rot angle: 0.0
    BMS section:
        bitmap length: 105625
    BDS section:
        min/max value: -15.167572 20.332428
        ref. value: -15.167572
        bin. scale: -2
        num bits: 8

Generalizing...
    grid size before: 325x325
    ... combining 3 columns and 3 rows ...
    new grid size: 109x109

Projecting...
    rotated lat/lon grid -> geographic coordinates

Projecting...
    geographic coordinates -> Azimuthal Lambert projection
    reference point: (10.0,50.0)
    new bounds: x=[-0.21727598, 0.13271724] y=[-0.17233898, 0.18625306]

Resizing grid extent...
    new bounds: x=[-912.5591, 557.4124] y=[-782.2628, 723.8237]

Moving grid...
    new bounds: x=[-532.5591, 937.4124] y=[-396.26285, 1109.8237]

Clipping...
    grid size before clip: 109x109
    clip window: min=(-20.0,-20.0) max=(850.0,620.0)
    ... clipping ...
    grid size after clip: 66x48

Vectorizing...
    iso values: -25.0 -20.0 -15.0 -10.0 -5.0 0.0 5.0 10.0 15.0 20.0 25.0 30.0 35.0 40.0
    ... searching for iso values and building polygons ...
    ... cleaning up polygons ...
    found 20 polygons (10 internal) with 1382 points and 37 labels

Clipping...
    20 shapes before clip
    clip window: min=(0.0,0.0) max=(800.0,600.0)
    ... clipping ...
    17 shapes after clip

Building weather document...

Translating document...

Printing document...

Quellcode 6.7: Grib2ml-Kontrollausgabe 

Zwei weitere Applikationen, die SWFML-Dateien erzeugen, sind Weather2ml und Map2ml. Beide Java-Programme lesen WeatherML- bzw. MapML-Dateien ein und geben dasselbe Format wieder aus oder wandeln es nach SWFML um, sofern ein XSLT-Stylesheet - z.B. weather2swfml.xslt bzw. map2swfml.xslt - als Kommandozeilenparameter angegeben wird.

Die Applikation Swfml2Swf erzeugt abschließend aus allen SWFML-Dateien den Flash-Film. Swfml2Swf wurde bereits in Abschnitt 5.7 vorgestellt. Der Quellcode befindet sich mit allen anderen Programmen dieser Beispielanwendung der FlashWeather-Bibliothek auf der beigefügten CD-ROM im Verzeichnis /beispiel.


6.4 Testläufe

6.4.1 Testumgebung

Um die Lauffähigkeit der oben genannten Progamme zu testen und ihren Ressourcenbedarf zu messen, wurde die Erzeugung von Flash-Wetterfilmen auf folgenden Rechnern und Betriebssystemen durchgeführt:

6.4.2 Programmaufrufe

Der Test umfasst die folgenden vier Programmaufrufe, bei denen die Konfigurationsdateien und XSLT-Stylesheets aus Abschnitt 6.3 zum Einsatz kommen:

  1. Map2ml: Erzeugen einer SWFML-Datei aus einer MapML-Datei
    Die MapML-Datei hat eine Dateigröße von 143KB und die erzeugte SWFML-Datei ist 140KB groß.
    java Map2ml country.mapml map_deu.configml \
                map2swfml.xslt country.swfml

  2. Grib2ml: Erzeugen einer SWFML-Datei aus einem GRIB-Record
    Die GRIB-Datei hat eine Dateigröße von 115KB und enthält nur einen Datenrecord. Die erzeugte SWFML-Datei ist 45KB groß.
    java Grib2ml dwd_tmp_15.grib 1 grib_dwd_tmp.configml \
                 weather2swfml.xslt tmp15.swfml

  3. Grib2ml: Erzeugen aller 24 SWFML-Dateien einer Tagesprognose
    Die GRIB-Dateien haben alle eine Dateigröße von 115KB und enthalten nur einen Datenrecord.
    for I in 00 01 02 03 04 05 06 07 08 09 10 11 \
             12 13 14 15 16 17 18 19 20 21 22 23
    do
         java Grib2ml dwd_tmp_"$I".grib 1 grib_dwd_tmp.configml \
                      weather2swfml.xslt tmp"$I".swfml
    done

  4. Swfml2Swf: Erstellen des Flash-Films aus 24 + 4 SWFML-Dateien
    Die SWFML-Dateien habe eine durchschnittliche Dateigröße von 45KB, der erzeugte Flash-Film hat eine Dateigröße von 170KB.
    java Swfml2Swf country.swfml river.swfml lake.swfml city.swfml \
                    tmp*.swfml tmp.swf

6.4.3 Messergebnisse

Auf jedem der vier Testrechner wurden alle vier Programmaufrufe durchgeführt. Die Laufzeit wurde mit dem time-Kommando gemessen und der maximale Arbeitsspeicherbedarf anschliessend in einem unabhängigen Test mit Hilfe von top oder dem NT-Taskmanager ermittelt. Die Testergebnisse können daher Ungenauigkeiten enthalten, geben aber eine recht gute Größenordnung der Laufzeit und des verwendeten Hauptspeichers wieder.

Die Ergebnisse der Testläufe enthält Tabelle 6.1.


  Pentium III 633Mhz
128MB, Linux 7.0
Pentium II 433Mhz
128MB, Linux 6.3
Pentium II  433Mhz
256MB, Windows 2000
 Pentium I  90Mhz
32MB, Linux 6.3
1. Map2ml 14.5s / 16.2MB 18.9s / 14.8MB 10.4s / 16.2MB 1min 3s / 15.4MB
2. Grib2ml 8.5s / 19.5MB 11.3s / 18.9MB 8.9s / 18.8MB 37.4s / 19.1MB
3. Grib2ml 3min 18s / 19.5MB 4min 18s / 18.9MB 3min 36s / 18.8MB 14min 5s / 19.1MB
4. Swfml2Swf 1min 7s / 51.0MB 1min 34s / 51.8MB 47s / 52.9MB 5min 56s / 52.0MB

Tabelle 6.1: Messergebnisse der Testläufe


Eine Optimierung der Laufzeit ist jederzeit durch die Flagge -Xms<Speichergröße> des Java-Interpreters möglich, die der Applikation schon zu Beginn der Ausführung die angegebene Menge Arbeitspeicher reserviert. Z.B. verkürzt der Aufruf

java -Xms20MB Grib2ml dwd_tmp_15.grib 1 grib_dwd_tmp.configml \
                      weather2swfml.xslt tmp15.swfml
die Laufzeit des zweiten Testkommandos auf dem Penium III auf 7.3s (vorher 8.5s).

 

6.5 Wetterfilme

Vom Deutschen Wetterdienst stehen Prognosedaten für den 26.12.1999 zur Verfügung, die die Parameter Temperatur, Niederschlag, Bewölkungsgrad und Luftdruck umfassen. Das rote Rechteck in Abbildung 6.2 markiert das Gebiet, das die Daten abdecken. Die daraus erzeugten Flash-Filme zeigen die Abbildungen 6.3 bis 6.6.


Abbildung 6.2: Abgedecktes Gebiet der DWD-Daten

Abbildung 6.3: Deutschland: Temperatur

Abbildung 6.4: Deutschland: Bewölkungsgrad

Abbildung 6.5: Deutschland: Niederschlag

Abbildung 6.6: Deutschland: Luftdruck

Weitere GRIB-Dateien wurden von einem Internetrechner des National Weather Service (NWS) der USA heruntergeladen [NWS2000]. Sie enthalten die Wetterprognose für die gesamte Erde, die Auflösung des Rasters ist jedoch viel geringer als bei den Daten des DWD. Außerdem liegt zwischen den Prognosen ein zeitlicher Abstand von drei Stunden. Die Abbildungen 6.7 und 6.8 zeigen Momentaufnahmen aus möglichen Wetterfilmen.

Abbildung 6.7: Deutschland: Temperatur und Bewölkungsgrad

Abbildung 6.8: Afrika: Temperatur


next up previous contents
Nächste Seite: 7. Resumée Aufwärts: Diplomarbeit Vorherige Seite: 5. Realisierung   Inhalt
Benjamin Stark
2001-02-14