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

Last change on this file since 33241 was 32556, checked in by donvip, 9 years ago

checkstyle

  • Property svn:eol-style set to native
File size: 28.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package cadastre_fr;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Color;
7import java.awt.Graphics;
8import java.awt.Graphics2D;
9import java.awt.Image;
10import java.awt.Point;
11import java.awt.RenderingHints;
12import java.awt.Toolkit;
13import java.awt.event.ActionEvent;
14import java.awt.image.BufferedImage;
15import java.awt.image.ImageObserver;
16import java.io.EOFException;
17import java.io.File;
18import java.io.IOException;
19import java.io.ObjectInputStream;
20import java.io.ObjectOutputStream;
21import java.util.ArrayList;
22import java.util.HashSet;
23import java.util.Locale;
24import java.util.Vector;
25import java.util.concurrent.locks.Lock;
26import java.util.concurrent.locks.ReentrantLock;
27
28import javax.swing.Action;
29import javax.swing.Icon;
30import javax.swing.ImageIcon;
31import javax.swing.JOptionPane;
32
33import org.openstreetmap.josm.Main;
34import org.openstreetmap.josm.actions.JosmAction;
35import org.openstreetmap.josm.data.Bounds;
36import org.openstreetmap.josm.data.coor.EastNorth;
37import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
38import org.openstreetmap.josm.gui.MapView;
39import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
40import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
41import org.openstreetmap.josm.gui.layer.Layer;
42import org.openstreetmap.josm.gui.util.GuiHelper;
43
44/**
45 * This is a layer that grabs the current screen from the French cadastre WMS
46 * server. The data fetched this way is tiled and managed to the disc to reduce
47 * server load.
48 */
49public class WMSLayer extends Layer implements ImageObserver {
50
51 private int lambertZone = -1;
52
53 public CadastreGrabber grabber = new CadastreGrabber();
54
55 protected static final Icon icon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(
56 CadastrePlugin.class.getResource("/images/cadastre_small.png")));
57
58 private Vector<GeorefImage> images = new Vector<>();
59
60 public Lock imagesLock = new ReentrantLock();
61
62 /**
63 * v1 to v2 = not supported
64 * v2 to v3 = add 4 more EastNorth coordinates in GeorefImages
65 * v3 to v4 = add original raster image width and height
66 */
67 protected final int serializeFormatVersion = 4;
68
69 public static int currentFormat;
70
71 private ArrayList<EastNorthBound> dividedBbox = new ArrayList<>();
72
73 private String location = "";
74
75 private String departement = "";
76
77 private String codeCommune = "";
78
79 public EastNorthBound communeBBox = new EastNorthBound(new EastNorth(0, 0), new EastNorth(0, 0));
80
81 private boolean isRaster;
82 private boolean isAlreadyGeoreferenced;
83 public double X0, Y0, angle, fX, fY;
84
85 // bbox of the georeferenced raster image (the nice horizontal and vertical box)
86 private EastNorth rasterMin;
87 private EastNorth rasterMax;
88 private double rasterRatio;
89
90 // offset for vector images temporarily shifted (correcting Cadastre artifacts), in pixels
91 public double deltaEast;
92 public double deltaNorth;
93
94 private Action saveAsPng;
95
96 private Action cancelGrab;
97
98 private Action refineGeoRef;
99
100 @SuppressWarnings("serial")
101 class ResetOffsetActionMenu extends JosmAction {
102 ResetOffsetActionMenu() {
103 super(tr("Reset offset"), null, tr("Reset offset (only vector images)"), null, false);
104 }
105
106 @Override
107 public void actionPerformed(ActionEvent arg0) {
108 deltaEast = 0;
109 deltaNorth = 0;
110 Main.map.mapView.repaint();
111 }
112 }
113
114 public boolean adjustModeEnabled;
115
116 public GrabThread grabThread;
117
118 /**
119 * Constructs a new {@code WMSLayer}.
120 */
121 public WMSLayer() {
122 this(tr("Blank Layer"), "", -1);
123 }
124
125 public WMSLayer(String location, String codeCommune, int lambertZone) {
126 super(buildName(location, codeCommune));
127 this.location = location;
128 this.codeCommune = codeCommune;
129 this.lambertZone = lambertZone;
130 grabThread = new GrabThread(this);
131 grabThread.start();
132 // enable auto-sourcing option
133 CadastrePlugin.pluginUsed = true;
134 }
135
136 @Override
137 public void destroy() {
138 // if the layer is currently saving the images in the cache, wait until it's finished
139 if (grabThread != null)
140 grabThread.cancel();
141 grabThread = null;
142 super.destroy();
143 images = null;
144 dividedBbox = null;
145 Main.info("Layer "+location+" destroyed");
146 }
147
148 private static String buildName(String location, String codeCommune) {
149 String ret = location.toUpperCase(Locale.FRANCE);
150 if (codeCommune != null && !codeCommune.isEmpty())
151 ret += "(" + codeCommune + ")";
152 return ret;
153 }
154
155 private String rebuildName() {
156 return buildName(this.location.toUpperCase(Locale.FRANCE), this.codeCommune);
157 }
158
159 public void grab(Bounds b) throws IOException {
160 grabThread.setCanceled(false);
161 grabThread.setGrabber(grabber);
162 // if it is the first layer, use the communeBBox as grab bbox (and not divided)
163 if (Main.getLayerManager().getLayers().size() == 1) {
164 final Bounds bounds = this.getCommuneBBox().toBounds();
165 GuiHelper.runInEDTAndWait(new Runnable() {
166 @Override
167 public void run() {
168 Main.map.mapView.zoomTo(bounds);
169 }
170 });
171 divideBbox(bounds, 1);
172 } else {
173 if (isRaster) {
174 divideBbox(new Bounds(Main.getProjection().eastNorth2latlon(rasterMin), Main.getProjection().eastNorth2latlon(rasterMax)),
175 Integer.parseInt(Main.pref.get("cadastrewms.rasterDivider", CadastrePreferenceSetting.DEFAULT_RASTER_DIVIDER)));
176 } else
177 divideBbox(b,
178 Integer.parseInt(Main.pref.get("cadastrewms.scale", CadastrePreferenceSetting.DEFAULT_GRAB_MULTIPLIER)));
179 }
180 grabThread.addImages(dividedBbox);
181 }
182
183 /**
184 * Divides the bounding box in smaller squares. Their size (and quantity) is configurable in Preferences.
185 *
186 * @param b the original bbox, usually the current bbox on screen
187 * @param factor 1 = source bbox 1:1
188 * 2 = source bbox divided by 2x2 smaller boxes
189 * 3 = source bbox divided by 3x3 smaller boxes
190 * 4 = configurable size from preferences (100 meters per default) rounded
191 * allowing grabbing of next contiguous zone
192 */
193 private void divideBbox(Bounds b, int factor) {
194 EastNorth lambertMin = Main.getProjection().latlon2eastNorth(b.getMin());
195 EastNorth lambertMax = Main.getProjection().latlon2eastNorth(b.getMax());
196 double minEast = lambertMin.east()+deltaEast;
197 double minNorth = lambertMin.north()+deltaNorth;
198 double dEast = (lambertMax.east() - minEast) / factor;
199 double dNorth = (lambertMax.north() - minNorth) / factor;
200 dividedBbox.clear();
201 if (factor < 4 || isRaster) {
202 for (int xEast = 0; xEast < factor; xEast++) {
203 for (int xNorth = 0; xNorth < factor; xNorth++) {
204 dividedBbox.add(new EastNorthBound(new EastNorth(minEast + xEast * dEast, minNorth + xNorth * dNorth),
205 new EastNorth(minEast + (xEast + 1) * dEast, minNorth + (xNorth + 1) * dNorth)));
206 }
207 }
208 } else {
209 // divide to fixed size squares
210 // grab all square in a spiral starting from the center (usually the most interesting place)
211 int c = Integer.parseInt(Main.pref.get("cadastrewms.squareSize", String.valueOf(CadastrePreferenceSetting.DEFAULT_SQUARE_SIZE)));
212 lambertMin = lambertMin.add(-minEast % c, -minNorth % c);
213 lambertMax = lambertMax.add(c - lambertMax.east() % c, c - lambertMax.north() % c);
214 EastNorth mid = lambertMax.getCenter(lambertMin);
215 mid = mid.add(-1, 1); // in case the boxes side is a pair, select the one one top,left to follow the rotation
216 mid = mid.add(-mid.east() % c, -mid.north() % c);
217 int x = (int) (lambertMax.east() -lambertMin.east())/c;
218 int y = (int) (lambertMax.north() -lambertMin.north())/c;
219 int[] dx = {+1, 0, -1, 0};
220 int[] dy = {0, -1, 0, +1};
221 int currDir = -1, lDir = 1, i = 1, j = 0, k = -1;
222 if (x == 1)
223 currDir = 0;
224 dividedBbox.add(new EastNorthBound(mid, new EastNorth(mid.east()+c, mid.north()+c)));
225 while (i < (x*y)) {
226 i++;
227 j++;
228 if (j >= lDir) {
229 k++;
230 if (k > 1) {
231 lDir++;
232 k = 0;
233 }
234 j = 0;
235 currDir = (currDir+1) % 4;
236 } else if (currDir >= 0 && j >= (currDir == 0 || currDir == 2 ? (x-1) : (y-1))) {
237 // the overall is a rectangle, not a square. Jump to the other side to grab next square.
238 k++;
239 if (k > 1) {
240 lDir++;
241 k = 0;
242 }
243 j = lDir-1;
244 currDir = (currDir+1) % 4;
245 mid = new EastNorth(mid.east() + dx[currDir]*c*(lDir-1), mid.north() + dy[currDir]*c*(lDir-1));
246 }
247 mid = new EastNorth(mid.east() + dx[currDir]*c, mid.north() + dy[currDir]*c);
248 dividedBbox.add(new EastNorthBound(mid, new EastNorth(mid.east()+c, mid.north()+c)));
249 }
250 }
251 }
252
253 @Override
254 public Icon getIcon() {
255 return icon;
256 }
257
258 @Override
259 public String getToolTipText() {
260 String str = tr("WMS layer ({0}), {1} tile(s) loaded", getName(), images.size());
261 if (isRaster) {
262 str += "\n"+tr("Is not vectorized.");
263 str += "\n"+tr("Bounding box: {0}", communeBBox);
264 if (!images.isEmpty())
265 str += "\n"+tr("Image size (px): {0}/{1}", images.get(0).image.getWidth(), images.get(0).image.getHeight());
266 } else {
267 str += "\n"+tr("Is vectorized.");
268 str += "\n"+tr("Commune bbox: {0}", communeBBox);
269 }
270 return str;
271 }
272
273 @Override
274 public boolean isMergable(Layer other) {
275 return false;
276 }
277
278 @Override
279 public void mergeFrom(Layer from) {
280 // Do nothing
281 }
282
283 @Override
284 public void paint(Graphics2D g, final MapView mv, Bounds bounds) {
285 synchronized (this) {
286 Object savedInterpolation = g.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
287 if (savedInterpolation == null) savedInterpolation = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
288 String interpolation = Main.pref.get("cadastrewms.imageInterpolation", "standard");
289 if (interpolation.equals("bilinear"))
290 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
291 else if (interpolation.equals("bicubic"))
292 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
293 else
294 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
295 imagesLock.lock();
296 for (GeorefImage img : images) {
297 img.paint(g, mv, CadastrePlugin.backgroundTransparent,
298 CadastrePlugin.transparency, CadastrePlugin.drawBoundaries);
299 }
300 imagesLock.unlock();
301 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, savedInterpolation);
302 }
303 if (this.isRaster) {
304 paintCrosspieces(g, mv);
305 }
306 grabThread.paintBoxesToGrab(g, mv);
307 if (this.adjustModeEnabled) {
308 WMSAdjustAction.paintAdjustFrames(g, mv);
309 }
310 }
311
312 @Override
313 public void visitBoundingBox(BoundingXYVisitor v) {
314 for (GeorefImage img : images) {
315 v.visit(img.min);
316 v.visit(img.max);
317 }
318 }
319
320 @Override
321 public Object getInfoComponent() {
322 return getToolTipText();
323 }
324
325 @Override
326 public Action[] getMenuEntries() {
327 saveAsPng = new MenuActionSaveRasterAs(this);
328 saveAsPng.setEnabled(isRaster);
329 cancelGrab = new MenuActionCancelGrab(this);
330 cancelGrab.setEnabled(!isRaster && grabThread.getImagesToGrabSize() > 0);
331 refineGeoRef = new MenuActionRefineGeoRef(this);
332 refineGeoRef.setEnabled(isRaster && grabThread.getImagesToGrabSize() == 0);
333 Action resetOffset = new ResetOffsetActionMenu();
334 resetOffset.setEnabled(!isRaster && !images.isEmpty() && (deltaEast != 0.0 || deltaNorth != 0.0));
335 return new Action[] {
336 LayerListDialog.getInstance().createShowHideLayerAction(),
337 LayerListDialog.getInstance().createDeleteLayerAction(),
338 new MenuActionLoadFromCache(),
339 saveAsPng,
340 cancelGrab,
341 refineGeoRef,
342 resetOffset,
343 new LayerListPopup.InfoAction(this),
344 };
345 }
346
347 public GeorefImage findImage(EastNorth eastNorth) {
348 // Iterate in reverse, so we return the image which is painted last.
349 // (i.e. the topmost one)
350 for (int i = images.size() - 1; i >= 0; i--) {
351 if (images.get(i).contains(eastNorth)) {
352 return images.get(i);
353 }
354 }
355 return null;
356 }
357
358 public boolean isOverlapping(Bounds bounds) {
359 GeorefImage georefImage =
360 new GeorefImage(null,
361 Main.getProjection().latlon2eastNorth(bounds.getMin()),
362 Main.getProjection().latlon2eastNorth(bounds.getMax()), this);
363 for (GeorefImage img : images) {
364 if (img.overlap(georefImage))
365 return true;
366 }
367 return false;
368 }
369
370 /**
371 * Convert the eastNorth input coordinates to raster coordinates.
372 * The original raster size is [0,0,12286,8730] where 0,0 is the upper left corner and
373 * 12286,8730 is the approx. raster max size.
374 * @return the raster coordinates for the wms server request URL (minX,minY,maxX,maxY)
375 */
376 public String eastNorth2raster(EastNorth min, EastNorth max) {
377 double minX = (min.east() - rasterMin.east()) / rasterRatio;
378 double minY = (min.north() - rasterMin.north()) / rasterRatio;
379 double maxX = (max.east() - rasterMin.east()) / rasterRatio;
380 double maxY = (max.north() - rasterMin.north()) / rasterRatio;
381 return minX+","+minY+","+maxX+","+maxY;
382 }
383
384 public String getLocation() {
385 return location;
386 }
387
388 public void setLocation(String location) {
389 this.location = location;
390 setName(rebuildName());
391 }
392
393 public String getDepartement() {
394 return departement;
395 }
396
397 public void setDepartement(String departement) {
398 this.departement = departement;
399 }
400
401 public String getCodeCommune() {
402 return codeCommune;
403 }
404
405 public void setCodeCommune(String codeCommune) {
406 this.codeCommune = codeCommune;
407 setName(rebuildName());
408 }
409
410 public boolean isRaster() {
411 return isRaster;
412 }
413
414 public void setRaster(boolean isRaster) {
415 this.isRaster = isRaster;
416 if (saveAsPng != null)
417 saveAsPng.setEnabled(isRaster);
418 }
419
420 public boolean isAlreadyGeoreferenced() {
421 return isAlreadyGeoreferenced;
422 }
423
424 public void setAlreadyGeoreferenced(boolean isAlreadyGeoreferenced) {
425 this.isAlreadyGeoreferenced = isAlreadyGeoreferenced;
426 }
427
428 /**
429 * Set raster positions used for grabbing and georeferencing.
430 * rasterMin is the Eaast North of bottom left corner raster image on the screen when image is grabbed.
431 * The bounds width and height are the raster width and height. The image width matches the current view
432 * and the image height is adapted.
433 * Required: the communeBBox must be set (normally it is catched by CadastreInterface and saved by DownloadWMSPlanImage)
434 * @param bounds the current main map view boundaries
435 */
436 public void setRasterBounds(Bounds bounds) {
437 EastNorth rasterCenter = Main.getProjection().latlon2eastNorth(bounds.getCenter());
438 EastNorth eaMin = Main.getProjection().latlon2eastNorth(bounds.getMin());
439 EastNorth eaMax = Main.getProjection().latlon2eastNorth(bounds.getMax());
440 double rasterSizeX = communeBBox.max.getX() - communeBBox.min.getX();
441 double rasterSizeY = communeBBox.max.getY() - communeBBox.min.getY();
442 double ratio = rasterSizeY/rasterSizeX;
443 // keep same ratio on screen as WMS bbox (stored in communeBBox)
444 rasterMin = new EastNorth(eaMin.getX(), rasterCenter.getY()-(eaMax.getX()-eaMin.getX())*ratio/2);
445 rasterMax = new EastNorth(eaMax.getX(), rasterCenter.getY()+(eaMax.getX()-eaMin.getX())*ratio/2);
446 rasterRatio = (rasterMax.getX()-rasterMin.getX())/rasterSizeX;
447 }
448
449 /**
450 * Called by CacheControl when a new cache file is created on disk.
451 * Save only primitives to keep cache independent of software changes.
452 */
453 public void write(File associatedFile, ObjectOutputStream oos) throws IOException {
454 currentFormat = this.serializeFormatVersion;
455 setAssociatedFile(associatedFile);
456 oos.writeInt(this.serializeFormatVersion);
457 oos.writeObject(this.location); // String
458 oos.writeObject(this.codeCommune); // String
459 oos.writeInt(this.lambertZone);
460 oos.writeBoolean(this.isRaster);
461 oos.writeBoolean(false); // previously buildingsOnly
462 if (this.isRaster) {
463 oos.writeDouble(this.rasterMin.getX());
464 oos.writeDouble(this.rasterMin.getY());
465 oos.writeDouble(this.rasterMax.getX());
466 oos.writeDouble(this.rasterMax.getY());
467 oos.writeDouble(this.rasterRatio);
468 }
469 oos.writeDouble(this.communeBBox.min.getX());
470 oos.writeDouble(this.communeBBox.min.getY());
471 oos.writeDouble(this.communeBBox.max.getX());
472 oos.writeDouble(this.communeBBox.max.getY());
473 }
474
475 /**
476 * Called by CacheControl when a cache file is read from disk.
477 * Cache uses only primitives to stay independent of software changes.
478 */
479 public boolean read(File associatedFile, ObjectInputStream ois, int currentLambertZone) throws IOException, ClassNotFoundException {
480 currentFormat = ois.readInt();;
481 if (currentFormat < 2) {
482 JOptionPane.showMessageDialog(Main.parent, tr("Unsupported cache file version; found {0}, expected {1}\nCreate a new one.",
483 currentFormat, this.serializeFormatVersion), tr("Cache Format Error"), JOptionPane.ERROR_MESSAGE);
484 return false;
485 }
486 this.setLocation((String) ois.readObject());
487 this.setCodeCommune((String) ois.readObject());
488 this.lambertZone = ois.readInt();
489 this.setRaster(ois.readBoolean());
490 setAssociatedFile(associatedFile);
491 if (currentFormat >= 4)
492 ois.readBoolean();
493 if (this.isRaster) {
494 double X = ois.readDouble();
495 double Y = ois.readDouble();
496 this.rasterMin = new EastNorth(X, Y);
497 X = ois.readDouble();
498 Y = ois.readDouble();
499 this.rasterMax = new EastNorth(X, Y);
500 this.rasterRatio = ois.readDouble();
501 }
502 double minX = ois.readDouble();
503 double minY = ois.readDouble();
504 double maxX = ois.readDouble();
505 double maxY = ois.readDouble();
506 this.communeBBox = new EastNorthBound(new EastNorth(minX, minY), new EastNorth(maxX, maxY));
507 if (this.lambertZone != currentLambertZone && currentLambertZone != -1) {
508 JOptionPane.showMessageDialog(Main.parent, tr("Lambert zone {0} in cache "+
509 "incompatible with current Lambert zone {1}",
510 this.lambertZone+1, currentLambertZone), tr("Cache Lambert Zone Error"), JOptionPane.ERROR_MESSAGE);
511 return false;
512 }
513 synchronized (this) {
514 boolean EOF = false;
515 try {
516 while (!EOF) {
517 GeorefImage newImage = (GeorefImage) ois.readObject();
518 for (GeorefImage img : this.images) {
519 if (CadastrePlugin.backgroundTransparent) {
520 if (img.overlap(newImage))
521 // mask overlapping zone in already grabbed image
522 img.withdraw(newImage);
523 else
524 // mask overlapping zone in new image only when
525 // new image covers completely the existing image
526 newImage.withdraw(img);
527 }
528 }
529 newImage.wmsLayer = this;
530 this.images.add(newImage);
531 }
532 } catch (EOFException ex) {
533 // expected exception when all images are read
534 Main.trace(ex);
535 }
536 }
537 Main.info("Cache loaded for location "+location+" with "+images.size()+" images");
538 return true;
539 }
540
541 /**
542 * Join the grabbed images into one single.
543 */
544 public void joinBufferedImages() {
545 if (images.size() > 1) {
546 EastNorth min = images.get(0).min;
547 EastNorth max = images.get(images.size()-1).max;
548 int oldImgWidth = images.get(0).image.getWidth();
549 int oldImgHeight = images.get(0).image.getHeight();
550 HashSet<Double> lx = new HashSet<>();
551 HashSet<Double> ly = new HashSet<>();
552 for (GeorefImage img : images) {
553 lx.add(img.min.east());
554 ly.add(img.min.north());
555 }
556 int newWidth = oldImgWidth*lx.size();
557 int newHeight = oldImgHeight*ly.size();
558 BufferedImage newImg = new BufferedImage(newWidth, newHeight, images.get(0).image.getType()/*BufferedImage.TYPE_INT_ARGB*/);
559 Graphics g = newImg.getGraphics();
560 // Coordinate (0,0) is on top,left corner where images are grabbed from bottom left
561 int rasterDivider = (int) Math.sqrt(images.size());
562 for (int h = 0; h < lx.size(); h++) {
563 for (int v = 0; v < ly.size(); v++) {
564 int newx = h*oldImgWidth;
565 int newy = newHeight - oldImgHeight - (v*oldImgHeight);
566 int j = h*rasterDivider + v;
567 g.drawImage(images.get(j).image, newx, newy, this);
568 }
569 }
570 synchronized (this) {
571 images.clear();
572 images.add(new GeorefImage(newImg, min, max, this));
573 }
574 }
575 }
576
577 /**
578 * Image cropping based on two EN coordinates pointing to two corners in diagonal
579 * Because it's coming from user mouse clics, we have to sort de positions first.
580 * Works only for raster image layer (only one image in collection).
581 * Updates layer georeferences.
582 */
583 public void cropImage(EastNorth en1, EastNorth en2) {
584 // adj1 is corner bottom, left
585 EastNorth adj1 = new EastNorth(en1.east() <= en2.east() ? en1.east() : en2.east(),
586 en1.north() <= en2.north() ? en1.north() : en2.north());
587 // adj2 is corner top, right
588 EastNorth adj2 = new EastNorth(en1.east() > en2.east() ? en1.east() : en2.east(),
589 en1.north() > en2.north() ? en1.north() : en2.north());
590 images.get(0).crop(adj1, adj2);
591 // update the layer georefs
592 rasterMin = adj1;
593 rasterMax = adj2;
594 setCommuneBBox(new EastNorthBound(
595 new EastNorth(0, 0),
596 new EastNorth(images.get(0).image.getWidth()-1, images.get(0).image.getHeight()-1)));
597 rasterRatio = (rasterMax.getX()-rasterMin.getX())/(communeBBox.max.getX() - communeBBox.min.getX());
598 }
599
600 public EastNorthBound getCommuneBBox() {
601 return communeBBox;
602 }
603
604 public EastNorthBound getFirstViewFromCacheBBox() {
605 if (isRaster) {
606 return communeBBox;
607 }
608 double minX = Double.MAX_VALUE;
609 double maxX = Double.MIN_VALUE;
610 double minY = Double.MAX_VALUE;
611 double maxY = Double.MIN_VALUE;
612 for (GeorefImage image:images) {
613 minX = image.min.east() < minX ? image.min.east() : minX;
614 maxX = image.max.east() > maxX ? image.max.east() : maxX;
615 minY = image.min.north() < minY ? image.min.north() : minY;
616 maxY = image.max.north() > maxY ? image.max.north() : maxY;
617 }
618 return new EastNorthBound(new EastNorth(minX, minY), new EastNorth(maxX, maxY));
619 }
620
621 public void setCommuneBBox(EastNorthBound entireCommune) {
622 this.communeBBox = entireCommune;
623 }
624
625 /**
626 * Method required by ImageObserver when drawing an image
627 */
628 @Override
629 public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
630 return false;
631 }
632
633 public int getLambertZone() {
634 return lambertZone;
635 }
636
637 public EastNorth getRasterCenter() {
638 return new EastNorth((images.get(0).max.east()+images.get(0).min.east())/2,
639 (images.get(0).max.north()+images.get(0).min.north())/2);
640 }
641
642 public void displace(double dx, double dy) {
643 if (isRaster) {
644 this.rasterMin = new EastNorth(rasterMin.east() + dx, rasterMin.north() + dy);
645 this.rasterMax = new EastNorth(rasterMax.east() + dx, rasterMax.north() + dy);
646 images.get(0).shear(dx, dy);
647 } else {
648 deltaEast += dx;
649 deltaNorth += dy;
650 }
651 }
652
653 public void resize(EastNorth rasterCenter, double proportion) {
654 this.rasterMin = rasterMin.interpolate(rasterCenter, proportion);
655 this.rasterMax = rasterMax.interpolate(rasterCenter, proportion);
656 images.get(0).scale(rasterCenter, proportion);
657 }
658
659 public void rotate(EastNorth rasterCenter, double angle) {
660 this.rasterMin = rasterMin.rotate(rasterCenter, angle);
661 this.rasterMax = rasterMax.rotate(rasterCenter, angle);
662 images.get(0).rotate(rasterCenter, angle);
663 this.angle += angle;
664 }
665
666 private void paintCrosspieces(Graphics g, MapView mv) {
667 String crosspieces = Main.pref.get("cadastrewms.crosspieces", "0");
668 if (!crosspieces.equals("0")) {
669 int modulo = 25;
670 if (crosspieces.equals("2")) modulo = 50;
671 if (crosspieces.equals("3")) modulo = 100;
672 EastNorthBound currentView = new EastNorthBound(mv.getEastNorth(0, mv.getHeight()),
673 mv.getEastNorth(mv.getWidth(), 0));
674 int minX = ((int) currentView.min.east()/modulo+1)*modulo;
675 int minY = ((int) currentView.min.north()/modulo+1)*modulo;
676 int maxX = ((int) currentView.max.east()/modulo)*modulo;
677 int maxY = ((int) currentView.max.north()/modulo)*modulo;
678 int size = (maxX-minX)/modulo;
679 if (size < 20) {
680 int px = size > 10 ? 2 : Math.abs(12-size);
681 g.setColor(Color.green);
682 for (int x = minX; x <= maxX; x += modulo) {
683 for (int y = minY; y <= maxY; y += modulo) {
684 Point p = mv.getPoint(new EastNorth(x, y));
685 g.drawLine(p.x-px, p.y, p.x+px, p.y);
686 g.drawLine(p.x, p.y-px, p.x, p.y+px);
687 }
688 }
689 }
690 }
691 }
692
693 public GeorefImage getImage(int index) {
694 imagesLock.lock();
695 GeorefImage img = null;
696 try {
697 img = this.images.get(index);
698 } catch (ArrayIndexOutOfBoundsException e) {
699 Main.error(e);
700 }
701 imagesLock.unlock();
702 return img;
703 }
704
705 public Vector<GeorefImage> getImages() {
706 return this.images;
707 }
708
709 public void addImage(GeorefImage img) {
710 imagesLock.lock();
711 this.images.add(img);
712 imagesLock.unlock();
713 }
714
715 public void setImages(Vector<GeorefImage> images) {
716 imagesLock.lock();
717 this.images = images;
718 imagesLock.unlock();
719 }
720
721 public void clearImages() {
722 imagesLock.lock();
723 this.images.clear();
724 imagesLock.unlock();
725 }
726}
Note: See TracBrowser for help on using the repository browser.