2016-11-22 67 views
1

我使用WorldWind並試圖「挑選」同一圖層中的多個表面圖像,並不理解它爲什麼不起作用。Worldwind SurfaceImage Deep/Batch Clicking

我的印象是,調用該:

this.getWwd().getSceneController().setDeepPickEnabled(true); 

將使我能夠選擇多個renderables在同一層。這似乎適用於除SurfaceImage以外的其他所有情況。我還注意到,如果我強制加載的SurfaceImage到不同的層,它按預期工作。

這是我使用測試了這一點代碼:

public class SurfaceImageViewer extends ApplicationTemplate 
{ 
    public static class AppFrame extends ApplicationTemplate.AppFrame 
    { 
     private JFileChooser fileChooser = new JFileChooser(); 
     private JSlider opacitySlider; 
     private SurfaceImageLayer layer; 
     private JLabel statusLabel = new JLabel("status: ready"); 

     public AppFrame() 
     { 
      super(true, true, false); 

      this.getWwd().getSceneController().setDeepPickEnabled(true); 

      try 
      { 
       this.layer = new SurfaceImageLayer(); 
       this.layer.setOpacity(1); 
       this.layer.setPickEnabled(true); 
       this.layer.setName("Surface Images"); 

       insertBeforeCompass(this.getWwd(), layer); 

       this.getControlPanel().add(makeControlPanel(), BorderLayout.SOUTH); 
      } 
      catch (Exception e) 
      { 
       e.printStackTrace(); 
      } 

      this.getWwd().addSelectListener(new SelectListener() { 

       @Override 
       public void selected(SelectEvent event) { 
        PickedObjectList pol = AppFrame.this.getWwd().getObjectsAtCurrentPosition(); 

        if(event.isLeftClick()){ 
         System.out.println("POL SIZE "+pol.size()); 
        } 

       } 
      }); 


     } 

     Action openElevationsAction = new AbstractAction("Open Elevation File...") 
     { 
      public void actionPerformed(ActionEvent e) 
      { 
       int status = fileChooser.showOpenDialog(AppFrame.this); 
       if (status != JFileChooser.APPROVE_OPTION) 
        return; 

       final File imageFile = fileChooser.getSelectedFile(); 
       if (imageFile == null) 
        return; 

       Thread t = new Thread(new Runnable() 
       { 
        public void run() 
        { 
         try 
         { 
          CompoundElevationModel cem 
           = (CompoundElevationModel) getWwd().getModel().getGlobe().getElevationModel(); 
          LocalElevationModel em = new LocalElevationModel(); 
          em.addElevations(imageFile.getPath()); 
          cem.addElevationModel(em); 
         } 
         catch (IOException e1) 
         { 
          e1.printStackTrace(); 
         } 
        } 
       }); 
       t.setPriority(Thread.MIN_PRIORITY); 
       t.start(); 
      } 
     }; 

     Action openImageAction = new AbstractAction("Open Image File...") 
     { 
      public void actionPerformed(ActionEvent actionEvent) 
      { 
       int status = fileChooser.showOpenDialog(AppFrame.this); 
       if (status != JFileChooser.APPROVE_OPTION) 
        return; 

       final File imageFile = fileChooser.getSelectedFile(); 
       if (imageFile == null) 
        return; 

       Thread t = new Thread(new Runnable() 
       { 
        public void run() 
        { 
         try 
         { 
          statusLabel.setText("status: Loading image"); 
          // TODO: proper threading 
          layer.addImage(imageFile.getAbsolutePath()); 

          getWwd().redraw(); 
          statusLabel.setText("status: ready"); 
         } 
         catch (IOException e) 
         { 
          e.printStackTrace(); 
         } 
        } 
       }); 
       t.setPriority(Thread.MIN_PRIORITY); 
       t.start(); 
      } 
     }; 

     private JPanel makeControlPanel() 
     { 
      JPanel controlPanel = new JPanel(new GridLayout(0, 1, 5, 5)); 
      JButton openImageButton = new JButton(openImageAction); 
      controlPanel.add(openImageButton); 

      this.opacitySlider = new JSlider(); 
      this.opacitySlider.setMaximum(100); 
      this.opacitySlider.setValue((int) (layer.getOpacity() * 100)); 
      this.opacitySlider.setEnabled(true); 
      this.opacitySlider.addChangeListener(new ChangeListener() 
      { 
       public void stateChanged(ChangeEvent e) 
       { 
        int value = opacitySlider.getValue(); 
        layer.setOpacity(value/100d); 
        getWwd().redraw(); 
       } 
      }); 
      JPanel opacityPanel = new JPanel(new BorderLayout(5, 5)); 
      opacityPanel.setBorder(new EmptyBorder(0, 10, 0, 0)); 
      opacityPanel.add(new JLabel("Opacity"), BorderLayout.WEST); 
      opacityPanel.add(this.opacitySlider, BorderLayout.CENTER); 

      controlPanel.add(opacityPanel); 

      JButton openElevationsButton = new JButton(openElevationsAction); 
      controlPanel.add(openElevationsButton); 

      controlPanel.add(statusLabel); 
      controlPanel.setBorder(new EmptyBorder(15, 15, 15, 15)); 

      return controlPanel; 
     } 
    } 

