Statistics
| Revision:

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

History | View | Annotate | Download (14.5 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 del 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
                clearSquares();
187
                addSquare(0.0D, 0.0D);
188
                addSquare(1.0D, 1.0D);
189
        }
190

    
191
        /**
192
         * Borra la lista de puntos
193
         */
194
        public void clearSquares() {
195
                listSquare.clear();
196
        }
197

    
198
        /**
199
         * A?ade un punto a la lista de puntos
200
         * @param x
201
         * @param y
202
         */
203
        public void addSquare(double x, double y) {
204
                listSquare.add(new Square(x, y));
205
        }
206
        
207
        /**
208
         * Dibujado de las l?neas y cuadros sobre el canvas
209
         */
210
        protected void paint(Graphics g) {
211
                super.paint(g);
212

    
213
                g.setColor(color);
214

    
215
                // Dibujamos una l?nea desde un punto hasta el siguiente
216
                Square square = null;
217
                Square lastSquare = null;
218

    
219
                if (listSquare.size() > 0) {
220
                        square = ((Square) listSquare.get(0));
221
                        g.drawLine(canvas.getCanvasMinX(), square.getPixelY(), square.getPixelX(), square.getPixelY());
222
                }
223
                for (int i = 0; i < listSquare.size(); i++) {
224
                        lastSquare = square;
225
                        square = ((Square) listSquare.get(i));
226
                        if (lastSquare != null)
227
                                g.drawLine(lastSquare.getPixelX(), lastSquare.getPixelY(), square.getPixelX(), square.getPixelY());
228
                }
229
                if (listSquare.size() > 0) {
230
                        square = ((Square) listSquare.get(listSquare.size() - 1));
231
                        g.drawLine(square.getPixelX(), square.getPixelY(), canvas.getCanvasMaxX(), square.getPixelY());
232
                }
233

    
234
                // Dibujamos los cuadrados de los puntos
235
                if (showSquares) {
236
                        for (int i = 0; i < listSquare.size(); i++) {
237
                                square = ((Square) listSquare.get(i));
238
                                square.setColor(color);
239
                                if (pointDragged != i)
240
                                        square.paint(g);
241
                                else
242
                                        square.paintCursor(g);
243
                        }
244
                }
245

    
246
                if (pointDragged != -1) {
247
                        setInfoPoint(pointDragged);
248
                }
249
        }
250
        
251
        /**
252
         * Visualiza la posicion de un punto en la barra de estado
253
         * @param square
254
         */
255
        private void setInfoPoint(int point) {
256
                ArrayList list = canvas.getDrawableElements(InfoLayer.class);
257
                if (list.size() > 0) {
258
                        InfoLayer infoLayer = (InfoLayer) list.get(0);
259
                        if (point != -1) {
260
                                Square square = ((Square) listSquare.get(point));
261
                                
262
                                double value = minx + (square.getX() * (maxx - minx));
263
                                value = infoLayer.getMin() + (value * (infoLayer.getMax() - infoLayer.getMin()));
264
                                
265
                                infoLayer.setStatusLeft("In: " + MathUtils.clipDecimals(value, 1));
266
                                infoLayer.setStatusRight("Out: " + Math.round(square.getY() * 255.0D));
267
                        } else {
268
                                infoLayer.setStatusLeft(null);
269
                                infoLayer.setStatusRight(null);
270
                        }
271
                }
272
        }
273

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

    
325
                if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0)
326
                        return true;
327
                // En caso de que nadie lo este tratando, osea, un cursor normal
328
                if (canvas.getCursor().getType() == Cursor.DEFAULT_CURSOR) {
329
                        pointDragged = insert(new Square(e.getX(), e.getY()));
330
                        this.mouseDragged(e);
331
                        return false;
332
                }
333
                return true;
334
        }
335

    
336
        /**
337
         * Inicializamos el punto arrastrado a un valor fuera del array
338
         */
339
        public boolean mouseReleased(MouseEvent e) {
340
                pointDragged = -1;
341
                setInfoPoint(-1);
342
                canvas.repaint();
343
                canvas.callDataChanged("line", this);
344
                return true;
345
        }
346

    
347
        /**
348
         * Cuando se ha pinchado un punto y se arrastra se define aqu? su comportamiento.
349
         */
350
        public boolean mouseDragged(MouseEvent e) {
351
                if (pointDragged >= 0) {
352
                        canvas.setCursor(transparentCursor);
353
                        int minX = canvas.getCanvasMinX();
354
                        int minY = canvas.getCanvasMinY();
355
                        int maxX = canvas.getCanvasMaxX();
356
                        int maxY = canvas.getCanvasMaxY();
357

    
358
                        // Controlamos que no se salga de los l?mites
359
                        int x = Math.min(Math.max(e.getX(), minX), maxX);
360
                        int y = Math.min(Math.max(e.getY(), minY), maxY);
361
                        Square point = ((Square) listSquare.get(pointDragged));
362

    
363
                        try {
364
                                // El primer punto no se desplaza en X
365
                                if (pointDragged == 0) {
366
                                        point.setPosition(minX, y);
367
                                        return false;
368
                                }
369
                                // El ?ltimo punto no se desplaza en X
370
                                if (pointDragged == (listSquare.size() - 1)) {
371
                                        point.setPosition(maxX, y);
372
                                        return false;
373
                                }
374

    
375
                                // Puntos centrales
376
                                point.setPosition(x, y);
377

    
378
                                // Arrastra a los de abajo si la X es menor que los inferiores
379
                                for (int i = 0; i < pointDragged; i++) {
380
                                        Square lowPoint = ((Square) listSquare.get(i));
381
                                        if (lowPoint.getPixelX() >= x) {
382
                                                lowPoint.setPosition(x, lowPoint.getPixelY());
383
                                                for (int j = i + 1; listSquare.get(j) != point;) {
384
                                                        listSquare.remove(j);
385
                                                        pointDragged--;
386
                                                }
387
                                                break;
388
                                        }
389
                                }
390

    
391
                                // Arrastra a los de arriba si la X es mayor que los superiores
392
                                for (int i = listSquare.size() - 1; i > pointDragged; i--) {
393
                                        Square upperPoint = ((Square) listSquare.get(i));
394
                                        if (upperPoint.getPixelX() <= x) {
395
                                                upperPoint.setPosition(x, upperPoint.getPixelY());
396
                                                for (int j = i - 1; listSquare.get(j) != point;) {
397
                                                        listSquare.remove(j);
398
                                                        j--;
399
                                                }
400
                                                break;
401
                                        }
402
                                }
403
                        } finally {
404
                                // Siempre repintamos
405
                                canvas.repaint();
406
                                canvas.callDataDragged("line", this);
407
                        }
408
                        return false;
409
                }
410
                return true;
411
        }
