2014年2月1日 星期六

NASA World Wind Java SDK

NASA World Wind Java SDK是由NASA (National Aeronautics and Space Administration, 美國太空總署) 以JOGL為基礎所開發支援類似Google Earth的進階套件,其API支援包括地球、火星、月亮等星球表面之圖片下載,並支援星球地形處理 (Terrain)、以平面方式呈現星球表面 (Flat World)、藍色大理石紋裡表面 (Blue Marble Surface)、地震分析 (Earthquake) 等特殊功能。

由於以NASA World Wind Java SDK所開發之程式,實際上是即時自NASA網站下載相關星球圖片,因此必須具有網路連線。此外,若以Java Applet方式處理,由於安全性的限制,Java Applet僅能與其置放的伺服器主機建立連線,不能與其他的主機如NASA建立連線,因此將產生Security例外錯誤,有關的解決方法,請參考Java Security Policy之說明。

NASA World Wind Java SDK是以JOGL為基礎所開發,因此其程式架構與JOGL類似。

在JOGL中,以GLCanvasGLJPanel類別建立JOGL繪圖物件,而在NASA World Wind Java SDK中,則是以WorldWindowGLCanvas類別或WorldWindowGLJPanel類別建立NASA World Wind繪圖物件以處理3D繪圖,前者繼承自GLCanvas類別,以支援Java AWT之繪圖,後者則繼承自GLJPanel類別,以支援Java Swing之繪圖。

WorldWindowGLCanvasWorldWindowGLJPanel類別所建立的繪圖物件,只是一個顯示NASA圖片的環境,而星球表面的圖片則是以層 (Layer) 的方式一層一層顯示,其層別可由以下之類別處理,皆繼承自gov.nasa.worldwind.layers.AbstractLayer抽象類別:
  • gov.nasa.worldwind.layers.CompassLayer
  • gov.nasa.worldwind.layers.Earth.BMNGSurfaceLayer
  • gov.nasa.worldwind.layers.Earth.EarthNASAPlaceNameLayer
  • gov.nasa.worldwind.layers.Earth.LandsatI3
  • gov.nasa.worldwind.layers.Earth.USGSDigitalOrtho
  • gov.nasa.worldwind.layers.Earth.USGSUrbanAreaOrtho
此外,以下為NASA World Wind Java SDK的各類層別,其中Earth、Mars、Moon分別代表地球、火星、月亮之表面圖片的層別:
  • gov.nasa.worldwind.layers.AnnotationLayer
  • gov.nasa.worldwind.layers.CrosshairLayer
  • gov.nasa.worldwind.layers.ScalebarLayer
  • gov.nasa.worldwind.layers.SkyColorLayer
  • gov.nasa.worldwind.layers.SkyGradientLayer
  • gov.nasa.worldwind.layers.StarsLayer
  • gov.nasa.worldwind.layers.TerrainProfileLayer
  • gov.nasa.worldwind.layers.TrackMarkerLayer
  • gov.nasa.worldwind.layers.TrackPipesLayer
  • gov.nasa.worldwind.layers.WorldMapLayer
  • gov.nasa.worldwind.layers.Earth.BMNGWMSLayer
  • gov.nasa.worldwind.layers.Earth.CountryBoundariesLayer
  • gov.nasa.worldwind.layers.Earth.LandsatI3WMSLayer
  • gov.nasa.worldwind.layers.Earth.MGRSGraticuleLayer
  • gov.nasa.worldwind.layers.Earth.NASAWFSPlaceNameLayer
  • gov.nasa.worldwind.layers.Earth.OpenStreetMapLayer
  • gov.nasa.worldwind.layers.Earth.UTMGraticuleLayer
  • gov.nasa.worldwind.layers.Mars.MOCColorizedBaseLayer
  • gov.nasa.worldwind.layers.Mars.MOCColorizedLayer
  • gov.nasa.worldwind.layers.Mars.MOCLayer
  • gov.nasa.worldwind.layers.Mars.MolaColorASULayer
  • gov.nasa.worldwind.layers.Mars.MolaColoredJPLLayer
  • gov.nasa.worldwind.layers.Mars.THEMISColorLayer
  • gov.nasa.worldwind.layers.Mars.THEMISLayer
  • gov.nasa.worldwind.layers.Moon.Clementine30Layer
  • gov.nasa.worldwind.layers.Moon.Clementine40BaseLayer
  • gov.nasa.worldwind.layers.Moon.Clementine40Layer
  • gov.nasa.worldwind.layers.Moon.ShadedElevationLayer
  • gov.nasa.worldwind.layers.placename.PlaceNameLayer
