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
|
}
|