Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extRasterTools-SE / src / org / gvsig / rastertools / georeferencing / ui / zoom / CanvasZone.java @ 18277

History | View | Annotate | Download (14.4 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2007 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
package org.gvsig.rastertools.georeferencing.ui.zoom;
20

    
21
import java.awt.Color;
22
import java.awt.Graphics;
23
import java.awt.Graphics2D;
24
import java.awt.event.MouseEvent;
25
import java.awt.event.MouseListener;
26
import java.awt.event.MouseMotionListener;
27
import java.awt.geom.Point2D;
28
import java.awt.geom.Rectangle2D;
29
import java.awt.image.BufferedImage;
30
import java.util.ArrayList;
31

    
32
import javax.swing.JPanel;
33

    
34
import org.gvsig.raster.util.MathUtils;
35
import org.gvsig.rastertools.georeferencing.ui.zoom.tools.BaseViewTool;
36

    
37
/**
38
 * Zona de dibujado del raster
39
 * 21/12/2007
40
 * @author Nacho Brodin nachobrodin@gmail.com
41
 */
42
public class CanvasZone extends JPanel implements MouseListener, MouseMotionListener {
43
        private static final long      serialVersionUID = 1308683333757367640L;
44
        
45
        private BufferedImage          image = null;
46
        private double                 scale = 1;
47
        private Rectangle2D            extent = null;
48
        private double                 pixelSize = 1;
49
        private Point2D                center = null;
50
        private ArrayList              graphicLayers = new ArrayList();
51
        /**
52
         * ?ltimo extent aplicado. Si no ha variado el siguiente a aplicar no hace falta que releamos de nuevo
53
         */
54
        private Rectangle2D            lastExtent = null;
55
        //Ultimo Image con la capa dibujada y con la transformaci?n que tiene en cuenta los desplazamientos dentro de un pixel
56
        //Este buffer no varia hasta que se hace la siguiente petici?n de setDrawParams
57
        private BufferedImage          lastImage = null;
58
        //lastImage sobre el que se pintan las capas gr?ficas. Este buffer varia en cada repaint. El orden en el que se carga
59
        //es: se vuelva el lastImage, se pintan las capas gr?ficas, se pintan las tools.
60
        private BufferedImage          lastImageWithLayers = null;
61
    
62
    private boolean                clear = false;
63
    private Color                  background = Color.WHITE;
64
    private BaseViewTool           selectedTool = null;
65
    
66
    private Point2D                realCoord = new Point2D.Double(0, 0);
67
    private Point2D                viewCoord = new Point2D.Double(0, 0);
68
    private boolean                showInfo = false;
69
                    
70
    /**
71
         * Asigna los par?metros de dibujado
72
         * @param img Buffer con un ?rea de datos
73
         * @param ext Rectangle2D del ?rea de datos dada 
74
         * @param pixelSize Tama?o de pixel
75
         * @param center Punto del ?rea de datos donde se quiere centrar el dibujado del buffer
76
         */
77
        public void setDrawParams(BufferedImage img, Rectangle2D ext, double pixelSize, Point2D center) {
78
                this.image = img;
79
                this.extent = ext;
80
                this.pixelSize = pixelSize;
81
                this.center = center;
82
                this.addMouseListener(this);
83
                this.addMouseMotionListener(this);
84
                repaint();
85
        }
86
        
87
        /**
88
         * Asigna un nuevo centro de visualizaci?n
89
         * @param center
90
         */
91
        public void setCenter(Point2D center) {
92
                this.center = center;
93
                repaint();
94
        }
95
        
96
        /**
97
         * Conversi?n de un punto en coordenadas del canvas a reales
98
         * @param p
99
         * @return
100
         */
101
        public Point2D viewCoordsToWorld(Point2D p) {
102
                int w = getVisibleRect().width;
103
                int h = getVisibleRect().height;
104
                Rectangle2D ex = lastExtent;
105
                if(lastExtent == null) 
106
                        ex = extent;
107
                double cx = ex.getX() + ((p.getX() * ex.getWidth()) / w);
108
                double cy = ex.getY() - (p.getY() * ex.getHeight()) / h;
109
                return new Point2D.Double(cx, cy);
110
        }
111
        
112
        /**
113
         * Conversi?n de un punto en coordenadas del canvas a reales
114
         * @param p
115
         * @return
116
         */
117
        public Point2D viewCoordsFromWorld(Point2D p) {
118
                int w = getVisibleRect().width;
119
                int h = getVisibleRect().height;
120
                Rectangle2D ex = lastExtent;
121
                if(lastExtent == null) 
122
                        ex = extent;
123
                double cx = ((p.getX() - ex.getMinX()) * w) / ex.getWidth();
124
                double cy = ((Math.abs(p.getY() - ex.getMinY()) * h) / ex.getHeight());
125
                return new Point2D.Double(cx, cy);
126
        }
127
        
128
        /**
129
         * Asigna un nuevo centro de visualizaci?n en coordenadas del
130
         * componente.
131
         * @param center
132
         */
133
        public void setViewCenter(Point2D c) {
134
                int w = getVisibleRect().width;
135
                int h = getVisibleRect().height;
136
                
137
                double cx = (c.getX() * lastExtent.getWidth()) / w;
138
                double cy = (c.getY() * lastExtent.getHeight()) / h;
139
                setPixelCenter(new Point2D.Double(cx, cy));
140
        }
141
        
142
        /**
143
         * Asigna un nuevo centro de visualizaci?n en coordenadas pixel
144
         * del ?rea de dibujado (canvas). El nuevo centro ser? calculado en coordenadas
145
         * del mapa.
146
         * @param center
147
         */
148
        public void setPixelCenter(Point2D c) {
149
                int w = getVisibleRect().width;
150
                int h = getVisibleRect().height;
151
                
152
                //Calculamos el extent del canvas 
153
                Rectangle2D ext = getCanvasExtent(w, h, scale);
154
                
155
                //Calculamos el nuevo centro en coordenadas reales
156
                double wWC = (c.getX() / scale) * pixelSize;
157
                double hWC = (c.getY() / scale) * pixelSize;
158
                this.center = new Point2D.Double(ext.getMinX() + wWC,
159
                                                                                 ext.getMinY() - hWC);
160
                repaint();
161
        }
162
        
163
        /**
164
         * Asigna un nuevo centro de visualizaci?n en coordenadas pixel. Esta llamada tiene
165
         * en cuenta solo p?xeles completos. No centra sobre porciones de pixel cuando el zoom es
166
         * mayor de 1:1. El nuevo centro es en coordenadas del mapa pero siempre centrar?
167
         * en la esquina inferior izquierda del pixel.
168
         * @param center
169
         */
170
        public void setPixelCenter(int x, int y) {
171
                int w = getVisibleRect().width;
172
                int h = getVisibleRect().height;
173
                
174
                //Calculamos el extent del canvas 
175
                Rectangle2D ext = getCanvasExtent(w, h, scale);
176
                
177
                //Calculamos el nuevo centro en coordenadas reales
178
                double wWC = (x / scale) * pixelSize;
179
                double hWC = (y / scale) * pixelSize;
180
                Point2D center = new Point2D.Double(ext.getMinX() + wWC,
181
                                                                                          ext.getMinY() - hWC);
182
                
183
                //Calculamos la coordena pixel a la que pertenece esa coordenada real
184
                int pxX = (int)((center.getX() * (w / scale)) / ext.getWidth());
185
                int pxY = (int)((center.getY() * (h / scale)) / ext.getHeight());
186
                
187
                //Despu?s de haber convertido a pixel y redondeado la coordenada a entero volvemos a convertirla en real
188
                double wcX = (pxX * ext.getWidth()) / (w / scale);
189
                double wcY = (pxY * ext.getHeight()) / (h / scale);
190

    
191
                this.center = new Point2D.Double(wcX, wcY);
192
                repaint();
193
        }
194
        
195
        /**
196
         * Asigna una capa gr?fica
197
         * @param layer IGraphicLayer
198
         */
199
        public void setGraphicLayer(IGraphicLayer layer) {
200
                graphicLayers.add(layer);
201
        }
202
        
203
        /**
204
         * Asigna la escala para el nuevo zoom
205
         * @param scale
206
         */
207
        public void setZoom(double scale) {
208
                this.scale = scale;
209
                repaint();
210
        }
211
        
212
        /**
213
         * Obtiene la escala aplicada en el dibujado
214
         * @return double
215
         */
216
        public double getZoom() {
217
                return scale;
218
        }
219
        
220
        /**
221
         * Obtiene el extent actual asignado al canvas
222
         * @return Rectangle2D
223
         */
224
        public Rectangle2D getCanvasExtent() {
225
                return lastExtent;
226
        }
227
        
228
        /**
229
         * Asigna el extent del canvas
230
         * @param r
231
         */
232
        public void setCanvasExtent(Rectangle2D r) {
233
                this.lastExtent = r;
234
        }
235
        
236
        /**
237
         * Obtiene el tama?o de pixel
238
         * @return double
239
         */
240
        public double getPixelSize() {
241
                return pixelSize;
242
        }
243
        
244
        /**
245
         * Obtiene el centro del canvas
246
         * @return Point2D
247
         */
248
        public Point2D getCenter() {
249
                return center;
250
        }
251
        
252
        /**
253
         * Obtiene el buffer de la vista activa y lo dibuja sobre el panel
254
         * con los datos de escala y desplazamiento seleccionados.
255
         */
256
        protected void paintComponent(Graphics g) {
257
                if(image == null)
258
                        return;
259
                                
260
                int w = getVisibleRect().width;
261
                int h = getVisibleRect().height;
262
                Rectangle2D ext = getCanvasExtent(w, h, scale);
263
                
264
                if(lastImage == null || !equal(lastExtent, ext)) { 
265
                        lastImage = new BufferedImage((int)w, (int)h, BufferedImage.TYPE_INT_RGB);
266
                        lastImageWithLayers = new BufferedImage((int)w, (int)h, BufferedImage.TYPE_INT_RGB);
267
                }
268
                                
269
                if(clear) {
270
                        g.setColor(Color.WHITE);
271
                        g.fillRect(0, 0, w, h);
272
                        return;
273
                }
274
                
275
                //Dibujamos el buffer sobre el grafics
276
                Graphics graphicsDB = draw(ext, w, h);        
277
                                
278
                //Dibujamos todas las capas registradas
279
                for (int i = 0; i < graphicLayers.size(); i++) 
280
                        ((IGraphicLayer)graphicLayers.get(i)).draw((Graphics2D)graphicsDB, ext, w, h);
281
                
282
                lastExtent = ext;
283
                
284
                if(selectedTool != null)
285
                        selectedTool.draw(graphicsDB);
286
                        
287
                if(showInfo)
288
                        showInfo(graphicsDB);
289
                                
290
                g.drawImage(lastImageWithLayers, 0, 0, this);
291
                graphicsDB.dispose();
292
        }
293
        
294
        /**
295
         * Muestra informaci?n sobre la vista
296
         * @param g
297
         */
298
        private void showInfo(Graphics g) {
299
                g.setColor(Color.RED);
300
                g.drawString("X: " + MathUtils.tailDecimals(viewCoord.getX(), 3), 12, 12);
301
                g.drawString("Y: " + MathUtils.tailDecimals(viewCoord.getY(), 3), 12, 26);
302
                g.drawString("X': " + MathUtils.tailDecimals(realCoord.getX(), 3), 12, 40);
303
                g.drawString("Y': " + MathUtils.tailDecimals(realCoord.getY(), 3), 12, 54);
304
        }
305
        
306
        /**
307
         * Compara dos extents y devuelve true si son iguales y false si son distintos
308
         * @param e1 Extent 1
309
         * @param e2 Extent 2
310
         * @return true si son iguales y false si son diferentes
311
         */
312
        private boolean equal(Rectangle2D e1, Rectangle2D e2) {
313
                return (e1 != null && e2 != null && e1.getMinX() == e2.getMinX() && e1.getMinY() == e2.getMinY() 
314
                                && e1.getMaxX() == e2.getMaxX() && e1.getMaxY() == e2.getMaxY());
315
        }
316
        
317
        /**
318
         * Obtiene el Extent del canvas. Este canvas tiene un ancho en pixeles
319
         * de w y un alto de h. Tiene en cuenta la escala a la que se quiere dibujar
320
         * para devolver el extent cuando el zoom ya est? aplicado.
321
         * @param w Ancho del canvas en p?xeles
322
         * @param h Alto del canvas en p?xeles
323
         * @return Rectangle2D
324
         */
325
        private Rectangle2D getCanvasExtent(double w, double h, double scale) {
326
                double tW = ((w / scale) / 2) * pixelSize;
327
                double tH = ((h / scale) / 2) * pixelSize;
328
                double minX = center.getX() - tW;
329
                double maxY = center.getY() + tH;
330
                double width = Math.abs((center.getX() + tW) - minX);
331
                double height = Math.abs(maxY - (center.getY() - tH));
332
                return new Rectangle2D.Double(minX, maxY, width, height);
333
        }
334
        
335
        /**
336
         * <P>
337
         * Dibujado del buffer de datos sobre el Graphics. 
338
         * </P><P>
339
         * No podemos aplicar un escalado al
340
         * Graphics y dibujar porque cuando el zoom es mayor a 1 los pixeles no empiezan a dibujarse
341
         * siempre en la esquina superior izquierda y al Graphics solo podemos ordenarle el dibujado
342
         * en coordenadas enteras. Para solucionarlo debemos copiar el trozo de buffer a dibujar teniendo
343
         * en cuenta el desplazamiento de la esquina superior izquierda de un pixel.
344
         * </P> 
345
         * @param g
346
         * @param ext
347
         * @param w
348
         * @param h
349
         */
350
        private Graphics draw(Rectangle2D ext, double w, double h) {
351
                if(!equal(lastExtent, ext)) {
352
                        //Hallamos la coordenada pixel del buffer de la esquina superior izquierda del extent
353
                        double pxX = ((ext.getMinX() - extent.getMinX()) * (w / scale)) / ext.getWidth();
354
                        double pxY = ((extent.getMaxY() - ext.getMinY()) * (h / scale)) / ext.getHeight();
355

    
356
                        //Creamos el buffer y lo cargamos teniendo en cuenta el desplazamiento inicial
357
                        double step = 1 / scale;
358

    
359
                        double xValue = pxX;
360
                        double yValue = pxY;
361

    
362
                        for (int i = 0; i < w; i++) {
363
                                yValue = pxY;
364
                                for (int j = 0; j < h; j++) {
365
                                        if((int)xValue >= 0 && (int)yValue >= 0 && (int)xValue < image.getWidth() && (int)yValue < image.getHeight()) {
366
                                                lastImage.setRGB(i, j, image.getRGB((int)xValue, (int)yValue));
367
                                                lastImageWithLayers.setRGB(i, j, image.getRGB((int)xValue, (int)yValue));
368
                                        } else {
369
                                                lastImage.setRGB(i, j, 0xffffffff);
370
                                                lastImageWithLayers.setRGB(i, j, 0xffffffff);
371
                                        }
372
                                        yValue += step;
373
                                }
374
                                xValue += step;
375
                        }
376
                } else 
377
                        ((Graphics2D)lastImageWithLayers.getGraphics()).drawImage(lastImage, 0, 0, null);
378
                
379
                return lastImageWithLayers.getGraphics();
380
        }
381

    
382
        /*
383
         * (non-Javadoc)
384
         * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
385
         */
386
        public void mouseClicked(MouseEvent e) {
387
                for (int i = 0; i < graphicLayers.size(); i++) 
388
                        ((IGraphicLayer)graphicLayers.get(i)).mouseClicked(e);
389
                repaint();
390
        }
391

    
392
        /*
393
         * (non-Javadoc)
394
         * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
395
         */
396
        public void mouseEntered(MouseEvent e) {
397
                for (int i = 0; i < graphicLayers.size(); i++) 
398
                        ((IGraphicLayer)graphicLayers.get(i)).mouseEntered(e);
399
                repaint();
400
        }
401

    
402
        /*
403
         * (non-Javadoc)
404
         * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
405
         */
406
        public void mouseExited(MouseEvent e) {
407
                for (int i = 0; i < graphicLayers.size(); i++) 
408
                        ((IGraphicLayer)graphicLayers.get(i)).mouseExited(e);
409
                repaint();
410
        }
411

    
412
        /*
413
         * (non-Javadoc)
414
         * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
415
         */
416
        public void mousePressed(MouseEvent e) {
417
                for (int i = 0; i < graphicLayers.size(); i++) 
418
                        ((IGraphicLayer)graphicLayers.get(i)).mousePressed(e);
419
                repaint();
420
        }
421

    
422
        /*
423
         * (non-Javadoc)
424
         * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
425
         */
426
        public void mouseReleased(MouseEvent e) {
427
                for (int i = 0; i < graphicLayers.size(); i++) 
428
                        ((IGraphicLayer)graphicLayers.get(i)).mouseReleased(e);
429
                repaint();
430
        }
431

    
432
        /*
433
         * (non-Javadoc)
434
         * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
435
         */
436
        public void mouseDragged(MouseEvent e) {
437
                for (int i = 0; i < graphicLayers.size(); i++) 
438
                        ((IGraphicLayer)graphicLayers.get(i)).mouseDragged(e);
439
                repaint();
440
        }
441

    
442
        /*
443
         * (non-Javadoc)
444
         * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
445
         */
446
        public void mouseMoved(MouseEvent e) {
447
                realCoord = viewCoordsToWorld((Point2D)e.getPoint());
448
                viewCoord = e.getPoint();
449
                for (int i = 0; i < graphicLayers.size(); i++) 
450
                        ((IGraphicLayer)graphicLayers.get(i)).mouseMoved(e);
451
                repaint();
452
        }
453

    
454
        /**
455
         * Asigna la tool seleccionada
456
         * @param selectedTool
457
         */
458
        public void setSelectedTool(BaseViewTool selectedTool) {
459
                this.selectedTool = selectedTool;
460
        }
461
        
462
        /**
463
         * Obtiene la herramienta seleccionada
464
         * @return BaseViewTool
465
         */
466
        public BaseViewTool getSelectedTool() {
467
                return selectedTool;
468
        }
469

    
470
        /**
471
         * Activa o desactiva el mostrado de informaci?n
472
         * @param showInfo
473
         */
474
        public void setShowInfo(boolean showInfo) {
475
                this.showInfo = showInfo;
476
        }
477
}