Ignore:
Timestamp:
2013-06-27T00:24:06+02:00 (11 years ago)
Author:
pieren
Message:

fix raster image georeferencing issues. Add new MenuActionRefineGeoRef for a new georeferencing already referenced plan image.

Location:
applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/CacheControl.java

    r29101 r29714  
    159159            }
    160160        }
    161         if (successfulRead && wmsLayer.isRaster()) {
    162             // serialized raster bufferedImage hangs-up on Java6. Recreate them here
    163             wmsLayer.getImage(0).image = RasterImageModifier.fixRasterImage(wmsLayer.getImage(0).image);
    164         }
     161        /*
     162        Previously contained a call to RasterImageModifier.fixRasterImage() to fix a de-serialization bug on some
     163        older java 6 versions. Request a jre update if any complains. 
     164        */
    165165        return successfulRead;
    166166    }
  • applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/CadastrePlugin.java

    r29194 r29714  
    131131 * 2.2 01-Jul-2011 - replace deprecated Main.proj by newest Main.getProjection()
    132132 *                 - fix list of raster images (Feuilles) parsing failing after a Cadastre server change/maintenance
    133  * 2.3 11-Jan-2013 - add various improvements from Don-Vip (Vincent Privat) trac #8175, #8229 and #5626.
     133 * 2.3 11-Jan-2013 - add various improvements from Don-Vip (Vincent Privat) trac #8175, #8229 and #5626.
     134 * 2.4 27-Jun-2013 - fix raster image georeferencing issues. Add new MenuActionRefineGeoRef for a new georeferencing
     135 *                   of already referenced plan image.                   
    134136 */
    135137public class CadastrePlugin extends Plugin {
  • applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/MenuActionGrabPlanImage.java

    r29677 r29714  
    55import static org.openstreetmap.josm.tools.I18n.marktr;
    66
    7 import java.awt.GridBagLayout;
    87import java.awt.event.ActionEvent;
    9 import java.awt.event.MouseEvent;
    10 import java.awt.event.MouseListener;
    11 import java.beans.PropertyChangeEvent;
    12 import java.beans.PropertyChangeListener;
    138import java.util.ArrayList;
    149
    15 import javax.swing.JDialog;
    16 import javax.swing.JLabel;
    1710import javax.swing.JOptionPane;
    18 import javax.swing.JPanel;
    19 import javax.swing.JTextField;
    2011
    2112import org.openstreetmap.josm.Main;
    2213import org.openstreetmap.josm.actions.JosmAction;
    23 import org.openstreetmap.josm.data.coor.EastNorth;
    2414import org.openstreetmap.josm.gui.layer.Layer;
    25 import org.openstreetmap.josm.tools.GBC;
    2615
    27 public class MenuActionGrabPlanImage extends JosmAction implements Runnable, MouseListener {
     16public class MenuActionGrabPlanImage extends JosmAction implements Runnable {
    2817
    2918    /**
     
    3625    private DownloadWMSPlanImage downloadWMSPlanImage;
    3726    private WMSLayer wmsLayer;
    38     private int countMouseClicked = 0;
    39     private int mode = 0;
    40     private int cGetCorners = 1;
    41     private int cGetLambertCrosspieces = 2;
    42     private EastNorth ea1;
    43     private EastNorth ea2;
    44     private long mouseClickedTime = 0;
    45     private EastNorth georefpoint1;
    46     private EastNorth georefpoint2;
    47     private boolean ignoreMouseClick = false;
    48     private boolean clickOnTheMap = false;
     27    private RasterImageGeoreferencer rasterImageGeoreferencer;
    4928   
    50     /**
    51      * The time which needs to pass between two clicks during georeferencing, in milliseconds
    52      */
    53     private int initialClickDelay;
    54 
    5529    public MenuActionGrabPlanImage() {
    5630        super(tr(name), "cadastre_small", tr("Grab non-georeferenced image"), null, false, "cadastrefr/grabplanimage", true);
    57     }
    58 
    59     public void actionCompleted() {
    60         countMouseClicked = 0;
    61         mode = 0;
    62         mouseClickedTime = System.currentTimeMillis();
    63     }
    64 
    65     public void actionInterrupted() {
    66         actionCompleted();
    67         if (wmsLayer != null) {
    68             Main.main.removeLayer(wmsLayer);
    69             wmsLayer = null;
    70         }
     31        rasterImageGeoreferencer = new RasterImageGeoreferencer();
    7132    }
    7233
     
    7435    protected void updateEnabledState() {
    7536        if (wmsLayer == null || Main.map == null || Main.map.mapView == null) return;
    76         if (countMouseClicked == 0 && mode == 0) return;
     37        if (!rasterImageGeoreferencer.isRunning()) return;
    7738        for (Layer l : Main.map.mapView.getAllLayersAsList())
    7839            if (l == wmsLayer)
    7940                return;
    8041        JOptionPane.showMessageDialog(Main.parent, tr("Georeferencing interrupted"));
    81         actionInterrupted();
     42        rasterImageGeoreferencer.actionInterrupted();
    8243    }
    8344
     
    8546        if (Main.map != null) {
    8647            if (CadastrePlugin.isCadastreProjection()) {
    87                 //wmsLayer = WMSDownloadAction.getLayer();
    8848                wmsLayer = new MenuActionNewLocation().addNewLayer(new ArrayList<WMSLayer>());
    8949                if (wmsLayer == null) return;
    9050                downloadWMSPlanImage = new DownloadWMSPlanImage();
    9151                downloadWMSPlanImage.download(wmsLayer);
    92                 initialClickDelay = Main.pref.getInteger("cadastrewms.georef-click-delay",200);
    9352                // download sub-images of the cadastre scan and join them into one single
    9453                Main.worker.execute(this);
     
    10665        } else if (wmsLayer.getImages().size() == 0) {
    10766            // action canceled or image loaded from cache (and already georeferenced)
    108             actionInterrupted();
     67            rasterImageGeoreferencer.actionInterrupted();
    10968        } else {
    11069            int reply = JOptionPane.CANCEL_OPTION;
     
    11776            }
    11877            if (reply == JOptionPane.OK_OPTION) {
    119                 transformGeoreferencedImg();
     78                rasterImageGeoreferencer.transformGeoreferencedImg();
    12079            } else {
    121                 mouseClickedTime = System.currentTimeMillis();
    122                 Main.map.mapView.addMouseListener(this);
     80                rasterImageGeoreferencer.addListener();
    12381                if (Main.pref.getBoolean("cadastrewms.noImageCropping", false) == false)
    124                     startCropping();
     82                    rasterImageGeoreferencer.startCropping(wmsLayer);
    12583                else
    126                     startGeoreferencing();
     84                    rasterImageGeoreferencer.startGeoreferencing(wmsLayer);
    12785            }
    12886        }
    12987    }
    130 
    131     public void mouseClicked(MouseEvent e) {
    132         if (System.currentTimeMillis() - mouseClickedTime < initialClickDelay) {
    133             System.out.println("mouse click bounce detected");
    134             return; // mouse click anti-bounce
    135         }
    136         else
    137             mouseClickedTime = System.currentTimeMillis();
    138         if (e.getButton() != MouseEvent.BUTTON1)
    139             return;
    140         if (ignoreMouseClick) return; // In case we are currently just allowing zooming to read lambert coordinates
    141         EastNorth ea = Main.getProjection().latlon2eastNorth(Main.map.mapView.getLatLon(e.getX(), e.getY()));
    142         System.out.println("clic:"+countMouseClicked+" ,"+ea+", mode:"+mode);
    143         if (clickOnTheMap) {
    144             clickOnTheMap = false;
    145             handleNewCoordinates(ea.east(), ea.north());
    146         } else {
    147             // ignore clicks outside the image
    148             if (ea.east() < wmsLayer.getImage(0).min.east() || ea.east() > wmsLayer.getImage(0).max.east()
    149                     || ea.north() < wmsLayer.getImage(0).min.north() || ea.north() > wmsLayer.getImage(0).max.north())
    150             {
    151                 System.out.println("ignore clic outside the image");
    152                 return;
    153             }
    154             countMouseClicked++;
    155             if (mode == cGetCorners) {
    156                 if (countMouseClicked == 1) {
    157                     ea1 = ea;
    158                     continueCropping();
    159                 }
    160                 if (countMouseClicked == 2) {
    161                     wmsLayer.cropImage(ea1, ea);
    162                     Main.map.mapView.repaint();
    163                     startGeoreferencing();
    164                 }
    165             } else if (mode == cGetLambertCrosspieces) {
    166                 if (countMouseClicked == 1) {
    167                     ea1 = ea;
    168                     inputLambertPosition(); // This will automatically asks for second point and continue the georeferencing
    169                 }
    170                 if (countMouseClicked == 2) {
    171                     ea2 = ea;
    172                     inputLambertPosition(); // This will automatically ends the georeferencing
    173                 }
    174             }
    175         }
    176     }
    177 
    178     /**
    179      *
    180      * @return false if all operations are canceled
    181      */
    182     private boolean startCropping() {
    183         mode = cGetCorners;
    184         countMouseClicked = 0;
    185         Object[] options = { "OK", "Cancel" };
    186         int ret = JOptionPane.showOptionDialog( null,
    187                 tr("Click first corner for image cropping\n(two points required)"),
    188                 tr("Image cropping"),
    189                 JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
    190                 null, options, options[0]);
    191         if (ret == JOptionPane.OK_OPTION) {
    192             mouseClickedTime = System.currentTimeMillis();
    193         } else
    194             if (canceledOrRestartCurrAction("image cropping"))
    195                 return startCropping();
    196         return true;
    197     }
    198 
    199     /**
    200      *
    201      * @return false if all operations are canceled
    202      */
    203     private boolean continueCropping() {
    204         Object[] options = { "OK", "Cancel" };
    205         int ret = JOptionPane.showOptionDialog( null,
    206                 tr("Click second corner for image cropping"),
    207                 tr("Image cropping"),
    208                 JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
    209                 null, options, options[0]);
    210         if (ret != JOptionPane.OK_OPTION) {
    211             if (canceledOrRestartCurrAction("image cropping"))
    212                 return startCropping();
    213         }
    214         return true;
    215     }
    216 
    217     /**
    218      *
    219      * @return false if all operations are canceled
    220      */
    221     private boolean startGeoreferencing() {
    222         countMouseClicked = 0;
    223         mode = cGetLambertCrosspieces;
    224         Object[] options = { "OK", "Cancel" };
    225         int ret = JOptionPane.showOptionDialog( null,
    226                 tr("Click first Lambert crosspiece for georeferencing\n(two points required)"),
    227                 tr("Image georeferencing"),
    228                 JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
    229                 null, options, options[0]);
    230         if (ret == JOptionPane.OK_OPTION) {
    231             mouseClickedTime = System.currentTimeMillis();
    232         } else
    233             if (canceledOrRestartCurrAction("georeferencing"))
    234                 return startGeoreferencing();
    235         return true;
    236     }
    237 
    238     /**
    239      *
    240      * @return false if all operations are canceled
    241      */
    242     private boolean continueGeoreferencing() {
    243         Object[] options = { "OK", "Cancel" };
    244         int ret = JOptionPane.showOptionDialog( null,
    245                 tr("Click second Lambert crosspiece for georeferencing"),
    246                 tr("Image georeferencing"),
    247                 JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
    248                 null, options, options[0]);
    249         if (ret != JOptionPane.OK_OPTION) {
    250             if (canceledOrRestartCurrAction("georeferencing"))
    251                 return startGeoreferencing();
    252         }
    253         return true;
    254     }
    255    
    256     /**
    257      * Ends the georeferencing by computing the affine transformation
    258      */
    259     private void endGeoreferencing() {
    260         Main.map.mapView.removeMouseListener(this);
    261         affineTransform(ea1, ea2, georefpoint1, georefpoint2);
    262         wmsLayer.grabThread.saveNewCache();
    263         Main.map.mapView.repaint();
    264         actionCompleted();
    265         clickOnTheMap = false;
    266         ignoreMouseClick = false;
    267     }
    268 
    269     /**
    270      *
    271      * @return false if all operations are canceled
    272      */
    273     private boolean canceledOrRestartCurrAction(String action) {
    274         Object[] options = { "Cancel", "Retry" };
    275         int selectedValue = JOptionPane.showOptionDialog( null,
    276                 tr("Do you want to cancel completely\n"+
    277                         "or just retry "+action+" ?"), "",
    278                 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
    279                 null, options, options[0]);
    280         countMouseClicked = 0;
    281         if (selectedValue == 0) { // "Cancel"
    282             // remove layer
    283             Main.main.removeLayer(wmsLayer);
    284             wmsLayer = null;
    285             Main.map.mapView.removeMouseListener(this);
    286             return false;
    287         }
    288         return true;
    289     }
    290 
    291     private void inputLambertPosition() {
    292         JLabel labelEnterPosition = new JLabel(
    293                 tr("Enter cadastre east,north position"));
    294         JLabel labelWarning = new JLabel(
    295                 tr("(Warning: verify north with arrow !!)"));
    296         JPanel p = new JPanel(new GridBagLayout());
    297         JLabel labelEast = new JLabel(tr("East"));
    298         JLabel labelNorth = new JLabel(tr("North"));
    299         final JTextField inputEast = new JTextField();
    300         final JTextField inputNorth = new JTextField();
    301         p.add(labelEnterPosition, GBC.eol());
    302         p.add(labelWarning, GBC.eol());
    303         p.add(labelEast, GBC.std().insets(0, 0, 10, 0));
    304         p.add(inputEast, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 5, 0, 5));
    305         p.add(labelNorth, GBC.std().insets(0, 0, 10, 0));
    306         p.add(inputNorth, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 5, 0, 5));
    307         final Object[] options = {tr("OK"),
    308                 tr("Cancel"),
    309                 tr("I use the mouse")};
    310         final JOptionPane pane = new JOptionPane(p,
    311                 JOptionPane.INFORMATION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION,
    312                 null, options, options[0]);
    313         String number;
    314         if (countMouseClicked == 1)
    315             number = "first";
    316         else
    317             number = "second";
    318         JDialog dialog = pane.createDialog(Main.parent, tr(
    319                 "Set {0} Lambert coordinates", number));
    320         dialog.setModal(false);
    321         ignoreMouseClick = true; // To avoid mouseClicked from being called
    322                                  // during coordinates reading
    323         dialog.setAlwaysOnTop(true);
    324         dialog.setVisible(true);
    325         pane.addPropertyChangeListener(new PropertyChangeListener() {
    326             public void propertyChange(PropertyChangeEvent evt) {
    327                 if (JOptionPane.VALUE_PROPERTY.equals(evt.getPropertyName())) {
    328                     ignoreMouseClick = false;
    329                     // Cancel
    330                     if (pane.getValue().equals(options[1])) {
    331                         if (canceledOrRestartCurrAction("georeferencing"))
    332                             startGeoreferencing();
    333                     }
    334                     // Click on the map
    335                     if (pane.getValue().equals(options[2])) {
    336                         clickOnTheMap = true;
    337                     } else {
    338                     // OK (coordinates manually entered)
    339                         clickOnTheMap = false;
    340                         if (inputEast.getText().length() != 0
    341                                 && inputNorth.getText().length() != 0) {
    342                             double e, n;
    343                             try {
    344                                 e = Double.parseDouble(inputEast.getText());
    345                                 n = Double.parseDouble(inputNorth.getText());
    346                             } catch (NumberFormatException ex) {
    347                                 return;
    348                             }
    349                             handleNewCoordinates(e, n);
    350                         }
    351                     }
    352                 }
    353             }
    354         });
    355     }
    356 
    357     private void handleNewCoordinates(double e, double n) {
    358         if (countMouseClicked == 1) {
    359             georefpoint1 = new EastNorth(e, n);
    360             continueGeoreferencing();
    361         } else {
    362             georefpoint2 = new EastNorth(e, n);
    363             endGeoreferencing();
    364         }
    365     }
    366 
    367     /**
    368      * Use point org1 as anchor for scale, then move org1 to dst1, then rotate org2 on dst2
    369      * around org1/dst1 anchor
    370      * @param org1 first point at original coordinate system (the grabbed image)
    371      * @param org2 second point "
    372      * @param dst1 first point at final destination coordinate system (the real east/north coordinate system)
    373      * @param dst2 second point "
    374      */
    375     private void affineTransform(EastNorth org1, EastNorth org2, EastNorth dst1, EastNorth dst2) {
    376         // handle an NPE case I'm not able to reproduce
    377         if(org1==null || org2==null || dst1==null || dst2==null)
    378         {
    379             JOptionPane.showMessageDialog(Main.parent,
    380                     tr("Ooops. I failed to catch all coordinates\n"+
    381                        "correctly. Retry please."));
    382             System.out.println("failed to transform: one coordinate missing:"
    383                        +"org1="+org1+", org2="+org2+", dst1="+dst1+", dst2="+dst2);
    384             return;
    385         }
    386         double angle = dst1.heading(dst2) - org1.heading(org2);
    387         double proportion = dst1.distance(dst2)/org1.distance(org2);
    388         // move
    389         double dx = dst1.getX() - org1.getX();
    390         double dy = dst1.getY() - org1.getY();
    391         wmsLayer.getImage(0).shear(dx, dy);
    392         org1 = org1.add(dx, dy); // org1=dst1 now
    393         org2 = org2.add(dx, dy);
    394         // rotate : org1(=dst1 now) is anchor for rotation and scale
    395         wmsLayer.getImage(0).rotate(dst1, angle);
    396         org2 = org2.rotate(dst1, angle);
    397         // scale image from anchor org1(=dst1 now)
    398         wmsLayer.getImage(0).scale(dst1, proportion);
    399     }
    400 
    401     private void transformGeoreferencedImg() {
    402         georefpoint1 = new EastNorth(wmsLayer.X0, wmsLayer.Y0);
    403         georefpoint2 = new EastNorth(wmsLayer.X0+wmsLayer.fX*wmsLayer.communeBBox.max.getX(),
    404                 wmsLayer.Y0+wmsLayer.fY*wmsLayer.communeBBox.max.getX());
    405         ea1 = new EastNorth(wmsLayer.getImage(0).min.east(), wmsLayer.getImage(0).max.north());
    406         EastNorth ea2 = wmsLayer.getImage(0).max;
    407         affineTransform(ea1, ea2, georefpoint1, georefpoint2);
    408         wmsLayer.grabThread.saveNewCache();
    409         Main.map.mapView.repaint();
    410     }
    411 
    412     public void mouseEntered(MouseEvent arg0) {
    413     }
    414 
    415     public void mouseExited(MouseEvent arg0) {
    416     }
    417 
    418     public void mousePressed(MouseEvent arg0) {
    419     }
    420 
    421     public void mouseReleased(MouseEvent arg0) {
    422     }
    423 
    42488}
  • applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/WMSLayer.java

    r29677 r29714  
    9292
    9393    private Action cancelGrab;
     94   
     95    private Action refineGeoRef;
    9496
    9597    @SuppressWarnings("serial")
     
    309311        cancelGrab = new MenuActionCancelGrab(this);
    310312        cancelGrab.setEnabled(!isRaster && grabThread.getImagesToGrabSize() > 0);
     313        refineGeoRef = new MenuActionRefineGeoRef(this);
     314        refineGeoRef.setEnabled(isRaster && grabThread.getImagesToGrabSize() == 0);
    311315        Action resetOffset = new ResetOffsetActionMenu();
    312316        resetOffset.setEnabled(!isRaster && images.size() > 0 && (deltaEast!=0.0 || deltaNorth!=0.0));
     
    317321                saveAsPng,
    318322                cancelGrab,
     323                refineGeoRef,
    319324                resetOffset,
    320325                new LayerListPopup.InfoAction(this),
Note: See TracChangeset for help on using the changeset viewer.