source: osm/applications/editors/josm/plugins/cadastre-fr/src/cadastre_fr/MenuActionGrabPlanImage.java@ 19267

Last change on this file since 19267 was 19267, checked in by pieren, 15 years ago

Several minor improvements.

File size: 13.6 KB
Line 
1// License: GPL. v2 and later. Copyright 2008-2009 by Pieren <pieren3@gmail.com> and others
2package cadastre_fr;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.GridBagLayout;
7import java.awt.event.ActionEvent;
8import java.awt.event.MouseEvent;
9import java.awt.event.MouseListener;
10import java.util.ArrayList;
11
12import javax.swing.JLabel;
13import javax.swing.JOptionPane;
14import javax.swing.JPanel;
15import javax.swing.JTextField;
16
17import org.openstreetmap.josm.Main;
18import org.openstreetmap.josm.actions.JosmAction;
19import org.openstreetmap.josm.data.coor.EastNorth;
20import org.openstreetmap.josm.gui.layer.Layer;
21import org.openstreetmap.josm.tools.GBC;
22
23public class MenuActionGrabPlanImage extends JosmAction implements Runnable, MouseListener {
24
25 /**
26 * Action calling the wms grabber for non georeferenced images called "plan image"
27 */
28 private static final long serialVersionUID = 1L;
29
30 public static String name = "Georeference an image";
31
32 private DownloadWMSPlanImage downloadWMSPlanImage;
33 private WMSLayer wmsLayer;
34 private int countMouseClicked = 0;
35 private int mode = 0;
36 private int cGetCorners = 1;
37 private int cGetLambertCrosspieces = 2;
38 private EastNorth ea1;
39 private long mouseClickedTime = 0;
40 private EastNorth georefpoint1;
41 private EastNorth georefpoint2;
42 /**
43 * The time which needs to pass between two clicks during georeferencing, in milliseconds
44 */
45 private int initialClickDelay;
46
47 public MenuActionGrabPlanImage() {
48 super(tr(name), "cadastre_small", tr("Grab non-georeferenced image"), null, false);
49 }
50
51 public void actionCompleted() {
52 countMouseClicked = 0;
53 mode = 0;
54 mouseClickedTime = System.currentTimeMillis();
55 }
56
57 public void actionInterrupted() {
58 actionCompleted();
59 wmsLayer = null;
60 }
61
62 @Override
63 protected void updateEnabledState() {
64 if (wmsLayer == null || Main.map == null || Main.map.mapView == null) return;
65 if (countMouseClicked == 0 && mode == 0) return;
66 for (Layer l : Main.map.mapView.getAllLayersAsList())
67 if (l == wmsLayer)
68 return;
69 JOptionPane.showMessageDialog(Main.parent, tr("Georeferencing interrupted"));
70 actionInterrupted();
71 }
72
73 public void actionPerformed(ActionEvent ae) {
74 if (Main.map != null) {
75 if (CadastrePlugin.isCadastreProjection()) {
76 //wmsLayer = WMSDownloadAction.getLayer();
77 wmsLayer = new MenuActionNewLocation().addNewLayer(new ArrayList<WMSLayer>());
78 if (wmsLayer == null) return;
79 downloadWMSPlanImage = new DownloadWMSPlanImage();
80 downloadWMSPlanImage.download(wmsLayer);
81 initialClickDelay = Main.pref.getInteger("cadastrewms.georef-click-delay",200);
82 // download sub-images of the cadastre scan and join them into one single
83 Main.worker.execute(this);
84 } else {
85 JOptionPane.showMessageDialog(Main.parent,
86 tr("To enable the cadastre WMS plugin, change\n"
87 + "the current projection to one of the cadastre\n"
88 + "projections and retry"));
89 }
90 }
91 }
92
93 public void run() {
94 // wait until plan image is fully loaded and joined into one single image
95 boolean loadedFromCache = downloadWMSPlanImage.waitFinished();
96 if (wmsLayer.images.size() == 1 && !loadedFromCache) {
97 int reply = JOptionPane.CANCEL_OPTION;
98 if (wmsLayer.isAlreadyGeoreferenced()) {
99 reply = JOptionPane.showConfirmDialog(null,
100 tr("This image contains georeference data.\n"+
101 "Do you want to use them ?"),
102 null,
103 JOptionPane.YES_NO_OPTION);
104 }
105 if (reply == JOptionPane.OK_OPTION) {
106 transformGeoreferencedImg();
107 } else {
108 mouseClickedTime = System.currentTimeMillis();
109 Main.map.mapView.addMouseListener(this);
110 if (Main.pref.getBoolean("cadastrewms.noImageCropping", false) == false)
111 startCropping();
112 else
113 startGeoreferencing();
114 }
115 } else // action cancelled or image loaded from cache (and already georeferenced)
116 Main.map.repaint();
117 }
118
119 public void mouseClicked(MouseEvent e) {
120 if (System.currentTimeMillis() - mouseClickedTime < initialClickDelay) {
121 System.out.println("mouse click bounce detected");
122 return; // mouse click anti-bounce
123 }
124 else
125 mouseClickedTime = System.currentTimeMillis();
126 if (e.getButton() != MouseEvent.BUTTON1)
127 return;
128 countMouseClicked++;
129 EastNorth ea = Main.proj.latlon2eastNorth(Main.map.mapView.getLatLon(e.getX(), e.getY()));
130 System.out.println("clic:"+countMouseClicked+" ,"+ea+", mode:"+mode);
131 // ignore clicks outside the image
132 if (ea.east() < wmsLayer.images.get(0).min.east() || ea.east() > wmsLayer.images.get(0).max.east()
133 || ea.north() < wmsLayer.images.get(0).min.north() || ea.north() > wmsLayer.images.get(0).max.north())
134 return;
135 if (mode == cGetCorners) {
136 if (countMouseClicked == 1) {
137 ea1 = ea;
138 continueCropping();
139 }
140 if (countMouseClicked == 2) {
141 wmsLayer.cropImage(ea1, ea);
142 Main.map.mapView.repaint();
143 startGeoreferencing();
144 }
145 } else if (mode == cGetLambertCrosspieces) {
146 if (countMouseClicked == 1) {
147 ea1 = ea;
148 if (inputLambertPosition())
149 continueGeoreferencing();
150 }
151 if (countMouseClicked == 2) {
152 if (inputLambertPosition()) {
153 Main.map.mapView.removeMouseListener(this);
154 affineTransform(ea1, ea, georefpoint1, georefpoint2);
155 wmsLayer.saveNewCache();
156 Main.map.mapView.repaint();
157 actionCompleted();
158 }
159 }
160 }
161 }
162
163 /**
164 *
165 * @return false if all operations are canceled
166 */
167 private boolean startCropping() {
168 mode = cGetCorners;
169 countMouseClicked = 0;
170 Object[] options = { "OK", "Cancel" };
171 int ret = JOptionPane.showOptionDialog( null,
172 tr("Click first corner for image cropping\n(two points required)"),
173 tr("Image cropping"),
174 JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
175 null, options, options[0]);
176 if (ret == JOptionPane.OK_OPTION) {
177 mouseClickedTime = System.currentTimeMillis();
178 } else
179 if (canceledOrRestartCurrAction("image cropping"))
180 return startCropping();
181 return true;
182 }
183
184 /**
185 *
186 * @return false if all operations are canceled
187 */
188 private boolean continueCropping() {
189 Object[] options = { "OK", "Cancel" };
190 int ret = JOptionPane.showOptionDialog( null,
191 tr("Click second corner for image cropping"),
192 tr("Image cropping"),
193 JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
194 null, options, options[0]);
195 if (ret != JOptionPane.OK_OPTION) {
196 if (canceledOrRestartCurrAction("image cropping"))
197 return startCropping();
198 }
199 return true;
200 }
201
202 /**
203 *
204 * @return false if all operations are canceled
205 */
206 private boolean startGeoreferencing() {
207 countMouseClicked = 0;
208 mode = cGetLambertCrosspieces;
209 Object[] options = { "OK", "Cancel" };
210 int ret = JOptionPane.showOptionDialog( null,
211 tr("Click first Lambert crosspiece for georeferencing\n(two points required)"),
212 tr("Image georeferencing"),
213 JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
214 null, options, options[0]);
215 if (ret == JOptionPane.OK_OPTION) {
216 mouseClickedTime = System.currentTimeMillis();
217 } else
218 if (canceledOrRestartCurrAction("georeferencing"))
219 return startGeoreferencing();
220 return true;
221 }
222
223 /**
224 *
225 * @return false if all operations are canceled
226 */
227 private boolean continueGeoreferencing() {
228 Object[] options = { "OK", "Cancel" };
229 int ret = JOptionPane.showOptionDialog( null,
230 tr("Click second Lambert crosspiece for georeferencing"),
231 tr("Image georeferencing"),
232 JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE,
233 null, options, options[0]);
234 if (ret != JOptionPane.OK_OPTION) {
235 if (canceledOrRestartCurrAction("georeferencing"))
236 return startGeoreferencing();
237 }
238 return true;
239 }
240
241 /**
242 *
243 * @return false if all operations are canceled
244 */
245 private boolean canceledOrRestartCurrAction(String action) {
246 Object[] options = { "Cancel", "Retry" };
247 int selectedValue = JOptionPane.showOptionDialog( null,
248 tr("Do you want to cancel completely\n"+
249 "or just retry "+action+" ?"), "",
250 JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
251 null, options, options[0]);
252 if (selectedValue == 0) { // "Cancel"
253 // remove layer
254 Main.map.mapView.removeLayer(wmsLayer);
255 wmsLayer = null;
256 Main.map.mapView.removeMouseListener(this);
257 return false;
258 } else
259 countMouseClicked = 0;
260 return true;
261 }
262
263 private boolean inputLambertPosition() {
264 JLabel labelEnterPosition = new JLabel(tr("Enter cadastre east,north position"));
265 JLabel labelWarning = new JLabel(tr("(Warning: verify north with arrow !!)"));
266 JPanel p = new JPanel(new GridBagLayout());
267 JLabel labelEast = new JLabel(tr("East"));
268 JLabel labelNorth = new JLabel(tr("North"));
269 final JTextField inputEast = new JTextField();
270 final JTextField inputNorth = new JTextField();
271 p.add(labelEnterPosition, GBC.eol());
272 p.add(labelWarning, GBC.eol());
273 p.add(labelEast, GBC.std().insets(0, 0, 10, 0));
274 p.add(inputEast, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 5, 0, 5));
275 p.add(labelNorth, GBC.std().insets(0, 0, 10, 0));
276 p.add(inputNorth, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 5, 0, 5));
277 JOptionPane pane = new JOptionPane(p, JOptionPane.INFORMATION_MESSAGE, JOptionPane.OK_CANCEL_OPTION, null);
278 String number;
279 if (countMouseClicked == 1) number = "first";
280 else number = "second";
281 pane.createDialog(Main.parent, tr("Set {0} Lambert coordinates",number)).setVisible(true);
282 if (!Integer.valueOf(JOptionPane.OK_OPTION).equals(pane.getValue())) {
283 if (canceledOrRestartCurrAction("georeferencing"))
284 startGeoreferencing();
285 return false;
286 }
287 if (inputEast.getText().length() != 0 && inputNorth.getText().length() != 0) {
288 try {
289 double e = Double.parseDouble(inputEast.getText());
290 double n = Double.parseDouble(inputNorth.getText());
291 if (countMouseClicked == 1)
292 georefpoint1 = new EastNorth(e, n);
293 else
294 georefpoint2 = new EastNorth(e, n);
295 return true;
296 } catch (NumberFormatException e) {
297 return false;
298 }
299 }
300 return false;
301 }
302
303 /**
304 * Use point org1 as anchor for scale, then move org1 to dst1, then rotate org2 on dst2
305 * around org1/dst1 anchor
306 * @param org1 first point at original coordinate system (the grabbed image)
307 * @param org2 second point "
308 * @param dst1 first point at final destination coordinate system (the real east/north coordinate system)
309 * @param dst2 second point "
310 */
311 private void affineTransform(EastNorth org1, EastNorth org2, EastNorth dst1, EastNorth dst2) {
312 double angle = dst1.heading(dst2) - org1.heading(org2);
313 double proportion = dst1.distance(dst2)/org1.distance(org2);
314 // move
315 double dx = dst1.getX() - org1.getX();
316 double dy = dst1.getY() - org1.getY();
317 wmsLayer.images.get(0).shear(dx, dy);
318 org1 = org1.add(dx, dy); // org1=dst1 now
319 org2 = org2.add(dx, dy);
320 // rotate : org1(=dst1 now) is anchor for rotation and scale
321 wmsLayer.images.get(0).rotate(dst1, angle);
322 org2 = org2.rotate(dst1, angle);
323 // scale image from anchor org1(=dst1 now)
324 wmsLayer.images.get(0).scale(dst1, proportion);
325 }
326
327 private void transformGeoreferencedImg() {
328 georefpoint1 = new EastNorth(wmsLayer.X0, wmsLayer.Y0);
329 georefpoint2 = new EastNorth(wmsLayer.X0+wmsLayer.fX*wmsLayer.communeBBox.max.getX(),
330 wmsLayer.Y0+wmsLayer.fY*wmsLayer.communeBBox.max.getX());
331 ea1 = new EastNorth(wmsLayer.images.get(0).min.east(), wmsLayer.images.get(0).max.north());
332 EastNorth ea2 = wmsLayer.images.get(0).max;
333 affineTransform(ea1, ea2, georefpoint1, georefpoint2);
334 wmsLayer.saveNewCache();
335 Main.map.mapView.repaint();
336 }
337
338 public void mouseEntered(MouseEvent arg0) {
339 }
340
341 public void mouseExited(MouseEvent arg0) {
342 }
343
344 public void mousePressed(MouseEvent arg0) {
345 }
346
347 public void mouseReleased(MouseEvent arg0) {
348 }
349
350}
Note: See TracBrowser for help on using the repository browser.