2016-11-22 5 views
1

Ich benutze WorldWind und versuche, mehrere Oberflächenbilder in der gleichen Schicht zu "pflücken" und verstehe nicht, warum es nicht funktioniert.Worldwind SurfaceImage Deep/Batch-Kommissionierung

Ich hatte den Eindruck, dass dieser Aufruf:

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

mir ermöglichen würde, mehrere renderables in der gleichen Schicht zu holen. Dies scheint für alle anderen Fälle außer SurfaceImage zu funktionieren. Ich habe auch bemerkt, wenn ich das geladene SurfaceImage in verschiedenen Ebenen erzwinge funktioniert es wie erwartet.

Dies ist der Code Ich verwende diese zu testen:

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

Dies sind 2 GeoTIFFs, die auf aufeinander geschichtet sind, dass ich dies aus zu testen, habe mit. Ich würde erwarten, dass mein println auf dem SelectListener "3" ausdruckt, wenn ich links auf beide geotiff klicke. (Ich habe die GeoTIFFs in eine zip hochgeladen verfügbar here)

Der Bereich, in dem Sie diese ist in San Francisco sehen, siehe Screenshot:

enter image description here

Antwort

1

Update:

Es wurde entdeckt dass die Beispiele für das Batch-Picking auf die Instanzen von AbstractSurfaceObject ausgerichtet waren, die in diesem Fall nicht zutreffen. Für die Behandlung von SurfaceImage-Instanzen sollte die Eigenschaft für setAlwaysOnTop auf false konfiguriert werden, wodurch das Auswahlereignis alle Elemente unter dem Cursor verarbeitet.


Lesen durch die Beispiele für DeepPicking, gibt es eigentlich zwei Dinge, die getan werden müssen.

  1. setDeepPickEnabled (true); //Das ist fertig.
  2. Disable Batch auf die gewünschten Elemente Kommissionierung

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

Um tief Picking zu ermöglichen, jede Charge für die gewünschten Elemente Kommissionierung muss deaktiviert sein und die tiefe Picking Unterkunft SceneController muss aktiviert sein . Siehe {@link gov.nasa.worldwind.SceneController # setDeepPickEnabled (boolean)

hat mich ein wenig, während die zweite zu verstehen, aber es erscheint dem AbstractSurfaceObject Klasse gebunden zu werden.


  • Ich gehe davon aus, dass die Dinge, die Sie auf der Schicht sind Zeichnung sind eine Unterklasse von AbstractSurfaceObject

Ich glaube, dass in dieser Situation würde ich die SurfaceImageLayer Unterklasse , und überschreiben Sie die addRenderable-Methoden.Ich würde das Renderable überprüfen, wenn es sich um eine Instanz eines AbstractSurfaceObject handelt, und die Stapelauswahl für das Objekt deaktivieren, bevor es an die Superklasse weitergeleitet wird.

Dieser Code ist möglicherweise nicht die beste langfristige Lösung, kann jedoch schnelle Ergebnisse liefern, um festzustellen, ob dies das zugrunde liegende Problem ist.

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

IF das, was Sie aufgenommen haben wollen direkt das Bild ist, das nicht out-of-the-box unterstützt zu sein scheint. Sie müssten etwas tun, um die SurfaceImage-Referenzen von SurfaceImageLayer für die RenderableLayer-Datei auf doPick sichtbar zu machen. Das könnte mit neuen Problemen verbunden sein, auf die man achten sollte.

  • Als Randnotiz, wenn Sie Icons sind Rendering dann alles, was Sie tun müssen, ist die IconRenderer.setAllowBatchPicking (false) gesetzt

Ich hoffe, dass zumindest ein wenig hilfreich ist.
Best of Luck.

+0

Danke für einen Blick - leider sieht es so aus, als ob das SurfaceImage-Importer die gov.nasa.worldwind.render.SurfaceImage als Renderable und SurfaceImage nicht gov.nasa.worldwind.render.AbstractSurfaceObject verwendet. Es scheint, dass SurfaceImage als ein spezieller Fall oder etwas behandelt wird, wenn es um Batch-/Deep-Picking geht, aber ich sehe nicht, wo das Problem darin besteht, es zu hacken. – systemoutprintln

+0

Vielen Dank für die Rückkehr zu den Resultaten von AbstractSurfaceObject! Wenn Sie die PickSupport-Referenz in der RenderableLayer debuggen, findet sie alle SurfaceImages unter dem Cursor? Möglicherweise sehen Sie das "TopPickedObject" in der Ausgabe, aber die PickSupport enthält die Map aller gültigen Objekte, für die der Layer ausgewählt werden soll. Wenn es über die Instanzen von surfaceImage weiß, können Sie möglicherweise einstellen, wie diese Klasse zum SceneController zurückmeldet. – Jeremiah

+0

Interessanter Gedanke. Ich werde in PickSupport graben, um zu sehen, ob ich finden kann, wo es die Referenz verliert. – systemoutprintln