SeguimientoFinalPointSnapper.txt

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

Download (8.8 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 los vertices 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
 *
23
 */
24
public class SeguimientoFinalPointSnapper extends AbstractSnapper implements ISnapperVectorialSeguimiento {
25

    
26
	private ArrayList<Point2D> listaPuntos;
27

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

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

    
41
		Point2D resul = null;
42

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

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

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

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

    
64

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

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

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

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

    
105
			case PathIterator.SEG_LINETO:
106

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

    
112
//				ahora comprobamos que no sean los puntos el primero
113
				if(cUltimo!=null){
114
					if(!cUltimo.equals(to)){
115
//						metemos primero esto por si a?ade un nuevo punto
116
						ultimoPuntoCercano = line.closestPoint(cUltimo);
117
						if((cUltimo.distance(ultimoPuntoCercano)<0.000001)&&(!cUltimo.equals(from))){
118
//							a?adimos el punto extra a la lista de puntos
119
//							pero no podemos a?adirlo el final de la lista, sino un
120
							listaPuntosAux.add(new Point2D.Double(ultimoPuntoCercano.x,ultimoPuntoCercano.y));
121
							indiceUltimoPunto = listaPuntosAux.size()-1;
122
						}
123
					}else{
124
//						le ponemos el indice como un numero mas ya que a?adiremos luego el punto
125
						indiceUltimoPunto = listaPuntosAux.size();
126
					}
127
				}
128
				if(cPoint.distance(to)<minDist){
129
//					le ponemos el indice como un numero mas ya que a?adiremos luego el punto
130
					indicePuntoEncontrado = listaPuntosAux.size();
131
					resul = new Point2D.Double(theData[0], theData[1]);
132
					puntoEncontrado = true;
133
				}
134

    
135
				listaPuntosAux.add(new Point2D.Double(theData[0], theData[1]));
136

    
137
				from = to;
138
				break;
139
			case PathIterator.SEG_CLOSE:
140
				line = new LineSegment(from, first);
141
				geometriaCerrada=true;
142
//				metemos primero esto por si a?ade un nuevo punto
143
				if(cUltimo!=null){
144
					ultimoPuntoCercano = line.closestPoint(cUltimo);
145
					if((cUltimo.distance(ultimoPuntoCercano)<0.000001)&&(!cUltimo.equals(from))){
146
//						a?adimos el punto extra a la lista de puntos
147
//						pero no podemos a?adirlo el final de la lista, sino un
148
						listaPuntosAux.add(new Point2D.Double(ultimoPuntoCercano.x,ultimoPuntoCercano.y));
149
						indiceUltimoPunto = listaPuntosAux.size()-1;
150
					}
151
				}
152
				from = first;
153
				break;
154

    
155
			} //end switch
156

    
157
			theIterator.next();
158
		}
159

    
160
//		ahora comprobaremos si el primer y el ultimo punto son el mismo
161
//		en cuyo caso borraremos el ultimo y actualizaremos los indices que correspondan
162
		if(listaPuntosAux!=null && listaPuntosAux.size()>1){
163
			Point2D primerPunto = (Point2D) listaPuntosAux.get(0);
164
			Point2D ultimoPunto = (Point2D) listaPuntosAux.get(listaPuntosAux.size()-1);
165
			if(primerPunto.equals(ultimoPunto)){
166
				if(indicePuntoEncontrado==listaPuntosAux.size()-1){
167
					indicePuntoEncontrado = 0;
168
				}
169
				if(indiceUltimoPunto == listaPuntosAux.size()-1){
170
					indiceUltimoPunto = 0;
171
				}
172
				listaPuntosAux.remove(listaPuntosAux.size()-1);
173
				geometriaCerrada=true;
174
			}
175
		}
176

    
177

    
178
		if(resul!=null){
179
			if(indiceUltimoPunto>=0 && indicePuntoEncontrado>=0 && indicePuntoEncontrado!=indiceUltimoPunto && Math.abs(indicePuntoEncontrado-indiceUltimoPunto)>1){
180
				listaPuntos = new ArrayList<Point2D>();
181
				if(indiceUltimoPunto>indicePuntoEncontrado){
182
					if(((indiceUltimoPunto-indicePuntoEncontrado)<=
183
					(((listaPuntosAux.size()-1)-indiceUltimoPunto)+indicePuntoEncontrado))||!geometriaCerrada){
184
						for(int i=indiceUltimoPunto-1;i>=indicePuntoEncontrado;i--){
185
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
186
						}
187
					}else{
188
						for(int i = indiceUltimoPunto+1; i<listaPuntosAux.size() ;i++){
189
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
190
						}
191
						for(int i = 0 ; i<=indicePuntoEncontrado;i++){
192
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
193
						}
194
					}
195
				}else{
196
					if(((indicePuntoEncontrado-indiceUltimoPunto)<=
197
						(((listaPuntosAux.size()-1)-indicePuntoEncontrado)+indiceUltimoPunto))||!geometriaCerrada){
198
						for(int i=indiceUltimoPunto+1;i<=indicePuntoEncontrado;i++){
199
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
200
						}
201
					}else{
202
						for(int i = indiceUltimoPunto-1; i>=0;i--){
203
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
204
						}
205
						for(int i = listaPuntosAux.size()-1  ; i>=indicePuntoEncontrado;i--){
206
							listaPuntos.add((Point2D)listaPuntosAux.get(i));
207
						}
208
					}
209
				}
210
			}
211
		}
212
		return resul;
213
	}
214

    
215
	public String getToolTipText() {
216
		return PluginServices.getText(this, "vertice_seguimiento");
217
		//return "Vertice seguimiento";
218
	}
219

    
220
	/* (non-Javadoc)
221
	 * @see com.iver.cit.gvsig.gui.cad.snapping.ISnapper#draw(java.awt.Graphics, java.awt.geom.Point2D)
222
	 */
223
	public void draw(PrimitivesDrawer g, Point2D pPixels) {
224
		g.setColor(getColor());
225

    
226
		int half = getSizePixels() / 2;
227
		g.drawRect((int) (pPixels.getX() - half),
228
			(int) (pPixels.getY() - half),
229
			getSizePixels(), getSizePixels());
230

    
231
	}
232

    
233
	/* (non-Javadoc)
234
	 * @see com.iver.cit.gvsig.gui.cad.snapping.ISnapper#getPriority()
235
	 */
236
	public int getPriority()
237
	{
238
		return 1;
239
	}
240

    
241
	/**
242
	 * Devuelve la lista de puntos que hay entre el ultimo y el anterior pulsado dentro de la
243
	 * geometria
244
	 */
245
	public ArrayList<Point2D> getSnappedPoints(){
246
		ArrayList<Point2D> retorno = listaPuntos;
247
		listaPuntos = null;
248

    
249
		return retorno;
250
	}
251
}