2016-11-22 17 views
1

Я использую WorldWind и пытаюсь «выбрать» несколько изображений на одном уровне и не понимаю, почему он не работает.Worldwind SurfaceImage Deep/Batch Picking

Я был под впечатлением, что, называя это:

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, которые наслаиваются друг на друга, что я использую, чтобы проверить это. Я бы ожидал, что мой println на SelectListener распечатает «3», когда я нажму левой кнопкой мыши на обоих геотифах. (Я загрузил GeoTiffs в почтовый индекс доступной here)

область, где вы будете видеть их в Сан-Франциско, см скриншот:

enter image description here

ответ

1

Update:

Было обнаружено, что примеры для пакетного выбора были ориентированы вокруг экземпляров AbstractSurfaceObject, которые в этом случае не применялись. Для обработки экземпляров SurfaceImage свойство для setAlwaysOnTop должно быть настроено на false, что означает, что событие выбора обрабатывает все элементы под курсором.


Чтение примеров DeepPicking, на самом деле существует 2 вещи, которые необходимо выполнить.

  1. setDeepPickEnabled (true); //Готово.
  2. Отключить Batch приставать желаемых элементов

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); 
     } 
    } 
} 

Если вещь вы хотите выбрали образ напрямую, что, как представляется, не поддерживается вне коробки. Вам нужно будет что-то сделать, чтобы ссылки SurfaceImage с SurfaceImageLayer были видны RenderableLayer на doPick. Это может привести к появлению нового набора проблем.

  • В качестве побочного сведению, если вы рендеринга иконки, то все, что вам нужно сделать, это установить IconRenderer.setAllowBatchPicking (ложь)

Я надеюсь, что по крайней мере несколько полезно.
Лучший из удачи.

+0

Спасибо, что посмотрели - к сожалению, похоже, что импортер SurfaceImage использует gov.nasa.worldwind.render.SurfaceImage, поскольку его Renderable и SurfaceImage не распространяют gov.nasa.worldwind.render.AbstractSurfaceObject. Кажется, что SurfaceImage рассматривается как особый случай или что-то, когда дело доходит до пакетного/глубокого выбора, но я не вижу, где проблема заключается в том, чтобы взломать его. – systemoutprintln

+0

Спасибо, что вернулись на результаты AbstractSurfaceObject! Если вы отлаживаете ссылку PickSupport внутри RenderableLayer, найдет ли она все SurfaceImages под курсором? Вы можете видеть «TopPickedObject» в выводе, но PickSupport содержит карту всех допустимых объектов для выбора для слоя. Если он знает о экземплярах surfaceImage, то, возможно, вы можете настроить, как этот класс возвращается к SceneController. – Jeremiah

+0

Интересная мысль. Я буду копаться в PickSupport, чтобы узнать, могу ли я найти, где он теряет ссылку. – systemoutprintln