Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extRasterTools-SE / src / org / gvsig / rastertools / geolocation / behavior / RotationBehavior.java @ 12626

History | View | Annotate | Download (16.9 KB)

1
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 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.geolocation.behavior;
20

    
21
import java.awt.AlphaComposite;
22
import java.awt.Color;
23
import java.awt.Component;
24
import java.awt.Cursor;
25
import java.awt.Graphics;
26
import java.awt.Graphics2D;
27
import java.awt.Image;
28
import java.awt.Point;
29
import java.awt.Rectangle;
30
import java.awt.Toolkit;
31
import java.awt.event.MouseEvent;
32
import java.awt.geom.AffineTransform;
33
import java.awt.geom.NoninvertibleTransformException;
34
import java.awt.geom.Point2D;
35
import java.awt.geom.Rectangle2D;
36
import java.awt.image.BufferedImage;
37

    
38
import javax.swing.ImageIcon;
39
import javax.swing.JOptionPane;
40

    
41
import com.iver.andami.PluginServices;
42
import com.iver.cit.gvsig.fmap.ViewPort;
43
import com.iver.cit.gvsig.fmap.tools.BehaviorException;
44
import com.iver.cit.gvsig.fmap.tools.Listeners.RectangleListener;
45
import com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener;
46

    
47

    
48
/**
49
 * Behaviour que espera un listener de tipo RedimListener.
50
 * Nacho Brodin (brodin_ign@gva.es)
51
 *
52
 */
