SeguimientoNearestPointSnapper.txt

Codigo java de la clase SeguimientoNearestPointSnapper - Leticia Riestra, 04/18/2012 01:32 PM

Download (10.2 KB)

 
1
import java.awt.geom.PathIterator;
2
import java.awt.geom.Point2D;
3
import java.awt.geom.Point2D.Double;
4
import java.util.ArrayList;
5

    
6
import org.gvsig.andami.PluginServices;
7
import org.gvsig.fmap.geom.Geometry;
8
import org.gvsig.fmap.geom.GeometryLocator;
9
import org.gvsig.fmap.geom.GeometryManager;
10
import org.gvsig.fmap.mapcontrol.PrimitivesDrawer;
11
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.ISnapperVectorialSeguimiento;
12
import org.gvsig.fmap.mapcontrol.tools.snapping.snappers.impl.AbstractSnapper;
13
import com.vividsolutions.jts.geom.Coordinate;
14
import com.vividsolutions.jts.geom.LineSegment;
15

    
16

    
17
/**
18
 * Este a clase implementa un snapper a las aristas de la geometria que ademas
19
 * permite recuperar la lista de puntos que hay dentro de la geometr?a desde el
20
 * ?ltimo pulsado y el anterior
21
 * @author Jose Ignacio Lamas Fonte
22
 *         Leticia Riestra Ainsua
23
 *
24
 */
