All Downloads are FREE. Search and download functionalities are using the official Maven repository.

src.gov.nasa.worldwindx.examples.RubberSheetImage Maven / Gradle / Ivy

Go to download

World Wind is a collection of components that interactively display 3D geographic information within Java applications or applets.

There is a newer version: 2.0.0-986
Show newest version
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

package gov.nasa.worldwindx.examples;

import gov.nasa.worldwind.*;
import gov.nasa.worldwind.avlist.*;
import gov.nasa.worldwind.event.*;
import gov.nasa.worldwindx.examples.util.*;
import gov.nasa.worldwind.formats.gcps.GCPSReader;
import gov.nasa.worldwind.formats.tab.TABRasterReader;
import gov.nasa.worldwind.formats.worldfile.WorldFile;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.pick.PickedObject;
import gov.nasa.worldwind.render.SurfaceImage;
import gov.nasa.worldwind.util.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.Box;
import javax.swing.event.*;
import javax.swing.filechooser.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.File;
import java.util.ArrayList;

/**
 * Demonstrates the use of the {@link gov.nasa.worldwind.render.SurfaceImage} class to create a "rubber sheet" image
 * that can be arbitrarily positioned, scaled and warped on the globe's surface using control points at the image's four
 * corners.
 *
 * @author tag
 * @version $Id: RubberSheetImage.java 1171 2013-02-11 21:45:02Z dcollins $
 */
public class RubberSheetImage extends ApplicationTemplate
{
    public static final String OPEN_IMAGE_FILE = "OpenImageFile";
    public static final String SET_IMAGE_OPACITY = "SetImageOpacity";
    public static final String TOGGLE_EDITING = "ToggleEditing";

    public static class AppFrame extends ApplicationTemplate.AppFrame implements ActionListener
    {
        private Controller controller;

        public AppFrame()
        {
            this.controller = new Controller(this);
            this.getWwd().addSelectListener(this.controller);

            this.initComponents();
        }

        private void initComponents()
        {
            Box controlBox = Box.createVerticalBox();
            controlBox.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); // top, left, bottom, right
            {
                JButton openFileButton = new JButton("Open Image File...");
                openFileButton.setActionCommand(OPEN_IMAGE_FILE);
                openFileButton.setAlignmentX(JComponent.LEFT_ALIGNMENT);
                openFileButton.addActionListener(this);
                controlBox.add(openFileButton);
                controlBox.add(Box.createVerticalStrut(10));

                JCheckBox toggleEditBox = new JCheckBox("Enable Editing", true);
                toggleEditBox.setActionCommand(TOGGLE_EDITING);
                toggleEditBox.setAlignmentX(JComponent.LEFT_ALIGNMENT);
                toggleEditBox.addActionListener(this);
                controlBox.add(toggleEditBox);
                controlBox.add(Box.createVerticalStrut(10));

                JLabel label = new JLabel("Opacity");
                JSlider slider = new JSlider(0, 100, 100);
                slider.addChangeListener(new ChangeListener()
                {
                    public void stateChanged(ChangeEvent event)
                    {

                        ActionEvent actionEvent = new ActionEvent(event.getSource(), 0, SET_IMAGE_OPACITY);
                        AppFrame.this.actionPerformed(actionEvent);
                    }
                });
                Box box = Box.createHorizontalBox();
                box.setAlignmentX(JComponent.LEFT_ALIGNMENT);
                box.add(label);
                box.add(slider);
                controlBox.add(box);

                controlBox.add(Box.createVerticalGlue());
            }
            this.getLayerPanel().add(controlBox, BorderLayout.SOUTH);
        }