53
public class RotationBehavior extends TransformationBehavior {
54
        //N?mero de pixeles de ancho del borde donde el cursor se activar?. Son pixeles del canvas de la vista.
55
        //De esta forma da igual la escala a la que est? la imagen siempre tiene la misma precisi?n
56
        private int                                                         PX_SELEC = 13;
57
        private int                                                         LONG_CORNER = 9;
58

    
59
        private Color                                                        rectangleColor = Color.RED;
60
        
61
        private RectangleListener listener;
62
        
63
        private final Image supIzq = new ImageIcon(getClass().getClassLoader().getResource(
64
                "images/RotSupIzqCursor.gif")).getImage(); 
65
        private final Image supDer = new ImageIcon(getClass().getClassLoader().getResource(
66
                "images/RotSupDerCursor.gif")).getImage();
67
        private final Image infIzq = new ImageIcon(getClass().getClassLoader().getResource(
68
                "images/RotInfIzqCursor.gif")).getImage();
69
        private final Image infDer = new ImageIcon(getClass().getClassLoader().getResource(
70
                "images/RotInfDerCursor.gif")).getImage();
71

    
72

    
73
        private Point2D                                                 ul = null;
74
        private Point2D                                                 lr = null;
75
        private Point2D                                                 tmpUl = null;
76
        private Point2D                                                 tmpLr = null;
77
        
78
        /**
79
         * Variable que si est? a true permite que se pinte el marco de la imagen. Se activa al
80
         * comenzar el redimensionado y se desactiva al terminar
81
         */
82
        private boolean                                                 isResizable = false;
83

    
84
        
85
        /**
86
         * Lista de flags de redimensionado para cada lado del raster
87
         * [0]-esquina superior derecha
88
         * [1]-esquina superior izquierda
89
         * [2]-esquina inferior derecha
90
         * [3]-esquina inferior izquierda
91
         */
92
        private boolean[]                                                cornerActive = {false, false, false, false};
93
                
94
        /**
95
         * Crea un nuevo RectangleBehavior.
96
         *
97
         * @param zili listener.
98
         */
99
        public RotationBehavior(GeoRasterBehavior grb, Cursor cur) {
100
                grBehavior = grb;
101
                defaultCursor = cur;
102
        }
103

    
104

    
105
        /**
106
         * Cuando se produce un evento de pintado dibujamos el marco de la imagen para
107
         * que el usuario pueda seleccionar y redimensionar.
108
         */
109
        public void paintComponent(Graphics g) {
110
                BufferedImage img = grBehavior.getMapControl().getImage();
111
                g.drawImage(img, 0, 0, null);
112
                g.setColor(rectangleColor);
113
                ViewPort vp = grBehavior.getMapControl().getMapContext().getViewPort();
114
                try{
115
                        Rectangle r = new Rectangle();
116
                        AffineTransform at = new AffineTransform();
117
                        at.setToShear(        lyr.getAffineTransform().getShearX() / lyr.getAffineTransform().getScaleX(),
118
                                                        lyr.getAffineTransform().getShearY() / lyr.getAffineTransform().getScaleY());
119
                                
120
                        if(tmpLr == null || tmpUl == null)
121
                                return;
122
                                                
123
                        if(isResizable){
124
                                if(lyr != null){
125
                                        ((Graphics2D)g).transform(at);
126
                
127
                                        try {
128
                                                Point2D pt = new Point2D.Double(tmpUl.getX(), tmpUl.getY());
129
                                                Point2D pt1 = new Point2D.Double(tmpLr.getX(), tmpLr.getY());
130
                                                at.inverseTransform(pt, pt);
131
                                                at.inverseTransform(pt1, pt1);
132
                                                ((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f));
133
                                                g.fillRect((int)pt.getX(), (int)pt.getY(), (int)Math.abs(pt.getX() - pt1.getX()), (int)Math.abs(pt.getY() - pt1.getY()));
134
                                                ((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
135
                                                g.drawRect((int)pt.getX(), (int)pt.getY(), (int)Math.abs(pt.getX() - pt1.getX()), (int)Math.abs(pt.getY() - pt1.getY()));
136
                                                ((Graphics2D)g).transform(at.createInverse());
137
                                        } catch (NoninvertibleTransformException e) {
138
                                        }
139
                                }else
140
                                        g.drawRect((int)tmpUl.getX(), (int)tmpUl.getY(), (int)Math.abs(tmpUl.getX() - tmpLr.getX()), (int)Math.abs(tmpUl.getY() - tmpLr.getY()));
141
                        }
142
                } catch(ClassCastException exc1){
143
                        JOptionPane.showMessageDialog((Component)PluginServices.getMainFrame(),
144
                                        PluginServices.getText(this, "error_capa_puntos"));
145
                }
146
                
147
        }
148

    
149
        /**
150
         * Reimplementaci?n del m?todo mousePressed de Behavior. Cuando se pulsa
151
         * estando sobre el marco de la imagen activamos la posibilidad de arrastrar
152
         * para redimensionar la imagen.
153
         *
154
         * @param e MouseEvent
155
         */
156
        public void mousePressed(MouseEvent e) {
157
                if (e.getButton() == MouseEvent.BUTTON1) {
158
                        setActiveTool(true);
159
                        isResizable = true;
160
                        
161
                        ViewPort vp = grBehavior.getMapControl().getMapContext().getViewPort();
162
                        if(lyr == null)
163
                                lyr = grBehavior.getLayer();
164
                        if(vp != null && lyr != null) {
165
                                tmpLr = vp.fromMapPoint(lyr.getMultiRasterDataset().getExtentForRequest().maxX(), lyr.getMultiRasterDataset().getExtentForRequest().minY());
166
                                tmpUl = vp.fromMapPoint(lyr.getMultiRasterDataset().getExtentForRequest().minX(), lyr.getMultiRasterDataset().getExtentForRequest().maxY());
167
                        }
168
                }
169

    
170
/*                if (listener.cancelDrawing())
171
                        grBehavior.getMapControl().cancelDrawing();*/
172
        }
173

    
174
        /**
175
         * Reimplementaci?n del m?todo mouseReleased de Behavior. Desactivamos
176
         * los flags de redimensionado y a partir de la selecci?n del usuario 
177
         * creamos un nuevo extent para la imagen. Con este extent creamos una nueva
178
         * capa que sustituir? a la anterior.
179
         *
180
         * @param e MouseEvent
181
         *
182
         * @throws BehaviorException Excepci?n lanzada cuando el Behavior.
183
         */
184
        public void mouseReleased(MouseEvent e) throws BehaviorException {
185
                resetBorderSelected();
186
                if (e.getButton() == MouseEvent.BUTTON1 && isResizable) {
187

    
188
                        //Asignamos el nuevo extent a la imagen
189
                        ViewPort vp = grBehavior.getMapControl().getMapContext().getViewPort();
190

    
191
                        if(lyr != null){
192
                                Rectangle2D r = new Rectangle2D.Double();
193
                                r.setFrameFromDiagonal(tmpUl, tmpLr);
194
                                
195
                                //Esquina donde se produce la traslaci?n
196
                                Point2D p = vp.toMapPoint(Math.round((int)r.getMinX()), Math.round((int)r.getMaxY()));
197
                                
198
                                //Para el calculo de el nuevo pixel size necesitamos saber el ancho en pixeles del raster y la distancia entre
199
                                //esquinas en metros y sin rotar luego calcularemos el nuevo pixel size como (metros/n?mero de pixels)
200
                                int distPxX = (int)lyr.getMultiRasterDataset().getWidth()[0];  //Width PX X
201
                                int distPxY = (int)lyr.getMultiRasterDataset().getHeight()[0]; //Width PX Y
202
                                Point2D tmpUlMap = vp.toMapPoint(Math.round((int)r.getMinX()), (int)Math.round(r.getMaxY()));
203
                                Point2D tmpLrMap = vp.toMapPoint(Math.round((int)r.getMaxX()), (int)Math.round(r.getMinY()));
204
                                double distWcX = Math.abs(tmpLrMap.getX() - tmpUlMap.getX()); //Mtrs X
205
                                double distWcY = Math.abs(tmpUlMap.getY() - tmpLrMap.getY()); //Mtrs Y
206
                                
207
                                
208
                                AffineTransform atOld = lyr.getAffineTransform();
209
                                
210
                                //Cuando modificamos el tama?o del pixel tenemos que recalcular proporcionalmente la rotaci?n aplicada porque
211
                                //sino cambiar? el angulo de giro
212
                                double shearNewX = (atOld.getShearX() * (distWcX / distPxX)) / atOld.getScaleX();
213
                                double shearNewY = (atOld.getShearY() * (distWcY / distPxY)) / atOld.getScaleY();
214
                                
215
                                //Conservamos el signo que tenian anteriormente el tama?o de pixel y la rotaci?n
216
                                AffineTransform atNew = new AffineTransform((atOld.getScaleX() > 0) ? Math.abs(distWcX / distPxX) : -Math.abs(distWcX / distPxX), 
217
                                                                                                                        (atOld.getShearY() > 0) ? Math.abs(shearNewY) : -Math.abs(shearNewY),
218
                                                                                                                        (atOld.getShearX() > 0) ? Math.abs(shearNewX) : -Math.abs(shearNewX), 
219
                                                                                                                        (atOld.getScaleY() > 0) ? Math.abs(distWcY / distPxY) : -Math.abs(distWcY / distPxY),
220
                                                                                                                        p.getX(), p.getY());
221
                                
222
                                //Asignamos la nueva matriz de transformaci?n a la capa de georreferenciaci?n
223
                                lyr.setAffineTransform(atNew);
224
                                
225
                                grBehavior.getMapControl().getMapContext().invalidate();
226
                                                                
227
                                tmpUl = null;
228
                                tmpLr = null;
229
                                
230
                        }
231
                        isResizable = false;
232
                }
233
        }
234
        
235
        /**
236
         * Al arrastrar cuando se ha pulsado sobre el marco de la imagen recalculamos
237
         * el marco de la imagen 
238
         *
239
         * @param e MouseEvent
240
         */
241
        public void mouseDragged(MouseEvent p) {
242
                /*setActiveTool(true);
243
                AffineTransform at = new AffineTransform();
244
                at.setToShear(        lyr.getAffineTransform().getShearX() / lyr.getAffineTransform().getScaleX(),
245
                                                lyr.getAffineTransform().getShearY() / lyr.getAffineTransform().getScaleY());
246
                Point2D e = new Point2D.Double(p.getX(), p.getY());
247
                try {
248
                        at.inverseTransform(e, e);
249
                } catch (NoninvertibleTransformException e1) {
250
                        e1.printStackTrace();
251
                }
252
                
253
                if(tmpLr == null || tmpUl == null)
254
                        return;
255
                
256
                double longLadoX = Math.abs(tmpLr.getX() - tmpUl.getX());
257
                double longLadoY = Math.abs(tmpLr.getY() - tmpUl.getY());
258
                double coordCentroV = 0D, coordCentroH = 0D;
259
                
260
                //Guardamos los puntos iniciales para poder reponerlos si excedemos el tama?o m?nimo
261
                Point2D antUl = tmpUl;
262
                Point2D antLr = tmpLr;
263
                
264
                coordCentroV = tmpUl.getY() + (Math.abs(tmpLr.getY() - tmpUl.getY()) / 2);
265
                coordCentroH = tmpUl.getX() + (Math.abs(tmpLr.getX() - tmpUl.getX()) / 2);
266
                if(sideActive[2]) {//vertical derecha
267
                        double newLadoX = (e.getX() - tmpUl.getX());
268
                        double newLadoY = (newLadoX * longLadoY) / longLadoX;
269
                        tmpUl = new Point2D.Double(tmpUl.getX(), coordCentroV - (newLadoY / 2));
270
                        tmpLr = new Point2D.Double(e.getX(), coordCentroV + (newLadoY / 2));
271
                } else if(sideActive[3]) {//vertical izquierda
272
                        double newLadoX = (e.getX() - tmpLr.getX());
273
                        double newLadoY = (newLadoX * longLadoY) / longLadoX;
274
                        tmpLr = new Point2D.Double(tmpLr.getX(), coordCentroV - (newLadoY / 2));
275
                        tmpUl = new Point2D.Double(e.getX(), coordCentroV + (newLadoY/2));
276
                } else if(sideActive[1]) {//horizontal abajo
277
                        double newLadoY = (e.getY() - tmpUl.getY());
278
                        double newLadoX = (newLadoY * longLadoX) / longLadoY;
279
                        tmpLr = new Point2D.Double(coordCentroH + (newLadoX / 2), e.getY());
280
                        tmpUl = new Point2D.Double(coordCentroH - (newLadoX / 2), tmpUl.getY());
281
                } else if(sideActive[0]) {//horizontal arriba
282
                        double newLadoY = (tmpLr.getY() - e.getY());
283
                        double newLadoX = (newLadoY * longLadoX) / longLadoY;
284
                        tmpUl = new Point2D.Double(coordCentroH - (newLadoX / 2), e.getY());
285
                        tmpLr = new Point2D.Double(coordCentroH + (newLadoX / 2), tmpLr.getY());
286
                } else if(sideActive[6]) {//Esquina inferior derecha
287
                         double rel = longLadoX / longLadoY;
288
                         double difY = (e.getY() - tmpLr.getY());
289
             double difX = (e.getX() - tmpLr.getX());
290
             if(difX > difY){
291
                     difY = difX / rel;
292
             }else
293
                     difX = difY * rel;
294
             tmpUl = new Point2D.Double(tmpUl.getX(), tmpUl.getY());
295
             tmpLr = new Point2D.Double(tmpLr.getX() + difX, tmpLr.getY() + difY);
296
                } else if(sideActive[5]) {//Esquina superior izquierda
297
                         double rel = longLadoX / longLadoY;
298
                         double difY = (tmpUl.getY() - e.getY());
299
             double difX = (tmpUl.getX() - e.getX());
300
             if(difX > difY){
301
                     difY = difX / rel;
302
             }else
303
                     difX = difY * rel;
304
             tmpUl = new Point2D.Double(tmpUl.getX() - difX, tmpUl.getY() - difY);
305
             tmpLr = new Point2D.Double(tmpLr.getX(), tmpLr.getY());
306
            } else if(sideActive[4]) {//Esquina superior derecha
307
                         double rel = longLadoX / longLadoY;
308
                         double difY = (tmpUl.getY() - e.getY());
309
             double difX = (e.getX() - tmpLr.getX());
310
             if(difX > difY){
311
                     difY = difX / rel;
312
             }else
313
                     difX = difY * rel;
314
             tmpUl = new Point2D.Double(tmpUl.getX(), tmpUl.getY() - difY);
315
             tmpLr = new Point2D.Double(tmpLr.getX() + difX, tmpLr.getY());
316
            } else if(sideActive[7]) {//Esquina inferior izquierda
317
                    double rel = longLadoX / longLadoY;
318
                        double difY = (e.getY() - tmpLr.getY());
319
            double difX = (tmpUl.getX() - e.getX());
320
            if(difX > difY)
321
                    difY = difX / rel;
322
            else
323
                    difX = difY * rel;
324
            tmpUl = new Point2D.Double(tmpUl.getX() - difX, tmpUl.getY());
325
            tmpLr = new Point2D.Double(tmpLr.getX(), tmpLr.getY() + difY);
326
            }
327
                
328
                //A partir de un tama?o m?nimo no reducimos m?s
329
        
330
            limiteMinimunSize(antUl, antLr);
331
                grBehavior.getMapControl().repaint();*/
332
        }
333

    
334
        /**
335
         * Limita el tama?o m?nimo de la ventana de escalado
336
         * @param p1 Esquina superior izquierda a restaurar cuando excedemos la petici?n de tama?o m?nimo
337
         * @param p2 Esquina inferior derecha a restaurar cuando excedemos la petici?n de tama?o m?nimo
338
         */
339
        private void limiteMinimunSize(Point2D p1, Point2D p2) {
340
                if( Math.abs(tmpLr.getX() - tmpUl.getX()) < 25 || Math.abs(tmpUl.getY() - tmpLr.getY()) < 25){
341
                        tmpUl = p1;
342
                        tmpLr = p2;
343
                }        
344
        }
345
        
346
        /**
347
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#setListener(org.gvsig.georeferencing.fmap.tools.ToolListener)
348
         */
349
        public void setListener(ToolListener listener) {
350
                this.listener = (RectangleListener) listener;
351
        }
352

    
353
        /**
354
         * @see com.iver.cit.gvsig.fmap.tools.Behavior.Behavior#getListener()
355
         */
356
        public ToolListener getListener() {
357
                return listener;
358
        }
359
        
360
        /**
361
         * Cuando movemos el rat?n detecta si estamos en el marco de la 
362
         * imagen y pone el icono del cursor del rat?n adecuado.
363
         */
364
        public boolean mouseMoved(MouseEvent e) throws BehaviorException {
365
                ViewPort vp = grBehavior.getMapControl().getMapContext().getViewPort();
366
                
367
                lyr = grBehavior.getLayer();
368
                if(lyr == null) {
369
                        setActiveTool(false);
370
                        return false;
371
                }
372
                
373
                Rectangle2D ext = lyr.getFullExtent();
374
                Point2D p1 = vp.fromMapPoint(ext.getMinX(), ext.getMaxY());
375
                Point2D p2 = vp.fromMapPoint(ext.getMaxX(), ext.getMinY());
376

    
377
                //esquina superior izquierda
378
                if ((e.getX() > (p1.getX() - PX_SELEC) && e.getX() <= (p1.getX() + LONG_CORNER) && e.getY() <= p1.getY() && e.getY() > (p1.getY() - PX_SELEC)) ||
379
                        (e.getX() <= p1.getX() && e.getX() > (p1.getX() - PX_SELEC) && e.getY() > p1.getY() && e.getY() <= (p1.getY() + LONG_CORNER))){
380
                        grBehavior.getMapControl().setCursor(Toolkit.getDefaultToolkit().createCustomCursor(supIzq, new Point(16, 16), ""));
381
                        setActiveTool(true);
382
                        cornerActive[1] = true;
383
                        return true;
384
                }
385
                
386
                //esquina superior derecha
387
                if ((e.getX() >= (p2.getX() - LONG_CORNER) && e.getX() < (p2.getX() + PX_SELEC) && e.getY() <= p1.getY() && e.getY() > (p1.getY() - PX_SELEC)) ||
388
                        (e.getX() >= p2.getX() && e.getX() < (p2.getX() + PX_SELEC) && e.getY() > p1.getY() && e.getY() <= (p1.getY() + LONG_CORNER))){
389
                        grBehavior.getMapControl().setCursor(Toolkit.getDefaultToolkit().createCustomCursor(supDer, new Point(16, 16), ""));
390
                        setActiveTool(true);
391
                        cornerActive[0] = true;
392
                        return true;
393
                }
394
                
395
                //esquina inferior izquierda
396
                if ((e.getX() > (p1.getX() - PX_SELEC) && e.getX() <= (p1.getX() + LONG_CORNER) && e.getY() >= p2.getY() && e.getY() < (p2.getY() + PX_SELEC)) ||
397
                        (e.getX() <= p1.getX() && e.getX() > (p1.getX() - PX_SELEC) && e.getY() < p2.getY() && e.getY() >= (p2.getY() - LONG_CORNER))){
398
                        grBehavior.getMapControl().setCursor(Toolkit.getDefaultToolkit().createCustomCursor(infIzq, new Point(16, 16), ""));
399
                        setActiveTool(true);
400
                        cornerActive[3] = true;
401
                        return true;
402
                }
403
                
404
                //esquina inferior derecha
405
                /*if ((e.getX() < p2.getX() && e.getX() >= (p2.getX() - LONG_CORNER) && e.getY() >= (p2.getY() - PX_SELEC) && e.getY() < p2.getY()) ||
406
                        (e.getX() < p2.getX() && e.getX() >= (p2.getX() - PX_SELEC) && e.getY() < p2.getY() && e.getY() >= (p2.getY() - LONG_CORNER))){
407
                        grBehavior.getMapControl().setCursor(Toolkit.getDefaultToolkit().createCustomCursor(infDer, new Point(16, 16), ""));
408
                        setActiveTool(true);
409
                        cornerActive[2] = true;
410
                        return true;
411
                }*/
412
                
413
                grBehavior.getMapControl().repaint();
414
                grBehavior.getMapControl().setCursor(defaultCursor);
415
                return false;
416
        }
417
        
418
        /**
419
         * Pone a false todos los elementos del array sideActive. Esto es equivalente 
420
         * a eliminar cualquier selecci?n de borde.
421
         */
422
        private void resetBorderSelected() {
423
                for (int i = 0; i < cornerActive.length; i++)
424
                        cornerActive[i] = false;
425
        }
426

    
427
}