Statistics
| Revision:

root / trunk / extensions / extRasterTools-SE / src / org / gvsig / raster / beans / canvas / layers / functions / StraightLine.java @ 20057

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.raster.beans.canvas.layers.functions;
20

    
21
import java.awt.Color;
22
import java.awt.Cursor;
23
import java.awt.Graphics;
24
import java.awt.Image;
25
import java.awt.Point;
26
import java.awt.Toolkit;
27
import java.awt.event.MouseEvent;
28
import java.awt.image.MemoryImageSource;
29
import java.util.ArrayList;
30

    
31
import org.gvsig.raster.beans.canvas.GCanvas;
32
import org.gvsig.raster.beans.canvas.layers.InfoLayer;
33
import org.gvsig.raster.util.MathUtils;
34
/**
35
 * Representa una linea recta con puntos de arrastre para la ecualizaci?n de
36
 * un histograma y realce lineales y dencity slicing.
37
 *
38
 * 14-oct-2007
39
 * @author Nacho Brodin (nachobrodin@gmail.com)
40
 */
41
public class StraightLine extends BaseFunction {
42

    
43
        /**
44
         * Representa un punto seleccionado sobre el canvas. Este es
45
         * dibujado como un peque?o cuadrado.
46
         *
47
         * 14-oct-2007
48
         * @author Nacho Brodin (nachobrodin@gmail.com)
49
         */
50
        class Square {
51
                private double x      = 0.0D;
52
                private double y      = 0.0D;
53
                private int    width  = 6;
54
                private Color  color  = Color.WHITE;
55
                
56
                
57
                /**
58
                 * Constructor. Calcula las esquinas del cuadrado
59
                 * @param p
60
                 */
61
                public Square(double x, double y) {
62
                        setPosition(x, y);
63
                }
64

    
65
                /**
66
                 * Constructor. Calcula las esquinas del cuadrado
67
                 * @param p
68
                 */
69
                public Square(int x, int y) {
70
                        setPosition(x, y);
71
                }
72
                
73
                /**
74
                 * Asigna una nueva posici?n al punto
75
                 * @param x
76
                 */
77
                public void setPosition(double x, double y) {
78
                        this.x = x;
79
                        this.y = y;
80

    
81
                        if (this.x > 1.0D) this.x = 1.0D;
82
                        if (this.x < 0.0D) this.x = 0.0D;
83
                        if (this.y > 1.0D) this.y = 1.0D;
84
                        if (this.y < 0.0D) this.y = 0.0D;
85
                }
86
                
87
                /**
88
                 * Asigna una nueva posici?n al punto
89
                 * @param x
90
                 */
91
                public void setPosition(int x, int y) {
92
                        setPosition(pixelToValueX(x), pixelToValueY(y));
93
                }
94
                
95
                public int getPixelX() {
96
                        return valueToPixelX(x);
97
                }
98

    
99
                public int getPixelY() {
100
                        return valueToPixelY(y);
101
                }
102
                
103
                public double getX() {
104
                        return x;
105
                }
106
                
107
                public double getY() {
108
                        return y;
109
                }
110
                
111
                /**
112
                 * Dibuja el cuadrado
113
                 * @param g
114
                 */
115
                protected void paint(Graphics g) {
116
                        g.setColor(color);
117
                        g.drawRect((int) valueToPixelX(x) - (width >> 1), (int) valueToPixelY(y) - (width >> 1), (int) width, (int)width);
118
                }
119

    
120
                /**
121
                 * Dibuja el cursor degetVisibleRect().widthl raton
122
                 * @param g
123
                 */
124
                protected void paintCursor(Graphics g) {
125
                        g.setColor(Color.white);
126
                        g.drawLine(valueToPixelX(x) - 6, valueToPixelY(y), valueToPixelX(x) + 6, valueToPixelY(y));
127
                        g.drawLine(valueToPixelX(x), valueToPixelY(y) - 6, valueToPixelX(x), valueToPixelY(y) + 6);
128
                }
129
                
130
                /**
131
                 * Informa de si el punto pasado por par?metro cae dentro del cuadro o no
132
                 * @param p Punto a comprobar
133
                 * @return true si el punto est? dentro y false si no lo est?
134
                 */
135
                public boolean isInside(Point p) {
136
                        if (p.getX() < (valueToPixelX(x) - (width >> 1)))
137
                                return false;
138
                        if (p.getX() > (valueToPixelX(x) + (width >> 1)))
139
                                return false;
140
                        if (p.getY() < (valueToPixelY(y) - (width >> 1)))
141
                                return false;
142
                        if (p.getY() > (valueToPixelY(y) + (width >> 1)))
143
                                return false;
144
                        return true;
145
                }
146
                
147
                /**
148
                 * Asigna el color del cuadrado
149
                 * @param c Color
150
                 */
151
                public void setColor(Color c) {
152
                        this.color = c;
153
                }
154
                
155
                private int valueToPixelX(double value) {
156
                        value = minx + ((maxx - minx) * value);
157
                        return (int) Math.round(canvas.getCanvasMinX() + border + ((canvas.getCanvasMaxX() - canvas.getCanvasMinX() - (border * 2)) * value));
158
                }
159

    
160
                private int valueToPixelY(double value) {
161
                        value = 1.0D - value;
162
                        return (int) Math.round(canvas.getCanvasMinY() + border + ((canvas.getCanvasMaxY() - canvas.getCanvasMinY() - (border * 2)) * value));
163
                }
164

    
165
        }
166
        
167
        /**
168
         * Lista de cuadrados que intersectan con la recta
169
         */
170
        protected ArrayList listSquare        = new ArrayList();
171
        private int         pointDragged      = -1;
172
        private Cursor      transparentCursor = null;
173
        private boolean     showSquares       = true;
174
        private int         border            = 2;
175
        
176
        /**
177
         * Constructor. Asigna el color
178
         * @param c
179
         */
180
        public StraightLine(Color c) {
181
                int[] pixels = new int[16 * 16];
182
                Image image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(16, 16, pixels, 0, 16));
183
                transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(0, 0), "invisibleCursor");
