#include <netbuild/NBNetBuilder.h>
#include <netedit/GNENet.h>
#include <netedit/GNESegment.h>
#include <netedit/GNETagProperties.h>
#include <netedit/GNEViewNet.h>
#include <netedit/elements/network/GNEConnection.h>
#include <utils/router/DijkstraRouter.h>
#include "GNEPathManager.h"
GNEPathManager::PathCalculator::PathCalculator(const GNENet* net) :
myNet(net),
myPathCalculatorUpdated(false),
myDijkstraRouter(nullptr) {
myDijkstraRouter = new DijkstraRouter<NBRouterEdge, NBVehicle>(
myNet->getNetBuilder()->getEdgeCont().getAllRouterEdges(),
true, &NBRouterEdge::getTravelTimeStatic, nullptr, true);
}
GNEPathManager::PathCalculator::~PathCalculator() {
delete myDijkstraRouter;
}
void
GNEPathManager::PathCalculator::updatePathCalculator() {
if (myDijkstraRouter) {
delete myDijkstraRouter;
}
myDijkstraRouter = new DijkstraRouter<NBRouterEdge, NBVehicle>(
myNet->getNetBuilder()->getEdgeCont().getAllRouterEdges(),
true, &NBRouterEdge::getTravelTimeStatic, nullptr, true);
myPathCalculatorUpdated = true;
}
std::vector<GNEEdge*>
GNEPathManager::PathCalculator::calculateDijkstraPath(const SUMOVehicleClass vClass, const std::vector<GNEEdge*>& edges) const {
std::vector<GNEEdge*> solution;
if (!myPathCalculatorUpdated) {
solution = edges;
return solution;
}
if (edges.size() == 0) {
return solution;
} else if (edges.size() == 1) {
solution.push_back(edges.front());
return solution;
} else if ((edges.size() == 2) && (edges.front() == edges.back())) {
solution.push_back(edges.front());
return solution;
} else {
NBVehicle tmpVehicle("temporalNBVehicle", vClass);
GNENet* net = edges.front()->getNet();
for (int i = 1; i < (int)edges.size(); i++) {
if (edges.at(i - 1)->getNBEdge() != edges.at(i)->getNBEdge()) {
std::vector<const NBRouterEdge*> partialRoute;
myDijkstraRouter->compute(edges.at(i - 1)->getNBEdge(), edges.at(i)->getNBEdge(), &tmpVehicle, 10, partialRoute);
if (partialRoute.empty()) {
return {};
} else {
for (const auto& edgeID : partialRoute) {
solution.push_back(net->getAttributeCarriers()->retrieveEdge(edgeID->getID()));
}
}
}
}
}
auto solutionIt = solution.begin();
while (solutionIt != solution.end()) {
if ((solutionIt + 1) != solution.end()) {
if (*solutionIt == *(solutionIt + 1)) {
solutionIt = solution.erase(solutionIt);
} else {
solutionIt++;
}
} else {
solutionIt++;
}
}
return solution;
}
std::vector<GNEEdge*>
GNEPathManager::PathCalculator::calculateDijkstraPath(const SUMOVehicleClass vClass, GNEEdge* fromEdge, GNEEdge* toEdge) const {
return calculateDijkstraPath(vClass, {fromEdge, toEdge});
}
std::vector<GNEEdge*>
GNEPathManager::PathCalculator::calculateDijkstraPath(const SUMOVehicleClass vClass, GNEEdge* fromEdge, GNEJunction* toJunction) const {
std::vector<GNEEdge*> edges;
const auto toEdges = toJunction->getGNEIncomingEdges();
for (const auto& toEdge : toEdges) {
edges = calculateDijkstraPath(vClass, fromEdge, toEdge);
if (edges.size() > 0) {
return optimizeJunctionPath(edges);
}
}
return {};
}
std::vector<GNEEdge*>
GNEPathManager::PathCalculator::calculateDijkstraPath(const SUMOVehicleClass vClass, GNEJunction* fromJunction, GNEEdge* toEdge) const {
std::vector<GNEEdge*> edges;
const auto fromEdges = fromJunction->getGNEOutgoingEdges();
for (const auto& fromEdge : fromEdges) {
edges = calculateDijkstraPath(vClass, fromEdge, toEdge);
if (edges.size() > 0) {
return optimizeJunctionPath(edges);
}
}
return {};
}
std::vector<GNEEdge*>
GNEPathManager::PathCalculator::calculateDijkstraPath(const SUMOVehicleClass vClass, GNEJunction* fromJunction, GNEJunction* toJunction) const {
std::vector<GNEEdge*> edges;
const auto fromEdges = fromJunction->getGNEOutgoingEdges();
const auto toEdges = toJunction->getGNEIncomingEdges();
for (const auto& fromEdge : fromEdges) {
for (const auto& toEdge : toEdges) {
edges = calculateDijkstraPath(vClass, fromEdge, toEdge);
if (edges.size() > 0) {
return optimizeJunctionPath(edges);
}
}
}
return {};
}
void
GNEPathManager::PathCalculator::calculateReachability(const SUMOVehicleClass vClass, GNEEdge* originEdge) {
for (const auto& edge : originEdge->getNet()->getAttributeCarriers()->getEdges()) {
for (const auto& lane : edge.second->getChildLanes()) {
lane->resetReachability();
}
}
const double defaultMaxSpeed = SUMOVTypeParameter::VClassDefaultValues(vClass).maxSpeed;
std::map<GNEEdge*, double> reachableEdges;
reachableEdges[originEdge] = 0;
std::vector<GNEEdge*> check;
check.push_back(originEdge);
while (check.size() > 0) {
GNEEdge* edge = check.front();
check.erase(check.begin());
double traveltime = reachableEdges[edge];
for (const auto& lane : edge->getChildLanes()) {
if ((edge->getNBEdge()->getLaneStruct(lane->getIndex()).permissions & vClass) == vClass) {
lane->setReachability(traveltime);
}
}
traveltime += edge->getNBEdge()->getLength() / MIN2(edge->getNBEdge()->getSpeed(), defaultMaxSpeed);
std::vector<GNEEdge*> sucessors;
for (const auto& sucessorEdge : edge->getToJunction()->getGNEOutgoingEdges()) {
if (consecutiveEdgesConnected(vClass, edge, sucessorEdge)) {
sucessors.push_back(sucessorEdge);
}
}
for (const auto& nextEdge : sucessors) {
if ((reachableEdges.count(nextEdge) == 0) || (reachableEdges[nextEdge] > traveltime)) {
reachableEdges[nextEdge] = traveltime;
check.push_back(nextEdge);
}
}
}
}
bool
GNEPathManager::PathCalculator::consecutiveEdgesConnected(const SUMOVehicleClass vClass, const GNEEdge* from, const GNEEdge* to) const {
if ((from == nullptr) || (to == nullptr)) {
return false;
} else if (from == to) {
return false;
} else if (vClass == SVC_PEDESTRIAN) {
return true;
} else {
for (const auto& fromLane : from->getChildLanes()) {
for (const auto& fromConnection : from->getGNEConnections()) {
for (const auto& toLane : to->getChildLanes()) {
if (fromConnection->getLaneTo() == toLane) {
const NBEdge::Lane NBFromLane = from->getNBEdge()->getLaneStruct(fromLane->getIndex());
const NBEdge::Lane NBToLane = to->getNBEdge()->getLaneStruct(toLane->getIndex());
if (((NBFromLane.permissions & vClass) == vClass) &&
((NBToLane.permissions & vClass) == vClass)) {
return true;
}
}
}
}
}
return false;
}
}
bool
GNEPathManager::PathCalculator::busStopConnected(const GNEAdditional* busStop, const GNEEdge* edge) const {
if (busStop->getTagProperty()->getTag() != SUMO_TAG_BUS_STOP) {
return false;
}
if ((busStop->getParentLanes().front()->getParentEdge() == edge) &&
(edge->getNBEdge()->getLaneStruct(busStop->getParentLanes().front()->getIndex()).permissions & SVC_PEDESTRIAN) != 0) {
return true;
}
std::vector<GNELane*> pedestrianLanes;
for (int laneIndex = 0; laneIndex < (int)edge->getChildLanes().size(); laneIndex++) {
if ((edge->getNBEdge()->getLaneStruct(laneIndex).permissions & SVC_PEDESTRIAN) != 0) {
pedestrianLanes.push_back(edge->getChildLanes().at(laneIndex));
}
}
for (const auto& access : busStop->getChildAdditionals()) {
if (access->getTagProperty()->getTag() == SUMO_TAG_ACCESS) {
for (const auto& lane : pedestrianLanes) {
if (access->getParentLanes().front() == lane) {
return true;
}
}
}
}
return false;
}
bool
GNEPathManager::PathCalculator::isPathCalculatorUpdated() const {
return myPathCalculatorUpdated;
}
void
GNEPathManager::PathCalculator::invalidatePathCalculator() {
myPathCalculatorUpdated = false;
}
std::vector<GNEEdge*>
GNEPathManager::PathCalculator::optimizeJunctionPath(const std::vector<GNEEdge*>& edges) const {
bool stop = false;
std::vector<GNEEdge*> solutionA, solutionB;
const auto fromJunction = edges.front()->getFromJunction();
const auto toJunction = edges.back()->getToJunction();
for (auto it = edges.rbegin(); (it != edges.rend()) && !stop; it++) {
solutionA.insert(solutionA.begin(), *it);
if ((*it)->getFromJunction() == fromJunction) {
stop = true;
}
}
stop = false;
for (auto it = solutionA.begin(); (it != solutionA.end()) && !stop; it++) {
solutionB.push_back(*it);
if ((*it)->getToJunction() == toJunction) {
stop = true;
}
}
return solutionB;
}
GNEPathManager::PathDraw::PathDraw() {}
GNEPathManager::PathDraw::~PathDraw() {}
void
GNEPathManager::PathDraw::clearPathDraw() {
myLaneDrawedElements.clear();
myLane2laneDrawedElements.clear();
}
bool
GNEPathManager::PathDraw::checkDrawPathGeometry(const GUIVisualizationSettings& s, const GNELane* lane,
const SumoXMLTag tag, const bool isPlan) {
if (s.drawForViewObjectsHandler) {
return true;
} else if (myLaneDrawedElements.count(lane) > 0) {
if (!isPlan && myLaneDrawedElements.at(lane).count(tag) > 0) {
return false;
} else {
myLaneDrawedElements.at(lane).insert(tag);
return true;
}
} else {
myLaneDrawedElements[lane].insert(tag);
return true;
}
}
bool
GNEPathManager::PathDraw::checkDrawPathGeometry(const GUIVisualizationSettings& s, const GNESegment* segment,
const SumoXMLTag tag, const bool isPlan) {
if (s.drawForViewObjectsHandler) {
return true;
} else {
const std::pair<const GNELane*, const GNELane*> lane2lane(segment->getPreviousLane(), segment->getNextLane());
if (myLane2laneDrawedElements.count(lane2lane) > 0) {
if (!isPlan && myLane2laneDrawedElements.at(lane2lane).count(tag) > 0) {
return false;
} else {
myLane2laneDrawedElements.at(lane2lane).insert(tag);
return true;
}
} else {
myLane2laneDrawedElements[lane2lane].insert(tag);
return true;
}
}
}
GNEPathManager::GNEPathManager(const GNENet* net) :
myPathCalculator(new PathCalculator(net)),
myPathDraw(new PathDraw()) {
}
GNEPathManager::~GNEPathManager() {
clearSegments();
delete myPathCalculator;
delete myPathDraw;
}
GNEPathManager::PathCalculator*
GNEPathManager::getPathCalculator() {
return myPathCalculator;
}
const GNEPathElement*
GNEPathManager::getPathElement(const GUIGlObject* GLObject) const {
const auto pathElement = dynamic_cast<const GNEPathElement*>(GLObject);
if (pathElement == nullptr) {
return nullptr;
} else {
auto it = myPaths.find(pathElement);
if (it == myPaths.end()) {
return nullptr;
} else {
return it->first;
}
}
}
const std::vector<GNESegment*>&
GNEPathManager::getPathElementSegments(GNEPathElement* pathElement) const {
if (myPaths.count(pathElement) > 0) {
return myPaths.at(pathElement);
} else {
return myEmptySegments;
}
}
GNEPathManager::PathDraw*
GNEPathManager::getPathDraw() {
return myPathDraw;
}
bool
GNEPathManager::isPathValid(const GNEPathElement* pathElement) const {
if (myPaths.count(pathElement) > 0) {
for (const auto& segment : myPaths.at(pathElement)) {
if (segment->getLane() && segment->getNextLane()) {
return false;
}
}
return true;
} else {
return false;
}
}
const GNELane*
GNEPathManager::getFirstLane(const GNEPathElement* pathElement) const {
if ((myPaths.count(pathElement) > 0) && (myPaths.at(pathElement).size() > 0)) {
return myPaths.at(pathElement).front()->getLane();
} else {
return nullptr;
}
}
void
GNEPathManager::calculatePath(GNEPathElement* pathElement, SUMOVehicleClass vClass, GNELane* fromLane, GNELane* toLane) {
buildPath(pathElement, vClass, myPathCalculator->calculateDijkstraPath(vClass, fromLane->getParentEdge(), toLane->getParentEdge()),
fromLane, nullptr, toLane, nullptr);
}
void
GNEPathManager::calculatePath(GNEPathElement* pathElement, SUMOVehicleClass vClass, GNELane* fromLane, GNEJunction* toJunction) {
buildPath(pathElement, vClass, myPathCalculator->calculateDijkstraPath(vClass, fromLane->getParentEdge(), toJunction),
fromLane, nullptr, nullptr, toJunction);
}
void
GNEPathManager::calculatePath(GNEPathElement* pathElement, SUMOVehicleClass vClass, GNEJunction* fromJunction, GNELane* toLane) {
buildPath(pathElement, vClass, myPathCalculator->calculateDijkstraPath(vClass, fromJunction, toLane->getParentEdge()),
nullptr, fromJunction, toLane, nullptr);
}
void
GNEPathManager::calculatePath(GNEPathElement* pathElement, SUMOVehicleClass vClass, GNEJunction* fromJunction, GNEJunction* toJunction) {
buildPath(pathElement, vClass, myPathCalculator->calculateDijkstraPath(vClass, fromJunction, toJunction), nullptr, fromJunction, nullptr, toJunction);
}
void
GNEPathManager::calculatePath(GNEPathElement* pathElement, SUMOVehicleClass vClass, const std::vector<GNEEdge*>& edges) {
if (edges.size() > 0) {
buildPath(pathElement, vClass, myPathCalculator->calculateDijkstraPath(vClass, edges),
edges.front()->getLaneByAllowedVClass(vClass), nullptr, edges.back()->getLaneByAllowedVClass(vClass), nullptr);
} else {
removePath(pathElement);
}
}
void
GNEPathManager::calculateConsecutivePathEdges(GNEPathElement* pathElement, SUMOVehicleClass vClass, const std::vector<GNEEdge*>& edges,
const int firstLaneIndex, const int lastLaneIndex) {
std::vector<GNELane*> lanes;
if (edges.size() > 0) {
lanes.reserve(edges.size());
if ((firstLaneIndex >= 0) && (firstLaneIndex < (int)edges.front()->getChildLanes().size())) {
lanes.push_back(edges.front()->getChildLanes().at(firstLaneIndex));
} else {
lanes.push_back(edges.front()->getLaneByAllowedVClass(vClass));
}
if (edges.size() > 1) {
for (int i = 1; i < ((int)edges.size() - 1); i++) {
lanes.push_back(edges[i]->getLaneByAllowedVClass(vClass));
}
if ((lastLaneIndex >= 0) && (lastLaneIndex < (int)edges.back()->getChildLanes().size())) {
lanes.push_back(edges.back()->getChildLanes().at(lastLaneIndex));
} else {
lanes.push_back(edges.back()->getLaneByAllowedVClass(vClass));
}
}
}
calculateConsecutivePathLanes(pathElement, lanes);
}
void
GNEPathManager::calculateConsecutivePathLanes(GNEPathElement* pathElement, const std::vector<GNELane*>& lanes) {
removePath(pathElement);
if (lanes.size() > 0) {
std::vector<GNESegment*> segments;
const int lastIndex = ((int)lanes.size() - 1);
segments.reserve(2 * lanes.size());
for (int i = 0; i < (int)lanes.size(); i++) {
new GNESegment(this, pathElement, lanes.at(i), segments);
if (i != lastIndex) {
new GNESegment(this, pathElement, lanes.at(i)->getParentEdge()->getToJunction(), segments);
}
}
markLabelSegment(segments);
myPaths[pathElement] = segments;
}
}
void
GNEPathManager::removePath(GNEPathElement* pathElement) {
if (myPaths.find(pathElement) != myPaths.end()) {
for (const auto& segment : myPaths.at(pathElement)) {
delete segment;
}
myPaths.erase(pathElement);
}
}
void
GNEPathManager::drawLanePathElements(const GUIVisualizationSettings& s, const GNELane* lane) const {
if (myLaneSegments.count(lane) > 0) {
int numRoutes = 0;
for (const auto& segment : myLaneSegments.at(lane)) {
if (gViewObjectsHandler.isPathElementMarkForRedraw(segment->getPathElement())) {
segment->getPathElement()->drawLanePartialGL(s, segment, 2);
if (segment->getPathElement()->isRoute()) {
numRoutes++;
}
}
}
for (const auto& segment : myLaneSegments.at(lane)) {
if (!gViewObjectsHandler.isPathElementMarkForRedraw(segment->getPathElement())) {
segment->getPathElement()->drawLanePartialGL(s, segment, 0);
if (segment->getPathElement()->isRoute()) {
numRoutes++;
}
}
}
if ((numRoutes > 1) && lane->getNet()->getViewNet()->getDemandViewOptions().showOverlappedRoutes()) {
lane->drawOverlappedRoutes(numRoutes);
}
}
}
void
GNEPathManager::drawJunctionPathElements(const GUIVisualizationSettings& s, const GNEJunction* junction) const {
if (myJunctionSegments.count(junction) > 0) {
for (const auto& segment : myJunctionSegments.at(junction)) {
if (gViewObjectsHandler.isPathElementMarkForRedraw(segment->getPathElement())) {
segment->getPathElement()->drawJunctionPartialGL(s, segment, 2);
}
}
for (const auto& segment : myJunctionSegments.at(junction)) {
if (!gViewObjectsHandler.isPathElementMarkForRedraw(segment->getPathElement())) {
segment->getPathElement()->drawJunctionPartialGL(s, segment, 0);
}
}
}
}
void
GNEPathManager::redrawPathElements(const GUIVisualizationSettings& s) const {
for (const auto& pathElementToRedraw : gViewObjectsHandler.getRedrawPathElements()) {
const auto it = myPaths.find(pathElementToRedraw);
if (it != myPaths.end()) {
for (const auto& segment : it->second) {
if (segment->getLane()) {
it->first->drawLanePartialGL(s, segment, 3);
} else if (segment->getJunction()) {
it->first->drawJunctionPartialGL(s, segment, 3);
}
}
}
}
}
void
GNEPathManager::invalidateLanePath(const GNELane* lane) {
std::vector<GNEPathElement*> pathElementsToCompute;
if (myLaneSegments.count(lane) > 0) {
for (const auto& segment : myLaneSegments.at(lane)) {
pathElementsToCompute.push_back(segment->getPathElement());
}
}
for (const auto& pathElement : pathElementsToCompute) {
pathElement->computePathElement();
}
}
void
GNEPathManager::invalidateJunctionPath(const GNEJunction* junction) {
std::vector<GNEPathElement*> pathElementsToCompute;
if (myJunctionSegments.count(junction) > 0) {
for (const auto& segment : myJunctionSegments.at(junction)) {
pathElementsToCompute.push_back(segment->getPathElement());
}
}
for (const auto& pathElement : pathElementsToCompute) {
pathElement->computePathElement();
}
}
void
GNEPathManager::clearSegments() {
myCleaningSegments = true;
for (const auto& path : myPaths) {
for (const auto& segment : path.second) {
delete segment;
}
}
myPaths.clear();
myJunctionSegments.clear();
myLaneSegments.clear();
myCleaningSegments = false;
}
void
GNEPathManager::addSegmentInLaneSegments(GNESegment* segment, const GNELane* lane) {
myLaneSegments[lane].insert(segment);
}
void
GNEPathManager::addSegmentInJunctionSegments(GNESegment* segment, const GNEJunction* junction) {
myJunctionSegments[junction].insert(segment);
}
void
GNEPathManager::clearSegmentFromJunctionAndLaneSegments(GNESegment* segment) {
if (segment->getLane()) {
auto lane = segment->getLane();
myLaneSegments[lane].erase(segment);
if (myLaneSegments.at(lane).empty()) {
myLaneSegments.erase(lane);
}
}
if (segment->getJunction()) {
auto junction = segment->getJunction();
myJunctionSegments[junction].erase(segment);
if (myJunctionSegments.at(junction).empty()) {
myJunctionSegments.erase(junction);
}
}
}
bool
GNEPathManager::connectedLanes(const GNELane* fromLane, const GNELane* toLane) const {
NBEdge* fromNBEdge = fromLane->getParentEdge()->getNBEdge();
NBEdge* toNBEdge = toLane->getParentEdge()->getNBEdge();
const std::vector<NBEdge::Connection> connections = fromNBEdge->getConnectionsFromLane(fromLane->getIndex());
std::vector<NBEdge::Connection>::const_iterator con_it = find_if(
connections.begin(), connections.end(),
NBEdge::connections_finder(fromLane->getIndex(), toNBEdge, toLane->getIndex()));
return (con_it != connections.end());
}
void
GNEPathManager::buildPath(GNEPathElement* pathElement, SUMOVehicleClass vClass, const std::vector<GNEEdge*> path,
GNELane* fromLane, GNEJunction* fromJunction, GNELane* toLane, GNEJunction* toJunction) {
removePath(pathElement);
std::vector<GNESegment*> segments;
if (path.size() > 0) {
const int lastIndex = ((int)path.size() - 1);
segments.reserve(2 * path.size());
if (fromJunction) {
new GNESegment(this, pathElement, fromJunction, segments);
}
for (int i = 0; i < (int)path.size(); i++) {
if ((i == 0) && fromLane) {
new GNESegment(this, pathElement, fromLane, segments);
if (i != lastIndex) {
new GNESegment(this, pathElement, path.at(i)->getToJunction(), segments);
}
} else if ((i == lastIndex) && toLane) {
new GNESegment(this, pathElement, toLane, segments);
} else {
const GNELane* lane = path.at(i)->getLaneByAllowedVClass(vClass);
new GNESegment(this, pathElement, lane, segments);
if (i != lastIndex) {
new GNESegment(this, pathElement, path.at(i)->getToJunction(), segments);
}
}
}
if (toJunction) {
new GNESegment(this, pathElement, toJunction, segments);
}
markLabelSegment(segments);
myPaths[pathElement] = segments;
} else {
GNESegment* firstSegment = nullptr;
GNESegment* lastSegment = nullptr;
if (fromLane) {
firstSegment = new GNESegment(this, pathElement, fromLane, segments);
} else if (fromJunction) {
firstSegment = new GNESegment(this, pathElement, fromJunction, segments);
}
if (toLane) {
lastSegment = new GNESegment(this, pathElement, toLane, segments);
} else if (toJunction) {
lastSegment = new GNESegment(this, pathElement, toJunction, segments);
}
if (firstSegment && lastSegment) {
firstSegment->markSegmentLabel();
myPaths[pathElement] = segments;
} else {
delete firstSegment;
delete lastSegment;
}
}
}
void
GNEPathManager::markLabelSegment(const std::vector<GNESegment*>& segments) const {
std::vector<GNESegment*> laneSegments;
laneSegments.reserve(segments.size());
for (const auto& segment : segments) {
if (segment->getLane()) {
laneSegments.push_back(segment);
}
}
const int laneSegmentIndex = (int)((double)laneSegments.size() * 0.5);
laneSegments.at(laneSegmentIndex)->markSegmentLabel();
}