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 @ 2585

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
                g.setColor(color);
209

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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