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

Last change on this file since 31993 was 30859, checked in by donvip, 10 years ago

[josm_cadastre-fr] replace calls to System.out/err by calls to Main.info/warn/error

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