svn-gvsig-desktop / trunk / extensions / extGraph / src / org / gvsig / graph / core / GvNode.java @ 35157
History | View | Annotate | Download (14.8 KB)
1 |
/* 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 org.gvsig.graph.core; |
42 |
|
43 |
import java.util.ArrayList; |
44 |
|
45 |
import org.gvsig.fmap.algorithm.triangulation.visad.SetException; |
46 |
|
47 |
public class GvNode implements Comparable<GvNode> { |
48 |
public final static int statNotInList = 0; |
49 |
public final static int statNowInList = 1; |
50 |
public final static int statWasInList = 2; |
51 |
private int idNode; |
52 |
private double x; |
53 |
private double y; |
54 |
|
55 |
// int from_link = -1; // id del Arco desde el que hemos llegado
|
56 |
int numSoluc = 0; // Empezamos con esto a cero en toda la red. |
57 |
// De manera global, habr? una variable numSolucGlobal que indica el n? de cada petici?n de ruta.
|
58 |
// Sirve para no tener que inicializar siempre tooooda la red. Lo que hacemos es comparar el
|
59 |
// n? de petici?n global con este. Si no coinciden, antes de hacer nada hay que inicializar su
|
60 |
// best_cost a infinito.
|
61 |
|
62 |
// double best_cost = Double.MAX_VALUE;
|
63 |
double accumulatedLength = 0; |
64 |
double stimation = Double.MAX_VALUE; // bestCost + something related to destiny's euclidean length |
65 |
int status;
|
66 |
// ArrayList<GvEdge> outputLinks = new ArrayList<GvEdge>(); // Neighbors links
|
67 |
// ArrayList<GvEdge> inputLinks = new ArrayList<GvEdge>(); // links with end node in this node.
|
68 |
|
69 |
ArrayList<GvConnector> connectors = new ArrayList<GvConnector>(2); |
70 |
|
71 |
ArrayList<GvTurn> turnCosts = new ArrayList<GvTurn>(0); // Turn costs. If a GvTurnCost exists, we add its cost. |
72 |
// If the cost is < 0, it is a prohibited cost.
|
73 |
|
74 |
public GvNode() {
|
75 |
initialize(); |
76 |
} |
77 |
|
78 |
public void initialize() { |
79 |
numSoluc = GlobalCounter.numSolucGlobal; |
80 |
// from_link = -1;
|
81 |
// best_cost = Double.MAX_VALUE;
|
82 |
stimation = Double.MAX_VALUE;
|
83 |
accumulatedLength = 0;
|
84 |
status = statNotInList; |
85 |
GvConnector c; |
86 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
87 |
{ |
88 |
c = connectors.get(iConec); |
89 |
|
90 |
c.setFrom_link_c(-1);
|
91 |
c.setBestCostOut(Double.MAX_VALUE);
|
92 |
c.setBestCostIn(Double.MAX_VALUE);
|
93 |
c.setMustBeRevised(true);
|
94 |
} |
95 |
|
96 |
|
97 |
} |
98 |
|
99 |
public int getIdNode() { |
100 |
return idNode;
|
101 |
} |
102 |
public void setIdNode(int idNode) { |
103 |
this.idNode = idNode;
|
104 |
} |
105 |
public double getX() { |
106 |
return x;
|
107 |
} |
108 |
public void setX(double x) { |
109 |
this.x = x;
|
110 |
} |
111 |
public double getY() { |
112 |
return y;
|
113 |
} |
114 |
public void setY(double y) { |
115 |
this.y = y;
|
116 |
} |
117 |
// public double getBestCost() {
|
118 |
// if (numSoluc != GlobalCounter.getGlobalSolutionNumber())
|
119 |
// return Double.MAX_VALUE;
|
120 |
// return best_cost;
|
121 |
// }
|
122 |
// public void setBestCost(double best_cost) {
|
123 |
// this.best_cost = best_cost;
|
124 |
// }
|
125 |
// public ArrayList getOutputLinks() {
|
126 |
// return outputLinks;
|
127 |
// }
|
128 |
public double getStimation() { |
129 |
return stimation;
|
130 |
} |
131 |
public void setStimation(double estimacion) { |
132 |
this.stimation = estimacion;
|
133 |
} |
134 |
// public int getFromLink() {
|
135 |
// return from_link;
|
136 |
// }
|
137 |
// public void setFromLink(int from_link) {
|
138 |
// this.from_link = from_link;
|
139 |
// }
|
140 |
public ArrayList<GvTurn> getTurnCosts() { |
141 |
return turnCosts;
|
142 |
} |
143 |
|
144 |
public void setTurnCosts(ArrayList<GvTurn> turns) { |
145 |
this.turnCosts = turns;
|
146 |
} |
147 |
public int getNumSoluc() { |
148 |
return numSoluc;
|
149 |
} |
150 |
public void setNumSoluc(int numSoluc) { |
151 |
this.numSoluc = numSoluc;
|
152 |
} |
153 |
public int getStatus() { |
154 |
return status;
|
155 |
} |
156 |
public void setStatus(int status) { |
157 |
this.status = status;
|
158 |
} |
159 |
|
160 |
public void calculateStimation(GvNode finalNode, double newCost) { |
161 |
double DeltaX = ((finalNode.getX() - x)/1000.0)*((finalNode.getX() - x)/1000.0); |
162 |
double DeltaY = ((finalNode.getY() - y)/1000.0)*((finalNode.getY() - y)/1000.0); |
163 |
double distLineaRecta = Math.sqrt(DeltaX + DeltaY); // En Km |
164 |
stimation = newCost + (distLineaRecta* 30.0); // Segundos que tardamos en recorrer esos Km a 120 Km/hora |
165 |
|
166 |
|
167 |
} |
168 |
|
169 |
public double getAccumulatedLength() { |
170 |
return accumulatedLength;
|
171 |
} |
172 |
|
173 |
public void setAccumulatedLength(double accumulatedLength) { |
174 |
this.accumulatedLength = accumulatedLength;
|
175 |
} |
176 |
|
177 |
public int getOutputDegree() { |
178 |
int numOutLink = 0; |
179 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
180 |
{ |
181 |
GvConnector c = connectors.get(iConec); |
182 |
|
183 |
if (c.getEdgeOut() == null) continue; |
184 |
numOutLink++; |
185 |
} |
186 |
return numOutLink;
|
187 |
} |
188 |
|
189 |
public int getInputDegree() { |
190 |
int numInLink = 0; |
191 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
192 |
{ |
193 |
GvConnector c = connectors.get(iConec); |
194 |
|
195 |
if (c.getEdgeIn() == null) continue; |
196 |
numInLink++; |
197 |
} |
198 |
return numInLink;
|
199 |
|
200 |
} |
201 |
|
202 |
public EdgeOutIterator getOutputEdgeIterator() {
|
203 |
return new EdgeOutIterator(this); |
204 |
} |
205 |
|
206 |
public EdgeInIterator getInputEdgeIterator() {
|
207 |
return new EdgeInIterator(this); |
208 |
} |
209 |
|
210 |
|
211 |
/**
|
212 |
* Returns the link that we have used to reach idEdgeOut. Important for turn costs.
|
213 |
* @param idArcoS
|
214 |
* @return
|
215 |
*/
|
216 |
public int get_from_link(long idEdgeOut) |
217 |
{ |
218 |
// Queremos saber desde qu? arco hemos entrado para llegar a este arco.
|
219 |
for (int iConec =0; iConec < connectors.size(); iConec++) { |
220 |
GvConnector c = connectors.get(iConec); |
221 |
if (c.getEdgeOut() != null) { |
222 |
if (c.getEdgeOut().getIdEdge() == idEdgeOut)
|
223 |
{ |
224 |
return c.getFrom_link_c();
|
225 |
} |
226 |
} |
227 |
|
228 |
} |
229 |
// TODO: throw exception??
|
230 |
return -1; |
231 |
|
232 |
} |
233 |
public int get_best_from_link() |
234 |
{ |
235 |
// Queremos saber desde qu? arco hemos entrado para llegar a este arco.
|
236 |
GvConnector c; |
237 |
int best_link = -1; |
238 |
double bestCost = Double.MAX_VALUE; |
239 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
240 |
{ |
241 |
c = connectors.get(iConec); |
242 |
if (c.getBestCostOut() < bestCost)
|
243 |
{ |
244 |
bestCost = c.getBestCostOut(); |
245 |
best_link = c.getFrom_link_c(); |
246 |
} |
247 |
|
248 |
} |
249 |
return best_link;
|
250 |
|
251 |
} |
252 |
|
253 |
public boolean existeMejora(GvEdge edge, double newCost) |
254 |
{ |
255 |
// Si entrando desde ese arco mejoramos el coste de alg?n conector, devolvemos que
|
256 |
// hay mejora
|
257 |
// NO QUEREMOS TOCAR EL CONECTOR PROPIO!!!! (Para evitar que en un nodo hagamos un U-turn) (Pero s? hay que marcarlo como con mejora, si existe)
|
258 |
// Y tampoco hay que tener en cuenta los costes de giros para los conectores que toque.
|
259 |
boolean hayMejora = false; |
260 |
GvConnector c; |
261 |
double auxCost;
|
262 |
boolean bGiroProhibido;
|
263 |
double costeGiro;
|
264 |
// char Msg[200];
|
265 |
|
266 |
// log("Dentro de existeMejora");
|
267 |
|
268 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
269 |
{ |
270 |
// sprintf(Msg,"Conector iConec=%ld de %ld. Capacity=%ld", iConec, Conectores.size(), Conectores.capacity());
|
271 |
// log(Msg);
|
272 |
auxCost = newCost; |
273 |
c = connectors.get(iConec); |
274 |
// sprintf(Msg,"pC->idArcoS=%ld, pc-idArcoE=%ld", pC->idArcoS, pC->idArcoE);
|
275 |
// log(Msg);
|
276 |
|
277 |
if (c.getEdgeOut() == null) continue; |
278 |
|
279 |
// Miramos la lista de Giros de ese nodo
|
280 |
bGiroProhibido = false;
|
281 |
costeGiro = 0;
|
282 |
for (int idGiro=0; idGiro < getTurnCosts().size(); idGiro++) |
283 |
{ |
284 |
// Si est? prohibido, a por otro
|
285 |
GvTurn elGiro = getTurnCosts().get(idGiro); |
286 |
// log("ANTES del if");
|
287 |
if ((elGiro.getIdArcFrom() == edge.getIdArc()) &&
|
288 |
(elGiro.getIdArcTo() == c.getEdgeOut().getIdArc())) |
289 |
{ |
290 |
if (elGiro.getCost() < 0) |
291 |
{ |
292 |
bGiroProhibido = true;
|
293 |
} |
294 |
else
|
295 |
costeGiro = elGiro.getCost(); |
296 |
|
297 |
break; // Salimos del for porque ya hemos encontrado el giro |
298 |
} |
299 |
// log("DESPUES del if");
|
300 |
} |
301 |
|
302 |
auxCost = newCost + costeGiro; |
303 |
// if (c.getEdgeIn() == edge) // Para evitar los U-turn
|
304 |
// {
|
305 |
// if (c.getBestCostIn() > newCost)
|
306 |
// {
|
307 |
// c.setBestCostIn(newCost);
|
308 |
// c.setFrom_link_c(edge.getIdEdge());
|
309 |
// hayMejora = true;
|
310 |
// }
|
311 |
// continue; // Miramos solo los conectores distintos al de entrada
|
312 |
// }
|
313 |
// Si est? prohibido, vamos a por otro enlace
|
314 |
if (bGiroProhibido)
|
315 |
{ |
316 |
c.setMustBeRevised(true);
|
317 |
// sprintf(Msg, "Encontrado giro prohibido en conector %ld del nodo %ld", iConec, idNodo);
|
318 |
// log(Msg);
|
319 |
continue;
|
320 |
} |
321 |
|
322 |
c.setMustBeRevised(false);
|
323 |
if (c.getBestCostOut() > auxCost)
|
324 |
{ |
325 |
hayMejora = true;
|
326 |
c.setFrom_link_c(edge.getIdEdge()); |
327 |
c.setBestCostOut(auxCost); |
328 |
c.setMustBeRevised(true);
|
329 |
// sprintf(Msg, "HAY MEJORA: idNodo=%ld, iConec=%ld, idArcoEntrada=%ld, auxCost= %lf", idNodo, iConec, idArcoEntrada, auxCost);
|
330 |
} |
331 |
} |
332 |
return hayMejora;
|
333 |
|
334 |
} |
335 |
public boolean reverseFoundBetterPath(GvEdge edge, double newCost) |
336 |
{ |
337 |
// Si entrando desde ese arco mejoramos el coste de alg?n conector, devolvemos que
|
338 |
// hay mejora
|
339 |
// NO QUEREMOS TOCAR EL CONECTOR PROPIO!!!!
|
340 |
// Y tampoco hay que tener en cuenta los costes de giros para los conectores que toque.
|
341 |
boolean hayMejora = false; |
342 |
GvConnector c; |
343 |
double auxCost;
|
344 |
boolean bGiroProhibido;
|
345 |
double costeGiro;
|
346 |
// char Msg[200];
|
347 |
|
348 |
// log("Dentro de existeMejora");
|
349 |
|
350 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
351 |
{ |
352 |
// sprintf(Msg,"Conector iConec=%ld de %ld. Capacity=%ld", iConec, Conectores.size(), Conectores.capacity());
|
353 |
// log(Msg);
|
354 |
auxCost = newCost; |
355 |
c = connectors.get(iConec); |
356 |
// sprintf(Msg,"pC->idArcoS=%ld, pc-idArcoE=%ld", pC->idArcoS, pC->idArcoE);
|
357 |
// log(Msg);
|
358 |
|
359 |
if (c.getEdgeIn() == null) continue; |
360 |
|
361 |
// Miramos la lista de Giros de ese nodo
|
362 |
bGiroProhibido = false;
|
363 |
costeGiro = 0;
|
364 |
for (int idGiro=0; idGiro < getTurnCosts().size(); idGiro++) |
365 |
{ |
366 |
// Si est? prohibido, a por otro
|
367 |
GvTurn elGiro = getTurnCosts().get(idGiro); |
368 |
// log("ANTES del if");
|
369 |
if ((elGiro.getIdArcTo() == edge.getIdArc()) &&
|
370 |
(elGiro.getIdArcFrom() == c.getEdgeIn().getIdArc())) |
371 |
{ |
372 |
if (elGiro.getCost() < 0) |
373 |
{ |
374 |
bGiroProhibido = true;
|
375 |
} |
376 |
else
|
377 |
costeGiro = elGiro.getCost(); |
378 |
|
379 |
break; // Salimos del for porque ya hemos encontrado el giro |
380 |
} |
381 |
// log("DESPUES del if");
|
382 |
} |
383 |
|
384 |
auxCost = newCost + costeGiro; |
385 |
if (c.getEdgeOut() == edge)
|
386 |
{ |
387 |
if (c.getBestCostIn() > newCost)
|
388 |
{ |
389 |
c.setBestCostIn(newCost); |
390 |
// pC->from_link_c = idArcoEntrada;
|
391 |
} |
392 |
continue; // Miramos solo los conectores distintos al de entrada |
393 |
} |
394 |
// Si est? prohibido, vamos a por otro enlace
|
395 |
if (bGiroProhibido)
|
396 |
{ |
397 |
c.setMustBeRevised(true);
|
398 |
// sprintf(Msg, "Encontrado giro prohibido en conector %ld del nodo %ld", iConec, idNodo);
|
399 |
// log(Msg);
|
400 |
continue;
|
401 |
} |
402 |
|
403 |
c.setMustBeRevised(false);
|
404 |
if (c.getBestCostOut() > auxCost)
|
405 |
{ |
406 |
hayMejora = true;
|
407 |
c.setFrom_link_c(edge.getIdEdge()); |
408 |
c.setBestCostOut(auxCost); |
409 |
c.setMustBeRevised(true);
|
410 |
// sprintf(Msg, "HAY MEJORA: idNodo=%ld, iConec=%ld, idArcoEntrada=%ld, auxCost= %lf", idNodo, iConec, idArcoEntrada, auxCost);
|
411 |
} |
412 |
} |
413 |
return hayMejora;
|
414 |
|
415 |
} |
416 |
|
417 |
|
418 |
public double getBestCost() |
419 |
{ |
420 |
if (numSoluc != GlobalCounter.getGlobalSolutionNumber())
|
421 |
return Double.MAX_VALUE; |
422 |
|
423 |
double bestCost = Double.MAX_VALUE; |
424 |
GvConnector c; |
425 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
426 |
{ |
427 |
c = connectors.get(iConec); |
428 |
|
429 |
if (c.getBestCostOut() < bestCost)
|
430 |
{ |
431 |
bestCost = c.getBestCostOut(); |
432 |
} |
433 |
} |
434 |
return bestCost;
|
435 |
|
436 |
} |
437 |
|
438 |
public double getBestCostIn() |
439 |
{ |
440 |
if (numSoluc != GlobalCounter.getGlobalSolutionNumber())
|
441 |
return Double.MAX_VALUE; |
442 |
|
443 |
double bestCost = Double.MAX_VALUE; |
444 |
GvConnector c; |
445 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
446 |
{ |
447 |
c = connectors.get(iConec); |
448 |
|
449 |
if (c.getBestCostIn() < bestCost)
|
450 |
{ |
451 |
bestCost = c.getBestCostIn(); |
452 |
} |
453 |
} |
454 |
return bestCost;
|
455 |
|
456 |
} |
457 |
|
458 |
public double getBestCostOfDirty() |
459 |
{ |
460 |
if (numSoluc != GlobalCounter.getGlobalSolutionNumber())
|
461 |
return Double.MAX_VALUE; |
462 |
|
463 |
double bestCost = Double.MAX_VALUE; |
464 |
GvConnector c; |
465 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
466 |
{ |
467 |
c = connectors.get(iConec); |
468 |
|
469 |
if ((c.isMustBeRevised()) && (c.getBestCostOut() < bestCost))
|
470 |
{ |
471 |
bestCost = c.getBestCostOut(); |
472 |
} |
473 |
} |
474 |
return bestCost;
|
475 |
|
476 |
} |
477 |
|
478 |
public void setCostZero() |
479 |
{ |
480 |
GvConnector c; |
481 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
482 |
{ |
483 |
c = connectors.get(iConec); |
484 |
c.setBestCostOut(0);
|
485 |
c.setBestCostIn(0);
|
486 |
} |
487 |
|
488 |
// TODO: provisional. QUITAR bestCost como atributo
|
489 |
// best_cost = 0;
|
490 |
setStimation(0);
|
491 |
} |
492 |
|
493 |
/**
|
494 |
* Add an edge out to this node. This function takes care of creating the needed connectors
|
495 |
* @param edge
|
496 |
*/
|
497 |
public void addOutputLink(GvEdge edge) { |
498 |
// outputLinks.add(edge);
|
499 |
// Create connectors
|
500 |
// First, search the connector if it is already created
|
501 |
GvConnector c; |
502 |
boolean bFound = false; |
503 |
GvConnector cFound = null;
|
504 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
505 |
{ |
506 |
c = connectors.get(iConec); |
507 |
if ((c.getEdgeIn() != null) && (c.getEdgeIn().getIdArc() == edge.getIdArc())) { |
508 |
// Found. This connector has been originated before by the same arc
|
509 |
bFound = true;
|
510 |
cFound = c; |
511 |
break;
|
512 |
} |
513 |
} |
514 |
if (!bFound) {
|
515 |
GvConnector newCon = new GvConnector();
|
516 |
newCon.setEdgeOut(edge); |
517 |
connectors.add(newCon); |
518 |
} |
519 |
else
|
520 |
{ |
521 |
cFound.setEdgeOut(edge); |
522 |
} |
523 |
|
524 |
} |
525 |
|
526 |
/**
|
527 |
* Add an input edge to this node. This function takes care of creating the needed connectors
|
528 |
* @param edge
|
529 |
*/
|
530 |
public void addInputLink(GvEdge edge) { |
531 |
// inputLinks.add(edge);
|
532 |
// First, search the connector if it is already created
|
533 |
GvConnector c; |
534 |
boolean bFound = false; |
535 |
GvConnector cFound = null;
|
536 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
537 |
{ |
538 |
c = connectors.get(iConec); |
539 |
if ((c.getEdgeOut() != null) && (c.getEdgeOut().getIdArc() == edge.getIdArc())) { |
540 |
// Found. This connector has been originated before by the same arc
|
541 |
bFound = true;
|
542 |
cFound = c; |
543 |
break;
|
544 |
} |
545 |
} |
546 |
if (!bFound) {
|
547 |
GvConnector newCon = new GvConnector();
|
548 |
newCon.setEdgeIn(edge); |
549 |
connectors.add(newCon); |
550 |
} |
551 |
else
|
552 |
{ |
553 |
cFound.setEdgeIn(edge); |
554 |
} |
555 |
|
556 |
} |
557 |
|
558 |
public ArrayList<GvConnector> getConnectors() { |
559 |
return connectors;
|
560 |
} |
561 |
|
562 |
/**
|
563 |
* Adds turnCost and setNode to turnCost. Useful to clear turncosts
|
564 |
* @param turnCost
|
565 |
*/
|
566 |
public void addTurnCost(GvTurn turnCost) { |
567 |
turnCost.setNode(this);
|
568 |
turnCosts.add(turnCost); |
569 |
|
570 |
} |
571 |
|
572 |
public void removeTurnCosts() { |
573 |
turnCosts = new ArrayList<GvTurn>(); |
574 |
|
575 |
} |
576 |
|
577 |
public int compareTo(GvNode o) { |
578 |
return Double.compare(getStimation(), o.getStimation()); |
579 |
} |
580 |
|
581 |
} |
582 |
|
583 |
|