層別類別之特殊在於可藉由動作 (Action) 之定義,處理其相對的事件,其程式架構如下:


public JOGLEarth.LayerAction[] layers = new JOGLEarth.LayerAction[] {
  new JOGLEarth.LayerAction(new MNGSurfaceLayer(), true),
  new JOGLEarth.LayerAction(new CompassLayer(), true),
  new JOGLEarth.LayerAction(new EarthNASAPlaceNameLayer(), true),
  new JOGLEarth.LayerAction(new LandsatI3(), true),
  new JOGLEarth.LayerAction(new USGSDigitalOrtho(), true),
  new JOGLEarth.LayerAction(new USGSUrbanAreaOrtho(), true),
};
...
LayerList layerList = new LayerList();

for (JOGLEarth.LayerAction action : layers) {
  JCheckBox jcb = new JCheckBox(action);
  jcb.setFont(new Font("dialog", Font.PLAIN, 10));
  
  jcb.setSelected(action.selected);
  layerPanel.add(jcb);
  layerList.add(action.layer);

  if (action.layer instanceof TiledImageLayer)
    ((TiledImageLayer) action.layer).setShowImageTileOutlines(false);

  if (action.layer instanceof LandsatI3)
    ((TiledImageLayer) action.layer).setDrawBoundingVolumes(false);

  if (action.layer instanceof USGSDigitalOrtho)
    ((TiledImageLayer) action.layer).setDrawTileIDs(false);
}
...
private static class LayerAction extends AbstractAction {
  private Layer layer;
  private boolean selected;

  public LayerAction(Layer layer, boolean selected) {
    super(layer.getName());
    this.layer = layer;
    this.selected = selected;
    this.layer.setEnabled(this.selected);
  }

  public void actionPerformed(ActionEvent actionEvent) {
    if (((JCheckBox) actionEvent.getSource()).isSelected())
      this.layer.setEnabled(true);
    else
      this.layer.setEnabled(false);

    Thread thread = new Thread() {
      public void run() {
        wwGLJPanel.repaint();
      }
    };
    thread.start();
  }
}


待各層別設定之後,則需將層別加入之前所建立的WorldWindowGLCanvasWorldWindowGLJPanel繪圖物件之中,以顯示星球表面各層別的圖片。

由於WorldWindowGLCanvasWorldWindowGLJPanel類別支援MVC架構,其Model部份可由Model介面或以WorldWind類別的createConfigurationComponent()方法建立。待MVC Model建立之後,則以Model介面的setLayers()方法將層別加入繪圖物件之中,並以WorldWindowGLCanvasWorldWindowGLJPanel類別的setModel()方法設定NASA World Wind繪圖物件之MVC Model,例如:


// 建立WorldWindowGLCanvas類別的MVC Model
gov.nasa.worldwind.Model wwModel = (Model)
  WorldWind.createConfigurationComponent(
    "gov.nasa.worldwind.avkey.ModelClassName";

// 將層別加入繪圖物件之中
wwModel.setLayers(layerList);
...
// 設定NASA World Wind繪圖物件之MVC Model
wwGLJPanel.setModel(wwModel);


【執行結果】


【參考資料】

[1] Java Platform, Standard Edition 7, API Specification.
[2] NASA World Wind Java SDK:http://worldwind.arc.nasa.gov/java/
[3] 黃嘉輝,完全探索網路程式設計 - 使用Java,上奇資訊。

© Chia-Hui Huang


沒有留言:

張貼留言