Statistics
| Revision:

gvsig-raster / org.gvsig.raster / trunk / org.gvsig.raster / org.gvsig.raster.swing / org.gvsig.raster.swing.impl / src / main / java / org / gvsig / raster / swing / impl / canvas / layer / function / DefaultStraightLine.java @ 2584

History | View | Annotate | Download (14 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.swing.impl.canvas.layer.function;
23

    
24
import java.awt.Color;
25
import java.awt.Component;
26
import java.awt.Cursor;
27
import java.awt.Graphics;
28
import java.awt.Image;
29
import java.awt.Point;
30
import java.awt.Toolkit;
31
import java.awt.event.MouseEvent;
32
import java.awt.image.MemoryImageSource;
33
import java.util.ArrayList;
34
import java.util.List;
35

    
36
import org.gvsig.raster.swing.gcanvas.DrawableElement;
37
import org.gvsig.raster.swing.gcanvas.StraightLine;
38
import org.gvsig.raster.swing.impl.canvas.DefaultGCanvas;
39
import org.gvsig.raster.swing.impl.canvas.layer.DefaultInfoLayer;
40
/**
41
 * Representa una linea recta con puntos de arrastre para la ecualizaci?n de
42
 * un histograma y realce lineales y dencity slicing.
43
 *
44
 * @author Nacho Brodin (nachobrodin@gmail.com)
45
 */
46
public class DefaultStraightLine extends DefaultBaseFunction implements StraightLine {
47

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

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

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

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

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

    
164
                private int valueToPixelY(double value) {
165
                        value = 1.0D - value;
166
                        return (int) Math.round(canvas.getCanvasMinY() + border + ((canvas.getCanvasMaxY() - canvas.getCanvasMinY() - (border * 2)) * value));
167
                }
168

    
169
        }
170
        
171
        /**
172
         * Lista de cuadrados que intersectan con la recta
173
         */
174
        protected List<Square> listSquare        = new ArrayList<Square>();
175
        private int            pointDragged      = -1;
176
        private Cursor         transparentCursor = null;
177
        private boolean        showSquares       = true;
178
        private int            border            = 2;
179
        
180
        /**
181
         * Constructor. Asigna el color
182
         * @param c
183
         */
184
        public DefaultStraightLine(Color c) {
185
                int[] pixels = new int[16 * 16];
186
                Image image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(16, 16, pixels, 0, 16));
187
                transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(0, 0), "invisibleCursor");
188
                
189
                setColor(c);
190
                clearSquares();
191
                addSquare(0.0D, 0.0D);
192
                addSquare(1.0D, 1.0D);
193
        }
194

    
195
        public void clearSquares() {
196
                listSquare.clear();
197
        }
198

    
199
        public void addSquare(double x, double y) {
200
                listSquare.add(new Square(x, y));
201
        }
202
        
203
        /**
204
         * Dibujado de las l?neas y cuadros sobre el canvas
205
         */
206
        protected void paint(Graphics g) {
207
                super.paint(g);
208

    
209
                g.setColor(color);
210

    
211
                // Dibujamos una l?nea desde un punto hasta el siguiente
212
                Square square = null;
213
                Square lastSquare = null;
214

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

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

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

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

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

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

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

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

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

    
377
                                // Puntos centrales
378
                                point.setPosition(x, y);
379

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

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

    
415
        /**
416
         * Variable para saber si se ha visualizado alguna informacion
417
         */
418
        boolean last = false;
419

    
420
        public boolean mouseMoved(MouseEvent e) {
421
                for (int i = 0; i < listSquare.size(); i++) {
422
                        if (((Square)listSquare.get(i)).isInside(e.getPoint())) {
423
                                ((Component)canvas).setCursor(new Cursor(Cursor.MOVE_CURSOR));
424
                                setInfoPoint(i);
425
                                ((Component)canvas).repaint();
426
                                last = true;
427
                                return false;
428
                        }
429
                }
430
                if (last) {
431
                        setInfoPoint(-1);
432
                        ((Component)canvas).repaint();
433
                        last = false;
434
                }
435
                return true;
436
        }
437

    
438
        public double[] getInValues(double min, double max) {
439
                double[] in = getPercentInValues(); 
440
                for (int i = 0; i < in.length; i++)
441
                        in[i] = min + (in[i] * (max - min));
442
                return in;
443
        }
444

    
445
        public int[] getOutValues() {
446
                double[] values = getPercentOutValues(); 
447
                int[] out = new int[values.length];
448
                for (int i = 0; i < values.length; i++)
449
                        out[i] = (int) Math.round(values[i] * 255.0D);
450
                return out;
451
        }
452

    
453
        public double[] getPercentInValues() {
454
                double[] in = new double[listSquare.size() + 2];
455
                for (int i = 0; i < listSquare.size(); i++) {
456
                        Square square = ((Square) listSquare.get(i));
457
                        in[i + 1] = minx + ((maxx - minx) * square.getX());
458
                }
459
                in[0] = 0.0D;
460
                in[in.length - 1] = 1.0D;
461
                return in;
462
        }
463

    
464
        public double[] getPercentOutValues() {
465
                double[] out = new double[listSquare.size() + 2];
466
                for (int i = 0; i < listSquare.size(); i++) {
467
                        Square square = ((Square) listSquare.get(i));
468
                        out[i + 1] = square.getY();
469
                }
470
                out[0] = out[1];
471
                out[out.length - 1] = out[out.length - 2];
472
                return out;
473
        }
474
        
475
        public void firstActions() {}
476
        public void firstDrawActions() {}
477

    
478
        /**
479
         * @param showSquares the showSquares to set
480
         */
481
        public void setShowSquares(boolean showSquares) {
482
                this.showSquares = showSquares;
483
        }
484

    
485
        protected double pixelToValueX(int pixel) {
486
                double value = ((double) (pixel - canvas.getCanvasMinX() - border) / (double) (canvas.getCanvasMaxX() - canvas.getCanvasMinX() - (border * 2.0D)));
487
                
488
                value = (value - minx) / (maxx - minx);
489
                
490
                return value;
491
        }
492

    
493
        protected double pixelToValueY(int pixel) {
494
                double div = (double) (canvas.getCanvasMaxY() - canvas.getCanvasMinY() - (border * 2.0D));
495
                if (div == 0.0D)
496
                        return 0.0D;
497
                
498
                return (1.0D - ((double) (pixel - canvas.getCanvasMinY() - border) / div));
499
        }
500
        
501
        public int getFunctionType() {
502
                return 0;
503
        }
504
        
505
        /**
506
         * En una funci?n lineal da igual lo que devuelva, pero es interesante para sus
507
         * clases derivadas
508
         * @return
509
         */
510
        public double getValueFunction() {
511
                return 0.0;
512
        }
513
}