/* * 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.worldwind.util.WorldWindGlimpseUtils.linkAxisToWorldWind; import static com.metsci.glimpse.worldwind.util.WorldWindGlimpseUtils.linkMouseEvents; import static com.metsci.glimpse.worldwind.util.WorldWindGlimpseUtils.linkWorldWindToAxis; import java.awt.BorderLayout; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; import com.jogamp.opengl.util.FPSAnimator; import com.metsci.glimpse.axis.Axis2D; import com.metsci.glimpse.axis.AxisUtil; import com.metsci.glimpse.canvas.NewtSwingGlimpseCanvas; import com.metsci.glimpse.examples.charts.bathy.BathymetryExample; import com.metsci.glimpse.layout.GlimpseAxisLayout2D; import com.metsci.glimpse.layout.GlimpseLayoutManagerMig; import com.metsci.glimpse.painter.decoration.BackgroundPainter; import com.metsci.glimpse.plot.MapPlot2D; import com.metsci.glimpse.support.settings.SwingLookAndFeel; import com.metsci.glimpse.util.geo.LatLonGeo; import com.metsci.glimpse.util.geo.projection.GeoProjection; import com.metsci.glimpse.util.geo.projection.TangentPlane; import com.metsci.glimpse.worldwind.projection.PlateCarreeProjection; import com.metsci.glimpse.worldwind.tile.GlimpseDynamicSurfaceTile; import com.metsci.glimpse.worldwind.tile.GlimpseReprojectingSurfaceTile; import gov.nasa.worldwind.BasicModel; import gov.nasa.worldwind.awt.WorldWindowGLCanvas; import gov.nasa.worldwind.geom.LatLon; import gov.nasa.worldwind.layers.ViewControlsLayer; import gov.nasa.worldwind.layers.ViewControlsSelectListener; import gov.nasa.worldwindx.examples.ApplicationTemplate; public class BathymetryTileExample { public static void main( String[] args ) throws IOException { // create a Worldwind Frame JFrame worldwindFrame = new JFrame( "Worldwind" ); JPanel panel = new JPanel( ); panel.setLayout( new BorderLayout( ) ); worldwindFrame.add( panel ); final WorldWindowGLCanvas wwc = new WorldWindowGLCanvas( ); BasicModel model = new BasicModel( ); // uncomment this line to use a flat globe //model.setGlobe( new EllipsoidalGlobe( Earth.WGS84_EQUATORIAL_RADIUS, Earth.WGS84_POLAR_RADIUS, Earth.WGS84_ES, new ZeroElevationModel( ) ) ); wwc.setModel( model ); panel.add( wwc, BorderLayout.CENTER ); // put any GlimpseLayout here! Axis2D wwaxis = new Axis2D( ); GlimpseAxisLayout2D baseLayout = new GlimpseAxisLayout2D( wwaxis ); GlimpseLayoutManagerMig manager = new GlimpseLayoutManagerMig( ); manager.setLayoutConstraints( String.format( "bottomtotop, gapx 0, gapy 0, insets 0 0 0 0" ) ); baseLayout.setLayoutManager( manager ); // WorldWind tile images must be projected using a PlateCarree projection in // order to appear properly geo-registered on the globe GeoProjection projectionTo = new PlateCarreeProjection( ); // however, we can use another GeoProjection to render our graphics, // and use GlimpseReprojectingSurfaceTile to automatically fix the projection TangentPlane projection = new TangentPlane( LatLonGeo.fromDeg( -30.637005, 65.476074 ) ); //TangentPlane projection = new TangentPlane( LatLonGeo.fromDeg( 24, -76 ) ); BathymetryExample example = new BathymetryExample( ); MapPlot2D plot = example.getLayout( projection ); Axis2D axis = plot.getAxis( ); GlimpseAxisLayout2D layout = new GlimpseAxisLayout2D( wwaxis ); // add a listener to the layout (which will receive mouse events translated from worldwind) AxisUtil.attachMouseListener( layout ); layout.addPainter( example.getBathymetryPainter( ) ); layout.addPainter( example.getContourPainter( ) ); baseLayout.addPainter( new BackgroundPainter( ).setColor( 0, 0, 0, 0 ) ); baseLayout.addLayout( layout ); LatLonGeo corner1 = projection.unproject( axis.getAxisX( ).getMin( ), axis.getAxisY( ).getMin( ) ); LatLonGeo corner2 = projection.unproject( axis.getAxisX( ).getMin( ), axis.getAxisY( ).getMax( ) ); LatLonGeo corner3 = projection.unproject( axis.getAxisX( ).getMax( ), axis.getAxisY( ).getMax( ) ); LatLonGeo corner4 = projection.unproject( axis.getAxisX( ).getMax( ), axis.getAxisY( ).getMin( ) ); List<LatLon> corners = new ArrayList<LatLon>( ); corners.add( LatLon.fromDegrees( corner1.getLatDeg( ), corner1.getLonDeg( ) ) ); corners.add( LatLon.fromDegrees( corner2.getLatDeg( ), corner2.getLonDeg( ) ) ); corners.add( LatLon.fromDegrees( corner3.getLatDeg( ), corner3.getLonDeg( ) ) ); corners.add( LatLon.fromDegrees( corner4.getLatDeg( ), corner4.getLonDeg( ) ) ); GlimpseDynamicSurfaceTile glimpseLayer = new GlimpseReprojectingSurfaceTile( baseLayout, wwaxis, projection, projectionTo, 4500, 4500, 3000, 3000, corners ); ApplicationTemplate.insertBeforePlacenames( wwc, glimpseLayer ); // 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 ) ); worldwindFrame.setSize( 800, 800 ); worldwindFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); worldwindFrame.setVisible( true ); // create a Glimpse Frame NewtSwingGlimpseCanvas glimpseCanvas = new NewtSwingGlimpseCanvas( wwc.getContext( ) ); glimpseCanvas.addLayout( plot ); glimpseCanvas.setLookAndFeel( new SwingLookAndFeel( ) ); JFrame glimpseFrame = new JFrame( "Glimpse" ); glimpseFrame.add( glimpseCanvas ); // attach a repaint manager which repaints the canvas in a loop final FPSAnimator animator = new FPSAnimator( glimpseCanvas.getGLDrawable( ), 120 ); animator.start( ); glimpseFrame.pack( ); glimpseFrame.setSize( 800, 800 ); glimpseFrame.setLocation( 800, 0 ); glimpseFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); glimpseFrame.setVisible( true ); // pass mouse events from WorldWind back to Glimpse linkMouseEvents( wwc, projection, glimpseLayer ); // force the WorldWind and Glimpse windows to pan together linkAxisToWorldWind( wwc, projection, plot.getAxis( ) ); linkWorldWindToAxis( wwc, projection, plot.getAxis( ) ); // add a thread to constantly repaint the WorldWind window // this isn't an ideal solution, but because Glimpse currently // uses busy repainting this is the easiest way to make the integration work ( new Thread( ) { public void run( ) { while ( true ) { wwc.redraw( ); try { Thread.sleep( ( long ) ( 1000.0 / 60.0 ) ); } catch ( InterruptedException e ) { } } } } ).start( ); WindowAdapter closeListener = new WindowAdapter( ) { @Override public void windowClosing( WindowEvent e ) { // stop the animation thread before exiting animator.stop( ); // dispose of GlimpseLayouts and GlimpsePainters attached to GlimpseCanvas glimpseCanvas.disposeAttached( ); // destroy heavyweight canvas and GLContext glimpseCanvas.destroy( ); } }; worldwindFrame.addWindowListener( closeListener ); glimpseFrame.addWindowListener( closeListener ); } }