Statistics
| Revision:

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

History | View | Annotate | Download (14.3 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
                double cx = lastExtent.getX() + ((p.getX() * lastExtent.getWidth()) / w);
105
                double cy = lastExtent.getY() - (p.getY() * lastExtent.getHeight()) / h;
106
                return new Point2D.Double(cx, cy);
107
        }
108
        
109
        /**
110
         * Conversi?n de un punto en coordenadas del canvas a reales
111
         * @param p
112
         * @return
113
         */
114
        public Point2D viewCoordsFromWorld(Point2D p) {
115
                int w = getVisibleRect().width;
116
                int h = getVisibleRect().height;
117
                double cx = ((p.getX() - lastExtent.getMinX()) * w) / lastExtent.getWidth();
118
                double cy = ((Math.abs(p.getY() - lastExtent.getMinY()) * h) / lastExtent.getHeight());
119
                return new Point2D.Double(cx, cy);
120
        }
121
        
122
        /**
123
         * Asigna un nuevo centro de visualizaci?n en coordenadas del
124
         * componente.
125
         * @param center
126
         */
127
        public void setViewCenter(Point2D c) {
128
                int w = getVisibleRect().width;
129
                int h = getVisibleRect().height;
130
                
131
                double cx = (c.getX() * lastExtent.getWidth()) / w;
132
                double cy = (c.getY() * lastExtent.getHeight()) / h;
133
                setPixelCenter(new Point2D.Double(cx, cy));
134
        }
135
        
136
        /**
137
         * Asigna un nuevo centro de visualizaci?n en coordenadas pixel
138
         * del ?rea de dibujado (canvas). El nuevo centro ser? calculado en coordenadas
139
         * del mapa.
140
         * @param center
141
         */
142
        public void setPixelCenter(Point2D c) {
143
                int w = getVisibleRect().width;
144
                int h = getVisibleRect().height;
145
                
146
                //Calculamos el extent del canvas 
147
                Rectangle2D ext = getCanvasExtent(w, h, scale);
148
                
149
                //Calculamos el nuevo centro en coordenadas reales
150
                double wWC = (c.getX() / scale) * pixelSize;
151
                double hWC = (c.getY() / scale) * pixelSize;
152
                this.center = new Point2D.Double(ext.getMinX() + wWC,
153
                                                                                 ext.getMinY() - hWC);
154
                repaint();
155
        }
156
        
157
        /**
158
         * Asigna un nuevo centro de visualizaci?n en coordenadas pixel. Esta llamada tiene
159
         * en cuenta solo p?xeles completos. No centra sobre porciones de pixel cuando el zoom es
160
         * mayor de 1:1. El nuevo centro es en coordenadas del mapa pero siempre centrar?
161
         * en la esquina inferior izquierda del pixel.
162
         * @param center
163
         */
164
        public void setPixelCenter(int x, int y) {
165
                int w = getVisibleRect().width;
166
                int h = getVisibleRect().height;
167
                
168
                //Calculamos el extent del canvas 
169
                Rectangle2D ext = getCanvasExtent(w, h, scale);
170
                
171
                //Calculamos el nuevo centro en coordenadas reales
172
                double wWC = (x / scale) * pixelSize;
173
                double hWC = (y / scale) * pixelSize;
174
                Point2D center = new Point2D.Double(ext.getMinX() + wWC,
175
                                                                                          ext.getMinY() - hWC);
176
                
177
                //Calculamos la coordena pixel a la que pertenece esa coordenada real
178
                int pxX = (int)((center.getX() * (w / scale)) / ext.getWidth());
179
                int pxY = (int)((center.getY() * (h / scale)) / ext.getHeight());
180
                
181
                //Despu?s de haber convertido a pixel y redondeado la coordenada a entero volvemos a convertirla en real
182
                double wcX = (pxX * ext.getWidth()) / (w / scale);
183
                double wcY = (pxY * ext.getHeight()) / (h / scale);
184

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

    
350
                        //Creamos el buffer y lo cargamos teniendo en cuenta el desplazamiento inicial
351
                        double step = 1 / scale;
352

    
353
                        double xValue = pxX;
354
                        double yValue = pxY;
355

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

    
376
        /*
377
         * (non-Javadoc)
378
         * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
379
         */
380
        public void mouseClicked(MouseEvent e) {
381
                for (int i = 0; i < graphicLayers.size(); i++) 
382
                        ((IGraphicLayer)graphicLayers.get(i)).mouseClicked(e);
383
                repaint();
384
        }
385

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

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

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

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

    
426
        /*
427
         * (non-Javadoc)
428
         * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
429
         */
430
        public void mouseDragged(MouseEvent e) {
431
                for (int i = 0; i < graphicLayers.size(); i++) 
432
                        ((IGraphicLayer)graphicLayers.get(i)).mouseDragged(e);
433
                repaint();
434
        }
435

    
436
        /*
437
         * (non-Javadoc)
438
         * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
439
         */
440
        public void mouseMoved(MouseEvent e) {
441
                realCoord = viewCoordsToWorld((Point2D)e.getPoint());
442
                viewCoord = e.getPoint();
443
                for (int i = 0; i < graphicLayers.size(); i++) 
444
                        ((IGraphicLayer)graphicLayers.get(i)).mouseMoved(e);
445
                repaint();
446
        }
447

    
448
        /**
449
         * Asigna la tool seleccionada
450
         * @param selectedTool
451
         */
452
        public void setSelectedTool(BaseViewTool selectedTool) {
453
                this.selectedTool = selectedTool;
454
        }
455
        
456
        /**
457
         * Obtiene la herramienta seleccionada
458
         * @return BaseViewTool
459
         */
460
        public BaseViewTool getSelectedTool() {
461
                return selectedTool;
462
        }
463

    
464
        /**
465
         * Activa o desactiva el mostrado de informaci?n
466
         * @param showInfo
467
         */
468
        public void setShowInfo(boolean showInfo) {
469
                this.showInfo = showInfo;
470
        }
471
}