184
                
185
                setColor(c);
186
                listSquare.add(new Square(0.0D, 0.0D));
187
                listSquare.add(new Square(1.0D, 1.0D));
188
        }
189
        
190
        /**
191
         * Dibujado de las l?neas y cuadros sobre el canvas
192
         */
193
        protected void paint(Graphics g) {
194
                super.paint(g);
195

    
196
                g.setColor(color);
197

    
198
                // Dibujamos una l?nea desde un punto hasta el siguiente
199
                Square square = null;
200
                Square lastSquare = null;
201

    
202
                if (listSquare.size() > 0) {
203
                        square = ((Square) listSquare.get(0));
204
                        g.drawLine(canvas.getCanvasMinX(), square.getPixelY(), square.getPixelX(), square.getPixelY());
205
                }
206
                for (int i = 0; i < listSquare.size(); i++) {
207
                        lastSquare = square;
208
                        square = ((Square) listSquare.get(i));
209
                        if (lastSquare != null)
210
                                g.drawLine(lastSquare.getPixelX(), lastSquare.getPixelY(), square.getPixelX(), square.getPixelY());
211
                }
212
                if (listSquare.size() > 0) {
213
                        square = ((Square) listSquare.get(listSquare.size() - 1));
214
                        g.drawLine(square.getPixelX(), square.getPixelY(), canvas.getCanvasMaxX(), square.getPixelY());
215
                }
216

    
217
                // Dibujamos los cuadrados de los puntos
218
                if (showSquares) {
219
                        for (int i = 0; i < listSquare.size(); i++) {
220
                                square = ((Square) listSquare.get(i));
221
                                square.setColor(color);
222
                                if (pointDragged != i)
223
                                        square.paint(g);
224
                                else
225
                                        square.paintCursor(g);
226
                        }
227
                }
228

    
229
                if (pointDragged != -1) {
230
                        setInfoPoint(pointDragged);
231
                }
232
        }
233
        
234
        /**
235
         * Visualiza la posicion de un punto en la barra de estado
236
         * @param square
237
         */
238
        private void setInfoPoint(int point) {
239
                ArrayList list = canvas.getDrawableElements(InfoLayer.class);
240
                if (list.size() > 0) {
241
                        InfoLayer infoLayer = (InfoLayer) list.get(0);
242
                        if (point != -1) {
243
                                Square square = ((Square) listSquare.get(point));
244
                                
245
                                double value = minx + (square.getX() * (maxx - minx));
246
                                value = infoLayer.getMin() + (value * (infoLayer.getMax() - infoLayer.getMin()));
247
                                
248
                                infoLayer.setStatusLeft("In: " + MathUtils.clipDecimals(value, 1));
249
                                infoLayer.setStatusRight("Out: " + Math.round(square.getY() * 255.0D));
250
                        } else {
251
                                infoLayer.setStatusLeft(null);
252
                                infoLayer.setStatusRight(null);
253
                        }
254
                }
255
        }
256

    
257
        /**
258
         * Asigna el objeto JComponent donde se pintan los elementos. Inicializa los puntos
259
         * de inicio y fin de l?nea y asigna los listener
260
         * @param canvas
261
         */
262
        public void setCanvas(GCanvas canvas) {
263
                super.setCanvas(canvas);
264
        }
265
        
266
        /**
267
         * Inserta un elemento (cuadrado) en el array entre los dos cuadrados entre los que se
268
         * encuentre el valor de su X, as? siempre est?n ordenados en el array por valor de X. 
269
         * @param element
270
         * @return Devuelve la posici?n del elemento insertado, en caso de no poder insertarse
271
         *         devolver? -1
272
         */
