svn-gvsig-desktop / tags / v1_1_2_Build_1044 / prototypes / VectorialAvanzado / extensions / extGraph / src / com / iver / cit / gvsig / graph / solvers / ShortestPathSolverAStar.java @ 20099
History | View | Annotate | Download (18 KB)
1 | 8499 | fjp | /* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
---|---|---|---|
2 | *
|
||
3 | * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
|
||
4 | *
|
||
5 | * This program is free software; you can redistribute it and/or
|
||
6 | * modify it under the terms of the GNU General Public License
|
||
7 | * as published by the Free Software Foundation; either version 2
|
||
8 | * of the License, or (at your option) any later version.
|
||
9 | *
|
||
10 | * This program is distributed in the hope that it will be useful,
|
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
13 | * GNU General Public License for more details.
|
||
14 | *
|
||
15 | * You should have received a copy of the GNU General Public License
|
||
16 | * along with this program; if not, write to the Free Software
|
||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
||
18 | *
|
||
19 | * For more information, contact:
|
||
20 | *
|
||
21 | * Generalitat Valenciana
|
||
22 | * Conselleria d'Infraestructures i Transport
|
||
23 | * Av. Blasco Ib??ez, 50
|
||
24 | * 46010 VALENCIA
|
||
25 | * SPAIN
|
||
26 | *
|
||
27 | * +34 963862235
|
||
28 | * gvsig@gva.es
|
||
29 | * www.gvsig.gva.es
|
||
30 | *
|
||
31 | * or
|
||
32 | *
|
||
33 | * IVER T.I. S.A
|
||
34 | * Salamanca 50
|
||
35 | * 46005 Valencia
|
||
36 | * Spain
|
||
37 | *
|
||
38 | * +34 963163400
|
||
39 | * dac@iver.es
|
||
40 | */
|
||
41 | package com.iver.cit.gvsig.graph.solvers; |
||
42 | |||
43 | import java.util.ArrayList; |
||
44 | import java.util.Stack; |
||
45 | |||
46 | import com.iver.cit.gvsig.fmap.DriverException; |
||
47 | import com.iver.cit.gvsig.fmap.core.IFeature; |
||
48 | import com.iver.cit.gvsig.fmap.core.IGeometry; |
||
49 | import com.iver.cit.gvsig.fmap.core.v02.FConverter; |
||
50 | 11631 | fjp | import com.iver.cit.gvsig.fmap.drivers.DriverIOException; |
51 | 8499 | fjp | import com.iver.cit.gvsig.fmap.layers.VectorialAdapter; |
52 | import com.iver.cit.gvsig.graph.core.AbstractNetSolver; |
||
53 | 20099 | fpenarrubia | import com.iver.cit.gvsig.graph.core.GraphException; |
54 | 8499 | fjp | import com.iver.cit.gvsig.graph.core.GvEdge; |
55 | import com.iver.cit.gvsig.graph.core.GvFlag; |
||
56 | import com.iver.cit.gvsig.graph.core.GvNode; |
||
57 | import com.iver.cit.gvsig.graph.core.GvTurn; |
||
58 | import com.iver.cit.gvsig.graph.core.IGraph; |
||
59 | 20099 | fpenarrubia | import com.iver.cit.gvsig.graph.core.NetworkUtils; |
60 | 8499 | fjp | import com.vividsolutions.jts.geom.Coordinate; |
61 | import com.vividsolutions.jts.geom.Geometry; |
||
62 | import com.vividsolutions.jts.geom.GeometryFactory; |
||
63 | import com.vividsolutions.jts.geom.LineString; |
||
64 | import com.vividsolutions.jts.geom.MultiLineString; |
||
65 | |||
66 | /**
|
||
67 | * @author fjp
|
||
68 | * Este es ?til solo cuando podemos calcular la distancia estimada entre
|
||
69 | * 2 nodos. (Es decir, para temas de cartograf?a). Para analizar relaciones
|
||
70 | * creo que no servir?a).
|
||
71 | */
|
||
72 | public class ShortestPathSolverAStar extends AbstractNetSolver { |
||
73 | |||
74 | private GeometryFactory geomFactory = new GeometryFactory(); |
||
75 | |||
76 | protected Route route = new Route(); |
||
77 | private int fieldIndexStreetName; |
||
78 | |||
79 | private class InfoShp { |
||
80 | public int idArc; |
||
81 | public double pct; |
||
82 | public double cost; |
||
83 | public double distance; |
||
84 | public int direction; |
||
85 | public boolean bFlip; |
||
86 | |||
87 | } |
||
88 | |||
89 | public void setFielStreetName(String name) { |
||
90 | try {
|
||
91 | int aux = net.getLayer().getRecordset().getFieldIndexByName(name);
|
||
92 | if (aux == -1) |
||
93 | throw new RuntimeException("Field " + name + " not found."); |
||
94 | fieldIndexStreetName = aux; |
||
95 | } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
|
||
96 | // TODO Auto-generated catch block
|
||
97 | e.printStackTrace(); |
||
98 | } catch (DriverException e) {
|
||
99 | // TODO Auto-generated catch block
|
||
100 | e.printStackTrace(); |
||
101 | } |
||
102 | |||
103 | } |
||
104 | |||
105 | /**
|
||
106 | * @return a list of features
|
||
107 | * @throws GraphException
|
||
108 | */
|
||
109 | public Route calculateRoute() throws GraphException { |
||
110 | GvFlag[] flags = net.getFlags();
|
||
111 | if (flags.length == 0) |
||
112 | throw new RuntimeException("Please, add flags before"); |
||
113 | int desde = 0; |
||
114 | int hasta = 1; |
||
115 | double elCoste1 = 0; |
||
116 | route = new Route();
|
||
117 | 8616 | fjp | GvFlag fFrom = flags[0];
|
118 | fFrom.setCost(0);
|
||
119 | 8499 | fjp | for (int i = 0; i < flags.length - 1; i++) { |
120 | 8616 | fjp | fFrom = flags[desde]; |
121 | 8499 | fjp | GvFlag fTo = flags[hasta]; |
122 | |||
123 | if (fFrom != fTo) {
|
||
124 | int idStart = net.creaArcosVirtuales(fFrom);
|
||
125 | int idStop = net.creaArcosVirtuales(fTo);
|
||
126 | |||
127 | 8522 | fjp | double newCost = AStar(idStart, idStop);
|
128 | 8616 | fjp | |
129 | 8499 | fjp | elCoste1 += newCost; |
130 | 8616 | fjp | fTo.setCost(elCoste1); |
131 | 8499 | fjp | |
132 | if (newCost != Double.MAX_VALUE) |
||
133 | { |
||
134 | try {
|
||
135 | populateRoute(fFrom, fTo, idStart, idStop); |
||
136 | } catch (DriverException e) {
|
||
137 | e.printStackTrace(); |
||
138 | throw new GraphException(e); |
||
139 | } |
||
140 | } |
||
141 | else
|
||
142 | { |
||
143 | // No way
|
||
144 | } |
||
145 | |||
146 | net.reconstruyeTramo(fFrom.getIdArc()); |
||
147 | net.reconstruyeTramo(fTo.getIdArc()); |
||
148 | desde = hasta; |
||
149 | } // if son puntos distintos
|
||
150 | hasta++; |
||
151 | } |
||
152 | |||
153 | return route;
|
||
154 | } |
||
155 | |||
156 | private void populateRouteSimple(int idStart, int idEnd) throws DriverException { |
||
157 | int idEnlace;
|
||
158 | GvNode node; |
||
159 | GvEdge link; |
||
160 | double costeEntrada;
|
||
161 | |||
162 | // Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los Enlaces
|
||
163 | double Coste = 0; |
||
164 | double Coste2 = 0; |
||
165 | IGraph graph = net.getGraph(); |
||
166 | node = graph.getNodeByID(idEnd); |
||
167 | int from_link = node.getFromLink();
|
||
168 | VectorialAdapter va = (VectorialAdapter) net.getLayer().getSource(); |
||
169 | while (node.getIdNode() != idStart)
|
||
170 | { |
||
171 | if (from_link == -1) |
||
172 | { |
||
173 | throw new RuntimeException("Fallo al recorrer de manera inversa la soluci?n. Encontrado arco con -1"); |
||
174 | // break; // FALLO!!
|
||
175 | } |
||
176 | link = graph.getEdgeByID(from_link); |
||
177 | IFeature feat = va.getFeature(link.getIdArc()); |
||
178 | route.addRouteFeature(feat.getGeometry(), link.getIdArc(), |
||
179 | link.getWeight(), link.getDistance(), feat.getAttribute(getFieldIndexStreetName()).toString()); |
||
180 | |||
181 | node = graph.getNodeByID(link.getIdNodeOrig()); |
||
182 | |||
183 | Coste = Coste + link.getWeight(); |
||
184 | Coste2 = Coste2 + link.getDistance(); |
||
185 | |||
186 | // TODO:
|
||
187 | // from_link = node.get_from_link(idEnlace, &costeEntrada);
|
||
188 | from_link = node.getFromLink(); |
||
189 | |||
190 | } |
||
191 | System.out.println("Salgo con node = " + node.getIdNode()); |
||
192 | } |
||
193 | |||
194 | 20099 | fpenarrubia | private void populateRoute(GvFlag origin, GvFlag dest, int idStart, |
195 | int idEnd) throws DriverException { |
||
196 | 8499 | fjp | int idEnlace;
|
197 | GvNode node; |
||
198 | GvEdge link; |
||
199 | double costeEntrada;
|
||
200 | |||
201 | 20099 | fpenarrubia | // Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los
|
202 | // Enlaces
|
||
203 | |||
204 | 8751 | fjp | if (idStart == idEnd)
|
205 | return;
|
||
206 | 8499 | fjp | IGraph graph = net.getGraph(); |
207 | node = graph.getNodeByID(idEnd); |
||
208 | int from_link = node.getFromLink();
|
||
209 | VectorialAdapter va = (VectorialAdapter) net.getLayer().getSource(); |
||
210 | 11631 | fjp | try {
|
211 | va.start(); |
||
212 | 20099 | fpenarrubia | /*
|
213 | * Miramos los nodos de los tramos inicio y final, y cogemos el nodo
|
||
214 | * que tenga el from_link rellenado. E IGUAL A NUMSOLUCGLOBAL!!!! A
|
||
215 | * partir de ah?, recorremos hacia atr?s y tenemos el cuerpo
|
||
216 | * principal del shape. Luego, para las puntas hay que tener en
|
||
217 | * cuenta los porcentajes, viendo el trozo que est? pegando a los
|
||
218 | * nodos que sabemos que est?n en el path
|
||
219 | */
|
||
220 | 8499 | fjp | |
221 | 20099 | fpenarrubia | /*
|
222 | * 22/9/2003 Corregimos el fallo que hab?a de escribir el shape de
|
||
223 | * atr?s adelante. Guardamos lo que necesitamos en listaShapes y
|
||
224 | * recorremos esa lista guardando los tramos con el sentido
|
||
225 | * adecuado.
|
||
226 | */
|
||
227 | 8499 | fjp | |
228 | 20099 | fpenarrubia | /*
|
229 | * 3/Febrero/2005 Limpieza de c?digo superfluo y correci?n de un
|
||
230 | * fallo raro. Ahora es m?s simple y parece que no falla. A ver si
|
||
231 | * dura. IDEA: quiz?s se necesite meter el porcentaje en los arcos
|
||
232 | * partidos.
|
||
233 | */
|
||
234 | 8499 | fjp | |
235 | 20099 | fpenarrubia | // Define a template class for a vector of IDs.
|
236 | InfoShp infoShp; |
||
237 | Stack pilaShapes = new Stack(); |
||
238 | // typedef stack<CInfoShp> PILAINFO;
|
||
239 | // PILAINFO pilaShapes;
|
||
240 | 8499 | fjp | |
241 | 20099 | fpenarrubia | double costeTramoFinal = -1; |
242 | GvNode nodeEnd = graph.getNodeByID(idEnd); |
||
243 | GvEdge finalEdge = graph.getEdgeByID(nodeEnd.getFromLink()); |
||
244 | costeTramoFinal = finalEdge.getWeight(); |
||
245 | 8499 | fjp | |
246 | 20099 | fpenarrubia | GvNode pNodo; |
247 | GvEdge pEnlace; |
||
248 | 8499 | fjp | |
249 | 20099 | fpenarrubia | boolean bFlipearShape = false; |
250 | 8499 | fjp | |
251 | 20099 | fpenarrubia | double pctMax, pctMin;
|
252 | 8499 | fjp | |
253 | 20099 | fpenarrubia | // ////////////////////////////////////////////////////////////////////////////////////
|
254 | // Trozo del final
|
||
255 | // El shape va de idStop1 a idStop2, y el porcentaje viene en ese
|
||
256 | // sentido.
|
||
257 | // Si el idEnd es idStop1, quiere decir que el tramo que falta va en
|
||
258 | // ese sentido tambi?n,
|
||
259 | // as? que recorremos ese shape desde idStop1 hasta que rebasemos o
|
||
260 | // igualemos ese porcentaje.
|
||
261 | // Si no, hemos pasado por idStop2 y la parte que hay que meter es
|
||
262 | // desde el pto interior a idStop2
|
||
263 | // /////////////////////////////////////////////////////////////////////////////////////
|
||
264 | IFeature feat = va.getFeature(finalEdge.getIdArc()); |
||
265 | MultiLineString jtsGeom = (MultiLineString) feat.getGeometry() |
||
266 | .toJTSGeometry(); |
||
267 | // CoordinateFilter removeDuplicates = new
|
||
268 | // UniqueCoordinateArrayFilter();
|
||
269 | // jtsGeom.apply(removeDuplicates);
|
||
270 | // jtsGeom.geometryChanged();
|
||
271 | 8499 | fjp | |
272 | 20099 | fpenarrubia | // SI ESTAMOS SOBRE EL MISMO TRAMO, CASO PARTICULAR
|
273 | // y el sentido de circulaci?n es correcto
|
||
274 | if ((origin.getIdArc() == dest.getIdArc())
|
||
275 | && (nodeEnd.getBestCost() <= costeTramoFinal)) { |
||
276 | if (dest.getPct() > origin.getPct()) {
|
||
277 | pctMax = dest.getPct(); |
||
278 | pctMin = origin.getPct(); |
||
279 | } else {
|
||
280 | pctMax = origin.getPct(); |
||
281 | pctMin = dest.getPct(); |
||
282 | bFlipearShape = true;
|
||
283 | } |
||
284 | 8499 | fjp | |
285 | 20099 | fpenarrubia | LineString line = NetworkUtils.getPartialLineString(jtsGeom, |
286 | pctMax, 1);
|
||
287 | 8499 | fjp | |
288 | 20099 | fpenarrubia | pctMin = pctMin / pctMax; // Porque ha cambiado la longitud
|
289 | // del shape
|
||
290 | 8499 | fjp | |
291 | 20099 | fpenarrubia | line = NetworkUtils.getPartialLineString(line, pctMin, 0);
|
292 | 8499 | fjp | |
293 | 20099 | fpenarrubia | if (bFlipearShape)
|
294 | line = line.reverse(); |
||
295 | 8499 | fjp | |
296 | 20099 | fpenarrubia | IGeometry geom = FConverter.jts_to_igeometry(line); |
297 | // TODO: Calcular bien el length de este arco,
|
||
298 | // basandonos en el porcentaje costeTramoFinal / costeOriginal
|
||
299 | route.addRouteFeature(geom, origin.getIdArc(), costeTramoFinal, |
||
300 | line.getLength(), feat.getAttribute( |
||
301 | getFieldIndexStreetName()).toString()); |
||
302 | 8499 | fjp | |
303 | 20099 | fpenarrubia | return; // Deber?a sacar el coste |
304 | } |
||
305 | 8499 | fjp | |
306 | 20099 | fpenarrubia | // Trazar el camino desde idEnd hasta idStart hacia atr?s marcando
|
307 | // los Enlaces
|
||
308 | pNodo = graph.getNodeByID(idEnd); |
||
309 | 8499 | fjp | |
310 | 20099 | fpenarrubia | while ((pNodo.getIdNode() != idStart)) {
|
311 | idEnlace = pNodo.getFromLink(); |
||
312 | pEnlace = graph.getEdgeByID(idEnlace); |
||
313 | 8499 | fjp | |
314 | 20099 | fpenarrubia | pNodo = graph.getNodeByID(pEnlace.getIdNodeOrig()); |
315 | 8499 | fjp | |
316 | 20099 | fpenarrubia | infoShp = new InfoShp();
|
317 | infoShp.distance = pEnlace.getDistance(); |
||
318 | infoShp.cost = pEnlace.getWeight(); |
||
319 | |||
320 | if ((pEnlace.getIdArc() == origin.getIdArc())
|
||
321 | || (pEnlace.getIdArc() == dest.getIdArc())) { |
||
322 | if (pEnlace.getIdArc() == origin.getIdArc()) {
|
||
323 | infoShp.pct = origin.getPct(); |
||
324 | infoShp.idArc = origin.getIdArc(); |
||
325 | if (pEnlace.getDirec() == 0) { |
||
326 | infoShp.direction = 1;
|
||
327 | infoShp.bFlip = true;
|
||
328 | } else // Hemos pasado por el 2 |
||
329 | { |
||
330 | infoShp.direction = 0;
|
||
331 | infoShp.bFlip = false;
|
||
332 | } // if else */
|
||
333 | } else {
|
||
334 | infoShp.pct = dest.getPct(); |
||
335 | infoShp.idArc = dest.getIdArc(); |
||
336 | if (pEnlace.getDirec() == 0) { |
||
337 | infoShp.direction = 0;
|
||
338 | infoShp.bFlip = true;
|
||
339 | } else {
|
||
340 | infoShp.direction = 1;
|
||
341 | infoShp.bFlip = false;
|
||
342 | } // if else */
|
||
343 | 8499 | fjp | } |
344 | 20099 | fpenarrubia | } else {
|
345 | infoShp.pct = 1.0;
|
||
346 | infoShp.idArc = pEnlace.getIdArc(); |
||
347 | |||
348 | infoShp.direction = 1;
|
||
349 | if (pEnlace.getDirec() == 1) |
||
350 | 8499 | fjp | infoShp.bFlip = false;
|
351 | else
|
||
352 | 20099 | fpenarrubia | infoShp.bFlip = true;
|
353 | 8499 | fjp | } |
354 | 20099 | fpenarrubia | |
355 | pilaShapes.push(infoShp); |
||
356 | 8499 | fjp | } |
357 | |||
358 | 20099 | fpenarrubia | // Y ahora recorremos hacia atr?s el vector y escribimos los shapes.
|
359 | // VECTORINFO::iterator theIterator;
|
||
360 | int auxC = 0; |
||
361 | 8499 | fjp | |
362 | 20099 | fpenarrubia | while (!pilaShapes.empty()) {
|
363 | infoShp = (InfoShp) pilaShapes.peek(); |
||
364 | feat = va.getFeature(infoShp.idArc); |
||
365 | MultiLineString line = (MultiLineString) feat.getGeometry() |
||
366 | .toJTSGeometry(); |
||
367 | // line.apply(removeDuplicates);
|
||
368 | // line.geometryChanged();
|
||
369 | 8499 | fjp | |
370 | 20099 | fpenarrubia | LineString aux = null;
|
371 | if (infoShp.pct < 1.0) |
||
372 | aux = NetworkUtils.getPartialLineString(line, infoShp.pct, |
||
373 | infoShp.direction); |
||
374 | 8499 | fjp | |
375 | 20099 | fpenarrubia | IGeometry geom = null;
|
376 | if (aux == null) { |
||
377 | if (infoShp.bFlip)
|
||
378 | line = line.reverse(); |
||
379 | geom = FConverter.jts_to_igeometry(line); |
||
380 | } else {
|
||
381 | if (infoShp.bFlip)
|
||
382 | aux = aux.reverse(); |
||
383 | geom = FConverter.jts_to_igeometry(aux); |
||
384 | } |
||
385 | 8499 | fjp | |
386 | 20099 | fpenarrubia | route.addRouteFeature(geom, infoShp.idArc, infoShp.cost, |
387 | infoShp.distance, feat.getAttribute( |
||
388 | getFieldIndexStreetName()).toString()); |
||
389 | 8499 | fjp | |
390 | 20099 | fpenarrubia | pilaShapes.pop(); |
391 | auxC++; |
||
392 | 8499 | fjp | |
393 | 20099 | fpenarrubia | } |
394 | va.stop(); |
||
395 | } catch (Exception e) { |
||
396 | 11631 | fjp | // TODO Auto-generated catch block
|
397 | e.printStackTrace(); |
||
398 | } |
||
399 | 8499 | fjp | |
400 | return;
|
||
401 | |||
402 | } |
||
403 | |||
404 | LineString SituaSobreTramo(Geometry geom, int idArc, double pct, int parte) |
||
405 | // Si parte vale cero, los v?lidos son los primeros. Si no, los segundos.
|
||
406 | { |
||
407 | int j, numVertices;
|
||
408 | double longAcum, longReal, longBuscada, distSobre, miniPorcentaje;
|
||
409 | double nuevaX, nuevaY; // Por cuestiones de claridad al programar |
||
410 | double dist=0; |
||
411 | |||
412 | longAcum = 0;
|
||
413 | longReal = geom.getLength(); |
||
414 | longBuscada = longReal * pct; |
||
415 | Coordinate[] coords = geom.getCoordinates();
|
||
416 | Coordinate c1 = null, c2 = null; |
||
417 | ArrayList savedCoords = new ArrayList(); |
||
418 | |||
419 | if (parte > 0) // Hemos entrado por el 1 hacia el 2 (al 2 no llegamos) |
||
420 | { |
||
421 | for( j = 0; j < coords.length-1; j++ ) |
||
422 | { |
||
423 | c1 = coords[j]; |
||
424 | c2 = coords[j+1];
|
||
425 | dist = c1.distance(c2); |
||
426 | longAcum += dist; |
||
427 | savedCoords.add(c1); |
||
428 | if (longAcum >= longBuscada)
|
||
429 | { |
||
430 | // Hasta aqu?. Ahora ahi que poner el punto sobre el tramo
|
||
431 | distSobre = dist - (longAcum - longBuscada); |
||
432 | miniPorcentaje = distSobre/dist; |
||
433 | |||
434 | nuevaX = c1.x + (c2.x-c1.x) * miniPorcentaje; |
||
435 | nuevaY = c1.y + (c2.y-c1.y) * miniPorcentaje; |
||
436 | |||
437 | savedCoords.add(new Coordinate(nuevaX, nuevaY));
|
||
438 | break;
|
||
439 | } // if longAcum >= longBuscada
|
||
440 | } // for j
|
||
441 | |||
442 | } |
||
443 | else // Hemos entrado por el 2 hacia el 1 |
||
444 | { |
||
445 | numVertices = 0;
|
||
446 | for( j = 0; j < coords.length; j++ ) |
||
447 | { |
||
448 | ////////////////////////////////////////////////////////////////
|
||
449 | // 13_ene_2005: Si el ?ltimo punto es el ?ltimo punto no
|
||
450 | // podemos acceder al elemento j+1 porque nos salimos del shape
|
||
451 | /////////////////////////////////////////////////////////////////
|
||
452 | c1 = coords[j]; |
||
453 | if (j < coords.length -1) |
||
454 | { |
||
455 | c2 = coords[j+1];
|
||
456 | |||
457 | dist = c1.distance(c2); |
||
458 | longAcum += dist; |
||
459 | } |
||
460 | |||
461 | if (longAcum >= longBuscada)
|
||
462 | { |
||
463 | // Hasta aqu?. Empezamos a meter puntos
|
||
464 | |||
465 | if (numVertices == 0) |
||
466 | { |
||
467 | distSobre = dist - (longAcum - longBuscada); |
||
468 | miniPorcentaje = distSobre/dist; |
||
469 | nuevaX = c1.x + (c2.x-c1.x) * miniPorcentaje; |
||
470 | nuevaY = c1.y + (c2.y-c1.y) * miniPorcentaje; |
||
471 | |||
472 | savedCoords.add(new Coordinate(nuevaX, nuevaY));
|
||
473 | } |
||
474 | else
|
||
475 | { |
||
476 | savedCoords.add(c2); |
||
477 | } |
||
478 | numVertices ++; |
||
479 | // break;
|
||
480 | } // if longAcum >= longBuscada
|
||
481 | } // for j
|
||
482 | |||
483 | // savedCoords.add(c2);
|
||
484 | |||
485 | } // if else
|
||
486 | |||
487 | |||
488 | return geomFactory.createLineString((Coordinate[] )savedCoords.toArray(new Coordinate[0])); |
||
489 | } |
||
490 | |||
491 | private int getFieldIndexStreetName() { |
||
492 | return fieldIndexStreetName;
|
||
493 | } |
||
494 | |||
495 | private double AStar(int idStart, int idStop) { |
||
496 | int nodeNum;
|
||
497 | int linkNum;
|
||
498 | double newCost;
|
||
499 | int idSiguienteNodo;
|
||
500 | GvNode node, toNode, finalNode, bestNode; // , *pNodoProv;
|
||
501 | GvEdge link; |
||
502 | boolean bExit = false; |
||
503 | |||
504 | boolean bGiroProhibido;
|
||
505 | ArrayList candidatos = new ArrayList(); |
||
506 | |||
507 | // char Mensaje[200];
|
||
508 | |||
509 | IGraph graph = net.getGraph(); |
||
510 | |||
511 | // NUEVO: 27-6-2003
|
||
512 | // Cada nodo y cada arco llevan un nuemero de soluci?n. Se supone
|
||
513 | // que si lo del nodo y el arco no coincide con
|
||
514 | // este numero, todav?a no ha sido inicializado y hay que hacerlo.
|
||
515 | // Para evitar coincidencias cuando de la vuelta el contador, cada
|
||
516 | // 65000 peticiones (por ejemplo), repasamos toda
|
||
517 | // la red y ponemos numSolucGlobal a -1
|
||
518 | if (numSolucGlobal > 65000) { |
||
519 | numSolucGlobal = -1;
|
||
520 | |||
521 | for (nodeNum = 0; nodeNum < graph.numVertices(); nodeNum++) { |
||
522 | node = graph.getNodeByID(nodeNum); |
||
523 | node.initialize(); |
||
524 | } // for nodeNum */
|
||
525 | |||
526 | } |
||
527 | numSolucGlobal++; |
||
528 | |||
529 | candidatos.clear(); |
||
530 | // A?adimos el Start Node a la lista de candidatosSTL
|
||
531 | // Nodo final
|
||
532 | finalNode = graph.getNodeByID(idStop); |
||
533 | finalNode.initialize(); |
||
534 | |||
535 | node = graph.getNodeByID(idStart); |
||
536 | node.initialize(); |
||
537 | bestNode = node; |
||
538 | |||
539 | candidatos.add(node); |
||
540 | node.setBestCost(0);
|
||
541 | node.setStatus(GvNode.statNowInList); |
||
542 | 8523 | fjp | node.calculateStimation(finalNode, 0);
|
543 | 8522 | fjp | |
544 | 8499 | fjp | // Mientras que la lista de candidatosSTL no est? vac?a, procesamos
|
545 | // Nodos
|
||
546 | 8522 | fjp | double bestStimation;
|
547 | 8499 | fjp | |
548 | while ((!bExit) && (candidatos.size() > 0)) { |
||
549 | // Buscamos el nodo con m?nimo coste
|
||
550 | node = (GvNode) candidatos.get(0);
|
||
551 | bestNode = node; |
||
552 | 8522 | fjp | bestStimation = node.getStimation(); |
553 | 8499 | fjp | for (nodeNum = 1; nodeNum < candidatos.size(); nodeNum++) { |
554 | node = (GvNode) candidatos.get(nodeNum); |
||
555 | 8522 | fjp | if (node.getStimation() < bestStimation) {
|
556 | bestStimation = node.getStimation(); |
||
557 | 8499 | fjp | bestNode = node; |
558 | } |
||
559 | } // for nodeNum candidatosSTL
|
||
560 | |||
561 | node = bestNode; |
||
562 | // Borramos el mejor nodo de la lista de candidatosSTL
|
||
563 | node.setStatus(GvNode.statWasInList); |
||
564 | // TODO: BORRAR POR INDEX, NO AS?. ES M?S LENTO QUE SI BORRAMOS EL i-?simo.
|
||
565 | candidatos.remove(node); |
||
566 | // System.out.println("LINK " + link.getIdArc() + " from ");
|
||
567 | // System.out.println("from " + idStart + " to " + finalNode.getIdNode() + ". node=" + node.getIdNode());
|
||
568 | // Miramos si hemos llegado donde quer?amos
|
||
569 | if (bestNode.getIdNode() == idStop) {
|
||
570 | bExit = true;
|
||
571 | break;
|
||
572 | } |
||
573 | |||
574 | // sprintf(Mensaje,"Enlaces en el nodo %ld:
|
||
575 | // %ld.",pNodo->idNodo,pNodo->Enlaces.GetSize());
|
||
576 | // AfxMessageBox(Mensaje);
|
||
577 | |||
578 | // A?adimos a la lista de candidatosSTL los vecinos del nodo que
|
||
579 | // acabamos de borrar
|
||
580 | // HAY Arcos QUE SALEN Y Arcos QUE LLEGAN. SOLO MIRAMOS LOS QUE
|
||
581 | // SALEN.
|
||
582 | for (linkNum = 0; linkNum < node.getEnlaces().size(); linkNum++) { |
||
583 | // Pillamos el nodo vecino
|
||
584 | link = (GvEdge) node.getEnlaces().get(linkNum); |
||
585 | idSiguienteNodo = link.getIdNodeEnd(); |
||
586 | |||
587 | toNode = graph.getNodeByID(idSiguienteNodo); |
||
588 | |||
589 | // 27_5_2004
|
||
590 | // Si un arco tiene coste negativo, lo ignoramos
|
||
591 | if (link.getWeight() < 0) |
||
592 | continue;
|
||
593 | |||
594 | // Fin arco con coste negativo
|
||
595 | |||
596 | // NUEVO: 26-7-2003: Comprobamos si est? inicializado
|
||
597 | if (toNode.getNumSoluc() != numSolucGlobal) {
|
||
598 | toNode.initialize(); |
||
599 | } |
||
600 | else
|
||
601 | { |
||
602 | // System.out.println("Nodo ya inicializado");
|
||
603 | } |
||
604 | |||
605 | 8522 | fjp | // Miramos a ver si podemos mejorar su best_cost
|
606 | newCost = node.getBestCost() + link.getWeight(); |
||
607 | 8499 | fjp | |
608 | 8522 | fjp | if (newCost < toNode.getBestCost()) {
|
609 | // Es una mejora, as? que actualizamos el vecino y
|
||
610 | // lo a?adimos a los candidatosSTL
|
||
611 | toNode.setBestCost(newCost); |
||
612 | toNode.setFromLink(link.getIdEdge()); |
||
613 | |||
614 | 8523 | fjp | toNode.calculateStimation(finalNode, newCost); |
615 | 8499 | fjp | |
616 | 8522 | fjp | if (toNode.getStatus() != GvNode.statNowInList) {
|
617 | toNode.setStatus(GvNode.statNowInList); |
||
618 | candidatos.add(toNode); |
||
619 | } |
||
620 | } // Si hay mejora
|
||
621 | 8499 | fjp | |
622 | } // for linkNum
|
||
623 | } // while candidatosSTL
|
||
624 | |||
625 | newCost = finalNode.getBestCost(); |
||
626 | |||
627 | return newCost;
|
||
628 | } |
||
629 | |||
630 | } |