Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_mapcontext / src / org / gvsig / fmap / mapcontext / ViewPort.java @ 35753

History | View | Annotate | Download (59.4 KB)

1 32880 jjdelcerro
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2 21200 vcaballero
 *
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 29506 jtorres
 *   Av. Blasco Ib??ez, 50
24 21200 vcaballero
 *   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
package org.gvsig.fmap.mapcontext;
42
43
import java.awt.Color;
44
import java.awt.Dimension;
45 26225 jmvivo
import java.awt.Toolkit;
46 21200 vcaballero
import java.awt.geom.AffineTransform;
47
import java.awt.geom.NoninvertibleTransformException;
48
import java.awt.geom.Point2D;
49
import java.awt.geom.Rectangle2D;
50
import java.util.ArrayList;
51
52
import org.cresques.cts.GeoCalc;
53
import org.cresques.cts.IProjection;
54 27514 cmartinez
import org.cresques.cts.UTM;
55 33652 jjdelcerro
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
56 35487 fdiaz
import org.gvsig.fmap.geom.Geometry;
57 27414 jpiera
import org.gvsig.fmap.geom.GeometryLocator;
58
import org.gvsig.fmap.geom.GeometryManager;
59
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
60 35487 fdiaz
import org.gvsig.fmap.geom.exception.CreateGeometryException;
61 21426 vcaballero
import org.gvsig.fmap.geom.primitive.Envelope;
62 35487 fdiaz
import org.gvsig.fmap.geom.primitive.Point;
63 21200 vcaballero
import org.gvsig.fmap.mapcontext.events.ColorEvent;
64
import org.gvsig.fmap.mapcontext.events.ExtentEvent;
65
import org.gvsig.fmap.mapcontext.events.ProjectionEvent;
66
import org.gvsig.fmap.mapcontext.events.listeners.ViewPortListener;
67 30173 jldominguez
import org.gvsig.tools.ToolsLocator;
68 32880 jjdelcerro
import org.gvsig.tools.dynobject.DynStruct;
69 33652 jjdelcerro
import org.gvsig.tools.lang.Cloneable;
70 32711 cmartinez
import org.gvsig.tools.persistence.PersistenceManager;
71 30173 jldominguez
import org.gvsig.tools.persistence.Persistent;
72
import org.gvsig.tools.persistence.PersistentState;
73 32880 jjdelcerro
import org.gvsig.tools.persistence.exception.PersistenceException;
74 33652 jjdelcerro
import org.gvsig.tools.util.Callable;
75 27414 jpiera
import org.slf4j.Logger;
76
import org.slf4j.LoggerFactory;
77 21200 vcaballero
78
/**
79 29519 jtorres
 * <p>
80
 * <code>ViewPort</code> class represents the logic needed to transform a
81
 * rectangular area of a map to the available area in screen to display it.
82
 * </p>
83
 *
84
 * <p>
85
 * Includes an affine transformation, between the rectangular area selected of
86
 * the external map, in its own <i>map coordinates</i>, to the rectangular area
87
 * available of a view in <i>screen coordinates</i>.
88
 * </p>
89
 *
90
 * <p>
91
 * Elements:
92 21200 vcaballero
 * <ul>
93
 * <li><i>extent</i>: the area selected of the map, in <i>map coordinates</i>.
94 29519 jtorres
 * <li><i>imageSize</i>: width and height in pixels (<i>screen coordinates</i>)
95
 * of the area available in screen to display the area selected of the map.
96
 * <li><i>adjustedExtent</i>: the area selected must be an scale of
97
 * <i>imageSize</i>.<br>
98
 * This implies adapt the extent, preserving and centering it, and adding around
99
 * the needed area to fill all the image size. That added area will be extracted
100
 * from the original map, wherever exists, and filled with the background color
101
 * wherever not.
102 21200 vcaballero
 * <li><i>scale</i>: the scale between the adjusted extent and the image size.
103 29519 jtorres
 * <li><i>backColor</i>: the default background color in the view, if there is
104
 * no map.
105 21200 vcaballero
 * <li><i>trans</i>: the affine transformation.
106
 * <li><i>proj</i>: map projection used in this view.
107
 * <li><i>distanceUnits</i>: distance measurement units, of data in screen.
108
 * <li><i>mapUnits</i>: measurement units, of data in map.
109 29519 jtorres
 * <li><i>extents</i>: an {@link ExtentHistory ExtentHistory} with the last
110
 * previous extents.
111
 * <li><i>offset</i>: position in pixels of the available rectangular area,
112
 * where start drawing the map.
113
 * <li><i>dist1pixel</i>: the distance in <i>world coordinates</i> equivalent to
114
 * 1 pixel in the view with the current extent.
115
 * <li><i>dist3pixel</i>: the distance in <i>world coordinates</i> equivalent to
116
 * 3 pixels in the view with the current extent.
117
 * <li><i>listeners</i>: list with the {@link ViewPortListener ViewPortListener}
118
 * registered.
119 21200 vcaballero
 * </ul>
120
 * </p>
121 29519 jtorres
 *
122 21200 vcaballero
 * @author Vicente Caballero Navarro
123
 */