273
        private int insert(Square element) {
274
                for (int i = 0; i < (listSquare.size() - 1); i++) {
275
                        double sqX = ((Square) listSquare.get(i)).getX();
276
                        double sqNextX = ((Square) listSquare.get(i + 1)).getX();
277
                        if (element.getX() >= sqX && element.getX() <= sqNextX) {
278
                                listSquare.add(i + 1, element);
279
                                return i + 1;
280
                        }
281
                }
282
                return -1;
283
        }
284
        
285
        /**
286
         * Se captura el punto a arrastrar, en caso de que no coincida con un punto,
287
         * se inserta
288
         */
289
        public boolean mousePressed(MouseEvent e) {
290
                for (int i = 0; i < listSquare.size(); i++) {
291
                        if (((Square) listSquare.get(i)).isInside(e.getPoint())) {
292
                                if ((e.getModifiersEx() & MouseEvent.BUTTON3_DOWN_MASK) != 0) {
293
                                        if ((i == 0) || ((i + 1) == listSquare.size()))
294
                                                continue;
295
                                        pointDragged = -1;
296
                                        listSquare.remove(i);
297
                                        canvas.repaint();
298
                                        return false;
299
                                }
300
                                if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) != 0) {
301
                                        pointDragged = i;
302
                                        this.mouseDragged(e);
303
                                        return false;
304
                                }
305
                        }
306
                }
307

    
308
                if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
309
                        return true;
310
                // En caso de que nadie lo este tratando, osea, un cursor normal
311
                if (canvas.getCursor().getType() == Cursor.DEFAULT_CURSOR) {
312
                        pointDragged = insert(new Square(e.getX(), e.getY()));
313
                        this.mouseDragged(e);
314
                        return false;
315
                }
316
                return true;
317
        }
318

    
319
        /**
320
         * Inicializamos el punto arrastrado a un valor fuera del array
321
         */
322
        public boolean mouseReleased(MouseEvent e) {
323
                pointDragged = -1;
324
                setInfoPoint(-1);
325
                canvas.repaint();
326
                canvas.callDataChanged("line", this);
327
                return true;
328
        }
329

    
330
        /**
331
         * Cuando se ha pinchado un punto y se arrastra se define aqu? su comportamiento.
332
         */
333
        public boolean mouseDragged(MouseEvent e) {
334
                if (pointDragged >= 0) {
335
                        canvas.setCursor(transparentCursor);
336
                        int minX = canvas.getCanvasMinX();
337
                        int minY = canvas.getCanvasMinY();
338
                        int maxX = canvas.getCanvasMaxX();
339
                        int maxY = canvas.getCanvasMaxY();
340

    
341
                        // Controlamos que no se salga de los l?mites
342
                        int x = Math.min(Math.max(e.getX(), minX), maxX);
343
                        int y = Math.min(Math.max(e.getY(), minY), maxY);
344
                        Square point = ((Square) listSquare.get(pointDragged));
345

    
346
                        try {
347
                                // El primer punto no se desplaza en X
348
                                if (pointDragged == 0) {
349
                                        point.setPosition(minX, y);
350
                                        return false;
351
                                }
352
                                // El ?ltimo punto no se desplaza en X
353
                                if (pointDragged == (listSquare.size() - 1)) {
354
                                        point.setPosition(maxX, y);
355
                                        return false;
356
                                }
357

    
358
                                // Puntos centrales
359
                                point.setPosition(x, y);
360

    
361
                                // Arrastra a los de abajo si la X es menor que los inferiores
362
                                for (int i = 0; i < pointDragged; i++) {
363
                                        Square lowPoint = ((Square) listSquare.get(i));
364
                                        if (lowPoint.getPixelX() >= x) {
365
                                                lowPoint.setPosition(x, lowPoint.getPixelY());
366
                                                for (int j = i + 1; listSquare.get(j) != point;) {
367
                                                        listSquare.remove(j);
368
                                                        pointDragged--;
369
                                                }
370
                                                break;
371
                                        }
372
                                }
373

    
374
                                // Arrastra a los de arriba si la X es mayor que los superiores
375
                                for (int i = listSquare.size() - 1; i > pointDragged; i--) {
376
                                        Square upperPoint = ((Square) listSquare.get(i));
377
                                        if (upperPoint.getPixelX() <= x) {
378
                                                upperPoint.setPosition(x, upperPoint.getPixelY());
379
                                                for (int j = i - 1; listSquare.get(j) != point;) {
380
                                                        listSquare.remove(j);
381
                                                        j--;
382
                                                }
383
                                                break;
384
                                        }
385
                                }
386
                        } finally {
387
                                // Siempre repintamos
388
                                canvas.repaint();
389
                                canvas.callDataDragged("line", this);
390
                        }
391
                        return false;
392
                }
393
                return true;
394
        }
