/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2007-2008, Open Source Geospatial Foundation (OSGeo) * * 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; * version 2.1 of the License. * * 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. */ package org.geotools.renderer3d.example; import org.geotools.data.FeatureSource; import org.geotools.data.shapefile.ShapefileDataStore; import org.geotools.factory.CommonFactoryFinder; import org.geotools.gui.swing.JMapPane; import org.geotools.map.DefaultMapContext; import org.geotools.map.MapContext; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.renderer.lite.StreamingRenderer; import org.geotools.renderer3d.Renderer3D; import org.geotools.renderer3d.Renderer3DImpl; import org.geotools.renderer3d.utils.canvas3d.FrameListener; import org.geotools.styling.BasicLineStyle; import org.geotools.styling.SLDParser; import org.geotools.styling.Style; import org.geotools.styling.StyleFactory; import org.opengis.referencing.crs.CoordinateReferenceSystem; import javax.swing.*; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Cursor; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.io.IOException; import java.net.URL; /** * An example of using the 3D map. * * @author Hans H�ggstr�m */ public class Show3DMapExample { //====================================================================== // Public Methods //---------------------------------------------------------------------- // Main Method public static void main( String[] args ) throws IOException { // Create some data /* DEBUG: final ExampleDataGenerator exampleDataGenerator = new ExampleDataGenerator(); final MapContext exampleMap = exampleDataGenerator.createExampleMap(); */ final MapContext exampleMap = createContextFromShapefile( new URL( "file:example_data/countries/countries.shp" ), new URL( "file:example_data/simple_style.sld" ) ); // Create a 3D renderer final Renderer3D renderer3D = new Renderer3DImpl( exampleMap ); final Component mapView3D = renderer3D.get3DView(); // Create a 2D renderer with the same data for comparsion final StreamingRenderer streamingRenderer = new StreamingRenderer(); final JMapPane mapView2D = new JMapPane( streamingRenderer, exampleMap ); mapView2D.setMapArea( exampleMap.getLayerBounds() ); mapView2D.setState( JMapPane.Pan ); mapView2D.setCursor( new Cursor( Cursor.MOVE_CURSOR ) ); // Build and show the rest of the UI final JLabel labelFor3DView = new JLabel( "3D map renderer" ); createUi( wrapInTitledPanel( mapView3D, labelFor3DView ), wrapInTitledPanel( mapView2D, new JLabel( "2D JMapPanel view" ) ) ); // Show frames per second in a swing label renderer3D.addFrameListener( createFpsDisplayer( labelFor3DView, "3D map renderer" ) ); } //====================================================================== // Private Methods private static FrameListener createFpsDisplayer( final JLabel labelFor3DView, final String message ) { return new FrameListener() { private double time_s = 0; private int frames = 0; public void onFrame( final double secondsSinceLastFrame ) { time_s += secondsSinceLastFrame; frames++; if ( time_s > 1 ) // Calculate average fps over one second { final int fps = (int) ( frames / time_s ); labelFor3DView.setText( message + " (" + fps + " FPS)" ); time_s = 0; frames = 0; } } }; } private static JPanel wrapInTitledPanel( Component component, final JLabel label ) { final JPanel panel = new JPanel( new BorderLayout() ); panel.add( component, BorderLayout.CENTER ); panel.add( label, BorderLayout.NORTH ); return panel; } private static void createUi( final Component view3D, final JComponent view2D ) { final JPanel mainPanel = new JPanel( new BorderLayout() ); // Add a menu also to demonstrate that the 3D view runs inside swing / awt. // TODO: The menu must be converted to a heavyweight awt component to overdraw the 3D awt canvas... // That requires using an AWT Frame, and that makes it hard to add Swing components. mainPanel.add( createMenuBar(), BorderLayout.NORTH ); // Show that menu renders on top of swing component but not awt canvas mainPanel.add( new JLabel( " " ), BorderLayout.WEST ); // TODO: Do this already at the Renderer3D level if not otherwise solvable. // Wrap the 3D canvas in another JPanel, as it seems to have redraw problems otherwise? final JPanel view3DHolder = new JPanel( new BorderLayout() ); view3DHolder.add( view3D, BorderLayout.CENTER ); // Put 2D and 3D view in a split pane. final JSplitPane splitPane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, view3DHolder, view2D ); splitPane.setDividerLocation( 500 ); splitPane.setOneTouchExpandable( true ); mainPanel.add( splitPane, BorderLayout.CENTER ); showInFrame( mainPanel, "3D Map Demo" ); } private static void showInFrame( final Component view, final String frameTitle ) { final JFrame frame3D = new JFrame( frameTitle ); final JPanel container = new JPanel( new BorderLayout() ); container.setPreferredSize( new Dimension( 800, 600 ) ); frame3D.getContentPane().add( container ); container.add( view, BorderLayout.CENTER ); frame3D.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); frame3D.pack(); frame3D.setVisible( true ); } private static JMenuBar createMenuBar() { final JMenuBar menuBar = new JMenuBar(); final JMenu menu = new JMenu( "Demo" ); menuBar.add( menu ); menu.add( new AbstractAction( "Exit" ) { public void actionPerformed( final ActionEvent e ) { System.exit( 0 ); } } ); return menuBar; } private static MapContext createContextFromShapefile( final URL shape ) throws IOException { return createContextFromShapefile( shape, null ); } private static MapContext createContextFromShapefile( final URL shape, final URL sld ) throws IOException { return loadShapefile( shape, loadStyle( sld ) ); } private static Style loadStyle( final URL sld ) throws IOException { final Style style; if ( sld != null ) { final StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory( null ); final SLDParser stylereader = new SLDParser( styleFactory, sld ); final Style[] styles = stylereader.readXML(); style = styles[ 0 ]; } else { style = new BasicLineStyle(); } return style; } private static MapContext loadShapefile( final URL shape, final Style style ) throws IOException { final ShapefileDataStore shapefileDataStore = new ShapefileDataStore( shape ); final FeatureSource featureSource = shapefileDataStore.getFeatureSource(); CoordinateReferenceSystem crs = featureSource.getSchema().getDefaultGeometry().getCoordinateSystem(); if ( crs == null ) { crs = DefaultGeographicCRS.WGS84; } final MapContext context = new DefaultMapContext( crs ); context.addLayer( featureSource, style ); context.getLayerBounds(); return context; } }