    public static void main(String[] args) 
    { 
     ApplicationTemplate.start("World Wind Surface Images", SurfaceImageViewer.AppFrame.class); 
    } 
} 

這些都是對對方說我一直在使用測試了這一點的上面一層2個geotiffs。我希望我在SelectListener上的println打印出「3」,當我單擊鼠標左鍵單擊這兩個geotiff時。 (我已上載的geotiffs成可用here一個zip)

在那裏你會看到這些是在舊金山的區域,見截圖:

enter image description here

回答

1

更新:

它被發現批量揀選的例子是圍繞AbstractSurfaceObject實例定向的,在這種情況下它並不適用。對於SurfaceImage實例的處理,setAlwaysOnTop的屬性應該配置爲false,這看起來會讓選擇事件處理光標下的所有元素。


通讀DeepPicking的例子,實際上有兩件事情需要完成。

  1. setDeepPickEnabled(true); //這個做完了。
  2. 禁用批量採摘所需的元素

https://github.com/nasa/World-Wind-Java/blob/master/WorldWind/src/gov/nasa/worldwindx/examples/DeepPicking.java

爲了使深採摘,任意批量採摘所需的元素必須被禁用,必須啓用 SceneController的深採摘財產。見{@link gov.nasa.worldwind.SceneController#setDeepPickEnabled(布爾)

我花了一些時間來了解第二個,但它似乎被捆綁到AbstractSurfaceObject類。


  • 我假設你正在圖層上繪製的東西是一個子類AbstractSurfaceObject

我認爲,在這種情況下,我會繼承了SurfaceImageLayer ,並重寫addRenderable方法。如果它是AbstractSurfaceObject的實例,我會檢查可渲染的,並在將其轉發給超類之前禁用它。

此代碼可能不是最佳的長期解決方案,但它可能會提供快速結果以確定這是否是潛在問題。

import gov.nasa.worldwind.layers.SurfaceImageLayer; 
import gov.nasa.worldwind.render.AbstractSurfaceObject; 
import gov.nasa.worldwind.render.Renderable; 

/** 
* Very Rough extension of SurfaceImageLayer which disables batch picking on all AbstractSurfaceobjects. 
* @author http://stackoverflow.com/users/5407189/jeremiah 
* @since Nov 26, 2016 
* 
*/ 
public class MySurfaceImageLayer extends SurfaceImageLayer { 


    @Override 
    public void addRenderable(Renderable renderable) { 
     if (renderable instanceof AbstractSurfaceObject) { 
      ((AbstractSurfaceObject)renderable).setEnableBatchPicking(false); 
     } 
     super.addRenderable(renderable); 
    } 

    @Override 
    public void addRenderables(Iterable<? extends Renderable> renderables) { 
     for (Renderable r : renderables) { 
      addRenderable(r); 
     } 
    } 
} 

如果你想有回升的東西是圖像直接,這似乎不支持外的開箱。您需要做一些事情來讓SurfaceImageLayer中的SurfaceImage引用對doPick上的RenderableLayer可見。這可能伴隨着一系列新問題需要注意。

  • 作爲一個側面說明,如果你渲染的圖標,那麼所有你需要做的是設置IconRenderer.setAllowBatchPicking(假)

我希望這至少在一定程度很有幫助。
祝你好運。

+0

感謝您的關注 - 不幸的是,它看起來像SurfaceImage導入程序使用gov.nasa.worldwind.render.SurfaceImage作爲其可渲染且SurfaceImage不擴展gov.nasa.worldwind.render.AbstractSurfaceObject。看起來像SurfaceImage被視爲一種特殊情況或什麼時候涉及到批量/深度採摘,但我沒有看到問題在哪裏破解。 – systemoutprintln

+0

感謝您取回AbstractSurfaceObject結果!如果您調試RenderableLayer內部的PickSupport引用,是否會找到光標下的所有SurfaceImages?您可能會在輸出中看到「TopPickedObject」,但PickSupport會保存要從該圖層中選擇的所有有效對象的地圖。如果它知道surfaceImage實例,那麼也許可以調整該類如何返回到SceneController。 – Jeremiah

+0

有趣的想法。我會深入挖掘PickSupport,看看能否找到失去參考的地方。 – systemoutprintln

相關問題