Revision 25628 trunk/extensions/extGraph/src/org/gvsig/graph/solvers/OneToManySolver.java
OneToManySolver.java | ||
---|---|---|
68 | 68 |
|
69 | 69 |
public class OneToManySolver extends AbstractNetSolver { |
70 | 70 |
|
71 |
private int idStart = -1;
|
|
72 |
private ArrayList idStops = null;
|
|
71 |
protected int idStart = -1;
|
|
72 |
protected ArrayList idStops = null;
|
|
73 | 73 |
|
74 | 74 |
// Soporte listeners |
75 |
private ArrayList<IDijkstraListener> listeners = new ArrayList<IDijkstraListener>();
|
|
75 |
protected ArrayList<IDijkstraListener> listeners = new ArrayList<IDijkstraListener>();
|
|
76 | 76 |
|
77 | 77 |
public void addListener(IDijkstraListener listener) { |
78 | 78 |
listeners.add(listener); |
79 | 79 |
} |
80 |
private boolean callMinimumCostNodeSelectedListeners(GvNode node) {
|
|
80 |
protected boolean callMinimumCostNodeSelectedListeners(GvNode node) {
|
|
81 | 81 |
for (IDijkstraListener listener : listeners) { |
82 | 82 |
if (listener.minimumCostNodeSelected(node)) |
83 | 83 |
return true; |
84 | 84 |
} |
85 | 85 |
return false; |
86 | 86 |
} |
87 |
private boolean callAdjacenteEdgeVisitedListeners(GvNode fromNode, GvEdge edge) {
|
|
87 |
protected boolean callAdjacenteEdgeVisitedListeners(GvNode fromNode, GvEdge edge) {
|
|
88 | 88 |
for (IDijkstraListener listener : listeners) { |
89 | 89 |
if (listener.adjacentEdgeVisited(fromNode, edge)) |
90 | 90 |
return true; |
... | ... | |
92 | 92 |
return false; |
93 | 93 |
} |
94 | 94 |
|
95 |
private class StopAux {
|
|
95 |
protected class StopAux {
|
|
96 | 96 |
public StopAux(Integer idStop2) { |
97 | 97 |
idStop = idStop2; |
98 | 98 |
bFound = false; |
... | ... | |
110 | 110 |
} |
111 | 111 |
} |
112 | 112 |
|
113 |
private GvFlag sourceFlag; |
|
114 |
private boolean bExploreAll = false; // by default |
|
115 |
private double maxCost = Double.MAX_VALUE; |
|
116 |
private double maxDistance = Double.MAX_VALUE; |
|
117 |
private GvFlag[] destinations; |
|
118 |
private GeometryFactory geomFactory = new GeometryFactory(); |
|
113 |
protected GvFlag sourceFlag; |
|
114 |
protected boolean bExploreAll = false; // by default |
|
115 |
protected double maxCost = Double.MAX_VALUE; |
|
116 |
protected double maxDistance = Double.MAX_VALUE; |
|
117 |
protected GvFlag[] destinations; |
|
119 | 118 |
protected Route route = new Route(); |
120 |
private int fieldIndexStreetName; |
|
121 | 119 |
|
122 | 120 |
|
123 | 121 |
|
... | ... | |
418 | 416 |
public void setMaxDistance(double maxDistance) { |
419 | 417 |
this.maxDistance = maxDistance; |
420 | 418 |
} |
421 |
public void setFielStreetName(String name) { |
|
422 |
try { |
|
423 |
int aux = net.getLayer().getRecordset().getFieldIndexByName(name); |
|
424 |
if (aux == -1) |
|
425 |
throw new RuntimeException("Field " + name + " not found."); |
|
426 |
fieldIndexStreetName = aux; |
|
427 |
} catch (BaseException e) { |
|
428 |
// TODO Auto-generated catch block |
|
429 |
e.printStackTrace(); |
|
430 |
} |
|
431 |
|
|
432 |
} |
|
433 |
private void populateRouteSimple(int idStart, int idEnd) |
|
434 |
throws BaseException { |
|
435 |
int idEnlace; |
|
436 |
GvNode node; |
|
437 |
GvEdge link; |
|
438 |
double costeEntrada; |
|
439 |
|
|
440 |
// Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los Enlaces |
|
441 |
double Coste = 0; |
|
442 |
double Coste2 = 0; |
|
443 |
IGraph graph = net.getGraph(); |
|
444 |
node = graph.getNodeByID(idEnd); |
|
445 |
int from_link = node.get_best_from_link(); |
|
446 |
VectorialAdapter va = (VectorialAdapter) net.getLayer().getSource(); |
|
447 |
while (node.getIdNode() != idStart) |
|
448 |
{ |
|
449 |
if (from_link == -1) |
|
450 |
{ |
|
451 |
throw new RuntimeException("Fallo al recorrer de manera inversa la soluci?n. Encontrado arco con -1"); |
|
452 |
// break; // FALLO!! |
|
453 |
} |
|
454 |
link = graph.getEdgeByID(from_link); |
|
455 |
IFeature feat = va.getFeature(link.getIdArc()); |
|
456 |
route.addRouteFeature(feat.getGeometry(), link.getIdArc(), |
|
457 |
link.getWeight(), link.getDistance(), feat.getAttribute(getFieldIndexStreetName()).toString()); |
|
458 |
|
|
459 |
node = graph.getNodeByID(link.getIdNodeOrig()); |
|
460 |
|
|
461 |
Coste = Coste + link.getWeight(); |
|
462 |
Coste2 = Coste2 + link.getDistance(); |
|
463 |
|
|
464 |
// TODO: |
|
465 |
// from_link = node.get_from_link(idEnlace, &costeEntrada); |
|
466 |
from_link = node.get_best_from_link(); |
|
467 |
|
|
468 |
} |
|
469 |
System.out.println("Salgo con node = " + node.getIdNode()); |
|
470 |
} |
|
471 |
protected void populateRoute(GvFlag origin, GvFlag dest, int idStart, |
|
472 |
int idEnd) throws BaseException { |
|
473 |
int idEnlace; |
|
474 |
GvNode node; |
|
475 |
GvEdge link; |
|
476 |
double costeEntrada; |
|
477 |
|
|
478 |
// Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los Enlaces |
|
479 |
IGraph graph = net.getGraph(); |
|
480 |
node = graph.getNodeByID(idEnd); |
|
481 |
int from_link = node.get_best_from_link(); |
|
482 |
VectorialAdapter va = (VectorialAdapter) net.getLayer().getSource(); |
|
483 |
|
|
484 |
/* Miramos los nodos de los tramos inicio y final, y cogemos el nodo que tenga el from_link rellenado. E IGUAL A NUMSOLUCGLOBAL!!!! |
|
485 |
A partir de ah?, recorremos hacia atr?s y tenemos el cuerpo principal del shape. Luego, para |
|
486 |
las puntas hay que tener en cuenta los porcentajes, viendo el trozo que est? pegando a los nodos |
|
487 |
que sabemos que est?n en el path |
|
488 |
*/ |
|
489 |
|
|
490 |
/* 22/9/2003 Corregimos el fallo que hab?a de escribir el shape de atr?s adelante. |
|
491 |
* Guardamos lo que necesitamos en listaShapes y recorremos esa lista guardando los tramos |
|
492 |
* con el sentido adecuado. |
|
493 |
*/ |
|
494 |
|
|
495 |
/* 3/Febrero/2005 Limpieza de c?digo superfluo y correci?n de un fallo raro. Ahora es m?s simple y parece |
|
496 |
* que no falla. A ver si dura. IDEA: quiz?s se necesite meter el porcentaje en los arcos partidos. |
|
497 |
*/ |
|
498 |
|
|
499 |
// Define a template class for a vector of IDs. |
|
500 |
InfoShp infoShp; |
|
501 |
Stack pilaShapes = new Stack(); |
|
502 |
// typedef stack<CInfoShp> PILAINFO; |
|
503 |
// PILAINFO pilaShapes; |
|
504 |
|
|
505 |
double costeTramoFinal=-1; |
|
506 |
GvNode nodeEnd = graph.getNodeByID(idEnd); |
|
507 |
GvEdge finalEdge = graph.getEdgeByID(nodeEnd.get_best_from_link()); |
|
508 |
costeTramoFinal = finalEdge.getWeight(); |
|
509 |
|
|
510 |
GvNode pNodo; |
|
511 |
GvEdge pEnlace; |
|
512 |
|
|
513 |
boolean bFlipearShape = false; |
|
514 |
|
|
515 |
double pctMax, pctMin; |
|
516 |
|
|
517 |
|
|
518 |
|
|
519 |
////////////////////////////////////////////////////////////////////////////////////// |
|
520 |
// Trozo del final |
|
521 |
// El shape va de idStop1 a idStop2, y el porcentaje viene en ese sentido. |
|
522 |
// Si el idEnd es idStop1, quiere decir que el tramo que falta va en ese sentido tambi?n, |
|
523 |
// as? que recorremos ese shape desde idStop1 hasta que rebasemos o igualemos ese porcentaje. |
|
524 |
// Si no, hemos pasado por idStop2 y la parte que hay que meter es desde el pto interior a idStop2 |
|
525 |
/////////////////////////////////////////////////////////////////////////////////////// |
|
526 |
IFeature feat = va.getFeature(finalEdge.getIdArc()); |
|
527 |
MultiLineString jtsGeom = (MultiLineString) feat.getGeometry().toJTSGeometry(); |
|
528 |
// CoordinateFilter removeDuplicates = new UniqueCoordinateArrayFilter(); |
|
529 |
// jtsGeom.apply(removeDuplicates); |
|
530 |
// jtsGeom.geometryChanged(); |
|
531 |
|
|
532 |
|
|
533 |
|
|
534 |
// SI ESTAMOS SOBRE EL MISMO TRAMO, CASO PARTICULAR |
|
535 |
// y el sentido de circulaci?n es correcto |
|
536 |
if ((origin.getIdArc() == dest.getIdArc()) && (nodeEnd.getBestCost() <= costeTramoFinal)) |
|
537 |
{ |
|
538 |
if (dest.getPct() > origin.getPct()) |
|
539 |
{ |
|
540 |
pctMax = dest.getPct(); |
|
541 |
pctMin = origin.getPct(); |
|
542 |
} |
|
543 |
else |
|
544 |
{ |
|
545 |
pctMax = origin.getPct(); |
|
546 |
pctMin = dest.getPct(); |
|
547 |
bFlipearShape = true; |
|
548 |
} |
|
549 |
|
|
550 |
LineString line = NetworkUtils.getPartialLineString(jtsGeom, |
|
551 |
pctMax, 1); |
|
552 |
|
|
553 |
pctMin = pctMin / pctMax; // Porque ha cambiado la longitud |
|
554 |
// del shape |
|
555 |
|
|
556 |
line = NetworkUtils.getPartialLineString(line, pctMin, 0); |
|
557 |
|
|
558 |
if (bFlipearShape) |
|
559 |
line = line.reverse(); |
|
560 |
|
|
561 |
IGeometry geom = FConverter.jts_to_igeometry(line); |
|
562 |
// TODO: Calcular bien el length de este arco, |
|
563 |
// basandonos en el porcentaje costeTramoFinal / costeOriginal |
|
564 |
route.addRouteFeature(geom, origin.getIdArc(), |
|
565 |
costeTramoFinal, line.getLength(), feat.getAttribute(getFieldIndexStreetName()).toString()); |
|
566 |
|
|
567 |
|
|
568 |
return ; // Deber?a sacar el coste |
|
569 |
} |
|
570 |
|
|
571 |
|
|
572 |
|
|
573 |
// Trazar el camino desde idEnd hasta idStart hacia atr?s marcando los Enlaces |
|
574 |
pNodo = graph.getNodeByID(idEnd); |
|
575 |
|
|
576 |
while ((pNodo.getIdNode() != idStart)) |
|
577 |
{ |
|
578 |
idEnlace = pNodo.get_best_from_link(); |
|
579 |
pEnlace = graph.getEdgeByID(idEnlace); |
|
580 |
|
|
581 |
pNodo = graph.getNodeByID(pEnlace.getIdNodeOrig()); |
|
582 |
|
|
583 |
infoShp = new InfoShp(); |
|
584 |
infoShp.distance = pEnlace.getDistance(); |
|
585 |
infoShp.cost = pEnlace.getWeight(); |
|
586 |
|
|
587 |
if ((pEnlace.getIdArc() == origin.getIdArc()) || (pEnlace.getIdArc() == dest.getIdArc())) |
|
588 |
{ |
|
589 |
if (pEnlace.getIdArc() == origin.getIdArc()) |
|
590 |
{ |
|
591 |
infoShp.pct = origin.getPct(); |
|
592 |
infoShp.idArc = origin.getIdArc(); |
|
593 |
if (pEnlace.getDirec() == 0) |
|
594 |
{ |
|
595 |
infoShp.direction = 1; |
|
596 |
infoShp.bFlip = true; |
|
597 |
} |
|
598 |
else // Hemos pasado por el 2 |
|
599 |
{ |
|
600 |
infoShp.direction = 0; |
|
601 |
infoShp.bFlip = false; |
|
602 |
} // if else */ |
|
603 |
} |
|
604 |
else |
|
605 |
{ |
|
606 |
infoShp.pct = dest.getPct(); |
|
607 |
infoShp.idArc = dest.getIdArc(); |
|
608 |
if (pEnlace.getDirec() == 0) |
|
609 |
{ |
|
610 |
infoShp.direction = 0; |
|
611 |
infoShp.bFlip = true; |
|
612 |
} |
|
613 |
else |
|
614 |
{ |
|
615 |
infoShp.direction = 1; |
|
616 |
infoShp.bFlip = false; |
|
617 |
} // if else */ |
|
618 |
} |
|
619 |
} |
|
620 |
else |
|
621 |
{ |
|
622 |
infoShp.pct = 1.0; |
|
623 |
infoShp.idArc = pEnlace.getIdArc(); |
|
624 |
|
|
625 |
infoShp.direction =1; |
|
626 |
if (pEnlace.getDirec() == 1) |
|
627 |
infoShp.bFlip = false; |
|
628 |
else |
|
629 |
infoShp.bFlip = true; |
|
630 |
} |
|
631 |
|
|
632 |
pilaShapes.push(infoShp); |
|
633 |
} |
|
634 |
|
|
635 |
// Y ahora recorremos hacia atr?s el vector y escribimos los shapes. |
|
636 |
// VECTORINFO::iterator theIterator; |
|
637 |
int auxC = 0; |
|
638 |
|
|
639 |
while (!pilaShapes.empty()) |
|
640 |
{ |
|
641 |
infoShp = (InfoShp) pilaShapes.peek(); |
|
642 |
feat = va.getFeature(infoShp.idArc); |
|
643 |
MultiLineString line = (MultiLineString) feat.getGeometry().toJTSGeometry(); |
|
644 |
// line.apply(removeDuplicates); |
|
645 |
// line.geometryChanged(); |
|
646 |
|
|
647 |
LineString aux = null; |
|
648 |
if (infoShp.pct < 1.0) |
|
649 |
aux = NetworkUtils.getPartialLineString(line, infoShp.pct, |
|
650 |
infoShp.direction); |
|
651 |
|
|
652 |
|
|
653 |
IGeometry geom = null; |
|
654 |
if (aux == null) |
|
655 |
{ |
|
656 |
if (infoShp.bFlip) |
|
657 |
line = line.reverse(); |
|
658 |
geom = FConverter.jts_to_igeometry(line); |
|
659 |
} |
|
660 |
else |
|
661 |
{ |
|
662 |
if (infoShp.bFlip) |
|
663 |
aux = aux.reverse(); |
|
664 |
geom = FConverter.jts_to_igeometry(aux); |
|
665 |
} |
|
666 |
|
|
667 |
|
|
668 |
route.addRouteFeature(geom, infoShp.idArc, |
|
669 |
infoShp.cost, infoShp.distance, feat.getAttribute(getFieldIndexStreetName()).toString()); |
|
670 |
|
|
671 |
|
|
672 |
pilaShapes.pop(); |
|
673 |
auxC++; |
|
674 |
|
|
675 |
} |
|
676 |
|
|
677 |
return; |
|
678 |
|
|
679 |
|
|
680 |
} |
|
681 |
LineString SituaSobreTramo(Geometry geom, int idArc, double pct, int parte) { |
|
682 |
int j, numVertices; |
|
683 |
double longAcum, longReal, longBuscada, distSobre, miniPorcentaje; |
|
684 |
double nuevaX, nuevaY; // Por cuestiones de claridad al programar |
|
685 |
double dist=0; |
|
686 |
|
|
687 |
longAcum = 0; |
|
688 |
longReal = geom.getLength(); |
|
689 |
longBuscada = longReal * pct; |
|
690 |
Coordinate[] coords = geom.getCoordinates(); |
|
691 |
Coordinate c1 = null, c2 = null; |
|
692 |
ArrayList savedCoords = new ArrayList(); |
|
693 |
|
|
694 |
if (parte > 0) // Hemos entrado por el 1 hacia el 2 (al 2 no llegamos) |
|
695 |
{ |
|
696 |
for( j = 0; j < coords.length-1; j++ ) |
|
697 |
{ |
|
698 |
c1 = coords[j]; |
|
699 |
c2 = coords[j+1]; |
|
700 |
dist = c1.distance(c2); |
|
701 |
longAcum += dist; |
|
702 |
savedCoords.add(c1); |
|
703 |
if (longAcum >= longBuscada) |
|
704 |
{ |
|
705 |
// Hasta aqu?. Ahora ahi que poner el punto sobre el tramo |
|
706 |
distSobre = dist - (longAcum - longBuscada); |
|
707 |
miniPorcentaje = distSobre/dist; |
|
708 |
|
|
709 |
nuevaX = c1.x + (c2.x-c1.x) * miniPorcentaje; |
|
710 |
nuevaY = c1.y + (c2.y-c1.y) * miniPorcentaje; |
|
711 |
|
|
712 |
savedCoords.add(new Coordinate(nuevaX, nuevaY)); |
|
713 |
break; |
|
714 |
} // if longAcum >= longBuscada |
|
715 |
} // for j |
|
716 |
|
|
717 |
} |
|
718 |
else // Hemos entrado por el 2 hacia el 1 |
|
719 |
{ |
|
720 |
numVertices = 0; |
|
721 |
for( j = 0; j < coords.length; j++ ) |
|
722 |
{ |
|
723 |
//////////////////////////////////////////////////////////////// |
|
724 |
// 13_ene_2005: Si el ?ltimo punto es el ?ltimo punto no |
|
725 |
// podemos acceder al elemento j+1 porque nos salimos del shape |
|
726 |
///////////////////////////////////////////////////////////////// |
|
727 |
c1 = coords[j]; |
|
728 |
if (j < coords.length -1) |
|
729 |
{ |
|
730 |
c2 = coords[j+1]; |
|
731 |
|
|
732 |
dist = c1.distance(c2); |
|
733 |
longAcum += dist; |
|
734 |
} |
|
735 |
|
|
736 |
if (longAcum >= longBuscada) |
|
737 |
{ |
|
738 |
// Hasta aqu?. Empezamos a meter puntos |
|
739 |
|
|
740 |
if (numVertices == 0) |
|
741 |
{ |
|
742 |
distSobre = dist - (longAcum - longBuscada); |
|
743 |
miniPorcentaje = distSobre/dist; |
|
744 |
nuevaX = c1.x + (c2.x-c1.x) * miniPorcentaje; |
|
745 |
nuevaY = c1.y + (c2.y-c1.y) * miniPorcentaje; |
|
746 |
|
|
747 |
savedCoords.add(new Coordinate(nuevaX, nuevaY)); |
|
748 |
} |
|
749 |
else |
|
750 |
{ |
|
751 |
savedCoords.add(c2); |
|
752 |
} |
|
753 |
numVertices ++; |
|
754 |
// break; |
|
755 |
} // if longAcum >= longBuscada |
|
756 |
} // for j |
|
757 |
|
|
758 |
// savedCoords.add(c2); |
|
759 |
|
|
760 |
} // if else |
|
761 |
|
|
762 |
|
|
763 |
return geomFactory.createLineString((Coordinate[] )savedCoords.toArray(new Coordinate[0])); |
|
764 |
} |
|
765 |
private int getFieldIndexStreetName() { |
|
766 |
return fieldIndexStreetName; |
|
767 |
} |
|
768 | 419 |
|
769 | 420 |
} |
Also available in: Unified diff