124 33613 fdiaz
public class ViewPort implements Persistent, Cloneable {
125 33352 cordinyana
126 33613 fdiaz
    private static final String FIELD_DISTANCE_AREA = "distanceArea";
127
    private static final String FIELD_IMAGE_SIZE = "imageSize";
128
    private static final String FIELD_PROJ = "proj";
129
    private static final String FIELD_OFFSET = "offset";
130
    private static final String FIELD_MAP_UNITS = "mapUnits";
131
    private static final String FIELD_EXTENT = "extent";
132
    private static final String FIELD_EXTENTS = "extents";
133
    private static final String FIELD_DISTANCE_UNITS = "distanceUnits";
134
    private static final String FIELD_DIST3PIXEL = "dist3pixel";
135
    private static final String FIELD_DIST1PIXEL = "dist1pixel";
136
    private static final String FIELD_CLIP = "clip";
137
    private static final String FIELD_BACK_COLOR = "backColor";
138
    private static final String FIELD_ADJUSTED_EXTENT = "adjustedExtent";
139 29519 jtorres
140 33613 fdiaz
    private static final GeometryManager geomManager =
141
        GeometryLocator.getGeometryManager();
142
    private static final Logger logger =
143
        LoggerFactory.getLogger(ViewPort.class);
144 21200 vcaballero
145 33613 fdiaz
    /**
146
     * <p>
147
     * Screen resolution in <i>dots-per-inch</i>. Useful to calculate the
148
     * geographic scale of the view.
149
     * </p>
150
     *
151
     * @see Toolkit#getScreenResolution()
152
     * @see #getScale()
153
     */
154
    private static int dpi = java.awt.Toolkit.getDefaultToolkit()
155
        .getScreenResolution();
156 21200 vcaballero
157 33613 fdiaz
    /**
158
     * <p>
159
     * Area selected by user using some tool.
160
     * </p>
161
     *
162
     * <p>
163
     * When the zoom changes (for instance when using the zoom in or zoom out
164
     * tools, but also zooming to a selected feature or shape) the extent that
165
     * covers that area is the value returned by this method. It is not the
166
     * actual area shown in the view because it does not care about the aspect
167
     * ratio of the available area. However, any part of the real world
168
     * contained in this extent is shown in the view.
169
     * </p>
170
     * <p>
171
     * Probably this is not what you are looking for. If you are looking for the
172
     * complete extent currently shown, you must use
173
     * {@linkplain #getAdjustedExtent()} method which returns the extent that
174
     * contains this one but regarding the current view's aspect ratio.
175
     * </p>
176
     *
177
     * @see #getExtent()
178
     * @see #setEnvelope(Envelope)
179
     */
180
    protected Rectangle2D extent;
181 21200 vcaballero
182 33613 fdiaz
    /**
183
     * <p>
184
     * Location and dimensions of the extent adjusted to the image size.
185
     * </p>
186
     *
187
     * @see #getAdjustedExtent()
188
     */
189
    protected Rectangle2D adjustedExtent;
190 29519 jtorres
191 33613 fdiaz
    /**
192
     * Draw version of the context. It's used for know when de componend has
193
     * changed any visualization property
194
     *
195
     * @see getDrawVersion
196
     * @see updateDrawVersion
197
     */
198
    private long drawVersion = 0L;
199 21200 vcaballero
200 33613 fdiaz
    /**
201
     * <p>
202
     * History with the last extents of the view.
203
     * </p>
204
     *
205
     * @see #setPreviousExtent()
206
     * @see #getExtents()
207
     */
208
    protected ExtentHistory extents = new ExtentHistory();
209 21200 vcaballero
210 33613 fdiaz
    /**
211
     * <p>
212
     * Size in <i>screen coordinates</i> of the rectangle where the image is
213
     * displayed.
214
     * </p>
215
     * <p>
216
     * Used by {@linkplain #calculateAffineTransform()} to calculate:<br>
217
     *
218
     * <ul>
219
     * <li>The new {@link #scale scale} .
220
     * <li>The new {@link #adjustedExtent adjustableExtent} .
221
     * <li>The new {@link #trans trans} .
222
     * <li>The new real world coordinates equivalent to 1 pixel (
223
     * {@link #dist1pixel dist1pixel}) .
224
     * <li>The new real world coordinates equivalent to 3 pixels (
225
     * {@link #dist3pixel dist3pixel}) .
226
     * </ul>
227
     * </p>
228
     *
229
     * @see #getImageSize()
230
     * @see #getImageHeight()
231
     * @see #getImageWidth()
232
     * @see #setImageSize(Dimension)
233
     */
234
    private Dimension imageSize;
235 21200 vcaballero
236 33613 fdiaz
    /**
237
     * <p>
238
     * the affine transformation between the {@link #extent extent} in <i>map 2D
239
     * coordinates</i> to the image area in the screen, in <i>screen 2D
240
     * coordinates</i> (pixels).
241
     * </p>
242
     *
243
     * @see AffineTransform
244
     *
245
     * @see #getAffineTransform()
246
     * @see #setAffineTransform(AffineTransform)
247
     * @see #calculateAffineTransform()
248
     */
249
    private AffineTransform trans = new AffineTransform();
250 21200 vcaballero
251 33613 fdiaz
    /**
252
     * <p>
253
     * Measurement unit used for measuring distances and displaying information.
254
     * </p>
255
     *
256
     * @see #getDistanceUnits()
257
     * @see #setDistanceUnits(int)
258
     */
259
    private int distanceUnits = 1;
260
    /**
261
     * <p>
262
     * Measurement unit used for measuring areas and displaying information.
263
     * </p>
264
     *
265
     * @see #getDistanceArea()
266
     * @see #setDistanceArea(int)
267
     */
268
    private int distanceArea = 1;
269
    /**
270
     * <p>
271
     * Measurement unit used by this view port for the map.
272
     * </p>
273
     *
274
     * @see #getMapUnits()
275
     * @see #setMapUnits(int)
276
     */
277
    private int mapUnits = 1;
278 21200 vcaballero
279 33613 fdiaz
    /**
280
     * <p>
281
     * Array with the {@link ViewPortListener ViewPortListener}s registered to
282
     * this view port.
283
     * </p>
284
     *
285
     * @see #addViewPortListener(ViewPortListener)
286
     * @see #removeViewPortListener(ViewPortListener)
287
     */
288
    private ArrayList listeners = new ArrayList();
289 21200 vcaballero
290 33613 fdiaz
    /**
291
     * <p>
292
     * The offset is the position where start drawing the map.
293
     * </p>
294
     * <p>
295
     * The offset of a <a href="http://www.gvsig.gva.es/">gvSIG</a>'s
296
     * <i>View</i> is always (0, 0) because the drawing area fits with the full
297
     * window area. But in a <a href="http://www.gvsig.gva.es/">gvSIG</a>'s
298
     * <i>Layout</i> it's up to the place where the <code>FFrameView</code> is
299
     * located.
300
     * </p>
301
     *
302
     * @see #getOffset()
303
     * @see #setOffset(Point2D)
304
     */
305
    private Point2D offset = new Point2D.Double(0, 0);
306 21200 vcaballero
307 33613 fdiaz
    /**
308
     * <p>
309
     * Clipping area.
310
     * </p>
311
     */
312
    // private Rectangle2D clip;
313 21200 vcaballero
314 33613 fdiaz
    /**
315
     * <p>
316
     * Background color of this view.
317
     * </p>
318
     *
319
     * @see #getBackColor()
320
     * @see #setBackColor(Color)
321
     */
322
    private Color backColor = null; // Color.WHITE;
323 21200 vcaballero
324 33613 fdiaz
    /**
325
     * <p>
326
     * Information about the map projection used in this view.
327
     * </p>
328
     *
329
     * @see #getProjection()
330
     * @see #setProjection(IProjection)
331
     */
332
    private IProjection proj;
333 21200 vcaballero
334 33613 fdiaz
    /**
335
     * <p>
336
     * Represents the distance in <i>world coordinates</i> equivalent to 1 pixel
337
     * in the view with the current extent.
338
     * </p>
339
     *
340
     * @see #getDist1pixel()
341
     * @see #setDist1pixel(double)
342
     */
343
    private double dist1pixel;
344 21200 vcaballero
345 33613 fdiaz
    /**
346
     * <p>
347
     * Represents the distance in <i>world coordinates</i> equivalent to 3
348
     * pixels in the view with the current extent.
349
     * </p>
350
     *
351
     * @see #getDist3pixel()
352
     * @see #setDist3pixel(double)
353
     */
354
    private double dist3pixel;
355 21200 vcaballero
356 33613 fdiaz
    /**
357
     * <p>
358
     * Ratio between the size of <code>imageSize</code> and <code>extent</code>:
359
     * <br>
360
     * <i>
361
     *
362
     * <pre>
363
     * min{(imageSize.getHeight()/extent.getHeight(), imageSize.getWidth()/extent.getWidth())}
364
     * </pre>
365
     *
366
     * </i>
367
     * </p>
368
     */
369
    private double scale;
370 21200 vcaballero
371 33613 fdiaz
    /**
372
     * <p>
373
     * Clipping area.
374
     * </p>
375
     *
376
     * @see #setClipRect(Rectangle2D)
377
     */
378
    private Rectangle2D cliprect;
379 21200 vcaballero
380 33613 fdiaz
    /**
381
     * <p>
382
     * Enables or disables the <i>"adjustable extent"</i> mode.
383
     * </p>
384
     *
385
     * <p>
386
     * When calculates the affine transform, if
387
     * <ul>
388
     * <li><i>enabled</i>: the new <code>adjustedExtent</code> will have the (X,
389
     * Y) coordinates of the <code>extent</code> and an area that will be an
390
     * scale of the image size. That area will have different height or width
391
     * (not both) of the extent according the least ratio (height or width) in
392
     *
393
     * <pre>
394
     * image.size/extent.size&quot;
395
     * </pre>.
396
     * <li><i>disabled</i>: the new <code>adjustedExtent</code> will be like
397
     * <code>extent</code>.
398
     * </ul>
399
     * </p>
400
     *
401
     * @see #setAdjustable(boolean)
402
     */
403
    private boolean adjustableExtent = true;
404 21200 vcaballero
405 33613 fdiaz
    public ViewPort() {
406 21200 vcaballero
407 33613 fdiaz
    }
408 21200 vcaballero
409 33613 fdiaz
    /**
410
     * <p>
411
     * Creates a new view port with the information of the projection in
412
     * <code>proj</code> argument, and default configuration:
413
     * </p>
414
     * <p>
415
     * <ul>
416
     * <li><i><code>distanceUnits</code></i> = meters
417
     * <li><i><code>mapUnits</code></i> = meters
418
     * <li><i><code>backColor</code></i> = <i>undefined</i>
419
     * <li><i><code>offset</code></i> = <code>new Point2D.Double(0, 0);</code>
420
     * </ul>
421
     * </p>
422
     *
423
     * @param proj
424
     *            information of the projection for this view port
425
     */
426
    public ViewPort(IProjection proj) {
427
        // Por defecto
428
        this.proj = proj;
429
    }
430 21200 vcaballero
431 33613 fdiaz
    /**
432
     * <p>
433
     * Changes the status of the <i>"adjustable extent"</i> option to enabled or
434
     * disabled.
435
     * </p>
436
     *
437
     * <p>
438
     * If view port isn't adjustable, won't bear in mind the aspect ratio of the
439
     * available rectangular area to calculate the affine transform from the
440
     * original map in real coordinates. (Won't scale the image to adapt it to
441
     * the available rectangular area).
442
     * </p>
443
     *
444
     * @param boolean the boolean to be set
445
     */
446
    public void setAdjustable(boolean adjustable) {
447
        if (adjustable == adjustableExtent) {
448
            return;
449
        }
450
        adjustableExtent = adjustable;
451
        this.updateDrawVersion();
452
    }
453 21200 vcaballero
454 33613 fdiaz
    /**
455
     * <p>
456
     * Appends the specified {@link ViewPortListener ViewPortListener} listener
457
     * if weren't.
458
     * </p>
459
     *
460
     * @param arg0
461
     *            the listener to add
462
     *
463
     * @return <code>true</code> if has been added successfully
464
     *
465
     * @see #removeViewPortListener(ViewPortListener)
466
     */
467
    public boolean addViewPortListener(ViewPortListener arg0) {
468
        if (!listeners.contains(arg0)) {
469
            return listeners.add(arg0);
470
        }
471
        return false;
472
    }
473 21200 vcaballero
474 33613 fdiaz
    /**
475
     * <p>
476
     * Removes the specified {@link ViewPortListener ViewPortListener} listener,
477
     * if existed.
478
     * </p>
479
     *
480
     * @param arg0
481
     *            the listener to remove
482
     *
483
     * @return <code>true</code> if the contained the specified listener.
484
     *
485
     * @see #addViewPortListener(ViewPortListener)
486
     */
487
    public boolean removeViewPortListener(ViewPortListener arg0) {
488
        return listeners.remove(arg0);
489
    }
490 21200 vcaballero
491 33613 fdiaz
    /**
492
     * <p>
493
     * Converts and returns the distance <code>d</code>, that is in <i>map
494
     * coordinates</i> to <i>screen coordinates</i> using a <i>delta
495
     * transform</i> with the transformation affine information in the
496
     * {@link #trans #trans} attribute.
497
     * </p>
498
     *
499
     * @param d
500
     *            distance in <i>map coordinates</i>
501
     *
502
     * @return distance equivalent in <i>screen coordinates</i>
503
     *
504
     * @see #toMapDistance(int)
505
     * @see AffineTransform#deltaTransform(Point2D, Point2D)S
506
     */
507
    public int fromMapDistance(double d) {
508
        Point2D.Double pWorld = new Point2D.Double(1, 1);
509
        Point2D.Double pScreen = new Point2D.Double();
510 21200 vcaballero
511 33613 fdiaz
        try {
512
            trans.deltaTransform(pWorld, pScreen);
513
        } catch (Exception e) {
514
            System.err.print(e.getMessage());
515
        }
516 21200 vcaballero
517 33613 fdiaz
        return (int) (d * pScreen.x);
518
    }
519 21200 vcaballero
520 33613 fdiaz
    /**
521
     * <p>
522
     * Converts and returns the 2D point <code>(x,y)</code>, that is in <i>map
523
     * coordinates</i> to <i>screen coordinates</i> (pixels) using the affine
524
     * transformation in the {@link #trans #trans} attribute.
525
     * </p>
526
     *
527
     * @param x
528
     *            the <code>x</code> <i>map coordinate</i> of a 2D point
529
     * @param y
530
     *            the <code>y</code> <i>map coordinate</i> of a 2D point
531
     *
532
     * @return 2D point equivalent in <i>screen coordinates</i> (pixels)
533
     *
534
     * @see #fromMapPoint(Point2D)
535
     * @see AffineTransform#transform(Point2D, Point2D)
536
     */
537
    public Point2D fromMapPoint(double x, double y) {
538
        Point2D.Double pWorld = new Point2D.Double(x, y);
539
        Point2D.Double pScreen = new Point2D.Double();
540 21200 vcaballero
541 33613 fdiaz
        try {
542
            trans.transform(pWorld, pScreen);
543
        } catch (Exception e) {
544
            System.err.print(e.getMessage());
545
        }
546 21200 vcaballero
547 33613 fdiaz
        return pScreen;
548
    }
549 21200 vcaballero
550 33613 fdiaz
    /**
551
     * <p>
552
     * Converts and returns the 2D point argument, that is in <i>map
553
     * coordinates</i> to <i>screen coordinates</i> (pixels) using the affine
554
     * transformation in the {@link #trans #trans} attribute.
555
     * </p>
556
     *
557
     * @param point
558
     *            the 2D point in <i>map coordinates</i>
559
     *
560
     * @return 2D point equivalent in <i>screen coordinates</i> (pixels)
561
     *
562
     * @see #toMapPoint(Point2D)
563
     * @see #fromMapPoint(double, double)
564
     */
565
    public Point2D fromMapPoint(Point2D point) {
566
        return fromMapPoint(point.getX(), point.getY());
567
    }
568 21200 vcaballero
569 33613 fdiaz
    /**
570
     * <p>
571
     * Converts and returns the 2D point <code>(x,y)</code>, that is in
572
     * <i>screen coordinates</i> (pixels) to <i>map coordinates</i> using the
573
     * affine transformation in the {@link #trans #trans} attribute.
574
     * </p>
575
     *
576
     * @param x
577
     *            the <code>x</code> <i>screen coordinate</i> of a 2D point
578
     * @param y
579
     *            the <code>y</code> <i>screen coordinate</i> of a 2D point
580
     *
581
     * @return 2D point equivalent in <i>map coordinates</i>
582
     *
583
     * @see #toMapPoint(Point2D)
584
     * @see #fromMapPoint(double, double)
585 35487 fdiaz
     * @deprecated use {@link #convertToMapPoint(int, int)}
586 33613 fdiaz
     */
587
    public Point2D toMapPoint(int x, int y) {
588
        Point2D pScreen = new Point2D.Double(x, y);
589 21200 vcaballero
590 33613 fdiaz
        return toMapPoint(pScreen);
591
    }
592 21200 vcaballero
593 33613 fdiaz
    /**
594
     * <p>
595
     * Converts and returns the {@link Rectangle2D Rectangle2D}, that is in
596
     * <i>screen coordinates</i> (pixels) to <i>map coordinates</i> using
597
     * {@linkplain #toMapDistance(int)}, and {@linkplain #toMapPoint(int, int)}.
598
     * </p>
599
     *
600
     * @param r
601
     *            the 2D rectangle in <i>screen coordinates</i> (pixels)
602
     * @return 2D rectangle equivalent in <i>map coordinates</i>
603
     *
604
     * @see #fromMapRectangle(Rectangle2D)
605
     * @see #toMapDistance(int)
606
     * @see #toMapPoint(int, int)
607
     */
608
    public Rectangle2D toMapRectangle(Rectangle2D r) {
609
        Rectangle2D rect = new Rectangle2D.Double();
610
        Point2D p1 = toMapPoint((int) r.getX(), (int) r.getY());
611
        Point2D p2 = toMapPoint((int) r.getMaxX(), (int) r.getMaxY());
612
        rect.setFrameFromDiagonal(p1, p2);
613
        return rect;
614
    }
615 21200 vcaballero
616 33613 fdiaz
    /**
617
     * <p>
618
     * Converts and returns the distance <code>d</code>, that is in <i>screen
619
     * coordinates</i> to <i>map coordinates</i> using the transformation affine
620
     * information in the {@link #trans #trans} attribute.
621
     * </p>
622
     *
623
     * @param d
624
     *            distance in pixels
625
     *
626
     * @return distance equivalent in <i>map coordinates</i>
627
     *
628
     * @see #fromMapDistance(double)
629
     * @see AffineTransform
630
     */
631
    public double toMapDistance(int d) {
632
        double dist = d / trans.getScaleX();
633 21200 vcaballero
634 33613 fdiaz
        return dist;
635
    }
636 21200 vcaballero
637 33613 fdiaz
    /**
638
     * <p>
639
     * Converts and returns the 2D point argument, that is in <i>screen
640
     * coordinates</i> (pixels) to <i>map coordinates</i> using the inverse
641
     * affine transformation of the {@link #trans #trans} attribute.
642
     * </p>
643
     *
644
     * @param pScreen
645
     *            the 2D point in <i>screen coordinates</i> (pixels)
646
     *
647
     * @return 2D point equivalent in <i>map coordinates</i>
648
     *
649
     * @see #toMapPoint(int, int)
650
     * @see AffineTransform#createInverse()
651
     * @see AffineTransform#transform(Point2D, Point2D)
652 35487 fdiaz
     * @deprecated use {@link #convertToMapPoint(Point2D)}
653 33613 fdiaz
     */
654
    public Point2D toMapPoint(Point2D pScreen) {
655
        Point2D.Double pWorld = new Point2D.Double();
656
        AffineTransform at;
657 21200 vcaballero
658 33613 fdiaz
        try {
659
            at = trans.createInverse();
660
            at.transform(pScreen, pWorld);
661
        } catch (NoninvertibleTransformException e) {
662
            throw new RuntimeException("Non invertible transform Exception", e);
663
        }
664 21200 vcaballero
665 33613 fdiaz
        return pWorld;
666
    }
667 29519 jtorres
668 35487 fdiaz
    public Point convertToMapPoint(Point2D pScreen) {
669
            Point2D p = toMapPoint(pScreen);
670
                try {
671
                        return geomManager.createPoint(
672
                                p.getX(),
673
                                p.getY(),
674
                                Geometry.SUBTYPES.GEOM2D
675
                        );
676
                } catch (CreateGeometryException e) {
677
                        // FIXME: Use a most especific exception.
678
                        throw new RuntimeException(e);
679
                }
680
    }
681
682
    public Point convertToMapPoint(int x, int y) {
683
        Point2D pScreen = new Point2D.Double(x, y);
684
685
        return convertToMapPoint(pScreen);
686
    }
687
688
689 33613 fdiaz
    /**
690
     * <p>
691
     * Returns the real distance (in <i>world coordinates</i>) at the graphic
692
     * layers of two 2D points (in <i>map coordinates</i>) of the plane where is
693
     * selected the <i>extent</i>.
694
     * </p>
695
     * <p>
696
     * If the projection of this view is UTM, considers the Earth curvature.
697
     * </p>
698
     *
699
     * @param pt1
700
     *            a 2D point in <i>map coordinates</i>
701
     * @param pt2
702
     *            another 2D point in <i>map coordinates</i>
703
     *
704
     * @return the distance in meters between the two points 2D
705
     *
706
     * @see GeoCalcImpl#distanceVincenty(Point2D, Point2D)
707
     */
708
    public double distanceWorld(Point2D pt1, Point2D pt2) {
709
        double dist = -1;
710
        dist = pt1.distance(pt2);
711 21200 vcaballero
712 33613 fdiaz
        if ((proj != null) && !(proj instanceof UTM)) {
713
            dist =
714
                new GeoCalc(proj).distanceVincenty(proj.toGeo(pt1),
715
                    proj.toGeo(pt2));
716
            return dist;
717
        }
718
        return (dist * MapContext.getDistanceTrans2Meter()[getMapUnits()]);
719
    }
720 21200 vcaballero
721 33613 fdiaz
    /**
722
     * <p>
723
     * Sets as extent and adjusted extent of this view port, the previous.
724
     * Recalculating its parameters.
725
     * </p>
726
     *
727
     * @see #getExtents()
728
     * @see #calculateAffineTransform()
729
     * @deprecated use {@link ViewPort#setPreviousEnvelope()}
730
     */
731
    public void setPreviousExtent() {
732
        setPreviousEnvelope();
733
    }
734 21200 vcaballero
735 33613 fdiaz
    /**
736
     * <p>
737
     * Sets as envelope and adjusted envelope of this view port, the previous.
738
     * Recalculating its parameters.
739
     * </p>
740
     *
741
     * @see #getExtents()
742
     * @see #calculateAffineTransform()
743
     */
744
    public void setPreviousEnvelope() {
745
        this.updateDrawVersion();
746
        extent = extents.removePrev();
747 29519 jtorres
748 33613 fdiaz
        // Calcula la transformaci?n af?n
749
        calculateAffineTransform();
750 21200 vcaballero
751 33613 fdiaz
        // Lanzamos los eventos de extent cambiado
752
        callExtentChanged(getAdjustedExtent());
753
    }
754 21200 vcaballero
755 33613 fdiaz
    /**
756
     * <p>
757
     * Gets the area selected by user using some tool.
758
     * </p>
759
     *
760
     * <p>
761
     * When the zoom changes (for instance using the <i>zoom in</i> or <i>zoom
762
     * out</i> tools, but also zooming to a selected feature or shape) the
763
     * extent that covers that area is the value returned by this method. It is
764
     * not the actual area shown because it doesn't care about the aspect ratio
765
     * of the image size of the view. However, any part of the real world
766
     * contained in this extent is shown in the view.
767
     * </p>
768
     *
769
     * <p>
770
     * If you are looking for the complete extent currently shown, you must use
771
     * the {@linkplain #getAdjustedExtent()} method.
772
     * </p>
773
     *
774
     * @return the current extent
775
     *
776
     * @see #setEnvelope(Envelope)
777
     * @see #getAdjustedExtent()
778
     * @see #setPreviousExtent()
779
     * @see #getExtents()
780
     *
781
     * @deprecated use {@link ViewPort#getEnvelope()}
782
     */
783
    public Rectangle2D getExtent() {
784
        return extent;
785
    }
786 26905 jmvivo
787 33613 fdiaz
    /**
788
     * <p>
789
     * Gets the envelope selected by user using some tool.
790
     * </p>
791
     *
792
     * <p>
793
     * When the zoom changes (for instance using the <i>zoom in</i> or <i>zoom
794
     * out</i> tools, but also zooming to a selected feature or shape) the
795
     * envelope that covers that area is the value returned by this method. It
796
     * is not the actual envelope shown because it doesn't care about the aspect
797
     * ratio of the image size of the view. However, any part of the real world
798
     * contained in this envelope is shown in the view.
799
     * </p>
800
     *
801
     * <p>
802
     * If you are looking for the complete extent currently shown, you must use
803
     * the {@linkplain #getAdjustedEnvelope()} method.
804
     * </p>
805
     *
806
     * @return the current envelope
807
     *
808
     * @see #setEnvelope(Envelope)
809
     * @see #getAdjustedEnvelope()
810
     * @see #setPreviousEnvelope()
811
     * @see #getEnvelopes()
812
     */
813
    public Envelope getEnvelope() {
814
        if (this.extent == null) {
815
            return null;
816
        }
817
        try {
818
            return geomManager.createEnvelope(extent.getMinX(),
819
                extent.getMinY(),
820
                extent.getMaxX(),
821
                extent.getMaxY(),
822
                SUBTYPES.GEOM2D);
823
            // This class has to use Envelope instead of Rectangle2D. This catch
824
            // will disappear
825
        } catch (CreateEnvelopeException e) {
826
            logger.error("Error creating the envelope");
827
        }
828
        return null;
829
    }
830 21200 vcaballero
831 33613 fdiaz
    /**
832
     * <p>
833
     * Changes the <i>extent</i> and <i>adjusted extent</i> of this view port:<br>
834
     * <ul>
835
     * <li>Stores the previous extent.
836
     * <li>Calculates the new extent using <code>r</code>:
837
     *
838
     * <pre>
839
     * extent =
840
     *     new Rectangle2D.Double(r.getMinX() - 0.1,
841
     *         r.getMinY() - 0.1,
842
     *         r.getWidth() + 0.2,
843
     *         r.getHeight() + 0.2);
844
     * </pre>
845
     *
846
     * <li>Executes {@linkplain #calculateAffineTransform()}: getting the new
847
     * scale, adjusted extent, affine transformation between map and screen
848
     * coordinates, the real world coordinates equivalent to 1 pixel, and the
849
     * real world coordinates equivalent to 3 pixels.
850
     * <li>Notifies all {@link ViewPortListener ViewPortListener} registered
851
     * that the extent has changed.
852
     * </ul>
853
     * </p>
854
     *
855
     * @param r
856
     *            the new extent
857
     *
858
     * @see #getExtent()
859
     * @see #getExtents()
860
     * @see #calculateAffineTransform()
861
     * @see #setPreviousExtent()
862
     */
863
    public void setEnvelope(Envelope r) {
864
        Rectangle2D newExtent = null;
865
        // Esto comprueba que el extent no es de anchura o altura = "0"
866
        // y si es as? lo redimensiona.
867
        if (r != null) {
868
            if ((r.getMaximum(0) - r.getMinimum(0) == 0)
869
                || (r.getMaximum(1) - r.getMinimum(1) == 0)) {
870
                newExtent =
871
                    new Rectangle2D.Double(r.getMinimum(0) - 0.1,
872
                        r.getMinimum(1) - 0.1,
873
                        r.getMaximum(0) - r.getMinimum(0) + 0.2,
874
                        r.getMaximum(1) - r.getMinimum(1) + 0.2);
875
            } else {
876
                newExtent =
877
                    new Rectangle2D.Double(r.getMinimum(0),
878
                        r.getMinimum(1),
879
                        Math.abs(r.getMaximum(0) - r.getMinimum(0)),
880
                        Math.abs(r.getMaximum(1) - r.getMinimum(1)));
881
            }
882
        }
883 21200 vcaballero
884 33613 fdiaz
        if (this.extent != null && this.extent.equals(newExtent)) {
885
            return;
886
        }
887
        if (extent != null) {
888
            extents.put(extent);
889
        }
890
        this.updateDrawVersion();
891
        this.extent = newExtent;
892 21200 vcaballero
893 33613 fdiaz
        // Calcula la transformaci?n af?n
894
        calculateAffineTransform();
895 21200 vcaballero
896 33613 fdiaz
        // Lanzamos los eventos de extent cambiado
897
        callExtentChanged(getAdjustedExtent());
898
    }
899 21200 vcaballero
900 33613 fdiaz
    /**
901
     * <p>
902
     * Changes the <i>extent</i> and <i>adjusted extent</i> of this view port:<br>
903
     * <ul>
904
     * <li>Executes {@linkplain #calculateAffineTransform()}: getting the new
905
     * scale, adjusted extent, affine transformation between map and screen
906
     * coordinates, the real world coordinates equivalent to 1 pixel, and the
907
     * real world coordinates equivalent to 3 pixels.
908
     * <li>Notifies to all {@link ViewPortListener ViewPortListener} registered
909
     * that the extent has changed.
910
     * </ul>
911
     * </p>
912
     *
913
     * @see #setEnvelope(Envelope)
914
     * @see #calculateAffineTransform()
915
     */
916
    public void refreshExtent() {
917
        // this.scale = scale;
918 21200 vcaballero
919 33613 fdiaz
        // Calcula la transformaci?n af?n
920
        calculateAffineTransform();
921 21200 vcaballero
922 33613 fdiaz
        // Lanzamos los eventos de extent cambiado
923
        callExtentChanged(getAdjustedExtent());
924
    }
925 21200 vcaballero
926 33613 fdiaz
    /**
927
     * <p>
928
     * Calculates and returns using the current projection of this view port,
929
     * the scale that is the extent in <i>screen coordinates</i> from the image
930
     * in <i>map coordinates</i>.
931
     * </p>
932
     *
933
     * @return the scale <i>extent / image size</i> projected by this view port
934
     *
935
     * @deprecated since 07/09/07, use {@linkplain MapContext#getScaleView()}
936
     */
937
    public double getScale() {
938
        return proj.getScale(extent.getMinX(),
939
            extent.getMaxX(),
940
            imageSize.width,
941
            dpi);
942
    }
943 26225 jmvivo
944 33613 fdiaz
    /**
945
     * <p>
946
     * Affine transformation between <i>map 2D coordinates</i> to <i>screen 2D
947
     * coordinates</i> (pixels), preserving the "straightness" and "parallelism"
948
     * of the lines.
949
     * </p>
950
     *
951
     * @return the affine transformation
952
     *
953
     * @see #setAffineTransform(AffineTransform)
954
     * @see #calculateAffineTransform()
955
     */
956
    public AffineTransform getAffineTransform() {
957
        return trans;
958
    }
959 21200 vcaballero
960 33613 fdiaz
    /**
961
     * <p>
962
     * Returns the size of the image projected.
963
     * </p>
964
     *
965
     * @return the image size
966
     *
967
     * @see #setImageSize(Dimension)
968
     * @see #getImageHeight()
969
     * @see #getImageWidth()
970
     */
971
    public Dimension getImageSize() {
972
        return imageSize;
973
    }
974 21200 vcaballero
975 33613 fdiaz
    /**
976
     * <p>
977
     * Sets the size of the image projected, recalculating the parameters of
978
     * this view port.
979
     * </p>
980
     *
981
     * @param imageSize
982
     *            the image size
983
     *
984
     * @see #getImageSize()
985
     * @see #calculateAffineTransform()
986
     */
987
    public void setImageSize(Dimension imageSize) {
988 21200 vcaballero
989 33613 fdiaz
        if (this.imageSize == null || (!this.imageSize.equals(imageSize))) {
990
            this.updateDrawVersion();
991
            this.imageSize = imageSize;
992
            calculateAffineTransform();
993
        }
994
    }
995 21200 vcaballero
996 33613 fdiaz
    /**
997
     * <p>
998
     * Notifies to all view port listeners registered, that the adjusted extent
999
     * of this view port has changed.
1000
     * </p>
1001
     *
1002
     * @param newRect
1003
     *            the new adjusted extend
1004
     *
1005
     * @see #refreshExtent()
1006
     * @see #setEnvelope(Envelope)
1007
     * @see #setPreviousExtent()
1008
     * @see ExtentEvent
1009
     * @see ViewPortListener
1010
     */
1011
    protected void callExtentChanged(Envelope newRect) {
1012
        ExtentEvent ev = ExtentEvent.createExtentEvent(newRect);
1013 21200 vcaballero
1014 33613 fdiaz
        for (int i = 0; i < listeners.size(); i++) {
1015
            ViewPortListener listener = (ViewPortListener) listeners.get(i);
1016
            listener.extentChanged(ev);
1017
        }
1018
    }
1019 21200 vcaballero
1020 33613 fdiaz
    /**
1021
     * <p>
1022
     * Notifies to all view port listeners registered, that the background color
1023
     * of this view port has changed.
1024
     * </p>
1025
     *
1026
     * @param c
1027
     *            the new background color
1028
     *
1029
     * @see #setBackColor(Color)
1030
     * @see ColorEvent
1031
     * @see ViewPortListener
1032
     */
1033
    private void callColorChanged(Color c) {
1034
        ColorEvent ce = ColorEvent.createColorEvent(c);
1035 21200 vcaballero
1036 33613 fdiaz
        for (int i = 0; i < listeners.size(); i++) {
1037
            ViewPortListener listener = (ViewPortListener) listeners.get(i);
1038
            listener.backColorChanged(ce);
1039
        }
1040
    }
1041 21200 vcaballero
1042 33613 fdiaz
    /**
1043
     * <p>
1044
     * Notifies to all view port listeners registered, that the projection of
1045
     * this view port has changed.
1046
     * </p>
1047
     *
1048
     * @param projection
1049
     *            the new projection
1050
     *
1051
     * @see #setProjection(IProjection)
1052
     * @see ProjectionEvent
1053
     * @see ViewPortListener
1054
     */
1055
    private void callProjectionChanged(IProjection projection) {
1056
        ProjectionEvent ev = ProjectionEvent.createProjectionEvent(projection);
1057 21200 vcaballero
1058 33613 fdiaz
        for (int i = 0; i < listeners.size(); i++) {
1059
            ViewPortListener listener = (ViewPortListener) listeners.get(i);
1060
            listener.projectionChanged(ev);
1061
        }
1062
    }
1063 21200 vcaballero
1064 33613 fdiaz
    /**
1065
     * <p>
1066
     * Calculates the affine transformation between the {@link #extent extent}
1067
     * in <i>map 2D coordinates</i> to the image area in the screen, in
1068
     * <i>screen 2D coordinates</i> (pixels).
1069
     * </p>
1070
     *
1071
     * <p>
1072
     * This process recalculates some parameters of this view port:<br>
1073
     *
1074
     * <ul>
1075
     * <li>The new {@link #scale scale} .
1076
     * <li>The new {@link #adjustedExtent adjustedExtent} .
1077
     * <li>The new {@link #trans trans} .
1078
     * <li>The new real world coordinates equivalent to 1 pixel (
1079
     * {@link #dist1pixel dist1pixel}) .
1080
     * <li>The new real world coordinates equivalent to 3 pixels (
1081
     * {@link #dist3pixel dist3pixel}) .
1082
     * </ul>
1083
     * </p>
1084
     *
1085
     * @see #getAffineTransform()
1086
     * @see #setAffineTransform(AffineTransform)
1087
     * @see #refreshExtent()
1088
     * @see #setEnvelope(Envelope)
1089
     * @see #setImageSize(Dimension)
1090
     * @see #setPreviousExtent()
1091
     * @see #createFromXML(XMLEntity)
1092
     * @see AffineTransform
1093
     */
1094
    private void calculateAffineTransform() {
1095
        if ((imageSize == null) || (extent == null) || (imageSize.width <= 0)
1096
            || (imageSize.height <= 0)) {
1097
            return;
1098
        }
1099 21200 vcaballero
1100 33613 fdiaz
        AffineTransform escalado = new AffineTransform();
1101
        AffineTransform translacion = new AffineTransform();
1102 21200 vcaballero
1103 33613 fdiaz
        double escalaX;
1104
        double escalaY;
1105 21200 vcaballero
1106 33613 fdiaz
        escalaX = imageSize.width / extent.getWidth();
1107
        escalaY = imageSize.height / extent.getHeight();
1108 21200 vcaballero
1109 33613 fdiaz
        double xCenter = extent.getCenterX();
1110
        double yCenter = extent.getCenterY();
1111
        double newHeight;
1112
        double newWidth;
1113 21200 vcaballero
1114 33613 fdiaz
        adjustedExtent = new Rectangle2D.Double();
1115 21200 vcaballero
1116 33613 fdiaz
        if (adjustableExtent) {
1117
            if (escalaX < escalaY) {
1118
                scale = escalaX;
1119
                newHeight = imageSize.height / scale;
1120
                adjustedExtent.setRect(xCenter - (extent.getWidth() / 2.0),
1121
                    yCenter - (newHeight / 2.0),
1122
                    extent.getWidth(),
1123
                    newHeight);
1124
            } else {
1125
                scale = escalaY;
1126
                newWidth = imageSize.width / scale;
1127
                adjustedExtent.setRect(xCenter - (newWidth / 2.0), yCenter
1128
                    - (extent.getHeight() / 2.0), newWidth, extent.getHeight());
1129
            }
1130
            escalado.setToScale(scale, -scale);
1131
        } else { // adjusted is same as extent
1132
            scale = escalaX;
1133
            adjustedExtent.setFrame(extent);
1134
            escalado.setToScale(escalaX, -escalaY);
1135
        }
1136
        Envelope env = getAdjustedExtent();
1137
        if (env == null) {
1138
            return;
1139
        }
1140
        translacion.setToTranslation(-env.getMinimum(0), -env.getMinimum(1)
1141
            - getAdjustedExtent().getLength(1));
1142 21200 vcaballero
1143 33613 fdiaz
        AffineTransform offsetTrans = new AffineTransform();
1144
        offsetTrans.setToTranslation(offset.getX(), offset.getY());
1145 21200 vcaballero
1146 33613 fdiaz
        trans.setToIdentity();
1147
        trans.concatenate(offsetTrans);
1148
        trans.concatenate(escalado);
1149 21200 vcaballero
1150 33613 fdiaz
        trans.concatenate(translacion);
1151 21200 vcaballero
1152 33613 fdiaz
        // Calculamos las distancias de 1 pixel y 3 pixel con esa
1153
        // transformaci?n
1154
        // de coordenadas, de forma que est?n precalculadas para cuando las
1155
        // necesitemos
1156
        AffineTransform at;
1157 21200 vcaballero
1158 33613 fdiaz
        try {
1159
            at = trans.createInverse();
1160 21200 vcaballero
1161 33613 fdiaz
            Point2D pPixel = new Point2D.Float(1, 1);
1162 21200 vcaballero
1163 33613 fdiaz
            Point2D.Float pProv = new Point2D.Float();
1164
            at.deltaTransform(pPixel, pProv);
1165 21200 vcaballero
1166 33613 fdiaz
            dist1pixel = pProv.x;
1167
            dist3pixel = 3 * pProv.x;
1168
        } catch (NoninvertibleTransformException e) {
1169
            System.err.println("transformada afin = " + trans.toString());
1170
            System.err.println("extent = " + extent.toString() + " imageSize= "
1171
                + imageSize.toString());
1172
            throw new RuntimeException("Non invertible transform Exception", e);
1173
        }
1174
    }
1175 21200 vcaballero
1176 33613 fdiaz
    /**
1177
     * <p>
1178
     * Sets the offset.
1179
     * </p>
1180
     * <p>
1181
     * The offset is the position where start drawing the map.
1182
     * </p>
1183
     *
1184
     * @param p
1185
     *            2D point that represents the offset in pixels
1186
     *
1187
     * @see #getOffset()
1188
     */
1189
    public void setOffset(Point2D p) {
1190
        if (!offset.equals(p)) {
1191
            this.updateDrawVersion();
1192
            offset = p;
1193
        }
1194
    }
1195 29519 jtorres
1196 33613 fdiaz
    /**
1197
     * <p>
1198
     * Gets the offset.
1199
     * </p>
1200
     * <p>
1201
     * The offset is the position where start drawing the map.
1202
     * </p>
1203
     *
1204
     * @return 2D point that represents the offset in pixels
1205
     *
1206
     * @see #setOffset(Point2D)
1207
     */
1208
    public Point2D getOffset() {
1209
        return offset;
1210
    }
1211 21200 vcaballero
1212 33613 fdiaz
    /**
1213
     * <p>
1214
     * Sets the background color.
1215
     * </p>
1216
     *
1217
     * @param c
1218
     *            the new background color
1219
     *
1220
     * @see #getBackColor()
1221
     */
1222
    public void setBackColor(Color c) {
1223
        if (!c.equals(this.backColor)) {
1224
            this.updateDrawVersion();
1225
            backColor = c;
1226
            callColorChanged(backColor);
1227
        }
1228
    }
1229 29519 jtorres
1230 33613 fdiaz
    /**
1231
     * <p>
1232
     * Gets the background color.
1233
     * </p>
1234
     *
1235
     * @return the background color of the view
1236
     *
1237
     * @see #setBackColor(Color)
1238
     */
1239
    public Color getBackColor() {
1240
        return backColor;
1241
    }
1242 29519 jtorres
1243 33613 fdiaz
    /**
1244
     * <p>
1245
     * Returns the extent currently covered by the view adjusted (scaled) to the
1246
     * image size aspect.
1247
     * </p>
1248
     *
1249
     * @return extent of the view adjusted to the image size aspect
1250
     *
1251
     * @see #setAdjustable(boolean)
1252
     * @deprecated use {@link ViewPort#getAdjustedEnvelope()} instead
1253
     */
1254
    public Envelope getAdjustedExtent() {
1255
        return getAdjustedEnvelope();
1256
    }
1257 29519 jtorres
1258 33613 fdiaz
    /**
1259
     * <p>
1260
     * Returns the envelope currently covered by the view adjusted (scaled) to
1261
     * the image size aspect.
1262
     * </p>
1263
     *
1264
     * @return envelope of the view adjusted to the image size aspect
1265
     *
1266
     * @see #setAdjustable(boolean)
1267
     */
1268
    public Envelope getAdjustedEnvelope() {
1269
        if (cliprect != null) {
1270
            Rectangle2D r = adjustedExtent.createIntersection(cliprect);
1271
            try {
1272
                return geomManager.createEnvelope(r.getX(),
1273
                    r.getY(),
1274
                    r.getMaxX(),
1275
                    r.getMaxY(),
1276
                    SUBTYPES.GEOM2D);
1277
            } catch (CreateEnvelopeException e) {
1278
                e.printStackTrace();
1279
                logger.error("Error adjusting the extent", e);
1280
            }
1281
        }
1282
        if (adjustedExtent != null) {
1283
            try {
1284
                return geomManager.createEnvelope(adjustedExtent.getX(),
1285
                    adjustedExtent.getY(),
1286
                    adjustedExtent.getMaxX(),
1287
                    adjustedExtent.getMaxY(),
1288
                    SUBTYPES.GEOM2D);
1289
            } catch (CreateEnvelopeException e) {
1290
                e.printStackTrace();
1291
                logger.error("Error adjusting the extent", e);
1292
            }
1293
        }
1294
        return null;
1295
    }
1296 29519 jtorres
1297 33613 fdiaz
    /**
1298
     * <p>
1299
     * Returns the measurement unit of this view port used for measuring
1300
     * distances and displaying information.
1301
     * </p>
1302
     *
1303
     * @return the measurement unit of this view used for measuring distances
1304
     *         and displaying information
1305
     *
1306
     * @see #setDistanceUnits(int)
1307
     */
1308
    public int getDistanceUnits() {
1309
        return distanceUnits;
1310
    }
1311 21200 vcaballero
1312 33613 fdiaz
    /**
1313
     * <p>
1314
     * Returns the measurement unit of this view port used for measuring areas
1315
     * and displaying information.
1316
     * </p>
1317
     *
1318
     * @return the measurement unit of this view used for measuring areas and
1319
     *         displaying information
1320
     *
1321
     * @see #setDistanceUnits(int)
1322
     */
1323
    public int getDistanceArea() {
1324
        return distanceArea;
1325
    }
1326 21200 vcaballero
1327 33613 fdiaz
    /**
1328
     * <p>
1329
     * Sets the measurement unit of this view port used for measuring distances
1330
     * and displaying information.
1331
     * </p>
1332
     *
1333
     * @param distanceUnits
1334
     *            the measurement unit of this view used for measuring distances
1335
     *            and displaying information
1336
     *
1337
     * @see #getDistanceUnits()
1338
     */
1339
    public void setDistanceUnits(int distanceUnits) {
1340
        this.distanceUnits = distanceUnits;
1341
    }
1342 21200 vcaballero
1343 33613 fdiaz
    /**
1344
     * <p>
1345
     * Sets the measurement unit of this view port used for measuring areas and
1346
     * displaying information.
1347
     * </p>
1348
     *
1349
     * @param distanceUnits
1350
     *            the measurement unit of this view used for measuring areas and
1351
     *            displaying information
1352
     *
1353
     * @see #getDistanceUnits()
1354
     */
1355
    public void setDistanceArea(int distanceArea) {
1356
        this.distanceArea = distanceArea;
1357
    }
1358 21200 vcaballero
1359 33613 fdiaz
    /**
1360
     * <p>
1361
     * Gets the measurement unit used by this view port for the map.
1362
     * </p>
1363
     *
1364
     * @return Returns the current map measure unit
1365
     *
1366
     * @see #setMapUnits(int)
1367
     */
1368
    public int getMapUnits() {
1369
        return mapUnits;
1370
    }
1371 21200 vcaballero
1372 33613 fdiaz
    /**
1373
     * <p>
1374
     * Sets the measurement unit used by this view port for the map.
1375
     * </p>
1376
     *
1377
     * @param mapUnits
1378
     *            the new map measure unit
1379
     *
1380
     * @see #getMapUnits()
1381
     */
1382
    public void setMapUnits(int mapUnits) {
1383
        this.mapUnits = mapUnits;
1384
    }
1385 21200 vcaballero
1386 33613 fdiaz
    /**
1387
     * <p>
1388
     * Gets the width in <i>screen coordinates</i> of the rectangle where the
1389
     * image is displayed.
1390
     * </p>
1391
     * <p>
1392
     * Used by {@linkplain #calculateAffineTransform()} to calculate:<br>
1393
     *
1394
     * <ul>
1395
     * <li>The new {@link #scale scale} .
1396
     * <li>The new {@link #adjustedExtent adjustableExtent} .
1397
     * <li>The new {@link #trans trans} .
1398
     * <li>The new real world coordinates equivalent to 1 pixel (
1399
     * {@link #dist1pixel dist1pixel}) .
1400
     * <li>The new real world coordinates equivalent to 3 pixels (
1401
     * {@link #dist3pixel dist3pixel}) .
1402
     * </ul>
1403
     * </p>
1404
     *
1405
     * @see #getImageHeight()
1406
     * @see #getImageSize()
1407
     * @see #setImageSize(Dimension)
1408
     */
1409
    public int getImageWidth() {
1410
        return imageSize.width;
1411
    }
1412 21200 vcaballero
1413 33613 fdiaz
    /**
1414
     * <p>
1415
     * Gets the height in <i>screen coordinates</i> of the rectangle where the
1416
     * image is displayed.
1417
     * </p>
1418
     * <p>
1419
     * Used by {@linkplain #calculateAffineTransform()} to calculate:<br>
1420
     *
1421
     * <ul>
1422
     * <li>The new {@link #scale scale} .
1423
     * <li>The new {@link #adjustedExtent adjustableExtent} .
1424
     * <li>The new {@link #trans trans} .
1425
     * <li>The new real world coordinates equivalent to 1 pixel (
1426
     * {@link #dist1pixel dist1pixel}) .
1427
     * <li>The new real world coordinates equivalent to 3 pixels (
1428
     * {@link #dist3pixel dist3pixel}) .
1429
     * </ul>
1430
     * </p>
1431
     *
1432
     * @see #getImageWidth()
1433
     * @see #getImageSize()
1434
     * @see #setImageSize(Dimension)
1435
     */
1436
    public int getImageHeight() {
1437
        return imageSize.height;
1438
    }
1439 21200 vcaballero
1440 33613 fdiaz
    /**
1441
     * <p>
1442
     * Gets the distance in <i>world coordinates</i> equivalent to 1 pixel in
1443
     * the view with the current extent.
1444
     * </p>
1445
     *
1446
     * @return the distance
1447
     *
1448
     * @see #setDist1pixel(double)
1449
     */
1450
    public double getDist1pixel() {
1451
        return dist1pixel;
1452
    }
1453 29519 jtorres
1454 33613 fdiaz
    /**
1455
     * <p>
1456
     * Sets the distance in <i>world coordinates</i> equivalent to 1 pixel in
1457
     * the view with the current extent.
1458
     * </p>
1459
     *
1460
     * @param dist1pixel
1461
     *            the distance
1462
     *
1463
     * @see #getDist1pixel()
1464
     */
1465
    public void setDist1pixel(double dist1pixel) {
1466
        if (dist1pixel == this.dist1pixel) {
1467
            return;
1468
        }
1469
        this.updateDrawVersion();
1470
        this.dist1pixel = dist1pixel;
1471
    }
1472 21200 vcaballero
1473 33613 fdiaz
    /**
1474
     * <p>
1475
     * Gets the distance in <i>world coordinates</i> equivalent to 3 pixels in
1476
     * the view with the current extent.
1477
     * </p>
1478
     *
1479
     * @return the distance
1480
     *
1481
     * @see #setDist3pixel(double)
1482
     */
1483
    public double getDist3pixel() {
1484
        return dist3pixel;
1485
    }
1486 21200 vcaballero
1487 33613 fdiaz
    /**
1488
     * <p>
1489
     * Sets the distance in <i>world coordinates</i> equivalent to 3 pixels in
1490
     * the view with the current extent.
1491
     * </p>
1492
     *
1493
     * @param dist3pixel
1494
     *            the distance
1495
     *
1496
     * @see #getDist3pixel()
1497
     */
1498
    public void setDist3pixel(double dist3pixel) {
1499
        if (this.dist3pixel == dist3pixel) {
1500
            return;
1501
        }
1502
        this.updateDrawVersion();
1503
        this.dist3pixel = dist3pixel;
1504
    }
1505 21200 vcaballero
1506 33613 fdiaz
    /**
1507
     * <p>
1508
     * Returns the last previous extents of this view port.
1509
     * </p>
1510
     *
1511
     * @return the last previous extents of this view port
1512
     *
1513
     * @see #setPreviousExtent()
1514
     * @deprecated use {@link ViewPort#getEnvelopes()}
1515
     */
1516
    public ExtentHistory getExtents() {
1517
        return getEnvelopes();
1518
    }
1519 21200 vcaballero
1520 33613 fdiaz
    /**
1521
     * <p>
1522
     * Returns the last previous extents of this view port.
1523
     * </p>
1524
     *
1525
     * @return the last previous extents of this view port
1526
     *
1527
     * @see #setPreviousExtent()
1528
     */
1529
    public ExtentHistory getEnvelopes() {
1530
        return extents;
1531
    }
1532 21200 vcaballero
1533 33613 fdiaz
    /**
1534
     * <p>
1535
     * Gets the projection used in this view port.
1536
     * </p>
1537
     *
1538
     * @return projection used in this view port
1539
     *
1540
     * @see #setProjection(IProjection)
1541
     */
1542
    public IProjection getProjection() {
1543
        return proj;
1544
    }
1545 21200 vcaballero
1546 33613 fdiaz
    /**
1547
     * <p>
1548
     * Sets the projection to this view port.
1549
     * </p>
1550
     *
1551
     * @param proj
1552
     *            the new projection
1553
     *
1554
     * @see #getProjection()
1555
     */
1556
    public void setProjection(IProjection proj) {
1557
        if (this.proj == null || !this.proj.getAbrev().equals(proj.getAbrev())) {
1558
            this.updateDrawVersion();
1559
            this.proj = proj;
1560
            callProjectionChanged(proj);
1561
        }
1562
    }
1563 21200 vcaballero
1564 33613 fdiaz
    // -----------------------------------------------------------------------------------------------------------
1565
    // NOTA PARA DESARROLLADORES SOBRE EL M?TODO
1566
    // "public void setAffineTransform(AffineTransform at)"
1567
    // ==============================================================================================
1568
    // Only used for print, should be removed, redefining the {@link
1569
    // RasterAdapter RasterAdapter} interface,
1570
    // allowing it to receive a {@link ViewPortData ViewPortData} .
1571
    // -----------------------------------------------------------------------------------------------------------
1572 21200 vcaballero
1573 33613 fdiaz
    /**
1574
     * <p>
1575
     * Sets only the affine transform to this view port, without updating
1576
     * dependent attributes.
1577
     * </p>
1578
     * <p>
1579
     * <b><i>This method could be problematic!</i></b>
1580
     * </p>
1581
     *
1582
     * @param at
1583
     *            the affine transform to set
1584
     *
1585
     * @see #getAffineTransform()
1586
     * @see #calculateAffineTransform()
1587
     */
1588
    public void setAffineTransform(AffineTransform at) {
1589
        this.trans = at;
1590
    }
1591 31681 jldominguez
1592 33613 fdiaz
    /**
1593
     * <p>
1594
     * Returns an XML entity that represents this view port instance:<br>
1595
     * <ul>
1596
     * <li>Properties:
1597
     * <ul>
1598
     * <li><i>className</i>: name of this class.
1599
     * <li>If defined, the adjusted extent:
1600
     * <ul>
1601
     * <li><i>adjustedExtentX</i>: X coordinate of the adjusted extent.
1602
     * <li><i>adjustedExtentY</i>: Y coordinate of the adjusted extent.
1603
     * <li><i>adjustedExtentW</i>: width of the adjusted extent.
1604
     * <li><i>adjustedExtentH</i>: height of the adjusted extent.
1605
     * </ul>
1606
     * <li>If defined, the background color:
1607
     * <ul>
1608
     * <li><i>backColor</i>: background color.
1609
     * </ul>
1610
     * <li>If defined, the clip:
1611
     * <ul>
1612
     * <li><i>clipX</i>: X coordinate of the clip.
1613
     * <li><i>clipY</i>: Y coordinate of clip.
1614
     * <li><i>clipW</i>: width of the clip.
1615
     * <li><i>clipH</i>: height of the clip.
1616
     * </ul>
1617
     * <li><i>dist1pixel</i>: the distance in world coordinates equivalent to 1
1618
     * pixel in the view.
1619
     * <li><i>dist3pixel</i>: the distance in world coordinates equivalent to 3
1620
     * pixels in the view.
1621
     * <li><i>distanceUnits</i>: the distance measurement unit.
1622
     * <li>If defined, the extent:
1623
     * <ul>
1624
     * <li><i>extentX</i>: X coordinate of the extent.
1625
     * <li><i>extentY</i>: Y coordinate of the extent.
1626
     * <li><i>extentW</i>: width of the extent.
1627
     * <li><i>extentH</i>: height of the extent.
1628
     * </ul>
1629
     * <li><i>mapUnits</i>: the map measurement unit.
1630
     * <li><i>offsetX</i>: X coordinate of the offset.
1631
     * <li><i>offsetY</i>: Y coordinate of the offset.
1632
     * <li>If defined, the projection:
1633
     * <ul>
1634
     * <li>If its defined, the projection:
1635
     * <ul>
1636
     * <li><i>proj</i>: the projection.</li>
1637
     * </ul>
1638
     * </ul>
1639
     * <li><i>scale</i>: ratio between the size of <code>imageSize</code> and
1640
     * <code>extent</code>.
1641
     * </ul>
1642
     * <li>Child branches:
1643
     * <ul>
1644
     * <li>XML entity of the internal {@link ExtentHistory ExtentHistory} .
1645
     * </ul>
1646
     * </ul>
1647
     *
1648
     * @return the XML entity
1649
     *
1650
     * @see #createFromXML(XMLEntity)
1651
     */
1652
    public void saveToState(PersistentState state) throws PersistenceException {
1653 31681 jldominguez
1654 33613 fdiaz
        state.set(FIELD_ADJUSTED_EXTENT, adjustedExtent);
1655
        state.set(FIELD_BACK_COLOR, backColor);
1656
        state.set(FIELD_CLIP, cliprect);
1657
        state.set(FIELD_DIST1PIXEL, dist1pixel);
1658
        state.set(FIELD_DIST3PIXEL, dist3pixel);
1659
        state.set(FIELD_DISTANCE_UNITS, distanceUnits);
1660
        state.set(FIELD_DISTANCE_AREA, distanceArea);
1661
1662
        state.set(FIELD_EXTENT, extent);
1663
        state.set(FIELD_EXTENTS, extents);
1664
1665
        state.set(FIELD_MAP_UNITS, mapUnits);
1666
        state.set(FIELD_OFFSET, offset);
1667
1668
        state.set(FIELD_PROJ, proj);
1669
1670
        state.set(FIELD_IMAGE_SIZE, imageSize);
1671
    }
1672
1673
    public void loadFromState(PersistentState state) throws PersistenceException {
1674
1675
        adjustedExtent = (Rectangle2D) state.get(FIELD_ADJUSTED_EXTENT);
1676
        backColor = (Color) state.get(FIELD_BACK_COLOR);
1677
        cliprect = (Rectangle2D) state.get(FIELD_CLIP);
1678
        dist1pixel = state.getDouble(FIELD_DIST1PIXEL);
1679
        dist3pixel = state.getDouble(FIELD_DIST3PIXEL);
1680
        distanceUnits = state.getInt(FIELD_DISTANCE_UNITS);
1681
        extents = (ExtentHistory) state.get(FIELD_EXTENTS);
1682
        extent = (Rectangle2D) state.get(FIELD_EXTENT);
1683
        mapUnits = state.getInt(FIELD_MAP_UNITS);
1684
        offset = (Point2D) state.get(FIELD_OFFSET);
1685
        proj = (IProjection) state.get(FIELD_PROJ);
1686
        imageSize = (Dimension) state.get(FIELD_IMAGE_SIZE);
1687
        distanceArea = state.getInt(FIELD_DISTANCE_AREA);
1688
1689
        refreshExtent();
1690
    }
1691
1692 33652 jjdelcerro
        public static class RegisterPersistence implements Callable {
1693
1694
                public Object call() throws Exception {
1695
                        PersistenceManager manager = ToolsLocator.getPersistenceManager();
1696
                        if( manager.getDefinition("ViewPort")==null ) {
1697
                        DynStruct definition =
1698
                            manager.addDefinition(ViewPort.class,
1699
                                "ViewPort",
1700
                                "ViewPort Persistence definition",
1701
                                null,
1702
                                null);
1703
1704
                        definition.addDynFieldObject(FIELD_ADJUSTED_EXTENT)
1705
                            .setClassOfValue(Rectangle2D.class)
1706
                            .setMandatory(false);
1707
1708
                        definition.addDynFieldObject(FIELD_BACK_COLOR)
1709
                            .setClassOfValue(Color.class)
1710
                            .setMandatory(false);
1711
1712
                        definition.addDynFieldObject(FIELD_CLIP)
1713
                            .setClassOfValue(Rectangle2D.class)
1714
                            .setMandatory(false);
1715
1716
                        definition.addDynFieldDouble(FIELD_DIST1PIXEL).setMandatory(true);
1717
1718
                        definition.addDynFieldDouble(FIELD_DIST3PIXEL).setMandatory(true);
1719
1720
                        definition.addDynFieldInt(FIELD_DISTANCE_UNITS).setMandatory(true);
1721
1722
                        definition.addDynFieldInt(FIELD_DISTANCE_AREA).setMandatory(false);
1723
1724
                        definition.addDynFieldObject(FIELD_EXTENT)
1725
                            .setClassOfValue(Rectangle2D.class)
1726
                            .setMandatory(false);
1727
1728
                        definition.addDynFieldObject(FIELD_EXTENTS)
1729
                            .setClassOfValue(ExtentHistory.class)
1730
                            .setMandatory(true);
1731
1732
                        definition.addDynFieldInt(FIELD_MAP_UNITS).setMandatory(true);
1733
1734
                        definition.addDynFieldObject(FIELD_OFFSET)
1735
                            .setClassOfValue(Point2D.class)
1736
                            .setMandatory(false);
1737
1738
                        definition.addDynFieldObject(FIELD_PROJ)
1739
                            .setClassOfValue(IProjection.class)
1740
                            .setMandatory(true);
1741
1742
                        definition.addDynFieldObject(FIELD_IMAGE_SIZE)
1743
                            .setClassOfValue(Dimension.class)
1744
                            .setMandatory(false);
1745
                        }
1746
                        return Boolean.TRUE;
1747
                }
1748
1749
        }
1750
1751
        /**
1752 33613 fdiaz
     * Clone the view port without clone the listeners nor the extent history.
1753
     *
1754
     * @return the cloned view port
1755
     */
1756
    public Object clone() throws CloneNotSupportedException {
1757
1758
        ViewPort clonedViewPort = (ViewPort) super.clone();
1759
        clonedViewPort.listeners = new ArrayList();
1760
        clonedViewPort.extents = new ExtentHistory();
1761
1762
        if (this.adjustedExtent!=null){
1763
            clonedViewPort.adjustedExtent =
1764
                (Rectangle2D) this.adjustedExtent.clone();
1765
        }
1766
1767
        if (this.cliprect!=null){
1768
            clonedViewPort.cliprect = (Rectangle2D) this.cliprect.clone();
1769
        }
1770 31681 jldominguez
1771 33613 fdiaz
        if (this.extent!=null) {
1772
            clonedViewPort.extent = (Rectangle2D) this.extent.clone();
1773
        }
1774
        if (this.imageSize!=null){
1775
            clonedViewPort.imageSize = (Dimension) this.imageSize.clone();
1776
        }
1777 31681 jldominguez
1778 33613 fdiaz
        if (this.offset!=null){
1779
            clonedViewPort.offset = (Point2D) this.offset.clone();
1780
        }
1781
        if (proj!=null){
1782
            clonedViewPort.proj = (IProjection) this.proj.clone();
1783
        }
1784 31681 jldominguez
1785 33613 fdiaz
        clonedViewPort.trans = (AffineTransform) this.trans.clone();
1786 31681 jldominguez
1787 33613 fdiaz
        return clonedViewPort;
1788
    }
1789 30173 jldominguez
1790 33613 fdiaz
    /**
1791
     * <p>
1792
     * Returns a <code>String</code> representation of the main values of this
1793
     * view port: <code>{@linkplain #extent}</code>,
1794
     * <code>{@linkplain #adjustedExtent}</code>,
1795
     * <code>{@linkplain #imageSize}</code>, <code>{@linkplain #scale}</code>,
1796
     * and <code>{@linkplain #trans}</code>.
1797
     * </p>
1798
     *
1799
     * @return a <code>string</code> representation of the main values of this
1800
     *         view port
1801
     */
1802
    public String toString() {
1803 21200 vcaballero
1804 33613 fdiaz
        String str;
1805
        str =
1806
            "Datos del viewPort:\nExtent=" + extent + "\nadjustedExtent="
1807
                + adjustedExtent + "\nimageSize=" + imageSize + "\nescale="
1808
                + scale + "\ntrans=" + trans;
1809 21200 vcaballero
1810 33613 fdiaz
        return str;
1811
    }
1812 21200 vcaballero
1813 33613 fdiaz
    /**
1814
     * <p>
1815
     * Sets the position and size of the clipping rectangle.
1816
     * </p>
1817
     *
1818
     * @param rectView
1819
     *            the clipping rectangle to set
1820
     */
1821
    public void setClipRect(Rectangle2D rectView) {
1822
        this.updateDrawVersion();
1823
        cliprect = rectView;
1824
    }
1825 21200 vcaballero
1826 33613 fdiaz
    /**
1827
     * <p>
1828
     * Converts and returns the {@link Rectangle2D Rectangle2D}, that is in
1829
     * <i>map coordinates</i> to <i>screen coordinates</i> (pixels) using an
1830
     * <i>inverse transform</i> with the transformation affine information in
1831
     * the {@link #trans #trans} attribute.
1832
     * </p>
1833
     *
1834
     * @param r
1835
     *            the 2D rectangle in <i>map coordinates</i>
1836
     * @return 2D rectangle equivalent in <i>screen coordinates</i> (pixels)
1837
     *
1838
     * @see #toMapRectangle(Rectangle2D)
1839
     * @see #fromMapDistance(double)
1840
     * @see #fromMapPoint(Point2D)
1841
     */
1842
    public Rectangle2D fromMapRectangle(Rectangle2D r) {
1843
        Rectangle2D rect = new Rectangle2D.Double();
1844
        Point2D p1 = fromMapPoint((int) r.getX(), (int) r.getY());
1845
        Point2D p2 = fromMapPoint((int) r.getMaxX(), (int) r.getMaxY());
1846
        rect.setFrameFromDiagonal(p1, p2);
1847
        return rect;
1848
    }
1849 21200 vcaballero
1850 33613 fdiaz
    /**
1851
     * <p>
1852
     * Recalculates the current <code>{@linkplain #extent}</code> using an
1853
     * scale. It's necessary execute {@linkplain #refreshExtent()} after.
1854
     * </p>
1855
     *
1856
     * @param s
1857
     *            the scale to set
1858
     *
1859
     * @deprecated since 07/09/07, use
1860
     *             {@linkplain MapContext#setScaleView(long)}
1861
     */
1862
    public void setScale(long s) {
1863
        double x = extent.getX();
1864
        double y = extent.getY();
1865
        double escalaX = imageSize.width / extent.getWidth();
1866
        // double w = imageSize.width / s;
1867
        // double h = imageSize.height / s;
1868
        double difw = escalaX / s;
1869 26905 jmvivo
1870 33613 fdiaz
        double x1 = (-x * difw) - x + extent.getWidth() / 2;
1871
        double y1 = (-y * difw) - y + extent.getHeight() / 2;
1872
        double w1 = extent.getWidth() * difw;
1873
        double h1 = extent.getHeight() * difw;
1874
        extent.setRect(-x1, -y1, w1, h1);
1875
    }
1876 21200 vcaballero
1877 33613 fdiaz
    public long getDrawVersion() {
1878
        return this.drawVersion;
1879
    }
1880 21200 vcaballero
1881 33613 fdiaz
    protected void updateDrawVersion() {
1882
        this.drawVersion++;
1883
    }
1884 29519 jtorres
1885 33652 jjdelcerro
//    /**
1886
//     * Obtiene la representaci?n de un color como String
1887
//     *
1888
//     * @param c
1889
//     *            Color
1890
//     *
1891
//     * @return String
1892
//     */
1893
//    public static String color2String(Color c) {
1894
//        if (c == null)
1895
//            return null;
1896
//        return c.getRed() + "," + c.getGreen() + "," + c.getBlue() + ","
1897
//            + c.getAlpha();
1898
//    }
1899
//
1900
//    /**
1901
//     * Obtiene el color de un string generado con color2String
1902
//     *
1903
//     * @param stringColor
1904
//     *            string
1905
//     *
1906
//     * @return Color
1907
//     */
1908
//    public static Color string2Color(String stringColor) {
1909
//        if (stringColor == null || stringColor.equals("null"))
1910
//            return null;
1911
//        String[] ints = new String[4];
1912
//
1913
//        ints = CompatLocator.getStringUtils().split(stringColor, ",");
1914
//
1915
//        int[] ret = new int[4];
1916
//
1917
//        for (int i = 0; i < ret.length; i++) {
1918
//            ret[i] = new Integer(ints[i]).intValue();
1919
//        }
1920
//
1921
//        return new Color(ret[0], ret[1], ret[2], ret[3]);
1922
//    }
1923 29519 jtorres
1924 21200 vcaballero
}