root / trunk / extensions / extGraph / src / org / gvsig / graph / core / GvNode.java @ 25339
History | View | Annotate | Download (11.6 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>(); |
68 |
|
69 |
ArrayList<GvTurn> turnCosts = new ArrayList<GvTurn>(); // 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().getIdEdge() == idEdgeOut)
|
219 |
{ |
220 |
return c.getFrom_link_c();
|
221 |
} |
222 |
|
223 |
} |
224 |
// TODO: throw exception??
|
225 |
return -1; |
226 |
|
227 |
} |
228 |
public int get_best_from_link() |
229 |
{ |
230 |
// Queremos saber desde qu? arco hemos entrado para llegar a este arco.
|
231 |
GvConnector c; |
232 |
int best_link = -1; |
233 |
double bestCost = Double.MAX_VALUE; |
234 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
235 |
{ |
236 |
c = connectors.get(iConec); |
237 |
if (c.getBestCostOut() < bestCost)
|
238 |
{ |
239 |
bestCost = c.getBestCostOut(); |
240 |
best_link = c.getFrom_link_c(); |
241 |
} |
242 |
|
243 |
} |
244 |
return best_link;
|
245 |
|
246 |
} |
247 |
|
248 |
public boolean existeMejora(GvEdge edge, double newCost) |
249 |
{ |
250 |
// Si entrando desde ese arco mejoramos el coste de alg?n conector, devolvemos que
|
251 |
// hay mejora
|
252 |
// NO QUEREMOS TOCAR EL CONECTOR PROPIO!!!!
|
253 |
// Y tampoco hay que tener en cuenta los costes de giros para los conectores que toque.
|
254 |
boolean hayMejora = false; |
255 |
GvConnector c; |
256 |
double auxCost;
|
257 |
boolean bGiroProhibido;
|
258 |
double costeGiro;
|
259 |
// char Msg[200];
|
260 |
|
261 |
// log("Dentro de existeMejora");
|
262 |
|
263 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
264 |
{ |
265 |
// sprintf(Msg,"Conector iConec=%ld de %ld. Capacity=%ld", iConec, Conectores.size(), Conectores.capacity());
|
266 |
// log(Msg);
|
267 |
auxCost = newCost; |
268 |
c = connectors.get(iConec); |
269 |
// sprintf(Msg,"pC->idArcoS=%ld, pc-idArcoE=%ld", pC->idArcoS, pC->idArcoE);
|
270 |
// log(Msg);
|
271 |
|
272 |
if (c.getEdgeOut() == null) continue; |
273 |
|
274 |
// Miramos la lista de Giros de ese nodo
|
275 |
bGiroProhibido = false;
|
276 |
costeGiro = 0;
|
277 |
for (int idGiro=0; idGiro < getTurnCosts().size(); idGiro++) |
278 |
{ |
279 |
// Si est? prohibido, a por otro
|
280 |
GvTurn elGiro = getTurnCosts().get(idGiro); |
281 |
// log("ANTES del if");
|
282 |
if ((elGiro.getIdArcFrom() == edge.getIdArc()) &&
|
283 |
(elGiro.getIdArcTo() == c.getEdgeOut().getIdArc())) |
284 |
{ |
285 |
if (elGiro.getCost() < 0) |
286 |
{ |
287 |
bGiroProhibido = true;
|
288 |
} |
289 |
else
|
290 |
costeGiro = elGiro.getCost(); |
291 |
|
292 |
break; // Salimos del for porque ya hemos encontrado el giro |
293 |
} |
294 |
// log("DESPUES del if");
|
295 |
} |
296 |
|
297 |
if (c.getEdgeIn() == edge)
|
298 |
{ |
299 |
if (c.getBestCostIn() > newCost)
|
300 |
{ |
301 |
c.setBestCostIn(newCost); |
302 |
// pC->from_link_c = idArcoEntrada;
|
303 |
} |
304 |
continue; // Miramos solo los conectores distintos al de entrada |
305 |
} |
306 |
// Si est? prohibido, vamos a por otro enlace
|
307 |
if (bGiroProhibido)
|
308 |
{ |
309 |
c.setMustBeRevised(true);
|
310 |
// sprintf(Msg, "Encontrado giro prohibido en conector %ld del nodo %ld", iConec, idNodo);
|
311 |
// log(Msg);
|
312 |
continue;
|
313 |
} |
314 |
auxCost = newCost + costeGiro; |
315 |
c.setMustBeRevised(false);
|
316 |
if (c.getBestCostOut() > auxCost)
|
317 |
{ |
318 |
hayMejora = true;
|
319 |
c.setFrom_link_c(edge.getIdEdge()); |
320 |
c.setBestCostOut(auxCost); |
321 |
c.setMustBeRevised(true);
|
322 |
// sprintf(Msg, "HAY MEJORA: idNodo=%ld, iConec=%ld, idArcoEntrada=%ld, auxCost= %lf", idNodo, iConec, idArcoEntrada, auxCost);
|
323 |
} |
324 |
} |
325 |
return hayMejora;
|
326 |
|
327 |
} |
328 |
public double getBestCost() |
329 |
{ |
330 |
if (numSoluc != GlobalCounter.getGlobalSolutionNumber())
|
331 |
return Double.MAX_VALUE; |
332 |
|
333 |
double bestCost = Double.MAX_VALUE; |
334 |
GvConnector c; |
335 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
336 |
{ |
337 |
c = connectors.get(iConec); |
338 |
|
339 |
if (c.getBestCostOut() < bestCost)
|
340 |
{ |
341 |
bestCost = c.getBestCostOut(); |
342 |
} |
343 |
} |
344 |
return bestCost;
|
345 |
|
346 |
} |
347 |
|
348 |
public double getBestCostOfDirty() |
349 |
{ |
350 |
if (numSoluc != GlobalCounter.getGlobalSolutionNumber())
|
351 |
return Double.MAX_VALUE; |
352 |
|
353 |
double bestCost = Double.MAX_VALUE; |
354 |
GvConnector c; |
355 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
356 |
{ |
357 |
c = connectors.get(iConec); |
358 |
|
359 |
if ((c.isMustBeRevised()) && (c.getBestCostOut() < bestCost))
|
360 |
{ |
361 |
bestCost = c.getBestCostOut(); |
362 |
} |
363 |
} |
364 |
return bestCost;
|
365 |
|
366 |
} |
367 |
|
368 |
public void setCostZero() |
369 |
{ |
370 |
GvConnector c; |
371 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
372 |
{ |
373 |
c = connectors.get(iConec); |
374 |
c.setBestCostOut(0);
|
375 |
c.setBestCostIn(0);
|
376 |
} |
377 |
|
378 |
// TODO: provisional. QUITAR bestCost como atributo
|
379 |
// best_cost = 0;
|
380 |
|
381 |
} |
382 |
|
383 |
/**
|
384 |
* Add an edge out to this node. This function takes care of creating the needed connectors
|
385 |
* @param edge
|
386 |
*/
|
387 |
public void addOutputLink(GvEdge edge) { |
388 |
// outputLinks.add(edge);
|
389 |
// Create connectors
|
390 |
// First, search the connector if it is already created
|
391 |
GvConnector c; |
392 |
boolean bFound = false; |
393 |
GvConnector cFound = null;
|
394 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
395 |
{ |
396 |
c = connectors.get(iConec); |
397 |
if ((c.getEdgeIn() != null) && (c.getEdgeIn().getIdArc() == edge.getIdArc())) { |
398 |
// Found. This connector has been originated before by the same arc
|
399 |
bFound = true;
|
400 |
cFound = c; |
401 |
break;
|
402 |
} |
403 |
} |
404 |
if (!bFound) {
|
405 |
GvConnector newCon = new GvConnector();
|
406 |
newCon.setEdgeOut(edge); |
407 |
connectors.add(newCon); |
408 |
} |
409 |
else
|
410 |
{ |
411 |
cFound.setEdgeOut(edge); |
412 |
} |
413 |
|
414 |
} |
415 |
|
416 |
/**
|
417 |
* Add an input edge to this node. This function takes care of creating the needed connectors
|
418 |
* @param edge
|
419 |
*/
|
420 |
public void addInputLink(GvEdge edge) { |
421 |
// inputLinks.add(edge);
|
422 |
// First, search the connector if it is already created
|
423 |
GvConnector c; |
424 |
boolean bFound = false; |
425 |
GvConnector cFound = null;
|
426 |
for (int iConec=0; iConec< connectors.size(); iConec++) |
427 |
{ |
428 |
c = connectors.get(iConec); |
429 |
if ((c.getEdgeOut() != null) && (c.getEdgeOut().getIdArc() == edge.getIdArc())) { |
430 |
// Found. This connector has been originated before by the same arc
|
431 |
bFound = true;
|
432 |
cFound = c; |
433 |
break;
|
434 |
} |
435 |
} |
436 |
if (!bFound) {
|
437 |
GvConnector newCon = new GvConnector();
|
438 |
newCon.setEdgeIn(edge); |
439 |
connectors.add(newCon); |
440 |
} |
441 |
else
|
442 |
{ |
443 |
cFound.setEdgeIn(edge); |
444 |
} |
445 |
|
446 |
} |
447 |
|
448 |
public ArrayList<GvConnector> getConnectors() { |
449 |
return connectors;
|
450 |
} |
451 |
|
452 |
/**
|
453 |
* Adds turnCost and setNode to turnCost. Useful to clear turncosts
|
454 |
* @param turnCost
|
455 |
*/
|
456 |
public void addTurnCost(GvTurn turnCost) { |
457 |
turnCost.setNode(this);
|
458 |
turnCosts.add(turnCost); |
459 |
|
460 |
} |
461 |
|
462 |
public void removeTurnCosts() { |
463 |
turnCosts = new ArrayList<GvTurn>(); |
464 |
|
465 |
} |
466 |
} |
467 |
|
468 |
|