Statistics
| Revision:

root / branches / v10 / libraries / libFMap / src / com / iver / cit / gvsig / fmap / ViewPort.java @ 20332

History | View | Annotate | Download (44.8 KB)

1 1100 fjp
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41 213 fernando
package com.iver.cit.gvsig.fmap;
42
43
import java.awt.Color;
44
import java.awt.Dimension;
45 234 fjp
import java.awt.Point;
46 13585 ppiqueras
import java.awt.Toolkit;
47 213 fernando
import java.awt.geom.AffineTransform;
48 234 fjp
import java.awt.geom.NoninvertibleTransformException;
49 213 fernando
import java.awt.geom.Point2D;
50
import java.awt.geom.Rectangle2D;
51
import java.util.ArrayList;
52
53 3884 caballero
import org.cresques.cts.GeoCalc;
54
import org.cresques.cts.IProjection;
55
import org.cresques.cts.gt2.CSUTM;
56 346 fernando
57 6164 luisw2
import com.iver.cit.gvsig.fmap.crs.CRSFactory;
58 3884 caballero
import com.iver.utiles.StringUtilities;
59
import com.iver.utiles.XMLEntity;
60
61 956 vcaballero
/**
62 20100 jmvivo
 * <p><code>ViewPort</code> class represents the logic needed to transform a rectangular area of a map
63
 *  to the available area in screen to display it.</p>
64 20332 vcaballero
 *
65 13635 ppiqueras
 * <p>Includes an affine transformation, between the rectangular area selected of the external map, in its own
66 20100 jmvivo
 *  <i>map coordinates</i>, to the rectangular area available of a view in <i>screen coordinates</i>.</p>
67 20332 vcaballero
 *
68 20100 jmvivo
 * <p>Elements:
69 13585 ppiqueras
 * <ul>
70
 * <li><i>extent</i>: the area selected of the map, in <i>map coordinates</i>.
71
 * <li><i>imageSize</i>: width and height in pixels (<i>screen coordinates</i>) of the area available
72 20332 vcaballero
 *  in screen to display the area selected of the map.
73 13585 ppiqueras
 * <li><i>adjustedExtent</i>: the area selected must be an scale of <i>imageSize</i>.<br>This implies adapt the
74
 *  extent, preserving and centering it, and adding around the needed area to fill all the image size. That
75
 *  added area will be extracted from the original map, wherever exists, and filled with the background color
76 20332 vcaballero
 *  wherever not.
77 13585 ppiqueras
 * <li><i>scale</i>: the scale between the adjusted extent and the image size.
78 20332 vcaballero
 * <li><i>backColor</i>: the default background color in the view, if there is no map.
79 13585 ppiqueras
 * <li><i>trans</i>: the affine transformation.
80 13635 ppiqueras
 * <li><i>proj</i>: map projection used in this view.
81 20100 jmvivo
 * <li><i>distanceUnits</i>: distance measurement units, of data in screen.
82
 * <li><i>mapUnits</i>: measurement units, of data in map.
83 13585 ppiqueras
 * <li><i>extents</i>: an {@link ExtentHistory ExtentHistory} with the last previous extents.
84 20100 jmvivo
 * <li><i>offset</i>: position in pixels of the available rectangular area, where start drawing the map.
85 13585 ppiqueras
 * <li><i>dist1pixel</i>: the distance in <i>world coordinates</i> equivalent to 1 pixel in the view with the
86
 *  current extent.
87
 * <li><i>dist3pixel</i>: the distance in <i>world coordinates</i> equivalent to 3 pixels in the view with the
88
 *  current extent.
89 20332 vcaballero
 * <li><i>listeners</i>: list with the {@link ViewPortListener ViewPortListener} registered.
90 13585 ppiqueras
 * </ul>
91
 * </p>
92 20332 vcaballero
 *
93 956 vcaballero
 * @author Vicente Caballero Navarro
94
 */
