svn-gvsig-desktop / trunk / extensions / extGraph_predes / src / com / iver / cit / gvsig / graph / core / Network.java @ 8211
History | View | Annotate | Download (15 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 com.iver.cit.gvsig.graph.core; |
42 |
|
43 |
import java.awt.geom.PathIterator; |
44 |
import java.awt.geom.Point2D; |
45 |
import java.util.ArrayList; |
46 |
|
47 |
import com.iver.cit.gvsig.fmap.DriverException; |
48 |
import com.iver.cit.gvsig.fmap.core.IGeometry; |
49 |
import com.iver.cit.gvsig.fmap.core.v02.FConverter; |
50 |
import com.iver.cit.gvsig.fmap.drivers.DriverIOException; |
51 |
import com.iver.cit.gvsig.fmap.layers.FBitSet; |
52 |
import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
53 |
import com.iver.cit.gvsig.fmap.layers.VectorialAdapter; |
54 |
import com.vividsolutions.jts.geom.Coordinate; |
55 |
import com.vividsolutions.jts.geom.LineSegment; |
56 |
|
57 |
public class Network { |
58 |
protected FLyrVect lyrVect;
|
59 |
protected IGraph graph;
|
60 |
protected ArrayList flags = new ArrayList(); |
61 |
|
62 |
public void reconstruyeTramo(int idArc) { |
63 |
// TODO Auto-generated method stub
|
64 |
|
65 |
} |
66 |
|
67 |
|
68 |
private int findClosestArc(double x, double y, double tolerance) |
69 |
{ |
70 |
Point2D p = new Point2D.Double(x, y); |
71 |
FBitSet bitSet; |
72 |
try {
|
73 |
bitSet = lyrVect.queryByPoint(p, tolerance); |
74 |
VectorialAdapter va = (VectorialAdapter) lyrVect.getSource(); |
75 |
int counter = 0; |
76 |
double minDist = tolerance;
|
77 |
int foundGeom = -1; |
78 |
for (int i = bitSet.nextSetBit(0); i >= 0; i = bitSet |
79 |
.nextSetBit(i + 1)) {
|
80 |
IGeometry geom; |
81 |
geom = va.getShape(i); |
82 |
Point2D nearest = getNearestPoint(p, geom, tolerance);
|
83 |
if (nearest != null) |
84 |
{ |
85 |
double dist = nearest.distance(p);
|
86 |
if (dist < minDist)
|
87 |
{ |
88 |
minDist = dist; |
89 |
foundGeom = i; |
90 |
} |
91 |
} |
92 |
} |
93 |
return foundGeom;
|
94 |
} catch (DriverException e1) {
|
95 |
// TODO Auto-generated catch block
|
96 |
e1.printStackTrace(); |
97 |
} catch (DriverIOException e) {
|
98 |
// TODO Auto-generated catch block
|
99 |
e.printStackTrace(); |
100 |
} |
101 |
return -1; |
102 |
|
103 |
|
104 |
} |
105 |
|
106 |
protected Point2D getNearestPoint(Point2D point, IGeometry geom, double tolerance) { |
107 |
Point2D resul = null; |
108 |
Coordinate c = new Coordinate(point.getX(), point.getY());
|
109 |
|
110 |
PathIterator theIterator = geom.getPathIterator(null, FConverter.FLATNESS); //polyLine.getPathIterator(null, flatness); |
111 |
double[] theData = new double[6]; |
112 |
double minDist = tolerance;
|
113 |
Coordinate from = null, first = null; |
114 |
while (!theIterator.isDone()) {
|
115 |
//while not done
|
116 |
int theType = theIterator.currentSegment(theData);
|
117 |
|
118 |
switch (theType) {
|
119 |
case PathIterator.SEG_MOVETO: |
120 |
from = new Coordinate(theData[0], theData[1]); |
121 |
first = from; |
122 |
break;
|
123 |
|
124 |
case PathIterator.SEG_LINETO: |
125 |
|
126 |
// System.out.println("SEG_LINETO");
|
127 |
Coordinate to = new Coordinate(theData[0], theData[1]); |
128 |
LineSegment line = new LineSegment(from, to);
|
129 |
Coordinate closestPoint = line.closestPoint(c); |
130 |
double dist = c.distance(closestPoint);
|
131 |
if ((dist < minDist)) {
|
132 |
resul = new Point2D.Double(closestPoint.x, closestPoint.y); |
133 |
minDist = dist; |
134 |
} |
135 |
|
136 |
from = to; |
137 |
break;
|
138 |
case PathIterator.SEG_CLOSE: |
139 |
line = new LineSegment(from, first);
|
140 |
closestPoint = line.closestPoint(c); |
141 |
dist = c.distance(closestPoint); |
142 |
if ((dist < minDist)) {
|
143 |
resul = new Point2D.Double(closestPoint.x, closestPoint.y); |
144 |
minDist = dist; |
145 |
} |
146 |
|
147 |
from = first; |
148 |
break;
|
149 |
|
150 |
|
151 |
} //end switch
|
152 |
|
153 |
theIterator.next(); |
154 |
} |
155 |
|
156 |
return resul;
|
157 |
} |
158 |
|
159 |
/**
|
160 |
* TODO: POR TERMINAR!!!
|
161 |
* @param flag
|
162 |
* @return
|
163 |
*/
|
164 |
public int creaArcosVirtualesComplejo(GvFlag flag) { |
165 |
// Devuelve el idNodo del nodo virtual creado.
|
166 |
/* 0.- Creamos el nuevo Nodo virtual.
|
167 |
1.- Recorremos los arcos nuevos mirando su idTramo.
|
168 |
2.- Si existe ese idtramo=> Ya hemos partido antes ese idTramo. Buscamos el arco virtual que contiene
|
169 |
ese nodo y lo partimos. Ojo, recorrer hasta el final los tramos para asegurarnos de que es el trozo
|
170 |
m?s peque?o.
|
171 |
3.- Si NO existe, utilizamos el IndiceArcos para coger los arcos que toca y partirlos.
|
172 |
|
173 |
4.- OJO: Si el porcentaje es 0 ? 100, no partimos el arco, devolvemos el id del nodo que toca.
|
174 |
*/
|
175 |
// NUEVO: 20/7/2004:
|
176 |
// Cuando trabajamos con sentidos, al partir un arco no podemos insertar 2 nuevos sin mirar
|
177 |
// si es o no de un ?nico sentido.) (Mirar idArco. Si es -1, no partimos el arco).
|
178 |
// FIN NUEVO
|
179 |
|
180 |
int idNodo1, idNodo2;
|
181 |
int idArco, elIdArco, elIdContraArco;
|
182 |
boolean encontrado;
|
183 |
GvNode newNode; |
184 |
|
185 |
// Sacamos los idNodos del tramo
|
186 |
EdgePair edgePair = graph.getEdgesByIdArc(flag.getIdArc()); |
187 |
if (edgePair.getIdEdge() != -1) |
188 |
{ |
189 |
// idNodo1 = Arcos[IndiceArcos[idTramo].idArco].idNodo1;
|
190 |
// idNodo2 = Arcos[IndiceArcos[idTramo].idArco].idNodo2;
|
191 |
idNodo1 = graph.getEdgeByID(edgePair.getIdEdge()).getIdNodeOrig(); |
192 |
idNodo2 = graph.getEdgeByID(edgePair.getIdEdge()).getIdNodeEnd(); |
193 |
|
194 |
} |
195 |
else
|
196 |
{ |
197 |
// idNodo2 = Arcos[IndiceArcos[idTramo].idContraArco].idNodo1;
|
198 |
// idNodo1 = Arcos[IndiceArcos[idTramo].idContraArco].idNodo2;
|
199 |
idNodo2 = graph.getEdgeByID(edgePair.getIdInverseEdge()).getIdNodeOrig(); |
200 |
idNodo1 = graph.getEdgeByID(edgePair.getIdInverseEdge()).getIdNodeEnd(); |
201 |
|
202 |
} |
203 |
|
204 |
if (flag.getPct() == 0) |
205 |
return idNodo1;
|
206 |
if (flag.getPct() == 1) |
207 |
return idNodo2;
|
208 |
|
209 |
// Creamos el nodo de enmedio
|
210 |
|
211 |
// if (numNodos == maxNodos) // La jodimos, T?rtola, hay que usar reallocate
|
212 |
// {
|
213 |
// // NOTA: ESTO EN DEBUG HACE QUE FALLE AL USAR DESPUES EnlacesSTL. ES POR NO S? QU? HISTORIA
|
214 |
// // DEL HEAP. EN RELEASE NO FALLA. (TAMPOCO S? SI FASTIDIA ALGO).
|
215 |
// Nodos = (CNode *) realloc(Nodos,(numNodos + MAX_RESERVA_NODOS) * sizeof(CNode)); // Deber?amos chequear que devuelve algo correcto
|
216 |
// maxNodos = numNodos + MAX_RESERVA_NODOS;
|
217 |
// }
|
218 |
|
219 |
newNode = new GvNode();
|
220 |
// Nodo = &Nodos[numNodos];
|
221 |
|
222 |
// pNuevoNodo->idNodo = numNodos;
|
223 |
newNode.setIdNode(graph.numVertices()); |
224 |
|
225 |
|
226 |
|
227 |
// OJO: Las coordenadas estas puede que no tengan que ver con la realidad. Algo m?s correcto
|
228 |
// ser?a tener en cuenta el shape de verdad, pero creo que no influye en el resultado final.
|
229 |
// pNuevoNodo->x = Nodos[idNodo1].x + (Nodos[idNodo2].x - Nodos[idNodo1].x) * Porcentaje;
|
230 |
// pNuevoNodo->y = Nodos[idNodo1].y + (Nodos[idNodo2].y - Nodos[idNodo1].y) * Porcentaje;
|
231 |
GvNode node1 = graph.getNodeByID(idNodo1); |
232 |
GvNode node2 = graph.getNodeByID(idNodo2); |
233 |
newNode.setX(node1.getX() + (node2.getX() - node1.getX()) * flag.getPct()); |
234 |
newNode.setY(node1.getY() + (node2.getY() - node1.getY()) * flag.getPct()); |
235 |
|
236 |
encontrado = false;
|
237 |
|
238 |
elIdArco = -1;
|
239 |
elIdContraArco = -1;
|
240 |
|
241 |
boolean bIdTramoYaPartido = false; |
242 |
|
243 |
// TODO: POR AQUI VOY
|
244 |
/* for (idArco = numArcosOriginal; idArco < numArcos; idArco++)
|
245 |
{
|
246 |
if (Arcos[idArco].idTramo == idTramo)
|
247 |
{
|
248 |
bIdTramoYaPartido = true;
|
249 |
|
250 |
idNodo1 = Arcos[idArco].idNodo1;
|
251 |
idNodo2 = Arcos[idArco].idNodo2;
|
252 |
|
253 |
// Comprobamos si est? enmedio
|
254 |
|
255 |
CVector2 vA(Nodos[idNodo1].x, Nodos[idNodo1].y);
|
256 |
CVector2 vB(Nodos[idNodo2].x, Nodos[idNodo2].y);
|
257 |
CVector2 vPoint(pNuevoNodo->x, pNuevoNodo->y);
|
258 |
|
259 |
CVector2 vVector1 = vPoint - vA;
|
260 |
|
261 |
// Create a normalized direction vector from end point vA to end point vB
|
262 |
CVector2 vVector2 = Normalize(vB - vA);
|
263 |
|
264 |
// Use the distance formula to find the distance of the line segment (or magnitude)
|
265 |
double d = Distance(vA, vB);
|
266 |
|
267 |
// Using the dot product, we project the vVector1 onto the vector vVector2.
|
268 |
// This essentially gives us the distance from our projected vector from vA.
|
269 |
double t = Dot(vVector2, vVector1);
|
270 |
|
271 |
// Si la proyecci?n es positiva y menor que la magnitud d, est? en medio
|
272 |
if ((t >= 0) && (t <= d))
|
273 |
{
|
274 |
encontrado = true;
|
275 |
if (t==0) return idNodo1; // No partimos
|
276 |
if (t==d) return idNodo2; // Tampoco partimos
|
277 |
|
278 |
if (Arcos[idArco].sentido)
|
279 |
elIdArco = idArco;
|
280 |
else
|
281 |
elIdContraArco = idArco;
|
282 |
|
283 |
} // if est? enmedio
|
284 |
} // if idTramo encontrado
|
285 |
} // for idArco
|
286 |
if (bIdTramoYaPartido && (! encontrado))
|
287 |
MessageBox(NULL,"Algo va mal con lo del producto escalar","",MB_OK);
|
288 |
|
289 |
|
290 |
if (encontrado)
|
291 |
{
|
292 |
// sprintf(Mensaje,"Voy a partir el idTramo= %ld (idArco %ld)",idTramo,elIdArco);
|
293 |
// MessageBox(NULL,Mensaje,"",MB_OK);
|
294 |
if (elIdArco != -1)
|
295 |
PartirArco(elIdArco, numNodos);
|
296 |
|
297 |
if (elIdContraArco != -1)
|
298 |
PartirArco(elIdContraArco, numNodos);
|
299 |
}
|
300 |
else
|
301 |
{
|
302 |
// Creamos 2 Arcos por cada arco que ten?amos antes.
|
303 |
if (IndiceArcos[idTramo].idArco != -1)
|
304 |
PartirArco(IndiceArcos[idTramo].idArco, numNodos);
|
305 |
|
306 |
if (IndiceArcos[idTramo].idContraArco != -1)
|
307 |
PartirArco(IndiceArcos[idTramo].idContraArco, numNodos);
|
308 |
|
309 |
} // else encontrado
|
310 |
|
311 |
numNodos++;
|
312 |
return (numNodos -1); */
|
313 |
return graph.numVertices();
|
314 |
|
315 |
} |
316 |
|
317 |
/**
|
318 |
* TODO: Por ahora, cogemos el nodo m?s cercano. Lo correcto
|
319 |
* es a?adir un nuevo nodo que divida el arco, y devolver el
|
320 |
* id de ese nodo.
|
321 |
* @param flag
|
322 |
* @return
|
323 |
*/
|
324 |
public int creaArcosVirtuales(GvFlag flag) { |
325 |
EdgePair pair = graph.getEdgesByIdArc(flag.getIdArc()); |
326 |
if (pair.getIdEdge() != -1) |
327 |
{ |
328 |
GvEdge edge = graph.getEdgeByID(pair.getIdEdge()); |
329 |
GvNode from = graph.getNodeByID(edge.getIdNodeOrig()); |
330 |
GvNode to = graph.getNodeByID(edge.getIdNodeEnd()); |
331 |
|
332 |
double dist1 = flag.getOriginalPoint().distance(from.getX(), from.getY());
|
333 |
double dist2 = flag.getOriginalPoint().distance(to.getX(), to.getY());
|
334 |
if (dist1 < dist2)
|
335 |
return from.getIdNode();
|
336 |
else
|
337 |
return to.getIdNode();
|
338 |
// if (flag.getPct() > 0.5)
|
339 |
// return to.getIdNode();
|
340 |
// else
|
341 |
// return from.getIdNode();
|
342 |
} |
343 |
else
|
344 |
{ |
345 |
GvEdge edge = graph.getEdgeByID(pair.getIdInverseEdge()); |
346 |
GvNode from = graph.getNodeByID(edge.getIdNodeOrig()); |
347 |
GvNode to = graph.getNodeByID(edge.getIdNodeEnd()); |
348 |
|
349 |
double dist1 = flag.getOriginalPoint().distance(from.getX(), from.getY());
|
350 |
double dist2 = flag.getOriginalPoint().distance(to.getX(), to.getY());
|
351 |
if (dist1 < dist2)
|
352 |
return from.getIdNode();
|
353 |
else
|
354 |
return to.getIdNode();
|
355 |
|
356 |
// if (flag.getPct() < 0.5)
|
357 |
// return to.getIdNode();
|
358 |
// else
|
359 |
// return from.getIdNode();
|
360 |
} |
361 |
} |
362 |
|
363 |
/**
|
364 |
* @param idArc
|
365 |
* @param x
|
366 |
* @param y
|
367 |
* @return entre 0.0 y 1.0
|
368 |
*/
|
369 |
private double percentAlong(long idArc, double x, double y) |
370 |
{ |
371 |
return 0; |
372 |
} |
373 |
|
374 |
/**
|
375 |
* Adds a flag on a network. flagDirection set if the flag
|
376 |
* must be on left or right edge.
|
377 |
* @param x
|
378 |
* @param y
|
379 |
* @param flagDirection
|
380 |
* @param tol tolerance in map units
|
381 |
* @return null if there is no place to add flag.
|
382 |
* You can increase the tolerance, then.
|
383 |
*/
|
384 |
public GvFlag addFlag(double x, double y, int flagDirection, double tol) |
385 |
{ |
386 |
int idArc = findClosestArc(x, y, tol);
|
387 |
if (idArc == -1) |
388 |
return null; |
389 |
GvFlag flag = new GvFlag(x,y);
|
390 |
flag.setIdArc(idArc); |
391 |
flag.setPct(percentAlong(idArc, x, y)); |
392 |
flag.setDirec(flagDirection); |
393 |
flag.setIdFlag(flags.size()); |
394 |
return flag;
|
395 |
} |
396 |
|
397 |
/**
|
398 |
* Adds 2 flags on a network. (On both sides of an arc)
|
399 |
* @param x
|
400 |
* @param y
|
401 |
* @param tol tolerance in map units
|
402 |
* @return null if there is no place to add flag.
|
403 |
* You can increase the tolerance, then.
|
404 |
*/
|
405 |
public GvFlag addFlag(double x, double y, double tol) |
406 |
{ |
407 |
int idArc = findClosestArc(x, y, tol);
|
408 |
if (idArc == -1) |
409 |
return null; |
410 |
|
411 |
GvFlag flag = new GvFlag(x, y);
|
412 |
flag.setIdArc(idArc); |
413 |
flag.setDirec(GvFlag.BOTH_DIRECTIONS); |
414 |
flag.setPct(percentAlong(idArc, x, y)); |
415 |
flag.setIdFlag(flags.size()); |
416 |
flags.add(flag); |
417 |
return flag;
|
418 |
} |
419 |
|
420 |
|
421 |
public void addFlag(GvFlag flag) { |
422 |
flags.add(flag); |
423 |
} |
424 |
public GvFlag[] getFlags() { |
425 |
return (GvFlag[]) flags.toArray(new GvFlag[0]); |
426 |
} |
427 |
public void setFlags(ArrayList flags) { |
428 |
this.flags = flags;
|
429 |
} |
430 |
public IGraph getGraph() {
|
431 |
return graph;
|
432 |
} |
433 |
public void setGraph(IGraph graph) { |
434 |
this.graph = graph;
|
435 |
} |
436 |
public FLyrVect getLayer() {
|
437 |
return lyrVect;
|
438 |
} |
439 |
public void setLayer(FLyrVect lyr) { |
440 |
this.lyrVect = lyr;
|
441 |
} |
442 |
|
443 |
|
444 |
public void removeFlags() { |
445 |
flags = new ArrayList(); |
446 |
} |
447 |
|
448 |
void PartirArco(int idEdge, int idNode) |
449 |
{ |
450 |
// Se supone que el nuevo Nodo YA est? creado. Aqui dentro se coge el arco viejo y se le pega un tajo.
|
451 |
// (Se modifican los enlaces de los nodos de ese arco y se crean los arcos nuevos, fijando sus costes).
|
452 |
// Para sacar el porcentaje nos aprovechamos de que el nuevo nodo est? puesto en base a ese porcentaje
|
453 |
// en distancia de los extremos.
|
454 |
GvEdge newEdge; |
455 |
GvEdge oldEdge; |
456 |
GvNode pN1, pN2; |
457 |
double pct;
|
458 |
|
459 |
oldEdge = graph.getEdgeByID(idEdge); |
460 |
|
461 |
// OJO, controlando los ceros por si acaso la recta es horizontal o vertical (Y si mide cero???)
|
462 |
|
463 |
// pN1 = &Nodos[Arcos[idArco].idNodo1];
|
464 |
// pN2 = &Nodos[Arcos[idArco].idNodo2];
|
465 |
pN1 = graph.getNodeByID(graph.getEdgeByID(idEdge).getIdNodeOrig()); |
466 |
pN2 = graph.getNodeByID(graph.getEdgeByID(idEdge).getIdNodeEnd()); |
467 |
GvNode newNode = graph.getNodeByID(idNode); |
468 |
|
469 |
if (newNode.getX() != pN1.getX())
|
470 |
pct = Math.abs((newNode.getX() - pN1.getX())/(pN2.getX()-pN1.getX()));
|
471 |
else
|
472 |
pct = Math.abs((newNode.getY() - pN1.getY())/(pN2.getY()-pN1.getY()));
|
473 |
|
474 |
|
475 |
|
476 |
GvEdge first = new GvEdge();
|
477 |
first.setIdEdge(graph.numEdges()); |
478 |
first.setIdArc(oldEdge.getIdArc()); |
479 |
first.setDistance(oldEdge.getDistance() * pct); |
480 |
first.setWeight(oldEdge.getWeight() * pct); |
481 |
|
482 |
first.setDirec(oldEdge.getDirec()); |
483 |
first.setIdNodeOrig(oldEdge.getIdNodeOrig()); |
484 |
first.setType(oldEdge.getType()); |
485 |
first.setIdNodeEnd(idNode); |
486 |
graph.addEdge(first); |
487 |
|
488 |
GvEdge second = new GvEdge();
|
489 |
second.setIdEdge(graph.numEdges()); |
490 |
second.setDistance(oldEdge.getDistance()*(1.0-pct));
|
491 |
second.setWeight(oldEdge.getWeight()*(1.0-pct));
|
492 |
second.setIdArc(oldEdge.getIdArc()); |
493 |
second.setDirec(oldEdge.getDirec()); |
494 |
second.setType(oldEdge.getType()); |
495 |
second.setIdNodeOrig(idNode); |
496 |
second.setIdNodeEnd(oldEdge.getIdNodeEnd()); |
497 |
graph.addEdge(second); |
498 |
|
499 |
|
500 |
//////////////////////////////////////////////////////
|
501 |
// Ahora retocamos los enlaces que salen de cada nodo
|
502 |
//////////////////////////////////////////////////////
|
503 |
int i;
|
504 |
boolean encontrado = false; |
505 |
for (i=0; i<pN1.getEnlaces().size(); i++) |
506 |
{ |
507 |
GvEdge aux = (GvEdge) pN1.getEnlaces().get(i); |
508 |
if (aux.getIdEdge() == idEdge)
|
509 |
{ |
510 |
pN1.getEnlaces().set(i, first); |
511 |
encontrado = true;
|
512 |
break;
|
513 |
} |
514 |
} // for
|
515 |
|
516 |
newNode.getEnlaces().add(second); |
517 |
|
518 |
} |
519 |
|
520 |
} |
521 |
|
522 |
|