25
public class SeguimientoNearestPointSnapper extends AbstractSnapper implements ISnapperVectorialSeguimiento {
26

    
27
	private ArrayList<Point2D> listaPuntos;
28

    
29
	private static GeometryManager manager = GeometryLocator.getGeometryManager();
30
	
31
	public SeguimientoNearestPointSnapper() {
32
	}
33

    
34
	/**
35
	 * Devuelve el punto, dentro de las aristas la geometr?a 'geom', m?s proximo al punto 'point'
36
	 * siempre que la cercan?a sea menor o igual a la toleracia 'tolerance'.
37
	 * Ademas actualiza la lista de puntos que hay entre el 'lastPointEntered' y el punto
38
	 * resultado.
39
	 */
40
	public Point2D getSnapPoint(Point2D point, Geometry geom, double tolerance, Point2D lastPointEntered) {
41

    
42
		Point2D resul = null;
43

    
44
		Coordinate cUltimo = null;
45
		Coordinate cPoint = new Coordinate(point.getX(), point.getY());
46
		if(lastPointEntered!=null){
47
			cUltimo = new Coordinate(lastPointEntered.getX(), lastPointEntered.getY());
48
		}
49

    
50
//		aqui almacenaremos los indices del ultimo punto encontrado y del punto mas peque?o que forme
51
//		parte del segmento en el que esta el nuevo punto encontrado
52
		int indiceUltimoPunto=-1;
53
		int indicePuntoEncontrado=-1;
54

    
55
//		encontramos el punto mas cercano al puntero del raton dentro de la geometria
56
//		y ademas miramos si el ultimo punto esta tambien dentro de algun segmento
57
		PathIterator theIterator = geom.getPathIterator(null, manager.getFlatness()); //polyLine.getPathIterator(null, flatness);
58
		double[] theData = new double[6];
59
		double minDist = tolerance;
60
		Coordinate from = null, first = null;
61

    
62
//		limpio la lista de puntos
63
//		listaPuntos = new ArrayList();
64

    
65

    
66
//		a?ado esto para ver si consigo tratar de forma coherente las multigeometrias
67
		ArrayList<Double> listaPuntosAux = new ArrayList<Double>();
68
		boolean puntoEncontrado = false;
69
		boolean multiGeometriaTerminada = false;
70

    
71
//		cons esta variable controlaremos que se este haciendo snapin sobre una liena abierta
72
//		o un poligono cerrado, ya que sobre la linea no podemos dar la vuelta a los puntos
73
//		para buscar el camino mas corto
74
		boolean geometriaCerrada = false;
75

    
76
		while ((!theIterator.isDone())&&(!multiGeometriaTerminada)) {
77
			//while not done
78
			int theType = theIterator.currentSegment(theData);
79

    
80
			switch (theType) {
81
			case PathIterator.SEG_MOVETO:
82
				from = new Coordinate(theData[0], theData[1]);
83
				first = from;
84
				if(!puntoEncontrado){
85
					geometriaCerrada=false;
86
					listaPuntosAux = new ArrayList<Double>();
87
					indiceUltimoPunto=-1;
88
					indicePuntoEncontrado=-1;
89
					listaPuntosAux.add(new Point2D.Double(theData[0], theData[1]));
90
//					ahora comprobamos que no sean los puntos el primero
91
					if(cPoint.distance(from)<minDist){
92
						indicePuntoEncontrado = listaPuntosAux.size()-1;
93
						resul = new Point2D.Double(theData[0], theData[1]);
94
						puntoEncontrado = true;
95
					}
96
					if(cUltimo!=null){
97
						if(cUltimo.equals(from)){
98
							indiceUltimoPunto = listaPuntosAux.size()-1;
99
						}
100
					}
101
				}else{
102
					multiGeometriaTerminada = true;
103
				}
104
				break;
105

    
106
			case PathIterator.SEG_LINETO:
107

    
108
				// System.out.println("SEG_LINETO");
109
				Coordinate to = new Coordinate(theData[0], theData[1]);
110
				LineSegment line = new LineSegment(from, to);
111
				Coordinate ultimoPuntoCercano = null;
112

    
113

    
114
//				comprobamos que el ultimo punto este dentro de la linea de este tramo
115
				if(cUltimo!=null){
116
					if(!cUltimo.equals(to)){
117
//						metemos primero esto por si a?ade un nuevo punto
118
						ultimoPuntoCercano = line.closestPoint(cUltimo);
119
						if((cUltimo.distance(ultimoPuntoCercano)<0.000001)&&(!cUltimo.equals(from))){
120
//							a?adimos el punto extra a la lista de puntos
121
							listaPuntosAux.add(new Point2D.Double(ultimoPuntoCercano.x,ultimoPuntoCercano.y));
122
							indiceUltimoPunto = listaPuntosAux.size()-1;
123
						}
124
					}
125
				}
126
//				ahora debamos comprobar que el punto encontrado este dentro de la linea de este tramo
127
				if((!(cPoint.distance(to)<minDist))&&(!(cPoint.distance(from)<minDist))){
128
					ultimoPuntoCercano = line.closestPoint(cPoint);
129
					if((cPoint.distance(ultimoPuntoCercano)<minDist)){
130
						listaPuntosAux.add(new Point2D.Double(ultimoPuntoCercano.x,ultimoPuntoCercano.y));
131
						indicePuntoEncontrado = listaPuntosAux.size()-1;
132
						resul = new Point2D.Double(ultimoPuntoCercano.x,ultimoPuntoCercano.y);
133
						puntoEncontrado = true;
134
					}
135
				}
136

    
137
//				ahora pasamos a comprobar si los puntos estan en los vertices
138
				if(cPoint.distance(to)<minDist){
139
//					le ponemos el indice como un numero mas ya que a?adiremos luego el punto
140
					indicePuntoEncontrado = listaPuntosAux.size();
141
					resul = new Point2D.Double(theData[0], theData[1]);
142
					puntoEncontrado = true;
143
				}
144
				if(cUltimo!=null&&cUltimo.equals(to)){
145
//					le ponemos el indice como un numero mas ya que a?adiremos luego el punto
146
					indiceUltimoPunto = listaPuntosAux.size();
147
				}
148
				listaPuntosAux.add(new Point2D.Double(theData[0], theData[1]));
149

    
150
				from = to;
151
				break;
152
			case PathIterator.SEG_CLOSE:
153
				line = new LineSegment(from, first);
154
				geometriaCerrada=true;
155
//				metemos primero esto por si a?ade un nuevo punto
156
				if(cUltimo!=null){
157
//						metemos primero esto por si a?ade un nuevo punto
158
						ultimoPuntoCercano = line.closestPoint(cUltimo);
159
						if((cUltimo.distance(ultimoPuntoCercano)<0.000001)&&(!cUltimo.equals(from))){
160
//							a?adimos el punto extra a la lista de puntos
161
							listaPuntosAux.add(new Point2D.Double(ultimoPuntoCercano.x,ultimoPuntoCercano.y));
162
							indiceUltimoPunto = listaPuntosAux.size()-1;
163
						}
164
				}
165
//				ahora debamos comprobar que el punto encontrado este dentro de la linea de este tramo
166
				if(!(cPoint.distance(from)<minDist)){
167
					ultimoPuntoCercano = line.closestPoint(cPoint);
168
					if((cPoint.distance(ultimoPuntoCercano)<minDist)){
169
						listaPuntosAux.add(new Point2D.Double(ultimoPuntoCercano.x,ultimoPuntoCercano.y));
170
						indicePuntoEncontrado = listaPuntosAux.size()-1;
171
						resul = new Point2D.Double(ultimoPuntoCercano.x,ultimoPuntoCercano.y);
172
						puntoEncontrado = true;
173
					}
174
				}
175
				from = first;
176
				break;
177

    
178
			} //end switch
179

    
180
			theIterator.next();
181
		}
182

    
183
//		ahora comprobaremos si el primer y el ultimo punto son el mismo
184
//		en cuyo caso borraremos el ultimo y actualizaremos los indices que correspondan
185
		if(listaPuntosAux!=null && listaPuntosAux.size()>1){
186
			Point2D primerPunto = (Point2D) listaPuntosAux.get(0);
187
			Point2D ultimoPunto = (Point2D) listaPuntosAux.get(listaPuntosAux.size()-1);
188
			if(primerPunto.equals(ultimoPunto)){
189
				if(indicePuntoEncontrado==listaPuntosAux.size()-1){
190
					indicePuntoEncontrado = 0;
191
				}
192
				if(indiceUltimoPunto == listaPuntosAux.size()-1){
193
					indiceUltimoPunto = 0;
194
				}
195
				listaPuntosAux.remove(listaPuntosAux.size()-1);
196
				geometriaCerrada=true;
197
			}
198
		}
199

    
200

    
201
		if(resul!=null){
202
			if(indiceUltimoPunto>=0 && indicePuntoEncontrado>=0 && indicePuntoEncontrado!=indiceUltimoPunto && Math.abs(indicePuntoEncontrado-indiceUltimoPunto)>1){
203
				listaPuntos = new ArrayList<Point2D>();
204
				if(indiceUltimoPunto>indicePuntoEncontrado){
205
					if(((indiceUltimoPunto-indicePuntoEncontrado)<=
206
					(((listaPuntosAux.size()-1)-indiceUltimoPunto)+indicePuntoEncontrado))||!geometriaCerrada){
207
						for(int i=indiceUltimoPunto-1;i>=indicePuntoEncontrado;i--){
208
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
209
						}
210
					}else{
211
						for(int i = indiceUltimoPunto+1; i<listaPuntosAux.size() ;i++){
212
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
213
						}
214
						for(int i = 0 ; i<=indicePuntoEncontrado;i++){
215
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
216
						}
217
					}
218
				}else{
219
					if(((indicePuntoEncontrado-indiceUltimoPunto)<=
220
						(((listaPuntosAux.size()-1)-indicePuntoEncontrado)+indiceUltimoPunto))||!geometriaCerrada){
221
						for(int i=indiceUltimoPunto+1;i<=indicePuntoEncontrado;i++){
222
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
223
						}
224
					}else{
225
						for(int i = indiceUltimoPunto-1; i>=0;i--){
226
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
227
						}
228
						for(int i = listaPuntosAux.size()-1  ; i>=indicePuntoEncontrado;i--){
229
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
230
						}
231
					}
232
				}
233
			}
234
		}
235
		return resul;
236
	}
237

    
238
	public String getToolTipText() {
239
		return PluginServices.getText(this, "arista_seguimiento");
240
		//return "Arista seguimiento";
241
	}
242

    
243
	/* (non-Javadoc)
244
	 * @see com.iver.cit.gvsig.gui.cad.snapping.ISnapper#draw(java.awt.Graphics, java.awt.geom.Point2D)
245
	 */
246
	public void draw(PrimitivesDrawer g, Point2D pPixels) {
247
		g.setColor(getColor());
248

    
249
		int half = getSizePixels() / 2;
250
		int x1 = (int) (pPixels.getX() - half);
251
		int x2 = (int) (pPixels.getX() + half);
252
		int y1 = (int) (pPixels.getY() - half);
253
		int y2 = (int) (pPixels.getY() + half);
254

    
255
		g.drawLine(x1, y1, x2, y1); // abajo
256
		g.drawLine(x1, y2, x2, y2); // arriba
257
		g.drawLine(x1, y1, x2, y2); // abajo - arriba
258
		g.drawLine(x1, y2, x2, y1); // arriba - abajo
259

    
260
	}
261

    
262
	/* (non-Javadoc)
263
	 * @see com.iver.cit.gvsig.gui.cad.snapping.ISnapper#getPriority()
264
	 */
265
	public int getPriority()
266
	{
267
		return 2;
268
	}
269

    
270
	/**
271
	 * Devuelve la lista de puntos que hay entre el ultimo y el anterior pulsado dentro de la
272
	 * geometria
273
	 */
274
	public ArrayList<Point2D> getSnappedPoints(){
275
		ArrayList<Point2D> retorno = listaPuntos;
276
		listaPuntos = null;
277

    
278
		return retorno;
279
	}
280

    
281
}