Changeset 24300 in osm for applications/editors/josm


Ignore:
Timestamp:
2010-11-17T18:51:59+01:00 (14 years ago)
Author:
ocroquette
Message:

PicLayer: many features: loading of multiple files, autozoom on load, autoload of cal files on loading, remember last dir in image load dialog, support for zoom on layer, scaling is now exponential

Location:
applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/LoadPictureCalibrationAction.java

    r23190 r24300  
    3838
    3939/**
    40  * Action for resetting properties of an image.
     40 * Action to load the calibration file.
    4141 *
    42  * TODO Four almost identical classes. Refactoring needed.
    4342 */
    4443public class LoadPictureCalibrationAction extends JosmAction {
     
    4746    PicLayerAbstract m_owner = null;
    4847   
     48    // Persistent FileChooser instance to remember last directory
     49    JFileChooser m_filechooser = null;
     50
    4951    /**
    5052     * Constructor
    5153     */
    5254    public LoadPictureCalibrationAction( PicLayerAbstract owner ) {
    53         super(tr("Load Picture Calibration..."), null, tr("Loads calibration data to a file"), null, false);
     55        super(tr("Load Picture Calibration..."), null, tr("Loads calibration data from a file"), null, false);
    5456        // Remember the owner...
    5557        m_owner = owner;
    5658    }
    57    
     59
    5860    /**
    5961     * Action handler
     
    6163    public void actionPerformed(ActionEvent arg0) {
    6264        // Save dialog
    63         final JFileChooser fc = new JFileChooser();
     65        JFileChooser fc = new JFileChooser();
    6466        fc.setAcceptAllFileFilterUsed( false );
    6567        fc.setFileFilter( new CalibrationFileFilter() );
     
    7173            // Load
    7274            try {
    73                 Properties props = new Properties();
    74                 props.load(new FileInputStream(fc.getSelectedFile()));
    75                 m_owner.loadCalibration(props);
     75                m_owner.loadCalibration(fc.getSelectedFile());
    7676            } catch (Exception e) {
    7777                // Error
     
    8181        }
    8282    }
     83   
    8384}
  • applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/NewLayerFromFileAction.java

    r23190 r24300  
    3333import org.openstreetmap.josm.Main;
    3434import org.openstreetmap.josm.actions.JosmAction;
     35import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
     36import org.openstreetmap.josm.gui.layer.Layer;
    3537
    3638/**
    37  * Action responsible for creation of a new layer based on
    38  * an image file.
     39 * Action responsible for creation of new layers based on image files.
    3940 */
    4041public class NewLayerFromFileAction extends JosmAction {
     42
     43    String m_lastdirprefname = "piclayer.lastdir";
    4144
    4245    /**
     
    8083
    8184        // Choose a file
    82         JFileChooser fc = new JFileChooser();
     85        JFileChooser fc = new JFileChooser(Main.pref.get(m_lastdirprefname));
    8386        fc.setAcceptAllFileFilterUsed( false );
    8487        fc.setFileFilter( new ImageFileFilter() );
     88        fc.setMultiSelectionEnabled(true);
    8589        int result = fc.showOpenDialog( Main.parent );
    8690
    8791        // Create a layer?
    8892        if ( result == JFileChooser.APPROVE_OPTION ) {
    89             // Create layer from file
    90             PicLayerFromFile layer = new PicLayerFromFile( fc.getSelectedFile() );
    91             // Add layer only if successfully initialized
    92             try {
    93                 layer.initialize();
     93            // The first loaded layer will be placed at the top of any other layer of the same class,
     94            // or at the bottom of the stack if there is no such layer yet
     95            // The next layers we load will be placed one after the other after this first layer
     96            int newLayerPos = Main.map.mapView.getAllLayers().size();
     97            for(Layer l : Main.map.mapView.getLayersOfType(PicLayerFromFile.class)) {
     98                int pos = Main.map.mapView.getLayerPos(l);
     99                if (pos < newLayerPos) newLayerPos = pos;
    94100            }
    95             catch (IOException e) {
    96                 // Failed
    97                 System.out.println( "NewLayerFromFileAction::actionPerformed - " + e.getMessage() );
    98                 JOptionPane.showMessageDialog(null, e.getMessage() );
    99                 return;
     101
     102            for(File file : fc.getSelectedFiles() ) {
     103                // TODO: we need a progress bar here, it can take quite some time
     104               
     105                // Create layer from file
     106                PicLayerFromFile layer = new PicLayerFromFile( file );
     107                // Add layer only if successfully initialized
     108                try {
     109                    layer.initialize();
     110                }
     111                catch (IOException e) {
     112                    // Failed
     113                    System.out.println( "NewLayerFromFileAction::actionPerformed - " + e.getMessage() );
     114                    JOptionPane.showMessageDialog(null, e.getMessage() );
     115                    return;
     116                }
     117                Main.pref.put(m_lastdirprefname, file.getParent());
     118       
     119                Main.main.addLayer( layer );
     120                Main.map.mapView.moveLayer(layer, newLayerPos++);
     121               
     122                if ( fc.getSelectedFiles().length == 1 && Main.pref.getInteger("piclayer.zoom-on-load", 1) != 0 ) {
     123                    // if we are loading a single picture file, zoom on it, so that the user can see something
     124                    BoundingXYVisitor v = new BoundingXYVisitor();
     125                    layer.visitBoundingBox(v);
     126                    Main.map.mapView.recalculateCenterScale(v);
     127                }
     128
    100129            }
    101             // Add layer
    102             Main.main.addLayer( layer );
    103130        }
    104 
    105131    }
    106132}
  • applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerAbstract.java

    r24292 r24300  
    3131import java.awt.event.ActionEvent;
    3232import java.awt.image.BufferedImage;
     33import java.io.File;
     34import java.io.FileInputStream;
     35import java.io.FileNotFoundException;
     36import java.io.FileOutputStream;
    3337import java.io.IOException;
    3438import java.util.List;
     
    7175    private double m_scaley = 1.0;
    7276    // The scale that was set on the map during image creation
    73     private double m_initial_scale = 0;
     77    private double m_initial_scale = 1.0;
    7478    // Layer icon
    7579    private Icon m_layericon = null;
     
    103107     */
    104108    public void initialize() throws IOException {
     109        // First, we initialize the calibration, so that createImage() can rely on it
     110       
     111        // If the map does not exist - we're screwed. We should not get into this situation in the first place!
     112        if ( Main.map != null && Main.map.mapView != null ) {
     113            // Geographical position of the image
     114            // getCenter() documentation claims it returns a clone, but this is not in line with the code,
     115            // which actually returns the same object upon subsequent calls. This messes things up
     116            // when we loading several pictures and associated cal's in one go.
     117            // So as a workaround, copy the object manually :
     118            // TODO: not sure about this code below, probably there is a better way to clone the objects
     119            EastNorth center = Main.map.mapView.getCenter();
     120            m_initial_position = new EastNorth(center.east(), center.north());
     121            m_position = new EastNorth(center.east(), center.north());
     122            // Initial scale at which the image was loaded
     123            m_initial_scale = Main.map.mapView.getDist100Pixel();
     124        } else {
     125            throw new IOException(tr("Could not find the map object."));
     126        }
    105127
    106128        // Create image
     
    113135        Graphics g = m_image.getGraphics();
    114136        g.drawImage( image, 0, 0, null );
    115 
    116         // If the map does not exist - we're screwed. We should not get into this situation in the first place!
    117         if ( Main.map != null && Main.map.mapView != null ) {
    118             // Geographical position of the image
    119             m_initial_position = m_position = Main.map.mapView.getCenter();
    120             // Initial scale at which the image was loaded
    121             m_initial_scale = Main.map.mapView.getDist100Pixel();
    122         } else {
    123             throw new IOException(tr("Could not find the map object."));
    124         }
    125137    }
    126138
     
    231243
    232244    /**
    233      * Scales the picture. Scaled in... don't know but works ok :)
     245     * Scales the picture. scalex and scaley will multiply the current factor
    234246     */
    235247    public void scalePictureBy( double scalex, double scaley ) {
    236         m_scalex += scalex;
    237         m_scaley += scaley;
     248        m_scalex *= scalex;
     249        m_scaley *= scaley;
    238250    }
    239251
     
    268280
    269281    @Override
     282    /**
     283     * Computes the (rough) bounding box.
     284     * We ignore the rotation, the resulting bounding box contains any possible
     285     * rotation.
     286     */
    270287    public void visitBoundingBox(BoundingXYVisitor arg0) {
    271         // TODO Auto-generated method stub
    272 
     288        if ( m_image == null )
     289            return;
     290        String projcode = Main.proj.toCode();
     291
     292        // TODO: bounding box only supported when coordinates are in meters
     293        // The reason for that is that this .cal think makes us a hard time.
     294        // The position is stored as a raw data (can be either in degrees or
     295        // in meters, depending on the projection used at creation), but the
     296        // initial scale is in m/100pix
     297        // So for now, we support the bounding box only when everything is in meters
     298        if ( projcode.equals("EPSG:3857") || projcode.equals("EPSG:4326") )
     299            return;
     300           
     301        EastNorth center = m_position;
     302        double w = m_image.getWidth(null);
     303        double h = m_image.getHeight(null);
     304        double diag_pix = Math.sqrt(w*w+h*h);
     305       
     306        // m_initial_scale is a the scale (unit: m/100pix) at creation time
     307        double diag_m = (diag_pix/100) * m_initial_scale;
     308       
     309        double factor = Math.max(m_scalex, m_scaley);
     310        double offset = factor * diag_m / 2.0;
     311
     312        EastNorth topleft = center.add(-offset, -offset);
     313        EastNorth bottomright = center.add(offset, offset);
     314        arg0.visit(topleft);
     315        arg0.visit(bottomright);
    273316    }
    274317
     
    287330        props.put(SCALEY, "" + m_scaley);
    288331        props.put(ANGLE, "" + m_angle);
     332    }
     333
     334    /**
     335     * Loads calibration data from file
     336     * @param file The file to read from
     337     * @return
     338     */
     339    public void loadCalibration(File file) throws IOException {
     340        Properties props = new Properties();
     341        props.load(new FileInputStream(file));
     342        loadCalibration(props);
    289343    }
    290344
  • applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/PicLayerFromFile.java

    r24291 r24300  
    2121package org.openstreetmap.josm.plugins.piclayer;
    2222
     23import static org.openstreetmap.josm.tools.I18n.tr;
     24
     25import org.openstreetmap.josm.Main;
     26
    2327import java.awt.Image;
    2428import java.io.File;
    2529import java.io.IOException;
    2630import javax.imageio.ImageIO;
    27 
     31import javax.swing.JDialog;
     32import javax.swing.JOptionPane;
    2833/**
    2934 * Layer displaying a picture loaded from a file.
     
    3944        // Remember the file
    4045        m_file = file;
     46
    4147        // Generate tooltip text
    4248        m_tooltiptext = m_file.getAbsolutePath();
     
    4450        // Set the name of the layer as the base name of the file
    4551        setName(m_file.getName());
    46         System.out.println( "name="+m_file.getName() );
    4752    }
    4853
     
    5560        return calFile;
    5661    }
    57 
     62   
    5863    @Override
    5964    protected Image createImage() throws IOException {
     
    6166        Image image = null;
    6267        image = ImageIO.read( m_file );
     68       
     69        // Manage a potential existing calibration file
     70        File calFile = getDefaultCalPath();
     71        if ( calFile.exists() ) {
     72            String prefkey = "piclayer.autoloadcal";
     73            String policy = Main.pref.get(prefkey, "");
     74            policy = policy.trim().toLowerCase();
     75            boolean loadcal = false;
     76
     77            String msg = tr("A calibration file associated to the picture file was found:")+"\n"+calFile.getName();
     78            if ( policy.equals("yes") ) {
     79                loadcal = true;
     80            }
     81            else if ( policy.equals("no") ) {
     82                loadcal = false;
     83            }
     84            else if ( policy.equals("ask") ) {
     85                msg += "\n" + tr("(set  \"{0}\"  to yes/no/ask in the preferences\n"+
     86                                "to control the autoloading of calibration files)", prefkey);
     87                msg += "\n" + tr("Do you want to apply it ?");
     88                int answer = JOptionPane.showConfirmDialog(Main.parent, msg, tr("Load calibration file ?"), JOptionPane.YES_NO_OPTION);
     89                if (answer == JOptionPane.YES_OPTION) {
     90                    loadcal = true;
     91                }
     92            }
     93            else {
     94                msg += "\n" + tr("It will be applied automatically.");
     95                msg += "\n" + tr("Also, frow now on, cal files will always be loaded automatically.");
     96                msg += "\n" + tr("Set  \"{0}\"  to yes/no/ask in the preferences\n"+
     97                                "to control the autoloading of calibration files.", prefkey);
     98                // TODO: there should be here a yes/no dialog with a checkbox "do not ask again"
     99                JOptionPane.showMessageDialog(Main.parent, msg,
     100                    "Automatic loading of the calibration", JOptionPane.INFORMATION_MESSAGE);
     101                Main.pref.put(prefkey, "yes");
     102                loadcal = true;
     103            }
     104            if ( loadcal )
     105                loadCalibration(calFile);
     106        }
     107               
    63108        return image;
    64109    }
  • applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScalePictureActionAbstract.java

    r24288 r24300  
    8787            double factor;
    8888            if ( ( e.getModifiersEx() & e.SHIFT_DOWN_MASK ) != 0 ) {
    89                 factor = Main.pref.getDouble("piclayer.scalefactors.high_precision", 4000);
     89                factor = Main.pref.getDouble("piclayer.scalefactors.high_precision", 1.0001);
    9090            }
    9191            else {
    92                 factor = Main.pref.getDouble("piclayer.scalefactors.low_precision", 400);
     92                factor = Main.pref.getDouble("piclayer.scalefactors.low_precision", 1.015);
    9393            }           
    94             doTheScale( ( e.getY() - m_prevY ) / factor );
     94            doTheScale( Math.pow(factor, m_prevY - e.getY() ) );
    9595            m_prevY = e.getY();
    9696            Main.map.mapView.repaint();
  • applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScaleXPictureAction.java

    r23190 r24300  
    4444
    4545    public void doTheScale( double scale ) {
    46             m_currentLayer.scalePictureBy( scale, 0.0 );
     46            m_currentLayer.scalePictureBy( scale, 1.0 );
    4747        }
    4848}
  • applications/editors/josm/plugins/piclayer/src/org/openstreetmap/josm/plugins/piclayer/ScaleYPictureAction.java

    r23190 r24300  
    4444
    4545    public void doTheScale( double scale ) {
    46             m_currentLayer.scalePictureBy( 0.0, scale );
     46            m_currentLayer.scalePictureBy( 1.0, scale );
    4747        }
    4848}
Note: See TracChangeset for help on using the changeset viewer.