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