package gov.nasa.worldwind.examples.applet; /* Copyright (C) 2001, 2006, 2007 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All Rights Reserved. */ import gov.nasa.worldwind.*; import gov.nasa.worldwind.util.StatusBar; import gov.nasa.worldwind.render.GlobeAnnotation; import gov.nasa.worldwind.render.FrameFactory; import gov.nasa.worldwind.render.MultiLineTextRenderer; import gov.nasa.worldwind.avlist.AVKey; import gov.nasa.worldwind.awt.WorldWindowGLCanvas; import gov.nasa.worldwind.event.*; import gov.nasa.worldwind.geom.*; import gov.nasa.worldwind.globes.Globe; import gov.nasa.worldwind.layers.*; import gov.nasa.worldwind.view.*; import netscape.javascript.JSObject; import javax.swing.*; import java.awt.*; /** * Provides a base application framework for simple WorldWind applets. * * A simple applet which runs World Wind with a StatusBar at the bottom * and lets javascript set some view attributes. * * @author Patrick Murris * @version $Id: */ public class WWJApplet extends JApplet { private WorldWindowGLCanvas wwd; private StatusBar statusBar; private RenderableLayer labelsLayer; public WWJApplet() { } public void init() { try { // Check for initial configuration values String value = getParameter("InitialLatitude"); if (value != null) Configuration.setValue(AVKey.INITIAL_LATITUDE, Double.parseDouble(value)); value = getParameter("InitialLongitude"); if (value != null) Configuration.setValue(AVKey.INITIAL_LONGITUDE, Double.parseDouble(value)); value = getParameter("InitialAltitude"); if (value != null) Configuration.setValue(AVKey.INITIAL_ALTITUDE, Double.parseDouble(value)); value = getParameter("InitialHeading"); if (value != null) Configuration.setValue(AVKey.INITIAL_HEADING, Double.parseDouble(value)); value = getParameter("InitialPitch"); if (value != null) Configuration.setValue(AVKey.INITIAL_PITCH, Double.parseDouble(value)); // Create World Window GL Canvas this.wwd = new WorldWindowGLCanvas(); this.getContentPane().add(this.wwd, BorderLayout.CENTER); // Create the default model as described in the current worldwind properties. Model m = (Model) WorldWind.createConfigurationComponent(AVKey.MODEL_CLASS_NAME); this.wwd.setModel(m); // Add a renderable layer for application labels this.labelsLayer = new RenderableLayer(); this.labelsLayer.setName("Labels"); insertBeforeLayerName(this.wwd, this.labelsLayer, "Compass"); // Add the status bar this.statusBar = new StatusBar(); this.getContentPane().add(statusBar, BorderLayout.PAGE_END); // Forward events to the status bar to provide the cursor position info. this.statusBar.setEventSource(this.wwd); // Setup a select listener for the worldmap click-and-go feature this.wwd.addSelectListener(new SelectListener() { public void selected(SelectEvent event) { if (event.getEventAction().equals(SelectEvent.LEFT_CLICK)) { if (event.hasObjects()) { if (event.getTopObject() instanceof WorldMapLayer) { // Left click on World Map : iterate view to target position Position targetPos = event.getTopPickedObject().getPosition(); OrbitView view = (OrbitView)WWJApplet.this.wwd.getView(); Globe globe = WWJApplet.this.wwd.getModel().getGlobe(); // Use a PanToIterator view.applyStateIterator(FlyToOrbitViewStateIterator.createPanToIterator( // The elevation component of 'targetPos' here is not the surface elevation, // so we ignore it when specifying the view center position. view, globe, new Position(targetPos.getLatLon(), 0), Angle.ZERO, Angle.ZERO, targetPos.getElevation())); } } } } }); // Call javascript appletInit() try { JSObject win = JSObject.getWindow(this); win.call("appletInit", null); } catch(Exception e) {} } catch (Throwable e) { e.printStackTrace(); } } public void start() { // Call javascript appletStart() try { JSObject win = JSObject.getWindow(this); win.call("appletStart", null); } catch(Exception e) {} } public void stop() { // Call javascript appletSop() try { JSObject win = JSObject.getWindow(this); win.call("appletStop", null); } catch(Exception e) {} // Shut down World Wind WorldWind.shutDown(); } /** * Adds a layer to WW current layerlist, before a named layer. * Target name can be a part of the layer name * @param wwd the <code>WorldWindow</code> reference. * @param layer the layer to be added. * @param targetName the partial layer name to be matched - case sensitive. */ public static void insertBeforeLayerName(WorldWindow wwd, Layer layer, String targetName) { // Insert the layer into the layer list just before the target layer. LayerList layers = wwd.getModel().getLayers(); int targetPosition = layers.size() - 1; for (Layer l : layers) { if (l.getName().indexOf(targetName) != -1) { targetPosition = layers.indexOf(l); break; } } layers.add(targetPosition, layer); } // ============== Public API - Javascript ======================= // /** * Move the current view position * @param lat the target latitude in decimal degrees * @param lon the target longitude in decimal degrees */ public void gotoLatLon(double lat, double lon) { this.gotoLatLon(lat, lon, Double.NaN, 0, 0); } /** * Move the current view position, zoom, heading and pitch * @param lat the target latitude in decimal degrees * @param lon the target longitude in decimal degrees * @param zoom the target eye distance in meters * @param heading the target heading in decimal degrees * @param pitch the target pitch in decimal degrees */ public void gotoLatLon(double lat, double lon, double zoom, double heading, double pitch) { OrbitView view = (OrbitView)this.wwd.getView(); Globe globe = this.wwd.getModel().getGlobe(); //view.setLatLon(new LatLon(Angle.fromDegrees(lat), Angle.fromDegrees(lon))); //view.firePropertyChange(AVKey.VIEW, null, view); if(!Double.isNaN(lat) || !Double.isNaN(lon) || !Double.isNaN(zoom)) { lat = Double.isNaN(lat) ? view.getCenterPosition().getLatitude().degrees : lat; lon = Double.isNaN(lon) ? view.getCenterPosition().getLongitude().degrees : lon; zoom = Double.isNaN(zoom) ? view.getZoom() : zoom; heading = Double.isNaN(heading) ? view.getHeading().degrees : heading; pitch = Double.isNaN(pitch) ? view.getPitch().degrees : pitch; view.applyStateIterator(FlyToOrbitViewStateIterator.createPanToIterator( view, globe, Position.fromDegrees(lat, lon, 0), Angle.fromDegrees(heading), Angle.fromDegrees(pitch), zoom, true)); } } /** * Set the current view heading and pitch * @param heading the traget heading in decimal degrees * @param pitch the target pitch in decimal degrees */ public void setHeadingAndPitch(double heading, double pitch) { OrbitView view = (OrbitView)this.wwd.getView(); if(!Double.isNaN(heading) || !Double.isNaN(pitch)) { heading = Double.isNaN(heading) ? view.getHeading().degrees : heading; pitch = Double.isNaN(pitch) ? view.getPitch().degrees : pitch; view.applyStateIterator(ScheduledOrbitViewStateIterator.createHeadingPitchIterator( view.getHeading(), Angle.fromDegrees(heading), view.getPitch(), Angle.fromDegrees(pitch))); } } /** * Set the current view zoom * @param zoom the target eye distance in meters */ public void setZoom(double zoom) { OrbitView view = (OrbitView)this.wwd.getView(); if(!Double.isNaN(zoom)) { view.applyStateIterator(ScheduledOrbitViewStateIterator.createZoomIterator( view.getZoom(), zoom)); } } /** * Get the WorldWindowGLCanvas * @return the current WorldWindowGLCanvas */ public WorldWindowGLCanvas getWW() { return this.wwd; } /** * Get the current OrbitView * @return the current OrbitView */ public OrbitView getOrbitView() { if(this.wwd.getView() instanceof OrbitView) return (OrbitView)this.wwd.getView(); return null; } /** * Get a reference to a layer with part of its name * @param layerName part of the layer name to match. * @return the corresponding layer or null if not found. */ public Layer getLayerByName(String layerName) { for (Layer layer : wwd.getModel().getLayers()) if (layer.getName().indexOf(layerName) != -1) return layer; return null; } /** * Add a text label at a position on the globe. * @param text the text to be displayed. * @param lat the latitude in decimal degrees. * @param lon the longitude in decimal degrees. * @param font a string describing the font to be used. * @param color the color to be used as an hexadecimal coded string. */ public void addLabel(String text, double lat, double lon, String font, String color) { GlobeAnnotation ga = new GlobeAnnotation(text, Position.fromDegrees(lat, lon, 0), Font.decode(font), Color.decode(color)); ga.getAttributes().setDrawOffset(new Point(0, 0)); ga.getAttributes().setFrameShape(FrameFactory.SHAPE_NONE); ga.getAttributes().setEffect(MultiLineTextRenderer.EFFECT_OUTLINE); ga.getAttributes().setTextAlign(MultiLineTextRenderer.ALIGN_CENTER); this.labelsLayer.addRenderable(ga); } }