/* * Copyright (c) 2016, Metron, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Metron, Inc. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL METRON, INC. BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.metsci.glimpse.examples.worldwind; import static com.metsci.glimpse.dnc.DncDataPaths.*; import static com.metsci.glimpse.util.GlimpseDataPaths.*; import static com.metsci.glimpse.util.io.StreamOpener.*; import static com.metsci.glimpse.util.logging.LoggerUtils.*; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.io.IOException; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; import com.metsci.glimpse.axis.Axis2D; import com.metsci.glimpse.context.GlimpseBounds; import com.metsci.glimpse.dnc.DncPainter; import com.metsci.glimpse.dnc.DncPainterSettings; import com.metsci.glimpse.dnc.DncPainterSettingsImpl; import com.metsci.glimpse.dnc.DncProjections; import com.metsci.glimpse.dnc.convert.Flat2Render.RenderCache; import com.metsci.glimpse.dnc.convert.Flat2Render.RenderCacheConfig; import com.metsci.glimpse.layout.GlimpseAxisLayout2D; import com.metsci.glimpse.worldwind.projection.PlateCarreeProjection; import com.metsci.glimpse.worldwind.tile.GlimpseResizingSurfaceTile; import gov.nasa.worldwind.BasicModel; import gov.nasa.worldwind.awt.WorldWindowGLJPanel; import gov.nasa.worldwind.geom.Angle; import gov.nasa.worldwind.geom.LatLon; import gov.nasa.worldwind.geom.Sector; import gov.nasa.worldwind.layers.ViewControlsLayer; import gov.nasa.worldwind.layers.ViewControlsSelectListener; import gov.nasa.worldwindx.examples.ApplicationTemplate; public class WorldwindDncPainterExample { public static void main( String[] args ) throws IOException { initializeLogging( "config/dnc-example-logging.properties", resourceOpener ); // setup RenderCacheConfig which points to DNC data files RenderCacheConfig dncCacheConfig = new RenderCacheConfig( ); dncCacheConfig.flatParentDir = requireExistingDir( glimpseDncFlatDir ); // setup projection for transforming DNC_FLAT lat/lon coordinates into flat map coordinates // here we choose the identity transform (plate carree) because that is what WorldWind // requires when tiling an image onto its globe dncCacheConfig.proj = DncProjections.dncPlateCarree; RenderCache dncCache = new RenderCache( dncCacheConfig, 4 ); // setup a Glimpse axis and layout to draw the DNC charts onto Axis2D axis = new Axis2D( ); GlimpseAxisLayout2D plot = new GlimpseAxisLayout2D( axis ); // configure DNC rendering DncPainterSettings dncPainterSettings = new DncPainterSettingsImpl( dncCacheConfig.proj ); DncPainter dncPainter = new DncPainter( dncCache, dncPainterSettings ); // removing "ecr" coverage removes dnc land polygons, making WorldWind satellite imagery visible dncPainter.activateCoverages( "lim", "nav", "cul", "iwy", "obs", "hyd", "por", "lcr", "env", "rel", "coa" ); dncPainter.addAxis( plot.getAxis( ) ); plot.addPainter( dncPainter ); // setup WorldWind JFrame worldwindFrame = new JFrame( "Worldwind" ); JPanel panel = new JPanel( ); panel.setLayout( new BorderLayout( ) ); worldwindFrame.add( panel ); final WorldWindowGLJPanel wwc = new WorldWindowGLJPanel( ); wwc.setModel( new BasicModel( ) ); panel.add( wwc, BorderLayout.CENTER ); // If Angle.POS180 is used, LatLonGeo will normalize that value to -180, causing axis bounds to be set to [-180, -180] Sector fullSector = new Sector( Angle.NEG90, Angle.POS90, Angle.NEG180, Angle.fromDegrees( Math.nextDown( 180 ) ) ); PlateCarreeProjection projection = new PlateCarreeProjection( ); // The charts look bad when we attempt to render over the whole globe. // So wait to render until the user is zoomed in on a particular area. final GlimpseResizingSurfaceTile glimpseLayer = new GlimpseResizingSurfaceTile( plot, axis, projection, 8192, 8192, 1024, 1024, fullSector.asList( )) { @Override protected void updateGeometry( List<LatLon> screenCorners ) { super.updateGeometry( screenCorners ); layout.setVisible( true ); } @Override protected void updateGeometryDefault( ) { layout.setVisible( false ); } }; glimpseLayer.setOpacity( 0.4f ); ApplicationTemplate.insertBeforePlacenames( wwc, glimpseLayer ); // When the WorlWindow changes size, adjust the preferred size of the offscreen GlimpseCanvas to match // if they are too different, the view will either look very blurry or lettering will be very small. // Also set the size of the Axis2D. The size is used to compute the pixel-per-value for the axis, which // in turn determines what level of detail is drawn on the DNC chart. panel.addComponentListener( new ComponentAdapter( ) { @Override public void componentResized( ComponentEvent e ) { Dimension dim = e.getComponent( ).getSize( ); glimpseLayer.setPreferredDimensions( ( int ) dim.getWidth( ) * 3, ( int ) dim.getHeight( ) * 3 ); axis.setSizePixels( new GlimpseBounds( dim ) ); } } ); // create and install the view controls layer and register a controller for it with the World Window. ViewControlsLayer viewControlsLayer = new ViewControlsLayer( ); ApplicationTemplate.insertBeforeCompass( wwc, viewControlsLayer ); wwc.addSelectListener( new ViewControlsSelectListener( wwc, viewControlsLayer ) ); // show the WorldWind frame worldwindFrame.setSize( 800, 800 ); worldwindFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); worldwindFrame.setVisible( true ); } }