//$Header: /home/deegree/jail/deegreerepository/deegree/src/org/deegree/demo/DemoMapView.java,v 1.34 2006/11/27 09:07:52 poth Exp $
/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2004 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/exse/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Meckenheimer Allee 176
53115 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.demo;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.StringReader;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import org.deegree.datatypes.QualifiedName;
import org.deegree.framework.xml.XMLTools;
import org.deegree.graphics.Layer;
import org.deegree.graphics.LazyRasterLayer;
import org.deegree.graphics.MapFactory;
import org.deegree.graphics.MapView;
import org.deegree.graphics.Theme;
import org.deegree.graphics.sld.StyleFactory;
import org.deegree.graphics.sld.UserStyle;
import org.deegree.io.datastore.schema.MappedFeatureType;
import org.deegree.io.datastore.schema.MappedGMLSchema;
import org.deegree.io.datastore.schema.MappedGMLSchemaDocument;
import org.deegree.io.shpapi.ShapeFile;
import org.deegree.model.crs.CRSFactory;
import org.deegree.model.crs.CoordinateSystem;
import org.deegree.model.feature.Feature;
import org.deegree.model.feature.FeatureCollection;
import org.deegree.model.feature.FeatureFactory;
import org.deegree.model.feature.GMLFeatureAdapter;
import org.deegree.model.feature.GMLFeatureCollectionDocument;
import org.deegree.model.filterencoding.AbstractFilter;
import org.deegree.model.filterencoding.Filter;
import org.deegree.model.spatialschema.Curve;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.model.spatialschema.Geometry;
import org.deegree.model.spatialschema.GeometryException;
import org.deegree.model.spatialschema.GeometryFactory;
import org.deegree.model.spatialschema.GeometryImpl;
import org.deegree.model.spatialschema.MultiCurve;
import org.deegree.model.spatialschema.MultiPoint;
import org.deegree.model.spatialschema.MultiSurface;
import org.deegree.model.spatialschema.Point;
import org.deegree.model.spatialschema.Ring;
import org.deegree.model.spatialschema.Surface;
import org.deegree.ogcwebservices.wcs.describecoverage.CoverageDescriptionDocument;
import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
import org.deegree.ogcwebservices.wfs.operation.Query;
import org.opengis.coverage.grid.GridCoverage;
import org.w3c.dom.Document;
/**
* Sample application to demonstrate deegree's mechanisms for reading vector and raster data from the
* following sources:
* <ul>
* <li>ESRI shape file</li>
* <li>GML file</li>
* <li>deegree feature persistence layer (datastore)</li>
* <li>Coverages</li>
* </ul>
* <p>
* The data is displayed in an interactive map.
* <p>
* Saving of vector data as either shape or GML is also demonstrated.
*
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
* @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
*
* @author last edited by: $Author: poth $
*
* @version 1.0, $Revision: 1.34 $, $Date: 2006/11/27 09:07:52 $
*/
public class DemoMapView extends JFrame {
private static final long serialVersionUID = -1665647914613642719L;
private static enum TYPE {
SHAPE, GML, RASTER, DATASTORE
};
//private static String INPUT = "E:\\deegree2_masterCD\\apache-tomcat-5.5.12\\webapps\\deegree2demo\\WEB-INF\\conf\\wfs\\featuretypes\\CountyBoundaries2003.xsd";
private static String INPUT = "D:\\java\\projekte\\testwcs\\data\\tiles\\wcs_utah_configuration.xml";
//private static String INPUT = "file:///e:/temp/wf.xml";
//private static String INPUT = "e:/temp/Mo-Usg-extrem";
// private static String INPUT = "E:\\deegree2_masterCD\\apache-tomcat-5.5.12\\webapps\\deegree2demo\\WEB-INF\\data\\utah\\vector\\admin\\SGID500_ZipCodes";
//private static String INPUT = "E:/temp/schema.xsd";
private static String OUTPUT = "e:\\temp\\output";
//private static String CRS = "epsg:4326";
//private static String CRS = "epsg:26912";
//private static String CRS = "epsg:2152";
//private static String CRS = "epsg:31466";
private static String CRS = "epsg:4326";
private MapView mapView;
private TYPE dataType = TYPE.RASTER;
/**
* Creates a new instance of <code>DemoMapView</code>.
*
*/
public DemoMapView( ) {
setSize( 750, 960 );
setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
getContentPane().setLayout( null );
this.addKeyListener( new MyKeyListener() );
setVisible( true );
}
/**
* Runs the application.
*/
public void run()
throws Exception {
List<Theme> themes = new ArrayList<Theme>();
if ( dataType == TYPE.GML ) {
FeatureCollection fc = loadGML();
saveAsGML( fc );
themes.add( createTheme( fc ) );
} else if ( dataType == TYPE.SHAPE ) {
FeatureCollection fc = loadShape();
saveAsShape( fc );
themes.add( createTheme( fc ) );
} else if ( dataType == TYPE.RASTER ) {
CoverageOffering co = loadRaster();
themes.add( createTheme( co ) );
} else if ( dataType == TYPE.DATASTORE ) {
FeatureCollection fc = loadFromDatastore();
saveAsGML( fc );
themes.add( createTheme( fc ) );
}
createMap( themes );
repaint();
}
/**
* Loads a shape file and returns the content as deegree <code>FeatureCollection</code>.
*
* @see FeatureCollection
* @return shape file content
*/
private FeatureCollection loadShape()
throws Exception {
ShapeFile sf = new ShapeFile( INPUT );
FeatureCollection fc =
FeatureFactory.createFeatureCollection( "id", sf.getRecordNum() );
CoordinateSystem crs = CRSFactory.create( CRS );
int k = 0;
System.out.println( "No. of features: " + sf.getRecordNum() );
for ( int i = 0; i < sf.getRecordNum(); i++ ) {
Feature feat = sf.getFeatureByRecNo( i + 1 );
GeometryImpl geom = (GeometryImpl) feat.getDefaultGeometryPropertyValue();
k = countVertices( k, geom );
geom.setCoordinateSystem( crs );
fc.add( feat );
}
System.out.println( "No. of vertices: " + k );
sf.close();
return fc;
}
/**
* Loads a GML file and returns the content as deegree <code>FeatureCollection</code>.
*
* @see FeatureCollection
* @return GML file content
*/
private FeatureCollection loadGML()
throws Exception {
GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument();
doc.load( new URL( INPUT ) );
FeatureCollection fc = doc.parse();
System.out.println( "No. of features: " + fc.size() );
int k = 0;
for ( int i = 0; i < fc.size(); i++ ) {
Geometry geom = fc.getFeature( i ).getDefaultGeometryPropertyValue();
k = countVertices( k, geom );
}
System.out.println( "No. of vertices: " + k );
return fc;
}
/**
* Loads a <code>FeatureCollection</code> using deegree's feature persistence layer.
* <p>
* This method uses a GML application schema with persistence annotations.
* <p>
* Currently, the following backends are implemented:
* <ul>
* <li>PostGIS (reading + transactions)</li>
* <li>Oracle spatial (reading + transactions)</li>
* <li>Generic SQL DBs (reading)</li>
* <li>ArcSDE (reading + transactions)</li>
* <li>ESRI ShapeFiles (reading) </li>
* <li>...</li>
* </ul>
*
* @return selected features as a FeatureCollection
* @throws Exception
* @see org.deegree.io.datastore.Datastore
*/
private FeatureCollection loadFromDatastore()
throws Exception {
// read annotated GML application schema
MappedGMLSchemaDocument schemaDoc = new MappedGMLSchemaDocument();
schemaDoc.load( new File( INPUT ).toURL() );
MappedGMLSchema schema = schemaDoc.parseMappedGMLSchema();
// get example feature type (Counties2003)
QualifiedName ftName = new QualifiedName( "app", "Counties2003",
new URI( "http://www.deegree.org/app" ) );
MappedFeatureType ft = (MappedFeatureType) schema.getFeatureType( ftName );
// query the feature type
Query query = buildExampleQuery1( ftName );
FeatureCollection fc = ft.performQuery( query );
System.out.println (fc.getBoundedBy());
return fc;
}
/**
* Builds a simple example query that selects all features of the feature type.
*
* @param ftName name of the feature type to query
* @return query
*/
private Query buildExampleQuery1( QualifiedName ftName ) {
Query query = Query.create( ftName );
return query;
}
/**
* Builds a simple example query that selects only features of the feature type that
* match certain criteria.
*
* @param ftName name of the feature type to query
* @return query
* @throws Exception
*/
private Query buildExampleQuery2( QualifiedName ftName ) throws Exception {
String filterString =
"<Filter xmlns=\"http://www.opengis.net/ogc\" xmlns:app=\"http://www.deegree.org/app\">" +
" " +
" <PropertyIsEqualTo>" +
" <PropertyName>app:name</PropertyName>" +
" <Literal>Washington</Literal>" +
" </PropertyIsEqualTo>" +
" " +
"</Filter>";
Document doc = XMLTools.parse(new StringReader(filterString));
Filter filter = AbstractFilter.buildFromDOM(doc.getDocumentElement());
Query query = Query.create( ftName, filter );
return query;
}
/**
* Builds a simple example query that selects only features of the feature type that
* match certain criteria.
*
* @param ftName name of the feature type to query
* @return query
* @throws Exception
*/
private Query buildExampleQuery3( QualifiedName ftName ) throws Exception {
String filterString =
"<Filter xmlns=\"http://www.opengis.net/ogc\" xmlns:app=\"http://www.deegree.org/app\" xmlns:gml=\"http://www.opengis.net/gml\">" +
" <Or>" +
" <PropertyIsEqualTo>" +
" <PropertyName>app:name</PropertyName>" +
" <Literal>Washington</Literal>" +
" </PropertyIsEqualTo>" +
" <Disjoint>" +
" <PropertyName>app:geom</PropertyName>" +
" <gml:Box>" +
" <gml:coord>" +
" <gml:X>450000</gml:X>" +
" <gml:Y>4450000</gml:Y>" +
" </gml:coord>" +
" <gml:coord>" +
" <gml:X>460000</gml:X>" +
" <gml:Y>4460000</gml:Y>" +
" </gml:coord>" +
" </gml:Box>" +
" </Disjoint>" +
" </Or>" +
"</Filter>";
Document doc = XMLTools.parse(new StringReader(filterString));
Filter filter = AbstractFilter.buildFromDOM(doc.getDocumentElement());
Query query = Query.create( ftName, filter );
return query;
}
/**
* Loads a raster dataset using a GridCoverage description.
*
* @return
* @throws Exception
* @see GridCoverage
*/
private CoverageOffering loadRaster()
throws Exception {
CoverageDescriptionDocument conf = new CoverageDescriptionDocument();
conf.load( new File( INPUT ).toURL() );
return conf.getCoverageOfferings()[0];
}
/**
* Counts the number of vertices in a Geometry.
*
* @param k
* @param geom
* @return
* @throws GeometryException
*/
private int countVertices( int k, Geometry geom )
throws GeometryException {
if ( geom instanceof Surface ) {
Surface s = (Surface) geom;
k += s.getSurfaceBoundary().getExteriorRing().getPositions().length;
Ring[] r = s.getSurfaceBoundary().getInteriorRings();
if ( r != null ) {
for ( int j = 0; j < r.length; j++ ) {
k += r[j].getPositions().length;
}
}
} else if ( geom instanceof MultiSurface ) {
MultiSurface ms = (MultiSurface) geom;
Surface[] s = ms.getAllSurfaces();
for ( int g = 0; g < s.length; g++ ) {
k += s[g].getSurfaceBoundary().getExteriorRing().getPositions().length;
Ring[] r = s[g].getSurfaceBoundary().getInteriorRings();
if ( r != null ) {
for ( int j = 0; j < r.length; j++ ) {
k += r[j].getPositions().length;
}
}
}
} else if ( geom instanceof Curve ) {
Curve c = (Curve) geom;
k += c.getAsLineString().getNumberOfPoints();
} else if ( geom instanceof MultiCurve ) {
MultiCurve mc = (MultiCurve) geom;
Curve[] c = mc.getAllCurves();
for ( int j = 0; j < c.length; j++ ) {
k += c[j].getAsLineString().getNumberOfPoints();
}
} else if ( geom instanceof MultiPoint ) {
MultiPoint mp = (MultiPoint) geom;
k += mp.getAllPoints().length;
}
return k;
}
/**
* Saves the passed <code>FeatureCollection</code> as a GML file.
*
* @param fc FeatureCollection to save
* @throws Exception
* @see FeatureCollection
*/
private void saveAsGML( FeatureCollection fc )
throws Exception {
FileOutputStream fos = new FileOutputStream( OUTPUT );
GMLFeatureAdapter adapter = new GMLFeatureAdapter();
adapter.export( fc, fos );
fos.close();
}
/**
* Saves the passed <code>FeatureCollection</code> as a shape file.
*
* @param fc FeatureCollection to save
* @throws Exception
* @see FeatureCollection
*/
private void saveAsShape( FeatureCollection fc )
throws Exception {
ShapeFile sf = new ShapeFile( OUTPUT, "rw" );
sf.writeShape( fc );
sf.close();
}
/**
* Creates a map from the passed <code>CoverageOffering</code> (raster data).
*
* @param co
* @throws Exception
* @see CoverageOffering
*/
private Theme createTheme( CoverageOffering co )
throws Exception {
Layer layer = new LazyRasterLayer( "raster", co );
return MapFactory.createTheme( "MyTheme", layer );
}
/**
* Creates a map from the passed <code>Theme</code>s (vector data + styles).
*
* @param themes
* @throws Exception
*/
public void createMap( List<Theme> themes )
throws Exception {
// add a small buffer around the datas bbox to ensure
// that everything will be visible
Envelope bb = themes.get( 0 ).getLayer().getBoundingBox();
bb = bb.getBuffer( bb.getWidth() / 10d );
CoordinateSystem crs = CRSFactory.create( CRS );
// transform bbox into desired map CRS
//GeoTransformer tr = new GeoTransformer( "EPSG:4314" );
//bb = tr.transformEnvelope( bb, CRS );
// create MapView using defined bbox and Themes
mapView = MapFactory.createMapView( "MyMap", bb, crs,
themes.toArray( new Theme[themes.size()] ) );
}
/**
* Returns the geometrytype read from a data file<br>
* <ul>
* <li>1 = point or multi point
* <li>2 = curve or multi curve
* <li>3 = surface or multi surface
* </ul>
* @param fc
* @return
*/
private int getGeometryType( FeatureCollection fc ) {
Geometry geom = fc.getFeature( 0 ).getDefaultGeometryPropertyValue();
if ( geom instanceof Point || geom instanceof MultiPoint ) {
return 1;
} else if ( geom instanceof Curve || geom instanceof MultiCurve ) {
return 2;
} else if ( geom instanceof Surface || geom instanceof MultiSurface ) {
return 3;
}
return -1;
}
/**
* Creates a <code>Theme</code> from the passed <code>FeatureCollection</code>.
*
* @param fc
* @see FeatureCollection
*/
private Theme createTheme( FeatureCollection fc )
throws Exception {
UserStyle st = null;
int geomType = getGeometryType( fc );
// create a style depending on geometry type
switch ( geomType ) {
case 1:
st = (UserStyle) StyleFactory.createPointStyle( "square", Color.PINK, Color.BLACK, 1,
1, 10, 10, 0, Double.MAX_VALUE );
break;
case 2:
st = (UserStyle) StyleFactory.createLineStyle( Color.PINK, 4, 1, 0, Double.MAX_VALUE );
break;
case 3:
st = (UserStyle) StyleFactory.createPolygonStyle( Color.BLUE, 1,
new Color( 22, 22, 22 ), 4, 1, 0,
Double.MAX_VALUE );
break;
}
UserStyle[] us = new UserStyle[] { st };
// create feature layer/theme using the datas CRS
CoordinateSystem cs = CRSFactory.create( CRS );
org.deegree.graphics.Layer layer =
MapFactory.createFeatureLayer( "MyLayer", cs, fc );
return MapFactory.createTheme( fc.getId(), layer, us );
}
/**
* overrides the paint method of @see JFrame
*/
public void paint( Graphics g ) {
if ( mapView != null ) {
try {
g.setColor( Color.WHITE );
g.fillRect( 0, 0, getWidth(), getHeight() );
long l = System.currentTimeMillis();
System.out.println( "pixel resolution: " + mapView.getBoundingBox().getWidth()
/ getWidth() );
mapView.paint( g );
System.out.println( "time for rendering: " + ( System.currentTimeMillis() - l ) );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
/**
*
* @param args
* @throws Exception
*/
public static void main( String[] args ) throws Exception {
DemoMapView test = new DemoMapView( );
test.run();
test.repaint();
}
/**
* Handler for key events:
* <ul>
* <li>'i': zoom in</li>
* <li>'o': zoom out</li>
* <li>cursor up: scroll up</li>
* <li>cursor down: scroll down</li>
* <li>cursor left: scroll left</li>
* <li>cursor right: scroll right</li>
* </ul>
*/
class MyKeyListener implements KeyListener {
public void keyTyped( KeyEvent arg0 ) {
}
public void keyPressed( KeyEvent arg0 ) {
}
public void keyReleased( KeyEvent key ) {
Envelope env = mapView.getBoundingBox();
if ( key.getKeyCode() == KeyEvent.VK_I ) {
double w = env.getWidth();
double h = env.getHeight();
double mx = env.getMin().getX() + w / 2d;
double my = env.getMin().getY() + h / 2d;
w = w - ( env.getWidth() / 10d );
h = h - ( env.getHeight() / 10d );
env = GeometryFactory.createEnvelope( mx - w / 2d, my - h / 2d, mx + w / 2d, my + w
/ 2d,
env.getCoordinateSystem() );
mapView.setBoundingBox( env );
repaint();
} else if ( key.getKeyCode() == KeyEvent.VK_O ) {
double w = env.getWidth();
double h = env.getHeight();
double mx = env.getMin().getX() + w / 2d;
double my = env.getMin().getY() + h / 2d;
w = w + ( env.getWidth() / 10d );
h = h + ( env.getHeight() / 10d );
env = GeometryFactory.createEnvelope( mx - w / 2d, my - h / 2d, mx + w / 2d, my + w
/ 2d,
env.getCoordinateSystem() );
mapView.setBoundingBox( env );
repaint();
} else if ( key.getKeyCode() == KeyEvent.VK_RIGHT ) {
double d = env.getWidth() / 20d;
mapView.setBoundingBox( env.translate( -d, 0 ) );
repaint();
} else if ( key.getKeyCode() == KeyEvent.VK_LEFT ) {
double d = env.getWidth() / 20d;
mapView.setBoundingBox( env.translate( d, 0 ) );
repaint();
} else if ( key.getKeyCode() == KeyEvent.VK_UP ) {
double d = env.getWidth() / 20d;
mapView.setBoundingBox( env.translate( 0, -d ) );
repaint();
} else if ( key.getKeyCode() == KeyEvent.VK_DOWN ) {
double d = env.getWidth() / 20d;
mapView.setBoundingBox( env.translate( 0, d ) );
repaint();
}
}
}
}
/* ********************************************************************
Changes to this class. What the people have been up to:
$Log: DemoMapView.java,v $
Revision 1.34 2006/11/27 09:07:52 poth
JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
Revision 1.33 2006/11/16 10:04:03 poth
*** empty log message ***
Revision 1.32 2006/10/17 15:00:37 poth
*** empty log message ***
Revision 1.31 2006/08/06 20:11:00 poth
*** empty log message ***
Revision 1.30 2006/08/06 20:06:55 poth
useless parameters removed
Revision 1.29 2006/08/02 18:50:40 poth
*** empty log message ***
Revision 1.28 2006/06/12 08:16:59 poth
*** empty log message ***
Revision 1.27 2006/06/08 17:59:59 poth
*** empty log message ***
Revision 1.26 2006/06/08 09:38:23 mschneider
Implemented loadFromDatastore(). Improved documentation.
Revision 1.25 2006/06/07 17:12:02 mschneider
Improved javadoc.
Revision 1.24 2006/06/03 12:23:48 poth
*** empty log message ***
Revision 1.23 2006/05/31 13:20:03 poth
*** empty log message ***
Revision 1.22 2006/05/31 13:00:32 poth
support for raster data (GridCoverages) as well as for zoom and pan (using keyboard) added
Revision 1.21 2006/05/31 08:43:11 poth
method for counting vertices added
Revision 1.20 2006/05/26 07:21:50 poth
some enhancements
Revision 1.19 2006/05/25 16:37:17 poth
*** empty log message ***
Revision 1.18 2006/05/25 16:17:03 poth
some code cleanups
Revision 1.17 2006/05/16 07:33:20 poth
commentation completed
********************************************************************** */