95
public class ViewPort {
96 13585 ppiqueras
        /**
97
         * <p>Metric unit or length equal to 1000 meters.</p>
98
         */
99 956 vcaballero
        public static int KILOMETROS = 0;
100 13585 ppiqueras
101
        /**
102
         * <p>The base unit of length in the International System of Units that is equal to the distance
103
         *  traveled by light in a vacuum in {frac;1;299,792,458} second or to about 39.37 inches.</p>
104
         */
105 956 vcaballero
        public static int METROS = 1;
106 13585 ppiqueras
107
        /**
108
         * <p>Metric unit or length equal to 0'01 meters.</p>
109
         */
110 956 vcaballero
        public static int CENTIMETRO = 2;
111 13585 ppiqueras
112
        /**
113
         * <p>Metric unit or length equal to 0'001 meters.</p>
114
         */
115 956 vcaballero
        public static int MILIMETRO = 3;
116 13585 ppiqueras
117
        /**
118 20100 jmvivo
         * <p>The international statute mile by international agreement. It is defined to be precisely
119 13682 ppiqueras
         *  1,760 international yards (by definition, 0.9144 m each) and is therefore exactly 1,609.344
120
         *  metres (1.609344 km).</p>
121 13585 ppiqueras
         */
122 956 vcaballero
        public static int MILLAS = 4;
123 13585 ppiqueras
124
        /**
125 20332 vcaballero
         * <p>Unit of length equal in the United States to 0.9144 meter.</p>
126 13585 ppiqueras
         */
127 956 vcaballero
        public static int YARDAS = 5;
128 13585 ppiqueras
129
        /**
130
         * <p>Any of various units of length based on the length of the human foot; especially :
131
         *  a unit equal to 1/3 yard and comprising 12 inches.</p>
132
         */
133 956 vcaballero
        public static int PIES = 6;
134 13585 ppiqueras
135
        /**
136
         * <p>Unit of length equal to 1/36 yard.</p>
137
         */
138 956 vcaballero
        public static int PULGADAS = 7;
139 13585 ppiqueras
140
        /**
141
         * <p>Grades according the current projection.</p>
142
         */
143 1443 jmorell
        public static int GRADOS = 8;
144 435 vcaballero
145 346 fernando
        /**
146 13585 ppiqueras
         * <p>Screen resolution in <i>dots-per-inch</i>. Useful to calculate the geographic scale of the view.</p>
147 20332 vcaballero
         *
148 13585 ppiqueras
         * @see Toolkit#getScreenResolution()
149
         * @see #getScale()
150 346 fernando
         */
151 13585 ppiqueras
        private static int dpi = java.awt.Toolkit.getDefaultToolkit().getScreenResolution();
152
153
        /**
154
         * <p>Area selected by user using some tool.</p>
155 20332 vcaballero
         *
156 13585 ppiqueras
         * <p>When the zoom changes (for instance when using the zoom in or zoom out tools,
157 13635 ppiqueras
         *  but also zooming to a selected feature or shape) the extent that covers that
158
         *  area is the value returned by this method. It is not the actual area shown
159
         *  in the view because it does not care about the aspect ratio of the available
160
         *  area. However, any part of the real world contained in this extent is shown
161
         *  in the view.
162 13585 ppiqueras
         * </p>
163
         * <p>
164
         * Probably this is not what you are looking for. If you are looking for
165
         * the complete extent currently shown, you must use {@linkplain #getAdjustedExtent()} method
166
         * which returns the extent that contains this one but regarding the current
167
         * view's aspect ratio.
168
         * </p>
169 20332 vcaballero
         *
170 13585 ppiqueras
         * @see #getExtent()
171 13635 ppiqueras
         * @see #setExtent(Rectangle2D)
172 13585 ppiqueras
         */
173 956 vcaballero
        private Rectangle2D extent;
174 13585 ppiqueras
175
        /**
176
         * <p>Location and dimensions of the extent adjusted to the image size.</p>
177 20332 vcaballero
         *
178 13585 ppiqueras
         * @see #getAdjustedExtent()
179
         */
180 956 vcaballero
        private Rectangle2D adjustedExtent;
181 13585 ppiqueras
182
        /**
183
         * <p>History with the last extents of the view.</p>
184 20332 vcaballero
         *
185 13585 ppiqueras
         * @see #setPreviousExtent()
186
         * @see #getExtents()
187
         */
188 956 vcaballero
        private ExtentHistory extents = new ExtentHistory();
189 13585 ppiqueras
190
        /**
191
         * <p>Size in <i>screen coordinates</i> of the rectangle where the image is displayed.</p>
192 13635 ppiqueras
         * <p>Used by {@linkplain #calculateAffineTransform()} to calculate:<br>
193 20332 vcaballero
           *
194 13585 ppiqueras
         * <ul>
195
         * <li>The new {@link #scale scale} .
196
         * <li>The new {@link #adjustedExtent adjustableExtent} .
197
         * <li>The new {@link #trans trans} .
198
         * <li>The new real world coordinates equivalent to 1 pixel ({@link #dist1pixel dist1pixel}) .
199
         * <li>The new real world coordinates equivalent to 3 pixels ({@link #dist3pixel dist3pixel}) .
200
         * </ul>
201
         * </p>
202 20332 vcaballero
         *
203 13585 ppiqueras
         * @see #getImageSize()
204
         * @see #getImageHeight()
205
         * @see #getImageWidth()
206
         * @see #setImageSize(Dimension)
207
         */
208 956 vcaballero
        private Dimension imageSize;
209 13585 ppiqueras
210
        /**
211 13635 ppiqueras
         * <p>the affine transformation between the {@link #extent extent} in <i>map 2D coordinates</i> to
212
         *  the image area in the screen, in <i>screen 2D coordinates</i> (pixels).</p>
213 20332 vcaballero
         *
214 13585 ppiqueras
         * @see AffineTransform
215 20332 vcaballero
         *
216 13585 ppiqueras
         * @see #getAffineTransform()
217
         * @see #setAffineTransform(AffineTransform)
218
         * @see #calculateAffineTransform()
219
         */
220 956 vcaballero
        private AffineTransform trans = new AffineTransform();
221 13585 ppiqueras
222
        /**
223
         * <p>Measurement unit used for measuring distances and displaying information.</p>
224 20332 vcaballero
         *
225 13585 ppiqueras
         * @see #getDistanceUnits()
226
         * @see #setDistanceUnits(int)
227
         */
228 213 fernando
        private int distanceUnits = METROS;
229 13585 ppiqueras
230
        /**
231
         * <p>Measurement unit used by this view port for the map.</p>
232 20332 vcaballero
         *
233 13585 ppiqueras
         * @see #getMapUnits()
234
         * @see #setMapUnits(int)
235
         */
236 213 fernando
        private int mapUnits = METROS;
237 13585 ppiqueras
238
        /**
239
         * <p>Array with the {@link ViewPortListener ViewPortListener}s registered to this view port.</p>
240 20332 vcaballero
         *
241 13585 ppiqueras
         * @see #addViewPortListener(ViewPortListener)
242
         * @see #removeViewPortListener(ViewPortListener)
243
         */
244 1197 fernando
        private ArrayList listeners = new ArrayList();
245 13585 ppiqueras
246
        /**
247
         * <p>The offset is the position where start drawing the map.</p>
248
         * <p>The offset of a <a href="http://www.gvsig.gva.es/">gvSIG</a>'s <i>View</i> is
249
         * always (0, 0) because the drawing area fits with the full window area. But in
250
         * a <a href="http://www.gvsig.gva.es/">gvSIG</a>'s <i>Layout</i> it's up to the place where
251
         * the <code>FFrameView</code> is located.</p>
252 20332 vcaballero
         *
253 13585 ppiqueras
         * @see #getOffset()
254
         * @see #setOffset(Point2D)
255
         */
256 956 vcaballero
        private Point2D offset = new Point2D.Double(0, 0);
257 13585 ppiqueras
258
        /**
259
         * <p>Clipping area.</p>
260
         */
261 956 vcaballero
        private Rectangle2D clip;
262 13585 ppiqueras
263
        /**
264
         * <p>Background color of this view.</p>
265 20332 vcaballero
         *
266 13585 ppiqueras
         * @see #getBackColor()
267
         * @see #setBackColor(Color)
268
         */
269 1282 fjp
        private Color backColor = null; //Color.WHITE;
270 13585 ppiqueras
271
        /**
272
         * <p>Information about the map projection used in this view.</p>
273 20332 vcaballero
         *
274 13585 ppiqueras
         * @see #getProjection()
275
         * @see #setProjection(IProjection)
276
         */
277 346 fernando
        private IProjection proj;
278 13585 ppiqueras
279
        /**
280
         * <p>Represents the distance in <i>world coordinates</i> equivalent to 1 pixel in the view with the current extent.</p>
281 20332 vcaballero
         *
282 13585 ppiqueras
         * @see #getDist1pixel()
283
         * @see #setDist1pixel(double)
284
         */
285 956 vcaballero
        private double dist1pixel;
286 13585 ppiqueras
287
        /**
288
         * <p>Represents the distance in <i>world coordinates</i> equivalent to 3 pixels in the view with the current extent.</p>
289 20332 vcaballero
         *
290 13585 ppiqueras
         * @see #getDist3pixel()
291
         * @see #setDist3pixel(double)
292
         */
293 956 vcaballero
        private double dist3pixel;
294 13585 ppiqueras
295
        /**
296
         * <p>Ratio between the size of <code>imageSize</code> and <code>extent</code>:<br> <i><pre>min{(imageSize.getHeight()/extent.getHeight(), imageSize.getWidth()/extent.getWidth())}</pre></i></p>
297
         */
298 213 fernando
        private double scale;
299 13585 ppiqueras
300
        /**
301
         * <p>Clipping area.</p>
302 20332 vcaballero
         *
303 13585 ppiqueras
         * @see #setClipRect(Rectangle2D)
304
         */
305 3683 caballero
        private Rectangle2D cliprect;
306 13585 ppiqueras
307
        /**
308
         * <p>Enables or disables the <i>"adjustable extent"</i> mode.</p>
309 20332 vcaballero
         *
310 13585 ppiqueras
         * <p>
311
         * When calculates the affine transform, if
312
         * <ul>
313
         * <li><i>enabled</i>: the new <code>adjustedExtent</code> will have the (X, Y) coordinates of the <code>extent</code> and
314 13635 ppiqueras
         *  an area that will be an scale of the image size. That area will have different
315
         *  height or width (not both) of the extent according the least ratio (height or width) in <pre>image.size/extent.size"</pre>.
316 13585 ppiqueras
         * <li><i>disabled</i>: the new <code>adjustedExtent</code> will be like <code>extent</code>.
317
         * </ul>
318
         * </p>
319 20332 vcaballero
         *
320 13585 ppiqueras
         * @see #setAdjustable(boolean)
321
         */
322 8765 jjdelcerro
        private boolean adjustableExtent=true;
323 20332 vcaballero
        /**
324
         * <p>Measurement unit used for measuring areas and displaying information.</p>
325
         *
326
         * @see #getDistanceArea()
327
         * @see #setDistanceArea(int)
328
         */
329
        private int distanceArea = 0;
330 956 vcaballero
331
        /**
332 13585 ppiqueras
         * <p>Creates a new view port with the information of the projection in <code>proj</code> argument, and
333 13635 ppiqueras
         *  default configuration:</p>
334
         * <p>
335 13585 ppiqueras
         * <ul>
336
         *  <li><i><code>distanceUnits</code></i> = meters
337
         *  <li><i><code>mapUnits</code></i> = meters
338
         *  <li><i><code>backColor</code></i> = <i>undefined</i>
339
         *  <li><i><code>offset</code></i> = <code>new Point2D.Double(0, 0);</code>
340
         * </ul>
341
         * </p>
342
         *
343
         * @param proj information of the projection for this view port
344 956 vcaballero
         */
345
        public ViewPort(IProjection proj) {
346 867 fjp
                // Por defecto
347 956 vcaballero
                this.proj = proj;
348 867 fjp
        }
349 213 fernando
350 956 vcaballero
        /**
351 13585 ppiqueras
         * <p>Changes the status of the <i>"adjustable extent"</i> option to enabled or disabled.</p>
352 20332 vcaballero
         *
353 20100 jmvivo
         * <p>If view port isn't adjustable, won't bear in mind the aspect ratio of the available rectangular area to
354
         *  calculate the affine transform from the original map in real coordinates. (Won't scale the image to adapt
355
         *  it to the available rectangular area).</p>
356 20332 vcaballero
         *
357 13585 ppiqueras
         * @param boolean the boolean to be set
358 8765 jjdelcerro
         */
359
        public void setAdjustable(boolean adjustable) {
360
                adjustableExtent = adjustable;
361
        }
362
363
        /**
364 13585 ppiqueras
         * <p>Appends the specified {@link ViewPortListener ViewPortListener} listener if weren't.</p>
365 20332 vcaballero
         *
366 13585 ppiqueras
         * @param arg0 the listener to add
367 956 vcaballero
         *
368 13585 ppiqueras
         * @return <code>true</code> if has been added successfully
369 20332 vcaballero
         *
370 13585 ppiqueras
         * @see #removeViewPortListener(ViewPortListener)
371 956 vcaballero
         */
372 1197 fernando
        public boolean addViewPortListener(ViewPortListener arg0) {
373 8765 jjdelcerro
                if (!listeners.contains(arg0))
374
                        return listeners.add(arg0);
375
                return false;
376 213 fernando
        }
377
378 956 vcaballero
        /**
379 20100 jmvivo
          * <p>Removes the specified {@link ViewPortListener ViewPortListener} listener, if existed.</p>
380 20332 vcaballero
         *
381 20100 jmvivo
         * @param arg0 the listener to remove
382 20332 vcaballero
         *
383 20100 jmvivo
         * @return <code>true</code> if the contained the specified listener.
384 20332 vcaballero
         *
385 13585 ppiqueras
         * @see #addViewPortListener(ViewPortListener)
386 956 vcaballero
         */
387 1197 fernando
        public boolean removeViewPortListener(ViewPortListener arg0) {
388
                return listeners.remove(arg0);
389 213 fernando
        }
390
391 956 vcaballero
        /**
392 20100 jmvivo
         * <p>Converts and returns the distance <code>d</code>, that is in <i>map
393 13635 ppiqueras
         *  coordinates</i> to <i>screen coordinates</i> using a <i>delta transform</i> with
394 13585 ppiqueras
         *  the transformation affine information in the {@link #trans #trans} attribute.</p>
395 956 vcaballero
         *
396 13585 ppiqueras
         * @param d distance in <i>map coordinates</i>
397 956 vcaballero
         *
398 13635 ppiqueras
         * @return distance equivalent in <i>screen coordinates</i>
399 20332 vcaballero
         *
400 13585 ppiqueras
         * @see #toMapDistance(int)
401
         * @see AffineTransform#deltaTransform(Point2D, Point2D)S
402 956 vcaballero
         */
403
        public int fromMapDistance(double d) {
404
                Point2D.Double pWorld = new Point2D.Double(1, 1);
405
                Point2D.Double pScreen = new Point2D.Double();
406 234 fjp
407 956 vcaballero
                try {
408
                        trans.deltaTransform(pWorld, pScreen);
409
                } catch (Exception e) {
410
                        System.err.print(e.getMessage());
411
                }
412 213 fernando
413 956 vcaballero
                return (int) (d * pScreen.x);
414
        }
415 234 fjp
416 956 vcaballero
        /**
417 20100 jmvivo
         * <p>Converts and returns the distance <code>d</code>, that is in <i>screen
418 13635 ppiqueras
         *  coordinates</i> to <i>map coordinates</i> using the transformation affine information
419 13585 ppiqueras
         *  in the {@link #trans #trans} attribute.</p>
420 956 vcaballero
         *
421 13585 ppiqueras
         * @param d distance in pixels
422 956 vcaballero
         *
423 13635 ppiqueras
         * @return distance equivalent in <i>map coordinates</i>
424 20332 vcaballero
         *
425 13585 ppiqueras
         * @see #fromMapDistance(double)
426
         * @see AffineTransform
427 956 vcaballero
         */
428 13585 ppiqueras
        public double toMapDistance(int d) {
429
                double dist = d / trans.getScaleX();
430
431
                return dist;
432
        }
433
434
        /**
435
         * <p>Converts and returns the {@link Rectangle2D Rectangle2D}, that is in <i>map
436 13635 ppiqueras
         *  coordinates</i> to <i>screen coordinates</i> (pixels) using an <i>inverse transform</i> with
437 13585 ppiqueras
         *  the transformation affine information in the {@link #trans #trans} attribute.</p>
438 20332 vcaballero
         *
439 13585 ppiqueras
         * @param r the 2D rectangle in <i>map coordinates</i>
440
         * @return 2D rectangle equivalent in <i>screen coordinates</i> (pixels)
441 20332 vcaballero
         *
442 13585 ppiqueras
         * @see #toMapRectangle(Rectangle2D)
443
         * @see #fromMapDistance(double)
444
         * @see #fromMapPoint(Point2D)
445
         */
446
        public Rectangle2D fromMapRectangle(Rectangle2D r) {
447
                double w=fromMapDistance((int)r.getWidth());
448
                double h=fromMapDistance((int)r.getHeight());
449
                Point2D p1=fromMapPoint((int)r.getX(),(int)r.getY());
450
                return new Rectangle2D.Double(p1.getX(),p1.getY(),w,h);
451
        }
452 20332 vcaballero
453 13585 ppiqueras
        /**
454
         * <p>Converts and returns the {@link Rectangle2D Rectangle2D}, that is in <i>screen
455 13635 ppiqueras
         *  coordinates</i> (pixels) to <i>map coordinates</i> using {@linkplain #toMapDistance(int)},
456
         *  and {@linkplain #toMapPoint(int, int)}.</p>
457 20332 vcaballero
         *
458 13585 ppiqueras
         * @param r the 2D rectangle in <i>screen coordinates</i> (pixels)
459
         * @return 2D rectangle equivalent in <i>map coordinates</i>
460 20332 vcaballero
         *
461 13585 ppiqueras
         * @see #fromMapRectangle(Rectangle2D)
462
         * @see #toMapDistance(int)
463
         * @see #toMapPoint(int, int)
464
         */
465
        public Rectangle2D toMapRectangle(Rectangle2D r){
466
                double w=toMapDistance((int)r.getWidth());
467
                double h=toMapDistance((int)r.getHeight());
468
                Point2D p1=toMapPoint((int)r.getX(),(int)r.getY());
469
                return new Rectangle2D.Double(p1.getX(),p1.getY(),w,h);
470
        }
471 20332 vcaballero
472 13585 ppiqueras
        /**
473
         * <p>Converts and returns the 2D point <code>(x,y)</code>, that is in <i>map
474 20332 vcaballero
         *  coordinates</i> to <i>screen coordinates</i> (pixels) using
475 13635 ppiqueras
         *  the affine transformation in the {@link #trans #trans} attribute.</p>
476 13585 ppiqueras
         *
477
         * @param x the <code>x</code> <i>map coordinate</i> of a 2D point
478
         * @param y the <code>y</code> <i>map coordinate</i> of a 2D point
479
         *
480 13635 ppiqueras
         * @return 2D point equivalent in <i>screen coordinates</i> (pixels)
481 20332 vcaballero
         *
482 13585 ppiqueras
         * @see #fromMapPoint(Point2D)
483
         * @see AffineTransform#transform(Point2D, Point2D)
484
         */
485 956 vcaballero
        public Point2D fromMapPoint(double x, double y) {
486
                Point2D.Double pWorld = new Point2D.Double(x, y);
487
                Point2D.Double pScreen = new Point2D.Double();
488 234 fjp
489 956 vcaballero
                try {
490
                        trans.transform(pWorld, pScreen);
491
                } catch (Exception e) {
492
                        System.err.print(e.getMessage());
493
                }
494 213 fernando
495 956 vcaballero
                return pScreen;
496
        }
497 1036 vcaballero
498
        /**
499 13585 ppiqueras
         * <p>Converts and returns the 2D point argument, that is in <i>map
500 13635 ppiqueras
         *  coordinates</i> to <i>screen coordinates</i> (pixels) using
501
         *  the affine transformation in the {@link #trans #trans} attribute.</p>
502 1036 vcaballero
         *
503 13585 ppiqueras
         * @param point the 2D point in <i>map coordinates</i>
504 1036 vcaballero
         *
505 13635 ppiqueras
         * @return 2D point equivalent in <i>screen coordinates</i> (pixels)
506 20332 vcaballero
         *
507 13585 ppiqueras
         * @see #toMapPoint(Point2D)
508
         * @see #fromMapPoint(double, double)
509 1036 vcaballero
         */
510 1004 vcaballero
        public Point2D fromMapPoint(Point2D point) {
511 1036 vcaballero
                return fromMapPoint(point.getX(), point.getY());
512 1004 vcaballero
        }
513 213 fernando
514 956 vcaballero
        /**
515 13635 ppiqueras
         * <p>Converts and returns the 2D point <code>(x,y)</code>, that is in <i>screen coordinates</i>
516
         *  (pixels) to <i>map coordinates</i> using
517
         *  the affine transformation in the {@link #trans #trans} attribute.</p>
518 956 vcaballero
         *
519 13585 ppiqueras
         * @param x the <code>x</code> <i>screen coordinate</i> of a 2D point
520
         * @param y the <code>y</code> <i>screen coordinate</i> of a 2D point
521 956 vcaballero
         *
522 13635 ppiqueras
         * @return 2D point equivalent in <i>map coordinates</i>
523 20332 vcaballero
         *
524 13585 ppiqueras
         * @see #toMapPoint(Point2D)
525
         * @see #fromMapPoint(double, double)
526 956 vcaballero
         */
527
        public Point2D toMapPoint(int x, int y) {
528
                Point pScreen = new Point(x, y);
529 213 fernando
530 956 vcaballero
                return toMapPoint(pScreen);
531
        }
532 234 fjp
533 956 vcaballero
        /**
534 13635 ppiqueras
         * <p>Converts and returns the 2D point argument, that is in <i>screen coordinates</i>
535
         *  (pixels) to <i>map coordinates</i> using the
536
         *  inverse affine transformation of the {@link #trans #trans} attribute.</p>
537 20332 vcaballero
         *
538 13585 ppiqueras
         * @param pScreen the 2D point in <i>screen coordinates</i> (pixels)
539 956 vcaballero
         *
540 13635 ppiqueras
         * @return 2D point equivalent in <i>map coordinates</i>
541 20332 vcaballero
         *
542 13585 ppiqueras
         * @see #toMapPoint(int, int)
543
         * @see AffineTransform#createInverse()
544
         * @see AffineTransform#transform(Point2D, Point2D)
545 956 vcaballero
         */
546
        public Point2D toMapPoint(Point2D pScreen) {
547
                Point2D.Double pWorld = new Point2D.Double();
548
                AffineTransform at;
549 20332 vcaballero
550 956 vcaballero
                try {
551
                        at = trans.createInverse();
552
                        at.transform(pScreen, pWorld);
553
                } catch (NoninvertibleTransformException e) {
554
                        throw new RuntimeException(e);
555
                }
556 20332 vcaballero
557 956 vcaballero
                return pWorld;
558
        }
559 1036 vcaballero
560 999 luisw
        /**
561 13682 ppiqueras
         * <p>Returns the real distance (in <i>world coordinates</i>) at the graphic layers of two 2D points
562
         *  (in <i>map coordinates</i>) of the plane where is selected the <i>extent</i>.</p>
563
         * <p>If the projection of this view is UTM, considers the Earth curvature.</p>
564 1036 vcaballero
         *
565 13585 ppiqueras
         * @param pt1 a 2D point in <i>map coordinates</i>
566
         * @param pt2 another 2D point in <i>map coordinates</i>
567 1036 vcaballero
         *
568 13585 ppiqueras
         * @return the distance in meters between the two points 2D
569 20332 vcaballero
         *
570 13585 ppiqueras
         * @see GeoCalc#distanceVincenty(Point2D, Point2D)
571 999 luisw
         */
572
        public double distanceWorld(Point2D pt1, Point2D pt2) {
573
                double dist = -1;
574
                dist = pt1.distance(pt2);
575 1036 vcaballero
576
                if ((proj != null) && !(proj instanceof CSUTM)) {
577
                        dist = new GeoCalc(proj).distanceVincenty(proj.toGeo(pt1),
578
                                        proj.toGeo(pt2));
579
                }
580
581 9446 caballero
                return dist*MapContext.CHANGEM[getMapUnits()];
582 999 luisw
        }
583 213 fernando
584 956 vcaballero
        /**
585 13635 ppiqueras
         * <p>Sets as extent and adjusted extent of this view port, the previous. Recalculating
586
         *  its parameters.</p>
587 20332 vcaballero
         *
588 13585 ppiqueras
         * @see #getExtents()
589
         * @see #calculateAffineTransform()
590 956 vcaballero
         */
591
        public void setPreviousExtent() {
592
                extent = extents.removePrev();
593 918 fernando
594 956 vcaballero
                //Calcula la transformaci?n af?n
595
                calculateAffineTransform();
596 680 fernando
597 956 vcaballero
                // Lanzamos los eventos de extent cambiado
598 3683 caballero
                callExtentChanged(getAdjustedExtent());
599 956 vcaballero
        }
600 213 fernando
601 956 vcaballero
        /**
602 13585 ppiqueras
         * <p>Gets the area selected by user using some tool.</p>
603 20332 vcaballero
         *
604 20100 jmvivo
         * <p>When the zoom changes (for instance using the <i>zoom in</i> or <i>zoom out</i> tools,
605 13585 ppiqueras
         *  but also zooming to a selected feature or shape) the extent that covers that
606
         *  area is the value returned by this method. It is not the actual area shown
607
         *  because it doesn't care about the aspect ratio of the image size of the view. However, any
608
         *  part of the real world contained in this extent is shown in the view.</p>
609 20332 vcaballero
         *
610 13585 ppiqueras
         * <p>If you are looking for the complete extent currently shown, you must use the
611
         *  {@linkplain #getAdjustedExtent()} method.</p>
612 20332 vcaballero
         *
613 13585 ppiqueras
         * @return the current extent
614 20332 vcaballero
         *
615 13585 ppiqueras
         * @see #setExtent(Rectangle2D)
616
         * @see #getAdjustedExtent()
617
         * @see #setPreviousExtent()
618
         * @see #getExtents()
619 956 vcaballero
         */
620
        public Rectangle2D getExtent() {
621
                return extent;
622
        }
623 213 fernando
624
        /**
625 20100 jmvivo
         * <p>Changes the <i>extent</i> and <i>adjusted extent</i> of this view port:<br>
626 13585 ppiqueras
         * <ul>
627
         * <li>Stores the previous extent.
628
         * <li>Calculates the new extent using <code>r</code>:
629
         * <pre>extent = new Rectangle2D.Double(r.getMinX() - 0.1, r.getMinY() - 0.1, r.getWidth() + 0.2, r.getHeight() + 0.2);</pre>
630
         * <li>Executes {@linkplain #calculateAffineTransform()}: getting the new scale, adjusted extent, affine transformation between
631
         *  map and screen coordinates, the real world coordinates equivalent to 1 pixel, and the real world coordinates equivalent to 3 pixels.
632 20100 jmvivo
         * <li>Notifies all {@link ViewPortListener ViewPortListener} registered that the extent has changed.
633 13585 ppiqueras
         * </ul>
634
         * </p>
635 956 vcaballero
         *
636 13585 ppiqueras
         * @param r the new extent
637 20332 vcaballero
         *
638 13585 ppiqueras
         * @see #getExtent()
639
         * @see #getExtents()
640
         * @see #calculateAffineTransform()
641
         * @see #setPreviousExtent()
642 956 vcaballero
         */
643
        public void setExtent(Rectangle2D r) {
644
                if (extent != null) {
645
                        extents.put(extent);
646
                }
647
648 3884 caballero
                //Esto comprueba que el extent no es de anchura o altura = "0"
649 956 vcaballero
                //y si es as? lo redimensiona.
650 2409 caballero
                if (r!=null &&((r.getWidth() == 0) || (r.getHeight() == 0))) {
651 956 vcaballero
                        extent = new Rectangle2D.Double(r.getMinX() - 0.1,
652
                                        r.getMinY() - 0.1, r.getWidth() + 0.2, r.getHeight() + 0.2);
653
                } else {
654
                        extent = r;
655
                }
656
657
                //Calcula la transformaci?n af?n
658
                calculateAffineTransform();
659
660
                // Lanzamos los eventos de extent cambiado
661 3683 caballero
                callExtentChanged(getAdjustedExtent());
662 956 vcaballero
        }
663
664
        /**
665 20100 jmvivo
         * <p>Changes the <i>extent</i> and <i>adjusted extent</i> of this view port:<br>
666 13585 ppiqueras
         * <ul>
667
         * <li>Executes {@linkplain #calculateAffineTransform()}: getting the new scale, adjusted extent, affine transformation between
668
         *  map and screen coordinates, the real world coordinates equivalent to 1 pixel, and the real world coordinates equivalent to 3 pixels.
669 20100 jmvivo
         * <li>Notifies to all {@link ViewPortListener ViewPortListener} registered that the extent has changed.
670 13585 ppiqueras
         * </ul>
671
         * </p>
672 20332 vcaballero
         *
673 13585 ppiqueras
         * @see #setExtent(Rectangle2D)
674
         * @see #calculateAffineTransform()
675 956 vcaballero
         */
676 6630 caballero
        public void refreshExtent() {
677 1135 vcaballero
                //this.scale = scale;
678 956 vcaballero
679
                //Calcula la transformaci?n af?n
680
                calculateAffineTransform();
681
682
                // Lanzamos los eventos de extent cambiado
683 3683 caballero
                callExtentChanged(getAdjustedExtent());
684 956 vcaballero
        }
685
686
        /**
687 13585 ppiqueras
         * <p>Calculates and returns using the current projection of this view port, the scale that
688
         *  is the extent in <i>screen coordinates</i> from the image in <i>map coordinates</i>.</p>
689 956 vcaballero
         *
690 13585 ppiqueras
         * @return the scale <i>extent / image size</i> projected by this view port
691 20332 vcaballero
         *
692 13585 ppiqueras
         * @deprecated since 07/09/07, use {@linkplain MapContext#getScaleView()}
693 213 fernando
         */
694 956 vcaballero
        public double getScale() {
695
                return proj.getScale(extent.getMinX(), extent.getMaxX(),
696
                        imageSize.getWidth(), dpi);
697
        }
698
699
        /**
700 13635 ppiqueras
         * <p>Recalculates the current <code>{@linkplain #extent}</code> using an scale. It's necessary execute {@linkplain #refreshExtent()} after.</p>
701 20332 vcaballero
         *
702 13585 ppiqueras
         * @param s the scale to set
703 20332 vcaballero
         *
704
         * @deprecated since 07/09/07, use {@linkplain MapContext#setScaleView(long)}
705 13585 ppiqueras
         */
706
        public void setScale(long s){
707
                double x=extent.getX();
708
                double y=extent.getY();
709
                double escalaX = imageSize.getWidth() / extent.getWidth();
710
                double w=imageSize.getWidth() / s;
711
                double h=imageSize.getHeight() / s;
712
                double difw = escalaX/s;
713
714
                double x1 = (-x * difw) -
715
            x+
716
            extent.getWidth()/2;
717
        double y1 = (-y * difw) -
718
            y +
719
            extent.getHeight()/2;
720
        double w1=extent.getWidth()*difw;
721
        double h1=extent.getHeight()*difw;
722
                extent.setRect(-x1,-y1,w1,h1);
723 20332 vcaballero
        }
724 13585 ppiqueras
725
        /**
726
         * <p>Affine transformation between <i>map 2D coordinates</i> to <i>screen 2D coordinates</i> (pixels),
727 20100 jmvivo
         * preserving the "straightness" and "parallelism" of the lines.</p>
728 956 vcaballero
         *
729 13585 ppiqueras
         * @return the affine transformation
730 20332 vcaballero
         *
731 13585 ppiqueras
         * @see #setAffineTransform(AffineTransform)
732
         * @see #calculateAffineTransform()
733 956 vcaballero
         */
734 213 fernando
        public AffineTransform getAffineTransform() {
735
                return trans;
736
        }
737 956 vcaballero
738 213 fernando
        /**
739 13585 ppiqueras
         * <p>Returns the size of the image projected.</p>
740 956 vcaballero
         *
741 13585 ppiqueras
         * @return the image size
742 20332 vcaballero
         *
743 13585 ppiqueras
         * @see #setImageSize(Dimension)
744
         * @see #getImageHeight()
745
         * @see #getImageWidth()
746 213 fernando
         */
747
        public Dimension getImageSize() {
748
                return imageSize;
749
        }
750 956 vcaballero
751 213 fernando
        /**
752 13585 ppiqueras
         * <p>Sets the size of the image projected, recalculating the parameters of this view port.</p>
753 956 vcaballero
         *
754 13585 ppiqueras
         * @param imageSize the image size
755 20332 vcaballero
         *
756 13585 ppiqueras
         * @see #getImageSize()
757
         * @see #calculateAffineTransform()
758 213 fernando
         */
759
        public void setImageSize(Dimension imageSize) {
760
                this.imageSize = imageSize;
761
                calculateAffineTransform();
762
        }
763
764 956 vcaballero
        /**
765 13585 ppiqueras
         * <p>Notifies to all view port listeners registered, that the adjusted extent of this view port
766
         *  has changed.</p>
767 956 vcaballero
         *
768 13585 ppiqueras
         * @param newRect the new adjusted extend
769 20332 vcaballero
         *
770 13585 ppiqueras
         * @see #refreshExtent()
771
         * @see #setExtent(Rectangle2D)
772
         * @see #setPreviousExtent()
773
         * @see ExtentEvent
774
         * @see ViewPortListener
775 956 vcaballero
         */
776 1197 fernando
        private void callExtentChanged(Rectangle2D newRect) {
777 1082 fernando
                ExtentEvent ev = ExtentEvent.createExtentEvent(newRect);
778 655 fjp
779 1197 fernando
                for (int i = 0; i < listeners.size(); i++) {
780
                        ViewPortListener listener = (ViewPortListener) listeners.get(i);
781 956 vcaballero
                        listener.extentChanged(ev);
782
                }
783
        }
784
785 213 fernando
        /**
786 13585 ppiqueras
         * <p>Notifies to all view port listeners registered, that the background color of this view port
787
         *  has changed.</p>
788 956 vcaballero
         *
789 13585 ppiqueras
         * @param c the new background color
790 20332 vcaballero
         *
791 13585 ppiqueras
         * @see #setBackColor(Color)
792
         * @see ColorEvent
793
         * @see ViewPortListener
794 213 fernando
         */
795 1197 fernando
        private void callColorChanged(Color c) {
796 1082 fernando
                ColorEvent ce = ColorEvent.createColorEvent(c);
797 956 vcaballero
798 1197 fernando
                for (int i = 0; i < listeners.size(); i++) {
799
                        ViewPortListener listener = (ViewPortListener) listeners.get(i);
800 956 vcaballero
                        listener.backColorChanged(ce);
801
                }
802
        }
803 13585 ppiqueras
804 5943 jmvivo
        /**
805 13585 ppiqueras
         * <p>Notifies to all view port listeners registered, that the projection of this view port
806
         *  has changed.</p>
807 5943 jmvivo
         *
808 13585 ppiqueras
         * @param projection the new projection
809 20332 vcaballero
         *
810 13585 ppiqueras
         * @see #setProjection(IProjection)
811
         * @see ProjectionEvent
812
         * @see ViewPortListener
813 5943 jmvivo
         */
814
        private void callProjectionChanged(IProjection projection) {
815
                ProjectionEvent ev = ProjectionEvent.createProjectionEvent(projection);
816 956 vcaballero
817 5943 jmvivo
                for (int i = 0; i < listeners.size(); i++) {
818
                        ViewPortListener listener = (ViewPortListener) listeners.get(i);
819
                        listener.projectionChanged(ev);
820
                }
821
        }
822
823 956 vcaballero
        /**
824 13585 ppiqueras
         * <p>Calculates the affine transformation between the {@link #extent extent} in <i>map 2D coordinates</i> to
825
         *  the image area in the screen, in <i>screen 2D coordinates</i> (pixels).</p>
826 20332 vcaballero
         *
827 13585 ppiqueras
         * <p>This process recalculates some parameters of this view port:<br>
828 20332 vcaballero
         *
829 13585 ppiqueras
         * <ul>
830
         * <li>The new {@link #scale scale} .
831 13682 ppiqueras
         * <li>The new {@link #adjustedExtent adjustedExtent} .
832 13585 ppiqueras
         * <li>The new {@link #trans trans} .
833
         * <li>The new real world coordinates equivalent to 1 pixel ({@link #dist1pixel dist1pixel}) .
834
         * <li>The new real world coordinates equivalent to 3 pixels ({@link #dist3pixel dist3pixel}) .
835
         * </ul>
836
         * </p>
837 20332 vcaballero
         *
838 13585 ppiqueras
         * @see #getAffineTransform()
839
         * @see #setAffineTransform(AffineTransform)
840
         * @see #refreshExtent()
841
         * @see #setExtent(Rectangle2D)
842
         * @see #setImageSize(Dimension)
843
         * @see #setPreviousExtent()
844
         * @see #createFromXML(XMLEntity)
845
         * @see AffineTransform
846 956 vcaballero
         */
847 213 fernando
        private void calculateAffineTransform() {
848 956 vcaballero
                if ((imageSize == null) || (extent == null) ||
849
                                (imageSize.getWidth() <= 0) || (imageSize.getHeight() <= 0)) {
850
                        return;
851
                }
852 213 fernando
853 956 vcaballero
                AffineTransform escalado = new AffineTransform();
854
                AffineTransform translacion = new AffineTransform();
855 213 fernando
856 956 vcaballero
                double escalaX;
857
                double escalaY;
858 213 fernando
859 956 vcaballero
                escalaX = imageSize.getWidth() / extent.getWidth();
860
                escalaY = imageSize.getHeight() / extent.getHeight();
861 213 fernando
862 956 vcaballero
                double xCenter = extent.getCenterX();
863
                double yCenter = extent.getCenterY();
864
                double newHeight;
865
                double newWidth;
866 213 fernando
867 956 vcaballero
                adjustedExtent = new Rectangle2D.Double();
868 213 fernando
869 8765 jjdelcerro
                if (adjustableExtent) {
870 13585 ppiqueras
                        // If is enabled the adjustable extent mode:
871
                        // the new 'adjustedExtent' will have the (X, Y) coordinates of the 'extent' and
872
                        // an area that will be an scale of the image size according the projection. That area will have different
873
                        // height or width (not both) of the extent according the least ratio image.size/extent.size
874
                        // The least ratio (height or width) will be used to calculate the other size value of the
875
                        // new 'adjustedExtent'
876 8765 jjdelcerro
                        if (escalaX < escalaY) {
877
                                scale = escalaX;
878
                                newHeight = imageSize.getHeight() / scale;
879
                                adjustedExtent.setRect(xCenter - (extent.getWidth() / 2.0),
880
                                        yCenter - (newHeight / 2.0), extent.getWidth(), newHeight);
881
                        } else {
882
                                scale = escalaY;
883
                                newWidth = imageSize.getWidth() / scale;
884
                                adjustedExtent.setRect(xCenter - (newWidth / 2.0),
885
                                        yCenter - (extent.getHeight() / 2.0), newWidth,
886
                                        extent.getHeight());
887
                        }
888
                        escalado.setToScale(scale, -scale);
889
                }
890
                else { // adjusted is same as extent
891 956 vcaballero
                        scale = escalaX;
892 8765 jjdelcerro
                        adjustedExtent.setFrame(extent);
893
                        escalado.setToScale(escalaX, -escalaY);
894 956 vcaballero
                }
895 213 fernando
896 3683 caballero
                translacion.setToTranslation(-getAdjustedExtent().getX(),
897
                        -getAdjustedExtent().getY() - getAdjustedExtent().getHeight());
898 956 vcaballero
899
                AffineTransform offsetTrans = new AffineTransform();
900
                offsetTrans.setToTranslation(offset.getX(), offset.getY());
901
902
                trans.setToIdentity();
903
                trans.concatenate(offsetTrans);
904
                trans.concatenate(escalado);
905
906
                trans.concatenate(translacion);
907
908 3884 caballero
                // Calculamos las distancias de 1 pixel y 3 pixel con esa transformaci?n
909 956 vcaballero
                // de coordenadas, de forma que est?n precalculadas para cuando las necesitemos
910
                AffineTransform at;
911
912 237 fjp
                try {
913
                        at = trans.createInverse();
914 956 vcaballero
915 237 fjp
                        java.awt.Point pPixel = new java.awt.Point(1, 1);
916 956 vcaballero
                        Point2D.Float pProv = new Point2D.Float();
917
                        at.deltaTransform(pPixel, pProv);
918 237 fjp
919 956 vcaballero
                        dist1pixel = pProv.x;
920
                        dist3pixel = 3 * pProv.x;
921 237 fjp
                } catch (NoninvertibleTransformException e) {
922 867 fjp
                        System.err.println("transformada afin = " + trans.toString());
923 956 vcaballero
                        System.err.println("extent = " + extent.toString() +
924
                                " imageSize= " + imageSize.toString());
925 918 fernando
                        throw new RuntimeException(e);
926 237 fjp
                }
927 213 fernando
        }
928 956 vcaballero
929
        /**
930 13585 ppiqueras
         * <p>Sets the offset.</p>
931
         * <p>The offset is the position where start drawing the map.</p>
932 956 vcaballero
         *
933 13585 ppiqueras
         * @param p 2D point that represents the offset in pixels
934 20332 vcaballero
         *
935 13585 ppiqueras
         * @see #getOffset()
936 956 vcaballero
         */
937
        public void setOffset(Point2D p) {
938
                offset = p;
939 351 vcaballero
        }
940 13585 ppiqueras
941 956 vcaballero
        /**
942 13585 ppiqueras
         * <p>Gets the offset.</p>
943
         * <p>The offset is the position where start drawing the map.</p>
944 1317 vcaballero
         *
945 13585 ppiqueras
         * @return 2D point that represents the offset in pixels
946 20332 vcaballero
         *
947 13585 ppiqueras
         * @see #setOffset(Point2D)
948 1317 vcaballero
         */
949
        public Point2D getOffset() {
950
                return offset;
951
        }
952 13585 ppiqueras
953 1317 vcaballero
        /**
954 20100 jmvivo
         * <p>Sets the background color.</p>
955 956 vcaballero
         *
956 13585 ppiqueras
         * @param c the new background color
957 20332 vcaballero
         *
958 13585 ppiqueras
         * @see #getBackColor()
959 956 vcaballero
         */
960 213 fernando
        public void setBackColor(Color c) {
961
                backColor = c;
962 1197 fernando
                callColorChanged(backColor);
963 213 fernando
        }
964
965 956 vcaballero
        /**
966 20100 jmvivo
         * <p>Gets the background color.</p>
967 956 vcaballero
         *
968 13585 ppiqueras
         * @return the background color of the view
969 20332 vcaballero
         *
970 13585 ppiqueras
         * @see #setBackColor(Color)
971 956 vcaballero
         */
972 213 fernando
        public Color getBackColor() {
973
                return backColor;
974
        }
975 956 vcaballero
976 213 fernando
        /**
977 13585 ppiqueras
         * <p>Returns the extent currently covered by the view adjusted (scaled) to the image size aspect.</p>
978 20332 vcaballero
         *
979 13585 ppiqueras
         * @return extent of the view adjusted to the image size aspect
980 20332 vcaballero
         *
981 13585 ppiqueras
         * @see #setAdjustable(boolean)
982 213 fernando
         */
983
        public Rectangle2D getAdjustedExtent() {
984 3683 caballero
                if (cliprect!=null){
985
                        return adjustedExtent.createIntersection(cliprect);
986
                }
987 213 fernando
                return adjustedExtent;
988
        }
989 956 vcaballero
990 213 fernando
        /**
991 13585 ppiqueras
         * <p>Returns the measurement unit of this view port used for measuring distances and displaying information.</p>
992 956 vcaballero
         *
993 13585 ppiqueras
         * @return the measurement unit of this view used for measuring distances and displaying information
994 20332 vcaballero
         *
995 13585 ppiqueras
         * @see #setDistanceUnits(int)
996 213 fernando
         */
997
        public int getDistanceUnits() {
998
                return distanceUnits;
999
        }
1000 20332 vcaballero
        /**
1001
         * <p>Returns the measurement unit of this view port used for measuring areas and displaying information.</p>
1002
         *
1003
         * @return the measurement unit of this view used for measuring areas and displaying information
1004
         *
1005
         * @see #setDistanceUnits(int)
1006
         */
1007
        public int getDistanceArea() {
1008
                return distanceArea;
1009
        }
1010 956 vcaballero
1011 20332 vcaballero
1012 213 fernando
        /**
1013 13585 ppiqueras
         * <p>Sets the measurement unit of this view port used for measuring distances and displaying information.</p>
1014 956 vcaballero
         *
1015 13585 ppiqueras
         * @param distanceUnits the measurement unit of this view used for measuring distances and displaying information
1016 20332 vcaballero
         *
1017 13585 ppiqueras
         * @see #getDistanceUnits()
1018 213 fernando
         */
1019
        public void setDistanceUnits(int distanceUnits) {
1020
                this.distanceUnits = distanceUnits;
1021
        }
1022 20332 vcaballero
        /**
1023
         * <p>Sets the measurement unit of this view port used for measuring areas and displaying information.</p>
1024
         *
1025
         * @param distanceUnits the measurement unit of this view used for measuring areas and displaying information
1026
         *
1027
         * @see #getDistanceUnits()
1028
         */
1029
        public void setDistanceArea(int distanceArea) {
1030
                this.distanceArea = distanceArea;
1031
        }
1032 956 vcaballero
1033 213 fernando
        /**
1034 13585 ppiqueras
         * <p>Gets the measurement unit used by this view port for the map.</p>
1035 956 vcaballero
         *
1036 13585 ppiqueras
         * @return Returns the current map measure unit
1037 20332 vcaballero
         *
1038 13585 ppiqueras
         * @see #setMapUnits(int)
1039 213 fernando
         */
1040
        public int getMapUnits() {
1041
                return mapUnits;
1042
        }
1043 956 vcaballero
1044 213 fernando
        /**
1045 13585 ppiqueras
         * <p>Sets the measurement unit used by this view port for the map.</p>
1046 956 vcaballero
         *
1047 13585 ppiqueras
         * @param mapUnits the new map measure unit
1048 20332 vcaballero
         *
1049 13585 ppiqueras
         * @see #getMapUnits()
1050 213 fernando
         */
1051
        public void setMapUnits(int mapUnits) {
1052
                this.mapUnits = mapUnits;
1053 956 vcaballero
        }
1054
1055
        /**
1056 20100 jmvivo
         * <p>Gets the width in <i>screen coordinates</i> of the rectangle where the image is displayed.</p>
1057 13635 ppiqueras
         * <p>Used by {@linkplain #calculateAffineTransform()} to calculate:<br>
1058 20332 vcaballero
           *
1059 13585 ppiqueras
         * <ul>
1060
         * <li>The new {@link #scale scale} .
1061
         * <li>The new {@link #adjustedExtent adjustableExtent} .
1062
         * <li>The new {@link #trans trans} .
1063
         * <li>The new real world coordinates equivalent to 1 pixel ({@link #dist1pixel dist1pixel}) .
1064
         * <li>The new real world coordinates equivalent to 3 pixels ({@link #dist3pixel dist3pixel}) .
1065
         * </ul>
1066
         * </p>
1067 20332 vcaballero
         *
1068 13585 ppiqueras
         * @see #getImageHeight()
1069
         * @see #getImageSize()
1070
         * @see #setImageSize(Dimension)
1071 956 vcaballero
         */
1072
        public int getImageWidth() {
1073 214 fernando
                return imageSize.width;
1074 213 fernando
        }
1075 956 vcaballero
1076
        /**
1077 20100 jmvivo
         * <p>Gets the height in <i>screen coordinates</i> of the rectangle where the image is displayed.</p>
1078 13635 ppiqueras
         * <p>Used by {@linkplain #calculateAffineTransform()} to calculate:<br>
1079 20332 vcaballero
           *
1080 13585 ppiqueras
         * <ul>
1081
         * <li>The new {@link #scale scale} .
1082
         * <li>The new {@link #adjustedExtent adjustableExtent} .
1083
         * <li>The new {@link #trans trans} .
1084
         * <li>The new real world coordinates equivalent to 1 pixel ({@link #dist1pixel dist1pixel}) .
1085
         * <li>The new real world coordinates equivalent to 3 pixels ({@link #dist3pixel dist3pixel}) .
1086
         * </ul>
1087
         * </p>
1088 20332 vcaballero
         *
1089 13585 ppiqueras
         * @see #getImageWidth()
1090
         * @see #getImageSize()
1091
         * @see #setImageSize(Dimension)
1092 956 vcaballero
         */
1093
        public int getImageHeight() {
1094 214 fernando
                return imageSize.height;
1095
        }
1096 956 vcaballero
1097
        /**
1098 20332 vcaballero
         * <p>Gets the distance in <i>world coordinates</i> equivalent to 1 pixel in the view with the current extent.</p>
1099 956 vcaballero
         *
1100 13585 ppiqueras
         * @return the distance
1101 20332 vcaballero
         *
1102 13585 ppiqueras
         * @see #setDist1pixel(double)
1103 956 vcaballero
         */
1104 237 fjp
        public double getDist1pixel() {
1105
                return dist1pixel;
1106
        }
1107 956 vcaballero
1108
        /**
1109 20332 vcaballero
         * <p>Sets the distance in <i>world coordinates</i> equivalent to 1 pixel in the view with the current extent.</p>
1110 956 vcaballero
         *
1111 13585 ppiqueras
         * @param dist1pixel the distance
1112 20332 vcaballero
         *
1113 13585 ppiqueras
         * @see #getDist1pixel()
1114 956 vcaballero
         */
1115 237 fjp
        public void setDist1pixel(double dist1pixel) {
1116
                this.dist1pixel = dist1pixel;
1117
        }
1118 956 vcaballero
1119
        /**
1120 20332 vcaballero
         * <p>Gets the distance in <i>world coordinates</i> equivalent to 3 pixels in the view with the current extent.</p>
1121 956 vcaballero
         *
1122 13585 ppiqueras
         * @return the distance
1123 20332 vcaballero
         *
1124 13585 ppiqueras
         * @see #setDist3pixel(double)
1125 956 vcaballero
         */
1126 237 fjp
        public double getDist3pixel() {
1127
                return dist3pixel;
1128
        }
1129 956 vcaballero
1130
        /**
1131 20332 vcaballero
         * <p>Sets the distance in <i>world coordinates</i> equivalent to 3 pixels in the view with the current extent.</p>
1132 956 vcaballero
         *
1133 13585 ppiqueras
         * @param dist3pixel the distance
1134 20332 vcaballero
         *
1135 13585 ppiqueras
         * @see #getDist3pixel()
1136 956 vcaballero
         */
1137 237 fjp
        public void setDist3pixel(double dist3pixel) {
1138
                this.dist3pixel = dist3pixel;
1139
        }
1140 956 vcaballero
1141 277 fernando
        /**
1142 13585 ppiqueras
         * <p>Returns the last previous extents of this view port.</p>
1143 956 vcaballero
         *
1144 13585 ppiqueras
         * @return the last previous extents of this view port
1145 20332 vcaballero
         *
1146 13585 ppiqueras
         * @see #setPreviousExtent()
1147 277 fernando
         */
1148
        public ExtentHistory getExtents() {
1149
                return extents;
1150
        }
1151
1152
        /**
1153 13585 ppiqueras
         * <p>Gets the projection used in this view port.</p>
1154 956 vcaballero
         *
1155 13585 ppiqueras
         * @return projection used in this view port
1156 20332 vcaballero
         *
1157 13585 ppiqueras
         * @see #setProjection(IProjection)
1158 346 fernando
         */
1159
        public IProjection getProjection() {
1160
                return proj;
1161
        }
1162 956 vcaballero
1163 346 fernando
        /**
1164 13585 ppiqueras
         * <p>Sets the projection to this view port.</p>
1165 956 vcaballero
         *
1166 13585 ppiqueras
         * @param proj the new projection
1167 20332 vcaballero
         *
1168 13585 ppiqueras
         * @see #getProjection()
1169 346 fernando
         */
1170
        public void setProjection(IProjection proj) {
1171 6187 jmvivo
                if(this.proj == null || !this.proj.getAbrev().equals(proj.getAbrev())) {
1172 6630 caballero
                        this.proj = proj;
1173 6187 jmvivo
                        callProjectionChanged(proj);
1174
                }
1175 346 fernando
        }
1176 3884 caballero
1177 13635 ppiqueras
//    -----------------------------------------------------------------------------------------------------------
1178
//    NOTA PARA DESARROLLADORES SOBRE EL M?TODO "public void setAffineTransform(AffineTransform at)"
1179
//    ==============================================================================================
1180
//          Only used for print, should be removed, redefining the {@link RasterAdapter RasterAdapter} interface,
1181
//           allowing it to receive a {@link ViewPortData ViewPortData} .
1182
//    -----------------------------------------------------------------------------------------------------------
1183
1184 1152 fjp
        /**
1185 13585 ppiqueras
         * <p>Sets only the affine transform to this view port, without updating dependent attributes.</p>
1186 20100 jmvivo
         * <p><b><i>This method could be problematic!</i></b></p>
1187 13585 ppiqueras
         *
1188
         * @param at the affine transform to set
1189 20332 vcaballero
         *
1190 13585 ppiqueras
         * @see #getAffineTransform()
1191
         * @see #calculateAffineTransform()
1192 1152 fjp
         */
1193 3884 caballero
        public void setAffineTransform(AffineTransform at)
1194 1152 fjp
        {
1195
            this.trans = at;
1196
        }
1197 956 vcaballero
1198
        /**
1199 13585 ppiqueras
         * <p>Returns an XML entity that represents this view port instance:<br>
1200
         * <ul>
1201
         * <li>Properties:
1202
         *  <ul>
1203
         *  <li><i>className</i>: name of this class.
1204
         *  <li>If defined, the adjusted extent:
1205
         *   <ul>
1206 20332 vcaballero
         *   <li><i>adjustedExtentX</i>: X coordinate of the adjusted extent.
1207 13585 ppiqueras
         *   <li><i>adjustedExtentY</i>: Y coordinate of the adjusted extent.
1208
         *   <li><i>adjustedExtentW</i>: width of the adjusted extent.
1209
         *   <li><i>adjustedExtentH</i>: height of the adjusted extent.
1210 20332 vcaballero
         *   </ul>
1211 13585 ppiqueras
         *  <li>If defined, the background color:
1212
         *   <ul>
1213
         *   <li><i>backColor</i>: background color.
1214 20332 vcaballero
         *   </ul>
1215 13585 ppiqueras
         *  <li>If defined, the clip:
1216
         *   <ul>
1217 20332 vcaballero
         *   <li><i>clipX</i>: X coordinate of the clip.
1218 13585 ppiqueras
         *   <li><i>clipY</i>: Y coordinate of clip.
1219
         *   <li><i>clipW</i>: width of the clip.
1220
         *   <li><i>clipH</i>: height of the clip.
1221 20332 vcaballero
         *   </ul>
1222 13585 ppiqueras
         *  <li><i>dist1pixel</i>: the distance in world coordinates equivalent to 1 pixel in the view.
1223
         *  <li><i>dist3pixel</i>: the distance in world coordinates equivalent to 3 pixels in the view.
1224
         *  <li><i>distanceUnits</i>: the distance measurement unit.
1225
         *  <li>If defined, the extent:
1226
         *   <ul>
1227 20332 vcaballero
         *   <li><i>extentX</i>: X coordinate of the extent.
1228 13585 ppiqueras
         *   <li><i>extentY</i>: Y coordinate of the extent.
1229
         *   <li><i>extentW</i>: width of the extent.
1230
         *   <li><i>extentH</i>: height of the extent.
1231 20332 vcaballero
         *   </ul>
1232
         *  <li><i>mapUnits</i>: the map measurement unit.
1233 13585 ppiqueras
         *  <li><i>offsetX</i>: X coordinate of the offset.
1234 20332 vcaballero
         *  <li><i>offsetY</i>: Y coordinate of the offset.
1235 13585 ppiqueras
         *  <li>If defined, the projection:
1236
         *   <ul>
1237
         *   <li><i>proj</i>: the projection.
1238 20332 vcaballero
         *   </ul>
1239 13635 ppiqueras
         *  <li><i>scale</i>: ratio between the size of <code>imageSize</code> and <code>extent</code>.
1240 13585 ppiqueras
         *  </ul>
1241
         * <li>Child branches:
1242
         *  <ul>
1243
         *  <li>XML entity of the internal {@link ExtentHistory ExtentHistory} .
1244
         *  </ul>
1245
         * </ul>
1246 20332 vcaballero
         *
1247 13635 ppiqueras
         * @return the XML entity
1248 20332 vcaballero
         *
1249 13585 ppiqueras
         * @see #createFromXML(XMLEntity)
1250 956 vcaballero
         */
1251
        public XMLEntity getXMLEntity() {
1252
                XMLEntity xml = new XMLEntity();
1253 1094 vcaballero
                xml.putProperty("className",this.getClass().getName());
1254 956 vcaballero
1255
                if (adjustedExtent != null) {
1256
                        xml.putProperty("adjustedExtentX", adjustedExtent.getX());
1257
                        xml.putProperty("adjustedExtentY", adjustedExtent.getY());
1258
                        xml.putProperty("adjustedExtentW", adjustedExtent.getWidth());
1259
                        xml.putProperty("adjustedExtentH", adjustedExtent.getHeight());
1260 741 vcaballero
                }
1261 956 vcaballero
1262 1282 fjp
                if (backColor != null)
1263
                    xml.putProperty("backColor", StringUtilities.color2String(backColor));
1264 956 vcaballero
1265
                if (clip != null) {
1266
                        xml.putProperty("clipX", clip.getX());
1267
                        xml.putProperty("clipY", clip.getY());
1268
                        xml.putProperty("clipW", clip.getWidth());
1269
                        xml.putProperty("clipH", clip.getHeight());
1270 435 vcaballero
                }
1271 956 vcaballero
1272
                xml.putProperty("dist1pixel", dist1pixel);
1273
                xml.putProperty("dist3pixel", dist3pixel);
1274
                xml.putProperty("distanceUnits", distanceUnits);
1275
1276
                if (extent != null) {
1277
                        xml.putProperty("extentX", extent.getX());
1278
                        xml.putProperty("extentY", extent.getY());
1279
                        xml.putProperty("extentW", extent.getWidth());
1280
                        xml.putProperty("extentH", extent.getHeight());
1281 741 vcaballero
                }
1282 956 vcaballero
1283 449 vcaballero
                xml.addChild(extents.getXMLEntity());
1284 956 vcaballero
                xml.putProperty("mapUnits", mapUnits);
1285
                xml.putProperty("offsetX", offset.getX());
1286
                xml.putProperty("offsetY", offset.getY());
1287
1288
                if (proj != null) {
1289
                        xml.putProperty("proj", proj.getAbrev());
1290 442 vcaballero
                }
1291 956 vcaballero
1292
                xml.putProperty("scale", scale);
1293
1294 435 vcaballero
                return xml;
1295
        }
1296 956 vcaballero
1297
        /**
1298 13585 ppiqueras
         * <p>Creates a new <code>ViewPort</code> from an XML entity.</p>
1299 956 vcaballero
         *
1300 13585 ppiqueras
         * @param xml an XML entity
1301 956 vcaballero
         *
1302 13585 ppiqueras
         * @return the new <code>ViewPort</code>
1303 20332 vcaballero
         *
1304 13585 ppiqueras
         * @see #getXMLEntity()
1305
         * @see #createFromXML(XMLEntity)
1306 956 vcaballero
         */
1307 2183 fernando
        public static ViewPort createFromXML03(XMLEntity xml) {
1308
                ViewPort vp = new ViewPort(null);
1309
1310
                if (xml.contains("adjustedExtentX")) {
1311
                        vp.adjustedExtent = new Rectangle2D.Double(xml.getDoubleProperty(
1312
                                                "adjustedExtentX"),
1313
                                        xml.getDoubleProperty("adjustedExtentY"),
1314
                                        xml.getDoubleProperty("adjustedExtentW"),
1315
                                        xml.getDoubleProperty("adjustedExtentH"));
1316
                }
1317
1318
                if (xml.contains("backColor")) {
1319
                        vp.setBackColor(StringUtilities.string2Color(xml.getStringProperty(
1320
                                                "backColor")));
1321
                }
1322
1323
                if (xml.contains("clipX")) {
1324
                        vp.clip = new Rectangle2D.Double(xml.getDoubleProperty("clipX"),
1325
                                        xml.getDoubleProperty("clipY"),
1326
                                        xml.getDoubleProperty("clipW"),
1327
                                        xml.getDoubleProperty("clipH"));
1328
                }
1329
1330
                vp.setDist1pixel(xml.getDoubleProperty("dist1pixel"));
1331
                vp.setDist3pixel(xml.getDoubleProperty("dist3pixel"));
1332
                vp.setDistanceUnits(xml.getIntProperty("distanceUnits"));
1333
                vp.extents = ExtentHistory.createFromXML03(xml.getChild(0));
1334
1335
                if (xml.contains("extentX")) {
1336
                        vp.setExtent(new Rectangle2D.Double(xml.getDoubleProperty("extentX"),
1337
                                        xml.getDoubleProperty("extentY"),
1338
                                        xml.getDoubleProperty("extentW"),
1339
                                        xml.getDoubleProperty("extentH")));
1340
1341
                        //Calcula la transformaci?n af?n
1342
                        vp.calculateAffineTransform();
1343
1344
                        // Lanzamos los eventos de extent cambiado
1345
                        // vp.callExtentListeners(vp.adjustedExtent);
1346
                }
1347
1348
                vp.setMapUnits(xml.getIntProperty("mapUnits"));
1349
                vp.setOffset(new Point2D.Double(xml.getDoubleProperty("offsetX"),
1350
                                xml.getDoubleProperty("offsetY")));
1351
1352
                if (xml.contains("proj")) {
1353 6164 luisw2
                        vp.proj = CRSFactory.getCRS(xml.getStringProperty("proj"));
1354 2183 fernando
                }
1355
1356
                //vp.setScale(xml.getDoubleProperty("scale"));
1357 6630 caballero
                vp.refreshExtent();
1358 2183 fernando
                return vp;
1359
        }
1360
1361
        /**
1362 13585 ppiqueras
         * <p>Creates a new <code>ViewPort</code> from an XML entity.</p>
1363 2183 fernando
         *
1364 13585 ppiqueras
         * @param xml an XML entity
1365 2183 fernando
         *
1366 13585 ppiqueras
         * @return the new <code>ViewPort</code>
1367 20332 vcaballero
         *
1368 13585 ppiqueras
         * @see #getXMLEntity()
1369
         * @see #createFromXML03(XMLEntity)
1370 2183 fernando
         */
1371 956 vcaballero
        public static ViewPort createFromXML(XMLEntity xml) {
1372
                ViewPort vp = new ViewPort(null);
1373
1374
                if (xml.contains("adjustedExtentX")) {
1375
                        vp.adjustedExtent = new Rectangle2D.Double(xml.getDoubleProperty(
1376
                                                "adjustedExtentX"),
1377
                                        xml.getDoubleProperty("adjustedExtentY"),
1378
                                        xml.getDoubleProperty("adjustedExtentW"),
1379
                                        xml.getDoubleProperty("adjustedExtentH"));
1380 741 vcaballero
                }
1381 956 vcaballero
1382
                if (xml.contains("backColor")) {
1383
                        vp.setBackColor(StringUtilities.string2Color(xml.getStringProperty(
1384
                                                "backColor")));
1385 8765 jjdelcerro
                }else {
1386
                        vp.setBackColor(Color.white);
1387 435 vcaballero
                }
1388 956 vcaballero
1389
                if (xml.contains("clipX")) {
1390
                        vp.clip = new Rectangle2D.Double(xml.getDoubleProperty("clipX"),
1391
                                        xml.getDoubleProperty("clipY"),
1392
                                        xml.getDoubleProperty("clipW"),
1393
                                        xml.getDoubleProperty("clipH"));
1394 741 vcaballero
                }
1395 956 vcaballero
1396 442 vcaballero
                vp.setDist1pixel(xml.getDoubleProperty("dist1pixel"));
1397
                vp.setDist3pixel(xml.getDoubleProperty("dist3pixel"));
1398
                vp.setDistanceUnits(xml.getIntProperty("distanceUnits"));
1399 20332 vcaballero
                if (xml.contains("distanceArea")){
1400
                        vp.setDistanceArea(xml.getIntProperty("distanceArea"));
1401
                }else{
1402
                        vp.setDistanceArea(xml.getIntProperty("distanceUnits"));
1403
                }
1404 956 vcaballero
                vp.extents = ExtentHistory.createFromXML(xml.getChild(0));
1405 918 fernando
1406 956 vcaballero
                if (xml.contains("extentX")) {
1407
                        vp.setExtent(new Rectangle2D.Double(xml.getDoubleProperty("extentX"),
1408
                                        xml.getDoubleProperty("extentY"),
1409
                                        xml.getDoubleProperty("extentW"),
1410
                                        xml.getDoubleProperty("extentH")));
1411
1412
                        //Calcula la transformaci?n af?n
1413
                        vp.calculateAffineTransform();
1414
1415
                        // Lanzamos los eventos de extent cambiado
1416 1040 fjp
                        // vp.callExtentListeners(vp.adjustedExtent);
1417 741 vcaballero
                }
1418 956 vcaballero
1419 442 vcaballero
                vp.setMapUnits(xml.getIntProperty("mapUnits"));
1420 956 vcaballero
                vp.setOffset(new Point2D.Double(xml.getDoubleProperty("offsetX"),
1421
                                xml.getDoubleProperty("offsetY")));
1422
1423
                if (xml.contains("proj")) {
1424 6164 luisw2
                        vp.proj = CRSFactory.getCRS(xml.getStringProperty("proj"));
1425 442 vcaballero
                }
1426 956 vcaballero
1427 1135 vcaballero
                //vp.setScale(xml.getDoubleProperty("scale"));
1428 6630 caballero
                vp.refreshExtent();
1429 435 vcaballero
                return vp;
1430
        }
1431 956 vcaballero
1432
        /**
1433 13585 ppiqueras
         * <p>Fast clone implementation: creates and returns a clone of this view port using XML entities.</p>
1434 20100 jmvivo
         * <p>Isn't a <i>deepclone</i> to avoid unnecessary memory consumption.</p>
1435 956 vcaballero
         *
1436 13585 ppiqueras
         * @return the new view port
1437 20332 vcaballero
         *
1438 13585 ppiqueras
         * @see #createFromXML(XMLEntity)
1439 956 vcaballero
         */
1440
        public ViewPort cloneViewPort() {
1441
                return createFromXML(getXMLEntity());
1442 798 vcaballero
        }
1443 956 vcaballero
1444
        /**
1445 20100 jmvivo
         * <p>Returns a <code>String</code> representation of the main values of this view port: <code>{@linkplain #extent}</code>,
1446 13635 ppiqueras
         *  <code>{@linkplain #adjustedExtent}</code>, <code>{@linkplain #imageSize}</code>, <code>{@linkplain #scale}</code>, and <code>{@linkplain #trans}</code>.</p>
1447 20332 vcaballero
         *
1448 13585 ppiqueras
         * @return a <code>string</code> representation of the main values of this view port
1449 956 vcaballero
         */
1450
        public String toString() {
1451 20332 vcaballero
1452 875 fjp
                String str;
1453 956 vcaballero
                str = "Datos del viewPort:\nExtent=" + extent + "\nadjustedExtent=" +
1454
                        adjustedExtent + "\nimageSize=" + imageSize + "\nescale=" + scale +
1455 875 fjp
                        "\ntrans=" + trans;
1456 956 vcaballero
1457 875 fjp
                return str;
1458
        }
1459 3683 caballero
1460 13585 ppiqueras
        /**
1461
         * <p>Sets the position and size of the clipping rectangle.</p>
1462 20332 vcaballero
         *
1463 13585 ppiqueras
         * @param rectView the clipping rectangle to set
1464
         */
1465 3683 caballero
        public void setClipRect(Rectangle2D rectView) {
1466
                cliprect=rectView;
1467
        }
1468 213 fernando
}