395

    
396
        /**
397
         * Variable para saber si se ha visualizado alguna informacion
398
         */
399
        boolean last = false;
400
        /*
401
         * (non-Javadoc)
402
         * @see org.gvsig.raster.beans.canvas.DrawableElement#mouseMoved(java.awt.event.MouseEvent)
403
         */
404
        public boolean mouseMoved(MouseEvent e) {
405
                for (int i = 0; i < listSquare.size(); i++) {
406
                        if (((Square)listSquare.get(i)).isInside(e.getPoint())) {
407
                                canvas.setCursor(new Cursor(Cursor.MOVE_CURSOR));
408
                                setInfoPoint(i);
409
                                canvas.repaint();
410
                                last = true;
411
                                return false;
412
                        }
413
                }
414
                if (last) {
415
                        setInfoPoint(-1);
416
                        canvas.repaint();
417
                        last = false;
418
                }
419
                return true;
420
        }
421

    
422
        /**
423
         * Valores de los datos de entrada correspondientes al m?nimo y al m?ximo de 
424
         * cada tramo. Estos tendr?n un rango entre el m?nimo y el m?ximo en cada
425
         * banda de la imagen.
426
         * @param min
427
         * @param max
428
         * @return
429
         */
430
        public double[] getInValues(double min, double max) {
431
                double[] in = getPercentInValues(); 
432
                for (int i = 0; i < in.length; i++)
433
                        in[i] = min + (in[i] * (max - min));
434
                return in;
435
        }
436

    
437
        /**
438
         * Valores de los datos de salida correspondientes al m?nimo y al m?ximo de
439
         * cada tramo. Estos tendr?n un rango entre 0 y 255.
440
         * @return
441
         */
442
        public int[] getOutValues() {
443
                double[] values = getPercentOutValues(); 
444
                int[] out = new int[values.length];
445
                for (int i = 0; i < values.length; i++)
446
                        out[i] = (int) Math.round(values[i] * 255.0D);
447
                return out;
448
        }
449

    
450
        /**
451
         * Valores de los datos de entrada correspondientes al m?nimo y al m?ximo de 
452
         * cada tramo devuelto en forma de porcentaje
453
         * 
454
         * @param min
455
         * @param max
456
         * @return
457
         */
458
        public double[] getPercentInValues() {
459
                double[] in = new double[listSquare.size() + 2];
460
                for (int i = 0; i < listSquare.size(); i++) {
461
                        Square square = ((Square) listSquare.get(i));
462
                        in[i + 1] = minx + ((maxx - minx) * square.getX());
463
                }
464
                in[0] = 0.0D;
465
                in[in.length - 1] = 1.0D;
466
                return in;
467
        }
468

    
469
        /**
470
         * Valores de los datos de salida correspondientes al m?nimo y al m?ximo de
471
         * cada tramo, devueltos en forma de porcentaje.
472
         * @return
473
         */
474
        public double[] getPercentOutValues() {
475
                double[] out = new double[listSquare.size() + 2];
476
                for (int i = 0; i < listSquare.size(); i++) {
477
                        Square square = ((Square) listSquare.get(i));
478
                        out[i + 1] = square.getY();
479
                }
480
                out[0] = out[1];
481
                out[out.length - 1] = out[out.length - 2];
482
                return out;
483
        }
484
        
485
        public void firstActions() {}
486
        public void firstDrawActions() {}
487

    
488
        /**
489
         * @param showSquares the showSquares to set
490
         */
491
        public void setShowSquares(boolean showSquares) {
492
                this.showSquares = showSquares;
493
        }
494

    
495
        protected double pixelToValueX(int pixel) {
496
                double value = ((double) (pixel - canvas.getCanvasMinX() - border) / (double) (canvas.getCanvasMaxX() - canvas.getCanvasMinX() - (border * 2.0D)));
497
                
498
                value = (value - minx) / (maxx - minx);
499
                
500
                return value;
501
        }
502

    
503
        protected double pixelToValueY(int pixel) {
504
                double div = (double) (canvas.getCanvasMaxY() - canvas.getCanvasMinY() - (border * 2.0D));
505
                if (div == 0.0D)
506
                        return 0.0D;
507
                
508
                return (1.0D - ((double) (pixel - canvas.getCanvasMinY() - border) / div));
509
        }
510
        
511
        /**
512
         * Devuelve 0 para indicar que estamos en una funcion lineal.
513
         * @return
514
         */
515
        public int getFunctionType() {
516
                return 0;
517
        }
518
        
519
        /**
520
         * En una funci?n lineal da igual lo que devuelva, pero es interesante para sus
521
         * clases derivadas
522
         * @return
523
         */
524
        public double getValueFunction() {
525
                return 0.0;
526
        }
527
}