#include <config.h>
#include <algorithm>
#include <cassert>
#include <cmath>
#include "MSRightOfWayJunction.h"
#include "MSLane.h"
#include "MSLink.h"
#include "MSEdge.h"
#include "MSJunctionLogic.h"
#include "MSInternalJunction.h"
MSInternalJunction::MSInternalJunction(const std::string& id,
SumoXMLNodeType type,
const Position& position,
const PositionVector& shape,
std::vector<MSLane*> incoming,
std::vector<MSLane*> internal)
: MSLogicJunction(id, type, position, shape, "", incoming, internal) {}
MSInternalJunction::~MSInternalJunction() {}
void
MSInternalJunction::postloadInit() {
if (myIncomingLanes.size() == 0) {
throw ProcessError(TLF("Internal junction % has no incoming lanes", getID()));
}
const MSLane* specialLane = myIncomingLanes[0];
assert(specialLane->getLinkCont().size() == 1);
MSLink* thisLink = specialLane->getLinkCont()[0];
const MSRightOfWayJunction* parent = dynamic_cast<const MSRightOfWayJunction*>(specialLane->getEdge().getToJunction());
if (parent == nullptr) {
return;
}
const int ownLinkIndex = specialLane->getIncomingLanes()[0].viaLink->getIndex();
const MSLogicJunction::LinkBits& response = parent->getLogic()->getResponseFor(ownLinkIndex);
for (MSLane* const lane : myInternalLanes) {
for (MSLink* const link : lane->getLinkCont()) {
if (link->getViaLane() != nullptr) {
const int foeIndex = lane->getIncomingLanes()[0].viaLink->getIndex();
if (response.test(foeIndex) || indirectBicycleTurn(specialLane, thisLink, lane, link)) {
myInternalLaneFoes.push_back(lane);
}
if (std::find(myInternalLaneFoes.begin(), myInternalLaneFoes.end(), link->getViaLane()) == myInternalLaneFoes.end()) {
myInternalLaneFoes.push_back(link->getViaLane());
}
} else {
if (std::find(myInternalLaneFoes.begin(), myInternalLaneFoes.end(), lane) == myInternalLaneFoes.end()) {
myInternalLaneFoes.push_back(lane);
if (lane->isCrossing()) {
myInternalLinkFoes.push_back(lane->getIncomingLanes()[0].viaLink);
}
}
}
}
}
for (std::vector<MSLane*>::const_iterator i = myIncomingLanes.begin() + 1; i != myIncomingLanes.end(); ++i) {
for (MSLink* const link : (*i)->getLinkCont()) {
int linkIndex = link->getCorrespondingEntryLink()->getIndex();
if (linkIndex != -1 && response.test(linkIndex)) {
myInternalLinkFoes.push_back(link);
const MSLane* via = link->getViaLane();
if (via != nullptr && via->getLinkCont().front()->getViaLane() != nullptr) {
myInternalLinkFoes.push_back(via->getLinkCont().front());
}
}
}
}
thisLink->setRequestInformation(ownLinkIndex, true, false, myInternalLinkFoes, myInternalLaneFoes, thisLink->getViaLane()->getLogicalPredecessorLane());
assert(thisLink->getViaLane()->getLinkCont().size() == 1);
MSLink* exitLink = thisLink->getViaLane()->getLinkCont()[0];
exitLink->setRequestInformation(ownLinkIndex, false, false, std::vector<MSLink*>(),
myInternalLaneFoes, thisLink->getViaLane());
for (const auto& ili : exitLink->getLane()->getIncomingLanes()) {
if (ili.lane->isWalkingArea()) {
exitLink->addWalkingAreaFoeExit(ili.lane);
break;
}
}
}
bool
MSInternalJunction::indirectBicycleTurn(const MSLane* specialLane, const MSLink* thisLink, const MSLane* foeFirstPart, const MSLink* foeLink) const {
if (specialLane->getPermissions() == SVC_BICYCLE && foeFirstPart->getPermissions() == SVC_BICYCLE
&& thisLink->getDirection() == LinkDirection::LEFT && foeLink->getDirection() == LinkDirection::LEFT
&& thisLink->getViaLane() != nullptr
&& thisLink->getViaLane()->getShape().intersects(foeFirstPart->getShape())) {
return true;
} else {
return false;
}
}