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

Last change on this file since 26835 was 26835, checked in by pieren, 13 years ago

Fixed issues with new offset in grabbing vector images

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