Statistics
| Revision:

gvsig-raster / org.gvsig.raster.tools / trunk / org.gvsig.raster.tools / org.gvsig.raster.tools.app / org.gvsig.raster.tools.app.basic / src / main / java / org / gvsig / raster / tools / app / basic / tool / clip / ui / listener / ClippingPanelListener.java @ 1028

History | View | Annotate | Download (34.3 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
* 
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
* 
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
* 
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
19
* MA  02110-1301, USA.
20
* 
21
*/
22
package org.gvsig.raster.tools.app.basic.tool.clip.ui.listener;
23

    
24
import java.awt.Component;
25
import java.awt.Cursor;
26
import java.awt.Dimension;
27
import java.awt.Image;
28
import java.awt.event.ActionEvent;
29
import java.awt.event.ActionListener;
30
import java.awt.geom.AffineTransform;
31
import java.awt.geom.NoninvertibleTransformException;
32
import java.awt.geom.Point2D;
33
import java.io.File;
34
import java.util.ArrayList;
35
import java.util.EventObject;
36

    
37
import javax.swing.JOptionPane;
38

    
39
import org.gvsig.andami.PluginServices;
40
import org.gvsig.andami.Utilities;
41
import org.gvsig.andami.ui.mdiManager.IWindow;
42
import org.gvsig.app.project.documents.view.gui.AbstractViewPanel;
43
import org.gvsig.app.project.documents.view.toolListeners.StatusBarListener;
44
import org.gvsig.fmap.dal.coverage.RasterLocator;
45
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
46
import org.gvsig.fmap.dal.coverage.grid.ROI;
47
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
48
import org.gvsig.fmap.geom.primitive.Envelope;
49
import org.gvsig.fmap.mapcontrol.MapControl;
50
import org.gvsig.fmap.mapcontrol.tools.BehaviorException;
51
import org.gvsig.fmap.mapcontrol.tools.Behavior.Behavior;
52
import org.gvsig.fmap.mapcontrol.tools.Behavior.MouseMovementBehavior;
53
import org.gvsig.fmap.mapcontrol.tools.Behavior.RectangleBehavior;
54
import org.gvsig.fmap.mapcontrol.tools.Events.EnvelopeEvent;
55
import org.gvsig.fmap.mapcontrol.tools.Listeners.RectangleListener;
56
import org.gvsig.gui.beans.buttonspanel.ButtonsPanel;
57
import org.gvsig.gui.beans.buttonspanel.ButtonsPanelEvent;
58
import org.gvsig.gui.beans.buttonspanel.ButtonsPanelListener;
59
import org.gvsig.gui.beans.coordinatespanel.CoordinatesEvent;
60
import org.gvsig.gui.beans.coordinatespanel.CoordinatesListener;
61
import org.gvsig.gui.beans.coordinatespanel.CoordinatesPanel;
62
import org.gvsig.gui.beans.datainput.DataInputContainerListener;
63
import org.gvsig.gui.beans.table.models.CheckBoxModel;
64
import org.gvsig.raster.fmap.layers.FLyrRaster;
65
import org.gvsig.raster.tools.app.basic.RasterToolsUtil;
66
import org.gvsig.raster.tools.app.basic.raster.bean.endinfo.EndInfoDialog;
67
import org.gvsig.raster.tools.app.basic.raster.process.ClippingProcess;
68
import org.gvsig.raster.tools.app.basic.raster.process.IProcessActions;
69
import org.gvsig.raster.tools.app.basic.raster.process.RasterProcess;
70
import org.gvsig.raster.tools.app.basic.tool.clip.ClippingData;
71
import org.gvsig.raster.tools.app.basic.tool.clip.ui.ClippingPanel;
72
import org.gvsig.raster.tools.app.basic.tool.clip.ui.panel.ClippingCoordinatesPanel;
73
import org.gvsig.raster.tools.app.basic.tool.clip.ui.panel.ClippingOptionsPanel;
74
import org.gvsig.raster.tools.app.basic.tool.clip.ui.panel.ClippingResolutionPanel;
75
import org.gvsig.raster.tools.app.basic.tool.clip.ui.panel.ClippingSelectionPanel;
76

    
77
/**
78
 * <code>ClippingPanelListener</code> es una clase donde se recoger?n y
79
 * tratar?n todos los eventos del panel de recorte
80
 *
81
 * @version 19/04/2007
82
 * @author BorSanZa - Borja S?nchez Zamorano (borja.sanchez@iver.es)
83
 */
84
public class ClippingPanelListener implements ActionListener, RectangleListener, ButtonsPanelListener, CoordinatesListener, DataInputContainerListener, IProcessActions {
85
        private Dimension             dim                     = new Dimension();
86
        private AffineTransform       at                      = null;
87
        private ClippingPanel         clippingPanel           = null;
88
        private ClippingData          data                    = null;
89
        private boolean               enableValueChangedEvent = true;
90
        private FLyrRaster            fLayer                  = null;
91
        private MapControl            mapControl              = null;
92
        /**
93
         * Herramienta seleccionada en el momento de la apertura del dialogo
94
         */
95
        private String                 lastTool                = null;
96
        private String                 viewName                = null;
97
        private static ClippingData    lastDataSaved           = null;
98

    
99
        /**
100
         * Crea un nuevo <code>ClippingPanelListener</code> con el
101
         * <code>ClippingPanelListener</code> asociado
102
         * @param panel
103
         */
104
        public ClippingPanelListener(ClippingPanel clippingPanel) {
105
                this.clippingPanel = clippingPanel;
106
        }
107

    
108
        /**
109
         * Asigna el modelo de datos
110
         * @param data
111
         */
112
        public void setData(ClippingData data) {
113
                this.data = data;
114
                if(fLayer != null) {
115
                        data.setPxWidth((int)fLayer.getPxWidth());
116
                        data.setPxHeight((int)fLayer.getPxHeight());
117
                }
118
        }
119

    
120
        /**
121
         * Asigna la matriz de transformaci?n entre puntos en coordenadas del raster y
122
         * puntos en coordenadas reales.
123
         * @param AffineTransform
124
         */
125
        private void setAffineTransform(AffineTransform at) {
126
                this.at = at;
127
        }
128

    
129
        /**
130
         * Asigna la dimensi?n del raster
131
         * @param dim
132
         */
133
        public void setDimension(Dimension dim) {
134
                this.dim = dim;
135
        }
136

    
137
        /**
138
         * M?todo que se invoca cuando se disparan los eventos de los botones de
139
         * extensi?n completa o de seleccion de extensi?n con el rat?n
140
         */
141
        @SuppressWarnings("deprecation")
142
        public void actionPerformed(ActionEvent e) {
143
                // Bot?n de selecci?n del extent completo
144
                // Modificamos las coordenadas reales y recalculamos las coordenadas pixel
145
                if (e.getSource() == getResolutionPanel().getButtonRestore()) {
146
                        getClippingPanel().restoreStatus(data);
147
                }
148

    
149
                //Load parameters
150
                if (e.getSource() == getCoordinatesPanel().getButtonBarContainer().getButton(0)) {
151
                        if(lastDataSaved != null) {
152
                                data = (ClippingData)lastDataSaved.clone();
153
                                data.addObserver(getClippingPanel());
154
                                data.updateObservers();
155
                                getClippingPanel().getButtonsPanel().getButton(ButtonsPanel.BUTTON_APPLY).setEnabled(true);
156
                                getClippingPanel().getButtonsPanel().getButton(ButtonsPanel.BUTTON_ACCEPT).setEnabled(true);
157
                        } else
158
                                RasterToolsUtil.messageBoxError(RasterToolsUtil.getText(this, "no_data_saved"), null);
159
                }
160

    
161
                //Save parameters
162
                if (e.getSource() == getCoordinatesPanel().getButtonBarContainer().getButton(1)) {
163
                        lastDataSaved = (ClippingData)data.clone();
164
                }
165
                
166
                //Redondear las coordenadas p?xel
167
                if (e.getSource() == getCoordinatesPanel().getButtonBarContainer().getButton(2)) {
168
                        roundPixels();
169
                        return;
170
                }
171

    
172
                //Bot?n de selecci?n del ?rea m?xima asociada a los ROIs
173
                if (e.getSource() == getCoordinatesPanel().getButtonBarContainer().getButton(3)) {
174
                        ArrayList<ROI> roiList = getFLayer().getRois();
175
                        if(roiList != null && roiList.size() > 0) {
176
                                Extent ext = RasterLocator.getManager().getRasterUtils().getROIsMaximunExtent(roiList);
177
                                assignROISExtent(ext, getFLayer());
178
                        } else
179
                                assignFullExtent();
180
                        return;
181
                }
182

    
183
                // Bot?n de selecci?n del extent completo
184
                // Modificamos las coordenadas reales y recalculamos las coordenadas pixel
185
                if (e.getSource() == getCoordinatesPanel().getButtonBarContainer().getButton(4)) {
186
                        assignFullExtent();
187
                        return;
188
                }
189

    
190
                // Bot?n de selecci?n de la herramienta de seleccionar desde la vista
191
                if (e.getSource() == getCoordinatesPanel().getButtonBarContainer().getButton(5)) {
192
                        selectToolButton();
193
                        return;
194
                }
195

    
196
        }
197
        
198
        /**
199
         * Round off the pixels value
200
         */
201
        private void roundPixels() {
202
                data.setUlxPx((int)(data.getUlxPx()));
203
                data.setUlyPx((int)(data.getUlyPx()));
204
                data.setLrxPx((int)(data.getLrxPx()));
205
                data.setLryPx((int)(data.getLryPx()));
206
                data.setUrxPx((int)(data.getUrxPx()));
207
                data.setUryPx((int)(data.getUryPx()));
208
                data.setLlxPx((int)(data.getLlxPx()));
209
                data.setLlyPx((int)(data.getLlyPx()));
210
                
211
                Point2D ulWc = new Point2D.Double();
212
                Point2D lrWc = new Point2D.Double();
213
                Point2D llWc = new Point2D.Double();
214
                Point2D urWc = new Point2D.Double();
215
                
216
                at.transform(new Point2D.Double(data.getUlxPx(), data.getUlyPx()), ulWc);
217
                at.transform(new Point2D.Double(data.getLrxPx() + 1, data.getLryPx() + 1), lrWc);
218
                at.transform(new Point2D.Double(data.getLlxPx(), data.getLlyPx() + 1), llWc);
219
                at.transform(new Point2D.Double(data.getUrxPx() + 1, data.getUryPx()), urWc);
220

    
221
                data.setCoorReal(ulWc, lrWc, llWc, urWc);
222
                data.setAffineTransform(at);
223
                data.initSize();
224
                data.updateObservers();
225
        }
226

    
227
        /**
228
         * Asigna el extent completo a los cuadros de texto donde se introducen las coordenadas
229
         * reales y p?xel.
230
         */
231
        @SuppressWarnings("deprecation")
232
        private void assignROISExtent(Extent ext, FLyrRaster layer) {
233
                AffineTransform at = layer.getAffineTransform();
234
                Point2D ulWc = new Point2D.Double(ext.minX(), ext.maxY());
235
                Point2D lrWc = new Point2D.Double(ext.maxX(), ext.minY());
236
                Point2D llWc = new Point2D.Double(ext.minX(), ext.minY());
237
                Point2D urWc = new Point2D.Double(ext.maxX(), ext.maxY());
238

    
239
                ulWc = getFLayer().adjustWorldRequest(ulWc);
240
                lrWc = getFLayer().adjustWorldRequest(lrWc);
241
                llWc = getFLayer().adjustWorldRequest(llWc);
242
                urWc = getFLayer().adjustWorldRequest(urWc);
243

    
244
                Point2D ulPx = new Point2D.Double();
245
                Point2D lrPx = new Point2D.Double();
246
                Point2D llPx = new Point2D.Double();
247
                Point2D urPx = new Point2D.Double();
248

    
249
                try {
250
                        at.inverseTransform(ulWc, ulPx);
251
                        at.inverseTransform(lrWc, lrPx);
252
                        at.inverseTransform(ulWc, llPx);
253
                        at.inverseTransform(lrWc, urPx);
254
                } catch (NoninvertibleTransformException e) {
255
                        JOptionPane.showMessageDialog((Component) PluginServices.getMainFrame(), PluginServices.getText(this, "coordenadas_erroneas"));
256
                        return;
257
                }
258

    
259
                data.setCoorPixel(ulPx, lrPx, llPx, urPx);
260
                data.setCoorReal(ulWc, lrWc, llWc, urWc);
261
                data.setAffineTransform(at);
262
                data.initSize();
263
                getClippingPanel().saveStatus(data);
264

    
265
                getClippingPanel().getButtonsPanel().getButton(ButtonsPanel.BUTTON_APPLY).setEnabled(true);
266
                getClippingPanel().getButtonsPanel().getButton(ButtonsPanel.BUTTON_ACCEPT).setEnabled(true);
267
        }
268

    
269
        /**
270
         * Asigna el extent completo a los cuadros de texto donde se introducen las coordenadas
271
         * reales y p?xel.
272
         */
273
        @SuppressWarnings("deprecation")
274
        private void assignFullExtent() {
275
                Point2D ulPx = new Point2D.Double(0, 0);
276
                Point2D lrPx = new Point2D.Double(dim.width, dim.height);
277
                Point2D urPx = new Point2D.Double(dim.width, 0);
278
                Point2D llPx = new Point2D.Double(0, dim.height);
279

    
280
                //Convertimos nuevamente a coordenadas reales
281
                Point2D ulWc = new Point2D.Double();
282
                Point2D lrWc = new Point2D.Double();
283
                Point2D urWc = new Point2D.Double();
284
                Point2D llWc = new Point2D.Double();
285
                at.transform(ulPx, ulWc);
286
                at.transform(lrPx, lrWc);
287
                at.transform(urPx, urWc);
288
                at.transform(llPx, llWc);
289

    
290
                ulPx = new Point2D.Double(0, 0);
291
                lrPx = new Point2D.Double(dim.width - 1, dim.height - 1);
292
                urPx = new Point2D.Double(dim.width - 1, 0);
293
                llPx = new Point2D.Double(0, dim.height - 1);
294

    
295
                data.setCoorPixel(ulPx, lrPx, llPx, urPx);
296
                data.setCoorReal(ulWc, lrWc, llWc, urWc);
297
                data.setAffineTransform(at);
298
                data.initSize();
299

    
300
                getClippingPanel().saveStatus(data);
301
                getClippingPanel().getButtonsPanel().getButton(ButtonsPanel.BUTTON_APPLY).setEnabled(true);
302
                getClippingPanel().getButtonsPanel().getButton(ButtonsPanel.BUTTON_ACCEPT).setEnabled(true);
303
        }
304

    
305
        /**
306
         * Al producirse un evento de perdida de foco o pulsaci?n de "enter" en un campo de texto de coordenadas
307
         * hay que asignar el nuevo valor introducido.
308
         * @param obj
309
         */
310
        private void eventJTextField(CoordinatesEvent e) {
311
                try {
312
                        if (e.getSource() == getCoordinatesPanel().getPixelCoordinates()) {
313
                                if (e.getName().equals("11")) {
314
                                        data.setUlxPx(Double.valueOf(getCoordinatesPanel().getPixelCoordinates().getValue11()).doubleValue());
315
                                        data.setLlxPx(Double.valueOf(getCoordinatesPanel().getPixelCoordinates().getValue11()).doubleValue());
316
                                }
317
                                if (e.getName().equals("12")) {
318
                                        data.setUlyPx(Double.valueOf(getCoordinatesPanel().getPixelCoordinates().getValue12()).doubleValue());
319
                                        data.setUryPx(Double.valueOf(getCoordinatesPanel().getPixelCoordinates().getValue12()).doubleValue());
320
                                }
321
                                if (e.getName().equals("21")) {
322
                                        data.setLrxPx(Double.valueOf(getCoordinatesPanel().getPixelCoordinates().getValue21()).doubleValue());
323
                                        data.setUrxPx(Double.valueOf(getCoordinatesPanel().getPixelCoordinates().getValue21()).doubleValue());
324
                                }
325
                                if (e.getName().equals("22")) {
326
                                        data.setLryPx(Double.valueOf(getCoordinatesPanel().getPixelCoordinates().getValue22()).doubleValue());
327
                                        data.setLlyPx(Double.valueOf(getCoordinatesPanel().getPixelCoordinates().getValue22()).doubleValue());
328
                                }
329
                                data.updateObservers();
330
                        }
331

    
332
                        if (e.getSource() == getCoordinatesPanel().getRealCoordinates()) {
333
                                if (e.getName().equals("11")) {
334
                                        data.setUlxWc(Double.valueOf(getCoordinatesPanel().getRealCoordinates().getValue11()).doubleValue());
335
                                        data.setLlxWc(Double.valueOf(getCoordinatesPanel().getRealCoordinates().getValue11()).doubleValue());
336
                                }
337
                                if (e.getName().equals("12")) {
338
                                        data.setUlyWc(Double.valueOf(getCoordinatesPanel().getRealCoordinates().getValue12()).doubleValue());
339
                                        data.setUryWc(Double.valueOf(getCoordinatesPanel().getRealCoordinates().getValue12()).doubleValue());
340
                                }
341
                                if (e.getName().equals("21")) {
342
                                        data.setLrxWc(Double.valueOf(getCoordinatesPanel().getRealCoordinates().getValue21()).doubleValue());
343
                                        data.setUrxWc(Double.valueOf(getCoordinatesPanel().getRealCoordinates().getValue21()).doubleValue());
344
                                }
345
                                if (e.getName().equals("22")) {
346
                                        data.setLryWc(Double.valueOf(getCoordinatesPanel().getRealCoordinates().getValue22()).doubleValue());
347
                                        data.setLlyWc(Double.valueOf(getCoordinatesPanel().getRealCoordinates().getValue22()).doubleValue());
348
                                }
349
                                data.updateObservers();
350
                        }
351
                } catch (NumberFormatException ex1) {
352
                        // No hay valores parseables a decimal en las cajas de texto. No hacemos nada
353
                }
354
        }
355

    
356
        
357
        /**
358
         * Recalcula el valor de los campos de coordenadas reales y pixel. Cuando modificamos alg?n campo
359
         * de las coordenadas reales se modifican los pixeles y viceversa.
360
         * @param modifyPx true si se ha modificado alg?n campo de coordenadas pixel y false si se ha modificado
361
         * alg?n campo de las coordenadas reales.
362
         */
363
        @SuppressWarnings("deprecation")
364
        private void recalcCoordFields(boolean modifyPx) {
365
                try {
366
                        Point2D ulPx = new Point2D.Double(data.getUlxPx(), data.getUlyPx());
367
                        Point2D lrPx = new Point2D.Double(data.getLrxPx(), data.getLryPx());
368
                        Point2D llPx = new Point2D.Double(data.getLlxPx(), data.getLlyPx());
369
                        Point2D urPx = new Point2D.Double(data.getUrxPx(), data.getUryPx());
370
                        
371
                        Point2D ulWc = new Point2D.Double(data.getUlxWc(), data.getUlyWc());
372
                        Point2D lrWc = new Point2D.Double(data.getLrxWc(), data.getLryWc());
373
                        Point2D llWc = new Point2D.Double(data.getLlxWc(), data.getLlyWc());
374
                        Point2D urWc = new Point2D.Double(data.getUrxWc(), data.getUryWc());
375
                        
376
                        if (modifyPx) {
377
                                at.transform(new Point2D.Double(ulPx.getX(), ulPx.getY()), ulWc);
378
                                at.transform(new Point2D.Double(lrPx.getX() + 1, lrPx.getY() + 1), lrWc);
379
                                at.transform(new Point2D.Double(llPx.getX(), llPx.getY() + 1), llWc);
380
                                at.transform(new Point2D.Double(urPx.getX() + 1, urPx.getY()), urWc);
381

    
382
                                data.setCoorReal(ulWc, lrWc, llWc, urWc);
383
                                data.setAffineTransform(at);
384
                                data.initSize();
385

    
386
                                getClippingPanel().saveStatus(data);
387
                        } else {
388
                                try {
389
                                        at.inverseTransform(ulWc, ulPx);
390
                                        at.inverseTransform(lrWc, lrPx);
391
                                        at.inverseTransform(llWc, llPx);
392
                                        at.inverseTransform(urWc, urPx);
393
                                } catch (NoninvertibleTransformException e) {
394
                                        JOptionPane.showMessageDialog((Component) PluginServices.getMainFrame(), PluginServices.getText(this, "coordenadas_erroneas"));
395
                                        return;
396
                                }
397

    
398
                                //adjustPoints(ulPx, lrPx);
399
                                //adjustPoints(llPx, urPx);
400
                                lrPx = new Point2D.Double(lrPx.getX() - 1, lrPx.getY() - 1);
401
                                llPx = new Point2D.Double(llPx.getX(), llPx.getY() - 1);
402
                                urPx = new Point2D.Double(urPx.getX() - 1, urPx.getY());
403
                                data.setCoorPixel(ulPx, lrPx, llPx, urPx);
404
                                data.setAffineTransform(at);
405
                                data.initSize();
406
                                getClippingPanel().saveStatus(data);
407
                        }
408
                        
409
                        //Condiciones para activar botones. 
410
                        if(activeButtons(ulPx, lrPx, ulWc, lrWc)) {
411
                                getClippingPanel().getButtonsPanel().getButton(ButtonsPanel.BUTTON_APPLY).setEnabled(true);
412
                                getClippingPanel().getButtonsPanel().getButton(ButtonsPanel.BUTTON_ACCEPT).setEnabled(true);
413
                        } else {
414
                                getClippingPanel().getButtonsPanel().getButton(ButtonsPanel.BUTTON_APPLY).setEnabled(false);
415
                                getClippingPanel().getButtonsPanel().getButton(ButtonsPanel.BUTTON_ACCEPT).setEnabled(false);
416
                        }
417
                        
418
                } catch (NumberFormatException ex) {
419
                        return;
420
                }
421

    
422
        }
423
        
424
        public boolean activeButtons(Point2D ulPx, Point2D lrPx, Point2D ulWc, Point2D lrWc) {
425
                if(ulPx.getX() < lrPx.getX() && ulPx.getY() < lrPx.getY() &&
426
                        ulWc.getX() < lrWc.getX() && ulWc.getY() > lrWc.getY() &&
427
                        (lrPx.getX() - ulPx.getX()) >= 2 && (lrPx.getY() - ulPx.getY()) >= 2 &&
428
                        ulPx.getX() >= 0 && ulPx.getY() >= 0 && 
429
                        lrPx.getX() <= (fLayer.getDataStore().getWidth() - 1) &&
430
                        lrPx.getY() <= (fLayer.getDataStore().getHeight() - 1)) {
431
                        return true;
432
                }
433
                return false;
434
        }
435
        
436
        /**
437
         * Turns world coordinates into entire numbers to avoid rounds errors 
438
         * @param ul
439
         *        Upper left coordinate
440
         * @param lr
441
         *        Lower right coordinate
442
         */
443
        @SuppressWarnings("unused")
444
        private void adjustPoints(Point2D ul, Point2D lr) {
445
                double a = (ul.getX() - (int)ul.getX());
446
                double b = (ul.getY() - (int)ul.getY());
447
                double c = (lr.getX() - (int)lr.getX());
448
                double d = (lr.getY() - (int)lr.getY());
449
                ul.setLocation(        (a > 0.95 || a < 0.05) ? Math.round(ul.getX()) : ul.getX(), 
450
                                                (b > 0.95 || b < 0.05) ? Math.round(ul.getY()) : ul.getY());
451
                lr.setLocation(        (c > 0.95 || c < 0.05) ? Math.round(lr.getX()) : lr.getX(), 
452
                                                (d > 0.95 || d < 0.05) ? Math.round(lr.getY()) : lr.getY());
453
        }
454

    
455
        /**
456
         * Ajusta las coordenadas especificadas en los par?metros al ?rea m?xima
457
         * del raster en p?xeles
458
         * @param req
459
         */
460
        @SuppressWarnings("unused")
461
        private Point2D adjustPixelRequest(Point2D req) {
462
                req.setLocation(Math.max(0, req.getX()), Math.max(0, req.getY()));
463
                req.setLocation(Math.min(dim.width - 1, req.getX()), Math.min(dim.height - 1, req.getY()));
464
                return req;
465
        }
466

    
467
        /**
468
         * Invocaci?n de los eventos de la ventana de <code>DefaultButtonsPanel</code>
469
         */
470
        public void actionButtonPressed(ButtonsPanelEvent e) {
471
                // Bot?n de Aceptar
472
                if (e.getButton() == ButtonsPanel.BUTTON_ACCEPT) {
473
                        accept();
474
                        close();
475
                }
476

    
477
                // Bot?n de Aplicar
478
                if (e.getButton() == ButtonsPanel.BUTTON_APPLY)
479
                        accept();
480

    
481
                // Bot?n de Cerrar
482
                if (e.getButton() == ButtonsPanel.BUTTON_CANCEL)
483
                        close();
484

    
485
                getFLayer().getMapContext().invalidate();
486
        }
487

    
488
        /**
489
         * Cerrar la ventana del recorte
490
         */
491
        private void close() {
492
                try {
493
                        if (getLastTool() != null)
494
                                getMapControl().setTool(getLastTool());
495
                        PluginServices.getMDIManager().closeWindow(getClippingPanel().getClippingDialog());
496
                } catch (ArrayIndexOutOfBoundsException ex) {
497
                        // Si la ventana no se puede eliminar no hacemos nada
498
                }
499
        }
500

    
501
        /**
502
         * Obtener el <code>ClippingPanel</code> asociado
503
         * @return ClippingPanel
504
         */
505
        private ClippingPanel getClippingPanel() {
506
                return clippingPanel;
507
        }
508

    
509
        private ClippingCoordinatesPanel getCoordinatesPanel() {
510
                return getClippingPanel().getCoordinatesPanel();
511
        }
512

    
513
        private ClippingResolutionPanel getResolutionPanel() {
514
                return getClippingPanel().getResolutionPanel();
515
        }
516

    
517
        private ClippingOptionsPanel getOptionsPanel() {
518
                return getClippingPanel().getOptionsPanel();
519
        }
520

    
521
        private ClippingSelectionPanel getSelectionPanel() {
522
                return getClippingPanel().getSelectionPanel();
523
        }
524

    
525
        /**
526
         * Acciones realizadas cuando se acepta en el dialogo. Se obtendr?n los datos
527
         * de recorte desde el dialogo, crearemos el objeto ClippingProcess que
528
         * gestiona el recortado, ajustamos el tama?o del grid de salida y procesamos.
529
         */
530
        private void accept() {
531
                if(data.getPxHeight() == 0 || data.getPxWidth() == 0) {
532
                        RasterToolsUtil.messageBoxError(RasterToolsUtil.getText(this, "wrong_resolution"), null);
533
                        return;
534
                }
535
                
536
                // Controlamos las coordenadas del recorte que no se salgan de la imagen.
537
                // De ser as? mostramos un error
538
                CoordinatesPanel coordinatesReales = getCoordinatesPanel().getRealCoordinates();
539
                double ulx = 0;
540
                double lrx = 0;
541
                double lry = 0;
542
                double uly = 0;
543
                try {
544
                        ulx = Double.parseDouble(coordinatesReales.getValue11());
545
                        lry = Double.parseDouble(coordinatesReales.getValue22());
546
                        lrx = Double.parseDouble(coordinatesReales.getValue21());
547
                        uly = Double.parseDouble(coordinatesReales.getValue12());
548
                        Envelope ext = getFLayer().getFullEnvelope();
549
                        if (((int) ulx) > ((int) ext.getMaximum(0)) || ((int) lrx) < ((int) ext.getMinimum(0)) || ((int) uly) > ((int) ext.getMaximum(1)) || ((int) lry) < ((int) ext.getMinimum(1))) {
550
                                RasterToolsUtil.messageBoxError(RasterToolsUtil.getText(this, "coordenadas_erroneas"), null);
551
                                return;
552
                        }
553
                } catch (NumberFormatException e) {
554
                        RasterToolsUtil.messageBoxError(RasterToolsUtil.getText(this, "coordenadas_erroneas"), null);
555
                        return;
556
                }
557

    
558
                double[] wcValues = data.getWcCoordinatesToClip();
559
                double[] pxValues = data.getPxCoordinatesToClip();
560
                boolean pxRound = arePixelsRound(pxValues);
561

    
562
                // Seleccionamos las bandas que se usaran en el recorte a partir de la tabla
563
                int countBands = 0;
564
                int rowCount = ((CheckBoxModel) getSelectionPanel().getTableContainer().getModel()).getRowCount();
565
                for (int iRow = 0; iRow < rowCount; iRow++)
566
                        if ((((Boolean) ((CheckBoxModel) getSelectionPanel().getTableContainer().getModel()).getValueAt(iRow, 0))).booleanValue())
567
                                countBands++;
568

    
569
                int[] drawableBands = new int[countBands];
570
                int i = 0;
571
                for (int iRow = 0; iRow < rowCount; iRow++) {
572
                        if ((((Boolean) ((CheckBoxModel) getSelectionPanel().getTableContainer().getModel()).getValueAt(iRow, 0))).booleanValue()) {
573
                                int row = ((Integer) ((CheckBoxModel) getSelectionPanel().getTableContainer().getModel()).getValueAt(iRow, 2)).intValue();
574
                                drawableBands[i++] = row;
575
                        }
576
                }
577

    
578
                /**
579
                 * Donde se va a guardar el fichero
580
                 */
581
                String path;
582
                if (getOptionsPanel().getCbSaveFile().isSelected()) {
583
                        path = getOptionsPanel().getDirectoryTextField().getText();
584
                        File f = new File(path);
585
                        if(!f.exists() || !f.canWrite()) {
586
                                RasterToolsUtil.messageBoxError(RasterToolsUtil.getText(this, "path_not_valid"), null);
587
                                return;
588
                        }
589
                } else
590
                        path = Utilities.createTempDirectory();
591

    
592
                String file = getOptionsPanel().getFilenameTextField().getText();
593
                if (file.compareTo(RasterLocator.getManager().getFileUtils().getOnlyLayerName()) == 0)
594
                        RasterLocator.getManager().getFileUtils().usesOnlyLayerName();
595

    
596
                if (file == "")
597
                        file = "cutlayer";
598

    
599
                String filename = path + File.separator + file;
600

    
601
                if (new File(filename + ".tif").exists())
602
                        if (!RasterToolsUtil.messageBoxYesOrNot("raster_error_file_exists", getOptionsPanel()))
603
                                return;
604

    
605
                /**
606
                 * Preparacion para la generacion del proceso del recorte
607
                 */
608
                if (getFLayer() == null)
609
                        return;
610

    
611
                AffineTransform transf = null;
612
                if(pxRound && 
613
                   ((pxValues[2] - pxValues[0] + 1) == data.getPxWidth()) && 
614
                   ((pxValues[3] - pxValues[1] + 1) == data.getPxHeight()))
615
                        transf = new AffineTransform(at.getScaleX(), at.getShearY(), at.getShearX(), at.getScaleY(), wcValues[0], wcValues[1]);
616
                else
617
                        transf = calcAffineTransform(wcValues[0], wcValues[1], wcValues[2], wcValues[3],
618
                                                                                Math.round(data.getPxWidth()), Math.round(data.getPxHeight()), at);
619
                
620

    
621
                int interpMethod = getResolutionPanel().getSelectedInterpolationMethod();
622

    
623
                // Creamos la interpretaci?n de color para el caso de que la salida tenga
624
                // m?s de una banda por fichero. Siempre creamos RED, GREEN y BLUE
625
                String[] ci = new String[drawableBands.length];
626
                for (int j = 0; j < ci.length; j++) {
627
                        switch (j) {
628
                                case 0:
629
                                        if (ci.length >= 3)
630
                                                ci[j] = ColorInterpretation.RED_BAND;
631
                                        else
632
                                                ci[j] = ColorInterpretation.GRAY_BAND;
633
                                        break;
634
                                case 1:
635
                                        if (ci.length >= 3)
636
                                                ci[j] = ColorInterpretation.GREEN_BAND;
637
                                        else
638
                                                ci[j] = ColorInterpretation.UNDEF_BAND;
639
                                        break;
640
                                case 2:
641
                                        ci[j] = ColorInterpretation.BLUE_BAND;
642
                                        break;
643
                                default:
644
                                        ci[j] = ColorInterpretation.UNDEF_BAND;
645
                                        break;
646
                        }
647
                }
648

    
649
                RasterProcess clippingProcess = new ClippingProcess();
650
                clippingProcess.setActions(this);
651
                clippingProcess.addParam("viewname", getViewName());
652
                if(pxRound)
653
                        clippingProcess.addParam("pixelcoordinates", pxValues);
654
                else
655
                        clippingProcess.addParam("realcoordinates", wcValues);
656
                clippingProcess.addParam("filename", filename);
657
                clippingProcess.addParam("layer", getFLayer());
658
                clippingProcess.addParam("drawablebands", drawableBands);
659
                clippingProcess.addParam("onelayerperband", new Boolean(getOptionsPanel().getCbOneLyrPerBand().isSelected()));
660
                clippingProcess.addParam("interpolationmethod", new Integer(interpMethod));
661
                clippingProcess.addParam("affinetransform", transf);
662
                clippingProcess.addParam("colorInterpretation",  RasterLocator.getManager().createColorInterpretation(ci));
663
                clippingProcess.addParam("resolution", new int[]{(int) Math.round(data.getPxWidth()),
664
                                                                                                                 (int) Math.round(data.getPxHeight())});
665
                clippingProcess.start();
666
        }
667

    
668
        /**
669
         * Calcula la matriz de transformaci?n que se usar? para el nuevo raster generado.
670
         * @param ulx Coordenada X real de la esquina superior izquierda
671
         * @param uly Coordenada Y real de la esquina superior izquierda
672
         * @param lrx Coordenada X real de la esquina inferior derecha
673
         * @param lry Coordenada Y real de la esquina inferior derecha
674
         * @param width Ancho en p?xeles del nuevo raster
675
         * @param height Alto en p?xeles del nuevo raster
676
         * @param trans Matriz de transformaci?n de la nueva capa
677
         * @return Matriz de transformaci?n para el nuevo raster
678
         */
679
        private AffineTransform calcAffineTransform(double ulx, double uly, double lrx, double lry,
680
                                                                                                double width, double height, AffineTransform trans) {
681
                Point2D ul = new Point2D.Double(ulx, uly);
682
                Point2D lr = new Point2D.Double(lrx, lry);
683
                try {
684
                        trans.inverseTransform(ul, ul);
685
                        trans.inverseTransform(lr, lr);
686
                } catch (NoninvertibleTransformException e) {
687
                        JOptionPane.showMessageDialog(null, RasterToolsUtil.getText(this, "coordenadas_erroneas"));
688
                        return new AffineTransform();
689
                }
690
                double w = Math.abs(lr.getX() - ul.getX());
691

    
692
                Point2D ur = new Point2D.Double(ul.getX() + w, ul.getY());
693
                Point2D ll = new Point2D.Double(lr.getX() - w, lr.getY() );
694

    
695
                //Obtenemos la georreferenciaci?n de las cuatro esquinas del nuevo raster
696
                trans.transform(ul, ul);
697
                trans.transform(ur, ur);
698
                trans.transform(lr, lr);
699
                trans.transform(ll, ll);
700

    
701
                double pixelSizeX = (lrx - ulx) / width;
702
                double pixelSizeY = (lry - uly) / height;
703
                double rotX = trans.getShearX();
704
                double rotY = trans.getShearY();
705
                return new AffineTransform(pixelSizeX, rotY, rotX, pixelSizeY, ulx, uly);
706
        }
707
        
708
        /**
709
         * Returns true if the pixels are round
710
         * @param pxValues
711
         * @return
712
         */
713
        private boolean arePixelsRound(double[] pxValues) {
714
                if((((int)pxValues[0]) - pxValues[0]) == 0 &&
715
                   (((int)pxValues[1]) - pxValues[1]) == 0 &&
716
                   (((int)pxValues[2]) - pxValues[2]) == 0 &&
717
                   (((int)pxValues[3]) - pxValues[3]) == 0) {
718
                        return true;
719
                }
720
                return false;
721
        }
722

    
723
        /*
724
         * (non-Javadoc)
725
         * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#cancelDrawing()
726
         */
727
        public boolean cancelDrawing() {
728
                return false;
729
        }
730

    
731
        /*
732
         * (non-Javadoc)
733
         * @see com.iver.cit.gvsig.fmap.tools.Listeners.ToolListener#getCursor()
734
         */
735
        public Cursor getCursor() {
736
                return null;
737
        }
738

    
739
        /*
740
         * (non-Javadoc)
741
         * @see org.gvsig.gui.beans.coordinatespanel.CoordinatesListener#actionValueChanged(org.gvsig.gui.beans.coordinatespanel.CoordinatesEvent)
742
         */
743
        public void actionValueChanged(CoordinatesEvent e) {
744
                if (e.getSource() == getCoordinatesPanel().getPixelCoordinates()) {
745
                        eventJTextField(e);
746
                        if (e.getName().equals("11") || 
747
                                e.getName().equals("12") || 
748
                                e.getName().equals("21") ||
749
                                e.getName().equals("22"))
750
                                recalcCoordFields(true);
751
                        
752
                }
753
                if (e.getSource() == getCoordinatesPanel().getRealCoordinates()) {
754
                        eventJTextField(e);
755
                        if (e.getName().equals("11") || 
756
                                e.getName().equals("12") || 
757
                                e.getName().equals("21") || 
758
                                e.getName().equals("22"))
759
                                recalcCoordFields(false);
760
                }
761
        }
762

    
763
        /*
764
         * (non-Javadoc)
765
         * @see org.gvsig.gui.beans.datainput.DataInputContainerListener#actionValueChanged(java.util.EventObject)
766
         */
767
        public void actionValueChanged(EventObject e) {
768
                if(!enableValueChangedEvent)
769
                        return;
770

    
771
                enableValueChangedEvent = false; //Desactivamos el evento de cambio de valor de las cajas de texto para que no se bucle
772

    
773
                if (e.getSource() == getResolutionPanel().getCCellSize().getDataInputField()) {
774
                        // Cambiamos PS ==> wPx=wWC/PS & hPx=wPx/rel
775
                        double ps = 0;
776
                        try {
777
                                ps = Double.parseDouble(getResolutionPanel().getCCellSize().getValue());
778
                        } catch (NumberFormatException ex) {
779
                                return;
780
                        }
781
                        data.setPxWidth(data.getWcWidth() / ps);
782
                        data.setPxHeight(data.getWcHeight() / ps);
783
                        data.updateObservers();
784
                } else if (e.getSource() == getResolutionPanel().getCWidth().getDataInputField()) {
785
                        // Cambiamos wPx ==> hPx=wPx/rel & PS=wWC/wPx
786
                        double wPx = 0;
787
                        try {
788
                                wPx = Double.parseDouble(getResolutionPanel().getCWidth().getValue());
789
                        } catch (NumberFormatException ex) {
790
                                return;
791
                        }
792
                        data.setPxWidth(wPx);
793
                        data.setPxHeight(Math.round(wPx / data.getRatio()));
794
                        data.updateObservers();
795
                } else if (e.getSource() == getResolutionPanel().getCHeight().getDataInputField()) {
796
                        // Cambiamos hPx ==> wPx=rel*wPx & PS=hWC/hPx
797
                        double hPx = 0;
798
                        try {
799
                                hPx = Double.parseDouble(getResolutionPanel().getCHeight().getValue());
800
                        } catch (NumberFormatException ex) {
801
                                return;
802
                        }
803
                        data.setPxHeight(hPx);
804
                        data.setPxWidth(Math.round(Math.round(hPx * data.getRatio())));
805
                        data.updateObservers();
806
                }
807
                enableValueChangedEvent = true;
808
        }
809

    
810
        /**
811
         * Asigna el valor para la activaci?n y desactivaci?n del evento de cambio de valor en
812
         * las cajas de texto.
813
         * @param enableValueChangedEvent
814
         */
815
        public void setEnableValueChangedEvent(boolean enableValueChangedEvent) {
816
                this.enableValueChangedEvent = enableValueChangedEvent;
817
        }
818

    
819
        /*
820
         * (non-Javadoc)
821
         * @see org.gvsig.raster.IProcessActions#end(java.lang.Object)
822
         */
823
        public void end(Object params) {
824
                if(        params instanceof Object[] &&
825
                        ((Object[])params).length == 2 &&
826
                        ((Object[])params)[0] instanceof String &&
827
                        ((Object[])params)[1] instanceof Long) {
828

    
829
                        String fName = (String)((Object[])params)[0];
830
                        long milis = ((Long)((Object[])params)[1]).longValue();
831

    
832
                        EndInfoDialog.show(fName, milis);
833
                }
834
        }
835

    
836
        /**
837
         * Obtener la capa de un raster.
838
         * @return
839
         */
840
        public FLyrRaster getFLayer() {
841
                return fLayer;
842
        }
843

    
844
        /**
845
         * Obtiene la ultima herramienta seleccionada antes de cargar el recorte
846
         * @return
847
         */
848
        public String getLastTool() {
849
                return lastTool;
850
        }
851

    
852
        /**
853
         * Obtiene el nombre de la vista
854
         * @return
855
         */
856
        public String getViewName() {
857
                return viewName;
858
        }
859

    
860
        /**
861
         * Establecer la capa para usarla en el recorte
862
         * @param fLayer
863
         */
864
        public void setLayer(FLyrRaster fLayer) {
865
                this.fLayer = fLayer;
866
                AbstractViewPanel view = (AbstractViewPanel) PluginServices.getMDIManager().getActiveWindow();
867
                viewName = PluginServices.getMDIManager().getWindowInfo(view).getTitle();
868
                mapControl = view.getMapControl();
869

    
870
                lastTool = mapControl.getCurrentTool();
871

    
872
                // Listener de eventos de movimiento que pone las coordenadas del rat?n en
873
                // la barra de estado
874
                StatusBarListener sbl = new StatusBarListener(mapControl);
875

    
876
                // Cortar Raster
877
                ClippingMouseViewListener clippingMouseViewListener = new ClippingMouseViewListener(mapControl, getClippingPanel(), data, fLayer);
878
                mapControl.addBehavior("cutRaster", new Behavior[] {
879
                                new RectangleBehavior(clippingMouseViewListener), new MouseMovementBehavior(sbl)
880
                        }
881
                );
882

    
883
                getSelectionPanel().setLayer(fLayer);
884

    
885
                // Obtener la extension completa de la capa
886

    
887
                setAffineTransform(fLayer.getAffineTransform());
888
                setDimension(new Dimension((int)fLayer.getPxWidth(), (int)fLayer.getPxHeight()));
889
                
890
                //Limitaciones del recorte para un servicio remoto
891
                //1-Interpolaci?n deshabilitada. Se hace la petici?n al servidor de los pixeles que queramos
892
                //2-No se pueden intercambiar bandas. Puede hacerse a posteriori cuando ya est? en disco
893
                //3-No se puede seleccionar por coordenadas pixel. Si la fuente es WebMapService puede no tener resoluci?n 
894
                //en pixeles por lo que puede no tener sentido este tipo de selecci?n
895
                if(getFLayer().isRemote()) {
896
                        getResolutionPanel().getComboInterpolation().setEnabled(false);
897
                        getClippingPanel().removeTab(getSelectionPanel());
898
                        getCoordinatesPanel().getPixelCoordinates().setVisible(false);
899
                }
900
        }
901

    
902
        /**
903
         * Acciones que se realizan para seleccionar la tool CutRaster
904
         */
905
        public void selectToolButton() {
906
                // seleccionamos la vista de gvSIG
907
                org.gvsig.app.project.documents.view.gui.AbstractViewPanel theView = null;
908
                try {
909
                        IWindow[] allViews = PluginServices.getMDIManager().getAllWindows();
910
                        for (int i = 0; i < allViews.length; i++) {
911
                                if (allViews[i] instanceof org.gvsig.app.project.documents.view.gui.AbstractViewPanel
912
                                                && PluginServices.getMDIManager().getWindowInfo((AbstractViewPanel) allViews[i])
913
                                                                .getTitle().equals(viewName))
914
                                        theView = (org.gvsig.app.project.documents.view.gui.AbstractViewPanel) allViews[i];
915
                        }
916
                        if (theView == null)
917
                                return;
918
                } catch (ClassCastException ex) {
919
                        // RasterToolsUtil.messageBoxError("cant_get_view "), this, ex);
920
                        return;
921
                }
922
                MapControl m_MapControl = theView.getMapControl();
923

    
924
                // Listener de eventos de movimiento que pone las coordenadas del rat?n en
925
                // la barra de estado
926
                //StatusBarListener sbl = new StatusBarListener(m_MapControl);
927

    
928
                // Cortar Raster
929
                /*ClippingMouseViewListener clippingMouseViewListener = new ClippingMouseViewListener(m_MapControl, getClippingPanel(), data, getFLayer());
930
                m_MapControl.addMapTool("cutRaster", new Behavior[] {
931
                                new RectangleBehavior(clippingMouseViewListener), new MouseMovementBehavior(sbl)
932
                                }
933
                );*/
934

    
935
                m_MapControl.setTool("clipRaster");
936
        }
937

    
938
        /**
939
         * Obtiene el <code>MapControl</code> de gvSIG
940
         * @return <code>MapControl</code>
941
         */
942
        public MapControl getMapControl() {
943
                return mapControl;
944
        }
945

    
946

    
947
        public void rectangle(EnvelopeEvent event) throws BehaviorException {}
948
        public void interrupted() {}
949

    
950
        /*
951
         * (non-Javadoc)
952
         * @see org.gvsig.fmap.mapcontrol.tools.Listeners.ToolListener#getImageCursor()
953
         */
954
        public Image getImageCursor() {
955
                return null;
956
        }
957
}