        public void actionPerformed(ActionEvent e)
        {
            if (e == null)
                return;

            if (this.controller == null)
                return;

            this.controller.actionPerformed(e);
        }
    }

    public static class SurfaceImageEntry
    {
        private SurfaceImage surfaceImage;
        private SurfaceImageEditor editor;
        private RenderableLayer layer;

        public SurfaceImageEntry(WorldWindow wwd, SurfaceImage surfaceImage, String name)
        {
            this.surfaceImage = surfaceImage;
            this.editor = new SurfaceImageEditor(wwd, surfaceImage);

            this.layer = new RenderableLayer();
            this.layer.setName(name);
            this.layer.setPickEnabled(true);
            this.layer.addRenderable(surfaceImage);

            insertBeforePlacenames(wwd, this.layer);
        }

        public SurfaceImage getSurfaceImage()
        {
            return this.surfaceImage;
        }

        public SurfaceImageEditor getEditor()
        {
            return this.editor;
        }

        public RenderableLayer getLayer()
        {
            return this.layer;
        }
    }

    public static class Controller implements ActionListener, SelectListener
    {
        private AppFrame appFrame;
        private JFileChooser openFileChooser;
        private boolean isEditingEnabled = true;

        private ArrayList entryList = new ArrayList();

        public Controller(AppFrame appFrame)
        {
            this.appFrame = appFrame;
        }

        @SuppressWarnings( {"StringEquality"})
        public void actionPerformed(ActionEvent event)
        {
            String actionCommand = event.getActionCommand();
            if (WWUtil.isEmpty(actionCommand))
                return;

            if (actionCommand == OPEN_IMAGE_FILE)
            {
                this.doOpenImageFile();
            }
            else if (actionCommand == SET_IMAGE_OPACITY)
            {
                JSlider slider = (JSlider) event.getSource();
                this.doSetImageOpacity(slider.getValue() / 100.0);
            }
            else if (actionCommand == TOGGLE_EDITING)
            {
                AbstractButton button = (AbstractButton) event.getSource();
                this.enableEditing(button.isSelected());
            }
        }

        public void selected(SelectEvent e)
        {
            PickedObject topObject = e.getTopPickedObject();

            if (e.getEventAction().equals(SelectEvent.LEFT_PRESS))
            {
                if (topObject != null && !topObject.isTerrain() && topObject.getObject() instanceof SurfaceImage)
                {
                    SurfaceImageEntry entry = this.getEntryFor((SurfaceImage) topObject.getObject());
                    if (entry != null)
                    {
                        this.setSelectedEntry(entry);
                    }
                }
            }
        }

        protected void enableEditing(boolean enable)
        {
            this.isEditingEnabled = enable;

            for (SurfaceImageEntry entry : this.entryList)
            {
                entry.getLayer().setPickEnabled(enable);
                if (!enable)
                {
                    entry.getEditor().setArmed(false);
                }
            }
        }

        protected void addSurfaceImage(SurfaceImage surfaceImage, String name)
        {
            SurfaceImageEntry entry = new SurfaceImageEntry(this.appFrame.getWwd(), surfaceImage, name);
            this.entryList.add(entry);
            this.setSelectedEntry(entry);

            entry.getLayer().setPickEnabled(this.isEditingEnabled);
            if (!this.isEditingEnabled)
            {
                entry.getEditor().setArmed(false);
            }

            this.appFrame.getLayerPanel().update(this.appFrame.getWwd());
        }

        protected SurfaceImageEntry getEntryFor(SurfaceImage surfaceImage)
        {
            for (SurfaceImageEntry entry : this.entryList)
            {
                if (entry.getSurfaceImage() == surfaceImage)
                {
                    return entry;
                }
            }

            return null;
        }

        protected void setSelectedEntry(SurfaceImageEntry selected)
        {
            for (SurfaceImageEntry entry : this.entryList)
            {
                if (entry != selected)
                {
                    if (entry.getEditor().isArmed())
                    {
                        entry.getEditor().setArmed(false);
                    }
                }
            }

            if (!selected.getEditor().isArmed())
            {
                selected.getEditor().setArmed(true);
            }
        }

        protected void doOpenImageFile()
        {
            if (this.openFileChooser == null)
            {
                this.openFileChooser = new JFileChooser(Configuration.getUserHomeDirectory());
                this.openFileChooser.setAcceptAllFileFilterUsed(false);
                this.openFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
                this.openFileChooser.setMultiSelectionEnabled(true);
                this.openFileChooser.addChoosableFileFilter(
                    new FileNameExtensionFilter("Images", ImageIO.getReaderFormatNames()));
            }

            int retVal = this.openFileChooser.showOpenDialog(this.appFrame);
            if (retVal != JFileChooser.APPROVE_OPTION)
                return;

            File[] files = this.openFileChooser.getSelectedFiles();
            this.loadFiles(files);
        }

        protected void doSetImageOpacity(double opacity)
        {
            for (SurfaceImageEntry entry : this.entryList)
            {
                entry.getSurfaceImage().setOpacity(opacity);
            }

            this.appFrame.getWwd().redraw();
        }

        protected void loadFiles(final File[] files)
        {
            this.appFrame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

            Thread thread = new Thread(new Runnable()
            {
                public void run()
                {
                    for (File f : files)
                    {
                        loadFile(f);
                    }

                    appFrame.setCursor(null);
                }
            });
            thread.start();
        }

        protected void loadFile(final File file)
        {
            final BufferedImage image = this.readImage(file);
            if (image == null)
                return;

            final SurfaceImage si = this.createGeoreferencedSurfaceImage(file, image);
            if (si == null)
            {
                this.addNonGeoreferencedSurfaceImage(file, image, this.appFrame.getWwd());
                return;
            }

            SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    addSurfaceImage(si, file.getName());
                }
            });
        }

        protected BufferedImage readImage(File file)
        {
            try
            {
                return ImageIO.read(file);
            }
            catch (Exception e)
            {
                e.printStackTrace();
                return null;
            }
        }

        protected SurfaceImage createGeoreferencedSurfaceImage(File file, BufferedImage image)
        {
            try
            {
                SurfaceImage si = null;

                File tabFile = this.getAssociatedTABFile(file);
                if (tabFile != null)
                    si = this.createSurfaceImageFromTABFile(image, tabFile);

                if (si == null)
                {
                    File gcpsFile = this.getAssociatedGCPSFile(file);
                    if (gcpsFile != null)
                        si = this.createSurfaceImageFromGCPSFile(image, gcpsFile);
                }

                if (si == null)
                {
                    File[] worldFiles = this.getAssociatedWorldFiles(file);
                    if (worldFiles != null)
                        si = this.createSurfaceImageFromWorldFiles(image, worldFiles);
                }

                return si;
            }
            catch (Exception e)
            {
                e.printStackTrace();
                return null;
            }
        }

        public File getAssociatedTABFile(File file)
        {
            File tabFile = TABRasterReader.getTABFileFor(file);
            if (tabFile != null && tabFile.exists())
            {
                TABRasterReader reader = new TABRasterReader();
                if (reader.canRead(tabFile))
                    return tabFile;
            }

            return null;
        }

        public File getAssociatedGCPSFile(File file)
        {
            File gcpsFile = GCPSReader.getGCPSFileFor(file);
            if (gcpsFile != null && gcpsFile.exists())
            {
                GCPSReader reader = new GCPSReader();
                if (reader.canRead(gcpsFile))
                    return gcpsFile;
            }

            return null;
        }

        public File[] getAssociatedWorldFiles(File file)
        {
            try
            {
                File[] worldFiles = WorldFile.getWorldFiles(file);
                if (worldFiles != null && worldFiles.length > 0)
                    return worldFiles;
            }
            catch (Exception ignored)
            {
            }

            return null;
        }

        protected SurfaceImage createSurfaceImageFromWorldFiles(BufferedImage image, File[] worldFiles)
            throws java.io.IOException
        {
            AVList worldFileParams = new AVListImpl();
            WorldFile.decodeWorldFiles(worldFiles, worldFileParams);

            BufferedImage alignedImage = createPowerOfTwoImage(image.getWidth(), image.getHeight());
            Sector sector = ImageUtil.warpImageWithWorldFile(image, worldFileParams, alignedImage);

            return new SurfaceImage(alignedImage, sector);
        }

        protected SurfaceImage createSurfaceImageFromTABFile(BufferedImage image, File tabFile)
            throws java.io.IOException
        {
            TABRasterReader reader = new TABRasterReader();
            RasterControlPointList controlPoints = reader.read(tabFile);

            return this.createSurfaceImageFromControlPoints(image, controlPoints);
        }

        protected SurfaceImage createSurfaceImageFromGCPSFile(BufferedImage image, File gcpsFile)
            throws java.io.IOException
        {
            GCPSReader reader = new GCPSReader();
            RasterControlPointList controlPoints = reader.read(gcpsFile);

            return this.createSurfaceImageFromControlPoints(image, controlPoints);
        }

        protected SurfaceImage createSurfaceImageFromControlPoints(BufferedImage image,
            RasterControlPointList controlPoints) throws java.io.IOException
        {
            int numControlPoints = controlPoints.size();
            Point2D[] imagePoints = new Point2D[numControlPoints];
            LatLon[] geoPoints = new LatLon[numControlPoints];

            for (int i = 0; i < numControlPoints; i++)
            {
                RasterControlPointList.ControlPoint p = controlPoints.get(i);
                imagePoints[i] = p.getRasterPoint();
                geoPoints[i] = p.getWorldPointAsLatLon();
            }

            BufferedImage destImage = createPowerOfTwoImage(image.getWidth(), image.getHeight());
            Sector sector = ImageUtil.warpImageWithControlPoints(image, imagePoints, geoPoints, destImage);

            return new SurfaceImage(destImage, sector);
        }

        protected void addNonGeoreferencedSurfaceImage(final File file, final BufferedImage image,
            final WorldWindow wwd)
        {
            if (!SwingUtilities.isEventDispatchThread())
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        addNonGeoreferencedSurfaceImage(file, image, wwd);
                    }
                });
            }
            else
            {
                StringBuilder message = new StringBuilder();
                message.append("Unable to find geographic coordinates for: ");
                message.append("\"").append(file.getPath()).append("\"");
                message.append("\n");
                message.append("Open image anyway?");

                int retVal = JOptionPane.showConfirmDialog(this.appFrame, message, null, JOptionPane.YES_NO_OPTION);
                if (retVal != JOptionPane.YES_OPTION)
                    return;

                Position position = ShapeUtils.getNewShapePosition(wwd);
                double lat = position.getLatitude().radians;
                double lon = position.getLongitude().radians;
                double sizeInMeters = ShapeUtils.getViewportScaleFactor(wwd);
                double arcLength = sizeInMeters / wwd.getModel().getGlobe().getRadiusAt(position);
                Sector sector = Sector.fromRadians(lat - arcLength, lat + arcLength, lon - arcLength, lon + arcLength);

                BufferedImage powerOfTwoImage = createPowerOfTwoScaledCopy(image);

                this.addSurfaceImage(new SurfaceImage(powerOfTwoImage, sector), file.getName());
            }
        }
    }

    protected static BufferedImage createPowerOfTwoImage(int minWidth, int minHeight)
    {
        return new BufferedImage(WWMath.powerOfTwoCeiling(minWidth), WWMath.powerOfTwoCeiling(minHeight),
            BufferedImage.TYPE_INT_ARGB);
    }

    protected static BufferedImage createPowerOfTwoScaledCopy(BufferedImage image)
    {
        if (WWMath.isPowerOfTwo(image.getWidth()) && WWMath.isPowerOfTwo(image.getHeight()))
            return image;

        BufferedImage powerOfTwoImage = createPowerOfTwoImage(image.getWidth(), image.getHeight());
        ImageUtil.getScaledCopy(image, powerOfTwoImage);
        return powerOfTwoImage;
    }

    public static void main(String[] args)
    {
        ApplicationTemplate.start("World Wind Rubber Sheet Image", RubberSheetImage.AppFrame.class);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy