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

Last change on this file since 17085 was 16791, checked in by guggis, 15 years ago

Updated to JOSM release 1893

  • Property svn:eol-style set to native
File size: 16.1 KB
Line 
1package cadastre_fr;
2
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.awt.Component;
6import java.awt.Graphics;
7import java.awt.Graphics2D;
8import java.awt.Toolkit;
9import java.awt.image.BufferedImage;
10import java.io.EOFException;
11import java.io.IOException;
12import java.io.ObjectInputStream;
13import java.io.ObjectOutputStream;
14import java.util.ArrayList;
15
16import javax.swing.Icon;
17import javax.swing.ImageIcon;
18import javax.swing.JMenuItem;
19import javax.swing.JOptionPane;
20
21import org.openstreetmap.josm.Main;
22import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
23import org.openstreetmap.josm.data.projection.Lambert;
24import org.openstreetmap.josm.data.Bounds;
25import org.openstreetmap.josm.gui.MapView;
26import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
27import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
28import org.openstreetmap.josm.gui.layer.Layer;
29import org.openstreetmap.josm.io.OsmTransferException;
30import org.openstreetmap.josm.data.coor.EastNorth;
31
32/**
33 * This is a layer that grabs the current screen from the French cadastre WMS
34 * server. The data fetched this way is tiled and managed to the disc to reduce
35 * server load.
36 */
37public class WMSLayer extends Layer {
38
39 Component[] component = null;
40
41 public int lambertZone = -1;
42
43 protected static final Icon icon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(
44 CadastrePlugin.class.getResource("/images/cadastre_small.png")));
45
46 protected ArrayList<GeorefImage> images = new ArrayList<GeorefImage>();
47
48 protected final int serializeFormatVersion = 2;
49
50 private ArrayList<EastNorthBound> dividedBbox = new ArrayList<EastNorthBound>();
51
52 private CacheControl cacheControl = null;
53
54 private String location = "";
55
56 private String codeCommune = "";
57
58 private EastNorthBound communeBBox = new EastNorthBound(new EastNorth(0,0), new EastNorth(0,0));
59
60 private boolean isRaster = false;
61
62 private EastNorth rasterMin;
63
64 private EastNorth rasterCenter;
65
66 private double rasterRatio;
67
68 double cRasterMaxSizeX = 12286;
69 double cRasterMaxSizeY = 8730;
70
71 public WMSLayer() {
72 this(tr("Blank Layer"), "", -1);
73 }
74
75 public WMSLayer(String location, String codeCommune, int lambertZone) {
76 super(buildName(location, codeCommune));
77 this.location = location;
78 this.codeCommune = codeCommune;
79 this.lambertZone = Lambert.layoutZone;
80 // enable auto-sourcing option
81 CadastrePlugin.pluginUsed = true;
82 }
83
84 private static String buildName(String location, String codeCommune) {
85 String ret = new String(location.toUpperCase());
86 if (codeCommune != null && !codeCommune.equals(""))
87 ret += "(" + codeCommune + ")";
88 return ret;
89 }
90
91 private String rebuildName() {
92 return buildName(this.location.toUpperCase(), this.codeCommune);
93 }
94
95 public void grab(CadastreGrabber grabber, Bounds b) throws IOException {
96 divideBbox(b, Integer.parseInt(Main.pref.get("cadastrewms.scale", Scale.X1.toString())));
97
98 for (EastNorthBound n : dividedBbox) {
99 GeorefImage newImage;
100 try {
101 newImage = grabber.grab(this, n.min, n.max);
102 } catch (IOException e) {
103 System.out.println("Download action cancelled by user or server did not respond");
104 break;
105 } catch (OsmTransferException e) {
106 System.out.println("OSM transfer failed");
107 break;
108 }
109 if (grabber.getWmsInterface().downloadCancelled) {
110 System.out.println("Download action cancelled by user");
111 break;
112 }
113 if (CadastrePlugin.backgroundTransparent) {
114 for (GeorefImage img : images) {
115 if (img.overlap(newImage))
116 // mask overlapping zone in already grabbed image
117 img.withdraw(newImage);
118 else
119 // mask overlapping zone in new image only when new
120 // image covers completely the existing image
121 newImage.withdraw(img);
122 }
123 }
124 images.add(newImage);
125 saveToCache(newImage);
126 Main.map.mapView.repaint();
127 /*
128 try { if (dividedBbox.size() > 1) Thread.sleep(1000);
129 } catch (InterruptedException e) {};*/
130 }
131 }
132
133 /**
134 *
135 * @param b the original bbox, usually the current bbox on screen
136 * @param factor 1 = source bbox 1:1
137 * 2 = source bbox divided by 2x2 smaller boxes
138 * 3 = source bbox divided by 3x3 smaller boxes
139 * 4 = hard coded size of boxes (100 meters) rounded allowing
140 * grabbing of next contiguous zone
141 */
142 private void divideBbox(Bounds b, int factor) {
143 EastNorth lambertMin = Main.proj.latlon2eastNorth(b.min);
144 EastNorth lambertMax = Main.proj.latlon2eastNorth(b.max);
145 double minEast = lambertMin.east();
146 double minNorth = lambertMin.north();
147 double dEast = (lambertMax.east() - minEast) / factor;
148 double dNorth = (lambertMax.north() - minNorth) / factor;
149 dividedBbox.clear();
150 if (factor < 4) {
151 for (int xEast = 0; xEast < factor; xEast++)
152 for (int xNorth = 0; xNorth < factor; xNorth++) {
153 dividedBbox.add(new EastNorthBound(new EastNorth(minEast + xEast * dEast, minNorth + xNorth * dNorth),
154 new EastNorth(minEast + (xEast + 1) * dEast, minNorth + (xNorth + 1) * dNorth)));
155 }
156 } else {
157 // divide to fixed size squares
158 int cSquare = Integer.parseInt(Main.pref.get("cadastrewms.squareSize", "100"));
159 minEast = minEast - minEast % cSquare;
160 minNorth = minNorth - minNorth % cSquare;
161 for (int xEast = (int)minEast; xEast < lambertMax.east(); xEast+=cSquare)
162 for (int xNorth = (int)minNorth; xNorth < lambertMax.north(); xNorth+=cSquare) {
163 dividedBbox.add(new EastNorthBound(new EastNorth(xEast, xNorth),
164 new EastNorth(xEast + cSquare, xNorth + cSquare)));
165 }
166 }
167 }
168
169 @Override
170 public Icon getIcon() {
171 return icon;
172 }
173
174 @Override
175 public String getToolTipText() {
176 String str = tr("WMS layer ({0}), {1} tile(s) loaded", getName(), images.size());
177 if (isRaster) {
178 str += "\n"+tr("Is not vectorized.");
179 str += "\n"+tr("Raster center: {0}", rasterCenter);
180 } else
181 str += "\n"+tr("Is vectorized.");
182 str += "\n"+tr("Commune bbox: {0}", communeBBox);
183 return str;
184 }
185
186 @Override
187 public boolean isMergable(Layer other) {
188 return false;
189 }
190
191 @Override
192 public void mergeFrom(Layer from) {
193 }
194
195 @Override
196 public void paint(Graphics g, final MapView mv) {
197 for (GeorefImage img : images)
198 img.paint((Graphics2D) g, mv, CadastrePlugin.backgroundTransparent,
199 CadastrePlugin.transparency, CadastrePlugin.drawBoundaries);
200 }
201
202 @Override
203 public void visitBoundingBox(BoundingXYVisitor v) {
204 for (GeorefImage img : images) {
205 v.visit(img.min);
206 v.visit(img.max);
207 }
208 }
209
210 @Override
211 public Object getInfoComponent() {
212 return getToolTipText();
213 }
214
215 @Override
216 public Component[] getMenuEntries() {
217 component = new Component[] { new JMenuItem(LayerListDialog.getInstance().createShowHideLayerAction(this)),
218 new JMenuItem(LayerListDialog.getInstance().createDeleteLayerAction(this)), new JMenuItem(new MenuActionLoadFromCache()),
219 new JMenuItem(new LayerListPopup.InfoAction(this)) };
220 return component;
221 }
222
223 public GeorefImage findImage(EastNorth eastNorth) {
224 // Iterate in reverse, so we return the image which is painted last.
225 // (i.e. the topmost one)
226 for (int i = images.size() - 1; i >= 0; i--) {
227 if (images.get(i).contains(eastNorth)) {
228 return images.get(i);
229 }
230 }
231 return null;
232 }
233
234 public boolean isOverlapping(Bounds bounds) {
235 GeorefImage georefImage =
236 new GeorefImage(new BufferedImage(1,1,BufferedImage.TYPE_INT_RGB ), // not really important
237 Main.proj.latlon2eastNorth(bounds.min),
238 Main.proj.latlon2eastNorth(bounds.max));
239 for (GeorefImage img : images) {
240 if (img.overlap(georefImage))
241 return true;
242 }
243 return false;
244 }
245
246 public void saveToCache(GeorefImage image) {
247 if (CacheControl.cacheEnabled) {
248 getCacheControl().saveCache(image);
249 }
250 }
251
252 public void saveNewCache() {
253 if (CacheControl.cacheEnabled) {
254 getCacheControl().deleteCacheFile();
255 for (GeorefImage image : images)
256 getCacheControl().saveCache(image);
257 }
258 }
259
260 public CacheControl getCacheControl() {
261 if (cacheControl == null)
262 cacheControl = new CacheControl(this);
263 return cacheControl;
264 }
265
266 /**
267 * Convert the eastNorth input coordinates to raster coordinates.
268 * The original raster size is [0,0,12286,8730] where 0,0 is the upper left corner and
269 * 12286,8730 is the approx. raster max size.
270 * @return the raster coordinates for the wms server request URL (minX,minY,maxX,maxY)
271 */
272 public String eastNorth2raster(EastNorth min, EastNorth max) {
273 double minX = (min.east() - rasterMin.east()) / rasterRatio;
274 double minY = (min.north() - rasterMin.north()) / rasterRatio;
275 double maxX = (max.east() - rasterMin.east()) / rasterRatio;
276 double maxY = (max.north() - rasterMin.north()) / rasterRatio;
277 return minX+","+minY+","+maxX+","+maxY;
278 }
279
280
281 public String getLocation() {
282 return location;
283 }
284
285 public void setLocation(String location) {
286 this.location = location;
287 setName(rebuildName());
288 }
289
290 public String getCodeCommune() {
291 return codeCommune;
292 }
293
294 public void setCodeCommune(String codeCommune) {
295 this.codeCommune = codeCommune;
296 setName(rebuildName());
297 }
298
299 public boolean isRaster() {
300 return isRaster;
301 }
302
303 public void setRaster(boolean isRaster) {
304 this.isRaster = isRaster;
305 }
306
307 /**
308 * Set the eastNorth position in rasterMin which is the 0,0 coordinate (bottom left corner).
309 * The bounds width is the raster width and height is calculate on a fixed image ratio.
310 * @param bounds
311 */
312 public void setRasterBounds(Bounds bounds) {
313 rasterMin = new EastNorth(Main.proj.latlon2eastNorth(bounds.min).east(), Main.proj.latlon2eastNorth(bounds.min).north());
314 EastNorth rasterMax = new EastNorth(Main.proj.latlon2eastNorth(bounds.max).east(), Main.proj.latlon2eastNorth(bounds.max).north());
315 // now, resize on same proportion as wms server raster images (bounds center)
316 double rasterHalfHeight = (rasterMax.east() - rasterMin.east())/cRasterMaxSizeX*cRasterMaxSizeY/2;
317 double rasterMid = rasterMin.north() + (rasterMax.north()-rasterMin.north())/2;
318 rasterMin.setLocation(rasterMin.east(), rasterMid - rasterHalfHeight);
319 rasterMax.setLocation(rasterMax.east(), rasterMid + rasterHalfHeight);
320 rasterCenter = new EastNorth(rasterMin.east()+(rasterMax.east()-rasterMin.east())/2,
321 rasterMin.north()+(rasterMax.north()-rasterMin.north())/2);
322 rasterRatio = (rasterMax.east() - rasterMin.east()) / cRasterMaxSizeX;
323 }
324
325 public EastNorth getRasterMin() {
326 return rasterMin;
327 }
328
329 public void setRasterMin(EastNorth rasterMin) {
330 this.rasterMin = rasterMin;
331 }
332
333 public void displace(double dx, double dy) {
334 this.rasterMin = new EastNorth(rasterMin.east() + dx, rasterMin.north() + dy);
335 this.rasterCenter = new EastNorth(rasterCenter.east() + dx, rasterCenter.north() + dy);
336 for (GeorefImage img : images)
337 img.displace(dx, dy);
338 }
339
340 public void resize(double proportion) {
341 this.rasterMin = rasterMin.interpolate(rasterCenter, proportion);
342 for (GeorefImage img : images)
343 img.resize(rasterCenter, proportion);
344 }
345
346 public void rotate(double angle) {
347 this.rasterMin = rasterMin.rotate(rasterCenter, angle);
348 for (GeorefImage img : images)
349 img.rotate(rasterCenter, angle);
350 }
351
352 /**
353 * Called by CacheControl when a new cache file is created on disk
354 * @param oos
355 * @throws IOException
356 */
357 public void write(ObjectOutputStream oos, ArrayList<GeorefImage> imgs) throws IOException {
358 oos.writeInt(this.serializeFormatVersion);
359 oos.writeObject(this.location);
360 oos.writeObject(this.codeCommune);
361 oos.writeInt(this.lambertZone);
362 oos.writeBoolean(this.isRaster);
363 if (this.isRaster) {
364 oos.writeObject(this.rasterMin);
365 oos.writeObject(this.rasterCenter);
366 oos.writeDouble(this.rasterRatio);
367 } else {
368 oos.writeObject(this.communeBBox);
369 }
370 for (GeorefImage img : imgs) {
371 oos.writeObject(img);
372 }
373 }
374
375 /**
376 * Called by CacheControl when a cache file is read from disk
377 * @param ois
378 * @throws IOException
379 * @throws ClassNotFoundException
380 */
381 public boolean read(ObjectInputStream ois, int currentLambertZone) throws IOException, ClassNotFoundException {
382 int sfv = ois.readInt();
383 if (sfv != this.serializeFormatVersion) {
384 JOptionPane.showMessageDialog(Main.parent, tr("Unsupported cache file version; found {0}, expected {1}\nCreate a new one.",
385 sfv, this.serializeFormatVersion), tr("Cache Format Error"), JOptionPane.ERROR_MESSAGE);
386 return false;
387 }
388 this.setLocation((String) ois.readObject());
389 this.setCodeCommune((String) ois.readObject());
390 this.lambertZone = ois.readInt();
391 this.isRaster = ois.readBoolean();
392 if (this.isRaster) {
393 this.rasterMin = (EastNorth) ois.readObject();
394 this.rasterCenter = (EastNorth) ois.readObject();
395 this.rasterRatio = ois.readDouble();
396 } else {
397 this.communeBBox = (EastNorthBound) ois.readObject();
398 }
399 if (this.lambertZone != currentLambertZone) {
400 JOptionPane.showMessageDialog(Main.parent, tr("Lambert zone {0} in cache "+
401 "incompatible with current Lambert zone {1}",
402 this.lambertZone+1, currentLambertZone), tr("Cache Lambert Zone Error"), JOptionPane.ERROR_MESSAGE);
403 return false;
404 }
405 boolean EOF = false;
406 try {
407 while (!EOF) {
408 GeorefImage newImage = (GeorefImage) ois.readObject();
409 for (GeorefImage img : this.images) {
410 if (CadastrePlugin.backgroundTransparent) {
411 if (img.overlap(newImage))
412 // mask overlapping zone in already grabbed image
413 img.withdraw(newImage);
414 else
415 // mask overlapping zone in new image only when
416 // new image covers completely the existing image
417 newImage.withdraw(img);
418 }
419 }
420 this.images.add(newImage);
421 }
422 } catch (EOFException ex) {
423 // expected exception when all images are read
424 }
425 return true;
426 }
427
428 public double getRasterRatio() {
429 return rasterRatio;
430 }
431
432 public void setRasterRatio(double rasterRatio) {
433 this.rasterRatio = rasterRatio;
434 }
435
436 public EastNorth getRasterCenter() {
437 return rasterCenter;
438 }
439
440 public void setRasterCenter(EastNorth rasterCenter) {
441 this.rasterCenter = rasterCenter;
442 }
443
444 public EastNorthBound getCommuneBBox() {
445 return communeBBox;
446 }
447
448 public void setCommuneBBox(EastNorthBound entireCommune) {
449 this.communeBBox = entireCommune;
450 }
451
452}
Note: See TracBrowser for help on using the repository browser.