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 | 2443 | nbrodin | /* 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 | 2584 | nbrodin | import java.util.List; |
35 | 2443 | nbrodin | |
36 | 2584 | nbrodin | import org.gvsig.raster.swing.gcanvas.DrawableElement; |
37 | 2443 | nbrodin | 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 | 2584 | nbrodin | 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 | 2443 | nbrodin | |
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 | 2584 | nbrodin | List<DrawableElement> list = canvas.getDrawableElements(DefaultInfoLayer.class);
|
252 | 2443 | nbrodin | 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 | 2584 | nbrodin | |
419 | 2443 | nbrodin | 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 | } |