412

    
413
        /**
414
         * Variable para saber si se ha visualizado alguna informacion
415
         */
416
        boolean last = false;
417
        /*
418
         * (non-Javadoc)
419
         * @see org.gvsig.raster.beans.canvas.DrawableElement#mouseMoved(java.awt.event.MouseEvent)
420
         */
421
        public boolean mouseMoved(MouseEvent e) {
422
                for (int i = 0; i < listSquare.size(); i++) {
423
                        if (((Square)listSquare.get(i)).isInside(e.getPoint())) {
424
                                canvas.setCursor(new Cursor(Cursor.MOVE_CURSOR));
425
                                setInfoPoint(i);
426
                                canvas.repaint();
427
                                last = true;
428
                                return false;
429
                        }
430
                }
431
                if (last) {
432
                        setInfoPoint(-1);
433
                        canvas.repaint();
434
                        last = false;
435
                }
436
                return true;
437
        }
438

    
439
        /**
440
         * Valores de los datos de entrada correspondientes al m?nimo y al m?ximo de 
441
         * cada tramo. Estos tendr?n un rango entre el m?nimo y el m?ximo en cada
442
         * banda de la imagen.
443
         * @param min
444
         * @param max
445
         * @return
446
         */
447
        public double[] getInValues(double min, double max) {
448
                double[] in = getPercentInValues(); 
449
                for (int i = 0; i < in.length; i++)
450
                        in[i] = min + (in[i] * (max - min));
451
                return in;
452
        }
453

    
454
        /**
455
         * Valores de los datos de salida correspondientes al m?nimo y al m?ximo de
456
         * cada tramo. Estos tendr?n un rango entre 0 y 255.
457
         * @return
458
         */
459
        public int[] getOutValues() {
460
                double[] values = getPercentOutValues(); 
461
                int[] out = new int[values.length];
462
                for (int i = 0; i < values.length; i++)
463
                        out[i] = (int) Math.round(values[i] * 255.0D);
464
                return out;
465
        }
466

    
467
        /**
468
         * Valores de los datos de entrada correspondientes al m?nimo y al m?ximo de 
469
         * cada tramo devuelto en forma de porcentaje
470
         * 
471
         * @param min
472
         * @param max
473
         * @return
474
         */
475
        public double[] getPercentInValues() {
476
                double[] in = new double[listSquare.size() + 2];
477
                for (int i = 0; i < listSquare.size(); i++) {
478
                        Square square = ((Square) listSquare.get(i));
479
                        in[i + 1] = minx + ((maxx - minx) * square.getX());
480
                }
481
                in[0] = 0.0D;
482
                in[in.length - 1] = 1.0D;
483
                return in;
484
        }
485

    
486
        /**
487
         * Valores de los datos de salida correspondientes al m?nimo y al m?ximo de
488
         * cada tramo, devueltos en forma de porcentaje.
489
         * @return
490
         */
491
        public double[] getPercentOutValues() {
492
                double[] out = new double[listSquare.size() + 2];
493
                for (int i = 0; i < listSquare.size(); i++) {
494
                        Square square = ((Square) listSquare.get(i));
495
                        out[i + 1] = square.getY();
496
                }
497
                out[0] = out[1];
498
                out[out.length - 1] = out[out.length - 2];
499
                return out;
500
        }
501
        
502
        public void firstActions() {}
503
        public void firstDrawActions() {}
504

    
505
        /**
506
         * @param showSquares the showSquares to set
507
         */
508
        public void setShowSquares(boolean showSquares) {
509
                this.showSquares = showSquares;
510
        }
511

    
512
        protected double pixelToValueX(int pixel) {
513
                double value = ((double) (pixel - canvas.getCanvasMinX() - border) / (double) (canvas.getCanvasMaxX() - canvas.getCanvasMinX() - (border * 2.0D)));
514
                
515
                value = (value - minx) / (maxx - minx);
516
                
517
                return value;
518
        }
519

    
520
        protected double pixelToValueY(int pixel) {
521
                double div = (double) (canvas.getCanvasMaxY() - canvas.getCanvasMinY() - (border * 2.0D));
522
                if (div == 0.0D)
523
                        return 0.0D;
524
                
525
                return (1.0D - ((double) (pixel - canvas.getCanvasMinY() - border) / div));
526
        }
527
        
528
        /**
529
         * Devuelve 0 para indicar que estamos en una funcion lineal.
530
         * @return
531
         */
532
        public int getFunctionType() {
533
                return 0;
534
        }
535
        
536
        /**
537
         * En una funci?n lineal da igual lo que devuelva, pero es interesante para sus
538
         * clases derivadas
539
         * @return
540
         */
541
        public double getValueFunction() {
542
                return 0.0;
543
        }
544
}