Worldwind SurfaceImage Deep/Batch 拾取

Worldwind SurfaceImage Deep/Batch Picking

我正在使用 WorldWind 并尝试 "pick" 同一层中的多个表面图像,但不明白为什么它不起作用。

我的印象是调用这个:

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

将使我能够在同一层中选择多个可渲染对象。这似乎适用于 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 个层叠在一起的 geotiff。当我左键单击两个 geotiffs 时,我希望 SelectListener 上的 println 打印出“3”。 (我已经将 geotiffs 上传到可用的 zip here

您将看到这些的区域在旧金山,请参见屏幕截图:

更新:

发现Batch Picking的例子是面向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

In order to enable deep picking, any batch picking for the desired elements must be disabled and the SceneController's deep picking property must be enabled. See {@link gov.nasa.worldwind.SceneController#setDeepPickEnabled(boolean)

我花了一点时间才理解第二个,但它似乎与 AbstractSurfaceObject class.

相关联
  • 我假设您在图层上绘制的东西是 AbstractSurfaceObject
  • 的子class

我相信在这种情况下,我会子class SurfaceImageLayer,并覆盖 addRenderable 方法。如果它是 AbstractSurfaceObject 的实例,我会检查可渲染对象,并在将其转发到超级 class.

之前禁用对其的批量拾取

This code may not be the best long-term solution, but it may provide quick results to determine if this is the underlying issue.

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://whosebug.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(false)

我希望这至少能有所帮助。
祝你好运。