std::pair<NIVissimConnectionCluster*, NBNode*> NIVissimEdge::getFromNode(NBNodeCont& nc, ConnectionClusters& clusters) { const SUMOReal MAX_DISTANCE = 10.; assert(clusters.size() >= 1); const Position& beg = myGeom.front(); NIVissimConnectionCluster* c = *(clusters.begin()); // check whether the edge starts within a already build node if (c->around(beg, MAX_DISTANCE)) { clusters.erase(clusters.begin()); return std::pair<NIVissimConnectionCluster*, NBNode*> (c, c->getNBNode()); } // check for a parking place at the begin if (myDistrictConnections.size() > 0) { SUMOReal pos = *(myDistrictConnections.begin()); if (pos < 10) { NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, NODETYPE_NOJUNCTION); if (!nc.insert(node)) { throw 1; } while (myDistrictConnections.size() > 0 && *(myDistrictConnections.begin()) < 10) { myDistrictConnections.erase(myDistrictConnections.begin()); } return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), node); } } // build a new node for the edge's begin otherwise NBNode* node = new NBNode(toString<int>(myID) + "-begin", beg, NODETYPE_NOJUNCTION); if (!nc.insert(node)) { throw 1; } return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), node); }
void NIVissimDistrictConnection::dict_BuildDistrictNodes(NBDistrictCont& dc, NBNodeCont& nc) { for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) { // get the connections const std::vector<int>& connections = (*k).second; // retrieve the current district std::string dsid = toString<int>((*k).first); NBDistrict* district = new NBDistrict(dsid); dc.insert(district); // compute the middle of the district PositionVector pos; for (std::vector<int>::const_iterator j = connections.begin(); j != connections.end(); j++) { NIVissimDistrictConnection* c = dictionary(*j); pos.push_back(c->geomPosition()); } Position distCenter = pos.getPolygonCenter(); if (connections.size() == 1) { // !!! ok, ok, maybe not the best way just to add an offset distCenter.add(10, 10); } district->setCenter(distCenter); // build the node std::string id = "District" + district->getID(); NBNode* districtNode = new NBNode(id, district->getPosition(), district); if (!nc.insert(districtNode)) { throw 1; } } }
void NIVissimNodeCluster::buildNBNode(NBNodeCont& nc) { if (myConnectors.size() == 0) { return; // !!! Check, whether this can happen } // compute the position PositionVector crossings; IntVector::iterator i, j; // check whether this is a split of an edge only if (myAmEdgeSplit) { // !!! should be assert(myTLID==-1); for (i = myConnectors.begin(); i != myConnectors.end(); i++) { NIVissimConnection* c1 = NIVissimConnection::dictionary(*i); crossings.push_back_noDoublePos(c1->getFromGeomPosition()); } } else { // compute the places the connections cross for (i = myConnectors.begin(); i != myConnectors.end(); i++) { NIVissimAbstractEdge* c1 = NIVissimAbstractEdge::dictionary(*i); c1->buildGeom(); for (j = i + 1; j != myConnectors.end(); j++) { NIVissimAbstractEdge* c2 = NIVissimAbstractEdge::dictionary(*j); c2->buildGeom(); if (c1->crossesEdge(c2)) { crossings.push_back_noDoublePos(c1->crossesEdgeAtPoint(c2)); } } } // alternative way: compute via positions of crossings if (crossings.size() == 0) { for (i = myConnectors.begin(); i != myConnectors.end(); i++) { NIVissimConnection* c1 = NIVissimConnection::dictionary(*i); crossings.push_back_noDoublePos(c1->getFromGeomPosition()); crossings.push_back_noDoublePos(c1->getToGeomPosition()); } } } // get the position (center) Position pos = crossings.getPolygonCenter(); // build the node /* if(myTLID!=-1) { !!! NIVissimTL *tl = NIVissimTL::dictionary(myTLID); if(tl->getType()=="festzeit") { node = new NBNode(getNodeName(), pos.x(), pos.y(), "traffic_light"); } else { node = new NBNode(getNodeName(), pos.x(), pos.y(), "actuated_traffic_light"); } }*/ NBNode* node = new NBNode(getNodeName(), pos, NODETYPE_PRIORITY_JUNCTION); if (!nc.insert(node)) { delete node; throw 1; } myNBNode = node; }
std::pair<NIVissimConnectionCluster*, NBNode*> NIVissimEdge::getToNode(NBNodeCont& nc, ConnectionClusters& clusters) { const Position& end = myGeom.back(); if (clusters.size() > 0) { const SUMOReal MAX_DISTANCE = 10.; assert(clusters.size() >= 1); NIVissimConnectionCluster* c = *(clusters.end() - 1); // check whether the edge ends within a already build node if (c->around(end, MAX_DISTANCE)) { clusters.erase(clusters.end() - 1); return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode()); } } // check for a parking place at the end if (myDistrictConnections.size() > 0) { SUMOReal pos = *(myDistrictConnections.end() - 1); if (pos > myGeom.length() - 10) { NBNode* node = new NBNode(toString<int>(myID) + "-end", end, NODETYPE_NOJUNCTION); if (!nc.insert(node)) { throw 1; } while (myDistrictConnections.size() > 0 && *(myDistrictConnections.end() - 1) < myGeom.length() - 10) { myDistrictConnections.erase(myDistrictConnections.end() - 1); } return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), node); } } // build a new node for the edge's end otherwise NBNode* node = new NBNode(toString<int>(myID) + "-end", end, NODETYPE_NOJUNCTION); if (!nc.insert(node)) { throw 1; } return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), node); /* if (clusters.size()>0) { NIVissimConnectionCluster *c = *(clusters.end()-1); clusters.erase(clusters.end()-1); return std::pair<NIVissimConnectionCluster*, NBNode*>(c, c->getNBNode()); } else { // !!! self-loop edge?! return std::pair<NIVissimConnectionCluster*, NBNode*>(static_cast<NIVissimConnectionCluster*>(0), (*(myConnectionClusters.begin()))->getNBNode()); } */ }
std::pair<NBNode*, NBNode*> NIVissimEdge::remapOneOfNodes(NBNodeCont& nc, NIVissimDistrictConnection* d, NBNode* fromNode, NBNode* toNode) { std::string nid = "ParkingPlace" + toString<int>(d->getID()); if (d->geomPosition().distanceTo(fromNode->getPosition()) < d->geomPosition().distanceTo(toNode->getPosition())) { NBNode* newNode = new NBNode(nid, fromNode->getPosition(), NODETYPE_NOJUNCTION); nc.erase(fromNode); nc.insert(newNode); return std::pair<NBNode*, NBNode*>(newNode, toNode); } else { NBNode* newNode = new NBNode(nid, toNode->getPosition(), NODETYPE_NOJUNCTION); nc.erase(toNode); nc.insert(newNode); return std::pair<NBNode*, NBNode*>(fromNode, newNode); } }
std::pair<NBNode*, NBNode*> NIVissimEdge::resolveSameNode(NBNodeCont& nc, SUMOReal offset, NBNode* prevFrom, NBNode* prevTo) { // check whether the edge is connected to a district // use it if so NIVissimDistrictConnection* d = NIVissimDistrictConnection::dict_findForEdge(myID); if (d != 0) { Position pos = d->geomPosition(); SUMOReal position = d->getPosition(); // the district is at the begin of the edge if (myGeom.length() - position > position) { std::string nid = "ParkingPlace" + toString<int>(d->getID()); NBNode* node = nc.retrieve(nid); if (node == 0) { node = new NBNode(nid, pos, NODETYPE_NOJUNCTION); if (!nc.insert(node)) { throw 1; } } return std::pair<NBNode*, NBNode*>(node, prevTo); } // the district is at the end of the edge else { std::string nid = "ParkingPlace" + toString<int>(d->getID()); NBNode* node = nc.retrieve(nid); if (node == 0) { node = new NBNode(nid, pos, NODETYPE_NOJUNCTION); if (!nc.insert(node)) { throw 1; } } assert(node != 0); return std::pair<NBNode*, NBNode*>(prevFrom, node); } } // otherwise, check whether the edge is some kind of // a dead end... // check which end is nearer to the node centre if (myConnectionClusters.size() == 1) { NBNode* node = prevFrom; // it is the same as getToNode() NIVissimConnectionCluster* c = *(myConnectionClusters.begin()); // no end node given if (c->around(myGeom.front(), offset) && !c->around(myGeom.back(), offset)) { NBNode* end = new NBNode( toString<int>(myID) + "-End", myGeom.back(), NODETYPE_NOJUNCTION); if (!nc.insert(end)) { throw 1; } return std::pair<NBNode*, NBNode*>(node, end); } // no begin node given if (!c->around(myGeom.front(), offset) && c->around(myGeom.back(), offset)) { NBNode* beg = new NBNode( toString<int>(myID) + "-Begin", myGeom.front(), NODETYPE_NOJUNCTION); if (!nc.insert(beg)) { std::cout << "nope, NIVissimDisturbance" << std::endl; throw 1; } return std::pair<NBNode*, NBNode*>(beg, node); } // self-loop edge - both points lie within the same cluster if (c->around(myGeom.front()) && c->around(myGeom.back())) { return std::pair<NBNode*, NBNode*>(node, node); } } // what to do in other cases? // It simply is a self-looping edge.... return std::pair<NBNode*, NBNode*>(prevFrom, prevTo); }
void NIVissimEdge::buildNBEdge(NBDistrictCont& dc, NBNodeCont& nc, NBEdgeCont& ec, SUMOReal sameNodesOffset) { // build the edge std::pair<NIVissimConnectionCluster*, NBNode*> fromInf, toInf; NBNode* fromNode, *toNode; fromNode = toNode = 0; sort(myConnectionClusters.begin(), myConnectionClusters.end(), connection_cluster_position_sorter(myID)); sort(myDistrictConnections.begin(), myDistrictConnections.end()); ConnectionClusters tmpClusters = myConnectionClusters; if (tmpClusters.size() != 0) { sort(tmpClusters.begin(), tmpClusters.end(), connection_cluster_position_sorter(myID)); // get or build the from-node // A node may have to be build when the edge starts or ends at // a parking place or something like this fromInf = getFromNode(nc, tmpClusters); fromNode = fromInf.second; // get or build the to-node //if(tmpClusters.size()>0) { toInf = getToNode(nc, tmpClusters); toNode = toInf.second; if (fromInf.first != 0 && toNode != 0 && fromInf.first->around(toNode->getPosition())) { WRITE_WARNING("Will not build edge '" + toString(myID) + "'."); myAmWithinJunction = true; return; } //} // if both nodes are the same, resolve the problem otherwise if (fromNode == toNode) { std::pair<NBNode*, NBNode*> tmp = resolveSameNode(nc, sameNodesOffset, fromNode, toNode); if (fromNode != tmp.first) { fromInf.first = 0; } if (toNode != tmp.second) { toInf.first = 0; } fromNode = tmp.first; toNode = tmp.second; } } // if (fromNode == 0) { fromInf.first = 0; Position pos = myGeom[0]; fromNode = new NBNode(toString<int>(myID) + "-SourceNode", pos, NODETYPE_NOJUNCTION); if (!nc.insert(fromNode)) { throw ProcessError("Could not insert node '" + fromNode->getID() + "' to nodes container."); } } if (toNode == 0) { toInf.first = 0; Position pos = myGeom[-1]; toNode = new NBNode(toString<int>(myID) + "-DestinationNode", pos, NODETYPE_NOJUNCTION); if (!nc.insert(toNode)) { throw ProcessError("Could not insert node '" + toNode->getID() + "' to nodes container."); } } // build the edge SUMOReal avgSpeed = 0; int i; for (i = 0; i < (int) myNoLanes; i++) { if (myLaneSpeeds.size() <= (size_t) i || myLaneSpeeds[i] == -1) { myLanesWithMissingSpeeds.push_back(toString(myID) + "_" + toString(i)); avgSpeed += OptionsCont::getOptions().getFloat("vissim.default-speed"); } else { avgSpeed += myLaneSpeeds[i]; } } avgSpeed /= (SUMOReal) myLaneSpeeds.size(); avgSpeed *= OptionsCont::getOptions().getFloat("vissim.speed-norm"); if (fromNode == toNode) { WRITE_WARNING("Could not build edge '" + toString(myID) + "'; would connect same node."); return; } NBEdge* buildEdge = new NBEdge(toString<int>(myID), fromNode, toNode, myType, avgSpeed / (SUMOReal) 3.6, myNoLanes, -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, myGeom, myName, LANESPREAD_CENTER, true); for (i = 0; i < (int) myNoLanes; i++) { if ((int) myLaneSpeeds.size() <= i || myLaneSpeeds[i] == -1) { buildEdge->setSpeed(i, OptionsCont::getOptions().getFloat("vissim.default-speed") / (SUMOReal) 3.6); } else { buildEdge->setSpeed(i, myLaneSpeeds[i] / (SUMOReal) 3.6); } } ec.insert(buildEdge); // check whether the edge contains any other clusters if (tmpClusters.size() > 0) { bool cont = true; for (ConnectionClusters::iterator j = tmpClusters.begin(); cont && j != tmpClusters.end(); ++j) { // split the edge at the previously build node std::string nextID = buildEdge->getID() + "[1]"; cont = ec.splitAt(dc, buildEdge, (*j)->getNBNode()); // !!! what to do if the edge could not be split? buildEdge = ec.retrieve(nextID); } } }
void NBRampsComputer::buildOffRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, SUMOReal rampLength, bool dontSplit, std::set<NBEdge*>& incremented) { NBEdge* potHighway, *potRamp, *prev; getOffRampEdges(cur, &potHighway, &potRamp, &prev); // compute the number of lanes to append const unsigned int firstLaneNumber = prev->getNumLanes(); int toAdd = (potRamp->getNumLanes() + potHighway->getNumLanes()) - firstLaneNumber; NBEdge* first = prev; NBEdge* last = prev; NBEdge* curr = prev; if (toAdd > 0 && find(incremented.begin(), incremented.end(), prev) == incremented.end()) { SUMOReal currLength = 0; while (curr != 0 && currLength + curr->getGeometry().length() - POSITION_EPS < rampLength) { if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) { curr->incLaneNo(toAdd); curr->invalidateConnections(true); incremented.insert(curr); moveRampRight(curr, toAdd); currLength += curr->getLength(); // !!! loaded length? last = curr; } NBNode* prevN = curr->getFromNode(); if (prevN->getIncomingEdges().size() == 1) { curr = prevN->getIncomingEdges()[0]; if (curr->getNumLanes() != firstLaneNumber) { // the number of lanes changes along the computation; we'll stop... curr = 0; } else if (last->isTurningDirectionAt(curr)) { // turnarounds certainly should not be included in a ramp curr = 0; } else if (curr == potHighway || curr == potRamp) { // circular connectivity. do not split! curr = 0; } } else { // ambigous; and, in fact, what should it be? ...stop curr = 0; } } // check whether a further split is necessary if (curr != 0 && !dontSplit && currLength - POSITION_EPS < rampLength && curr->getNumLanes() == firstLaneNumber && find(incremented.begin(), incremented.end(), curr) == incremented.end()) { // there is enough place to build a ramp; do it bool wasFirst = first == curr; Position pos = curr->getGeometry().positionAtOffset(curr->getGeometry().length() - (rampLength - currLength)); NBNode* rn = new NBNode(curr->getID() + "-AddedOffRampNode", pos); if (!nc.insert(rn)) { throw ProcessError("Ups - could not build on-ramp for edge '" + curr->getID() + "' (node could not be build)!"); } std::string name = curr->getID(); bool ok = ec.splitAt(dc, curr, rn, curr->getID(), curr->getID() + "-AddedOffRampEdge", curr->getNumLanes(), curr->getNumLanes() + toAdd); if (!ok) { WRITE_ERROR("Ups - could not build on-ramp for edge '" + curr->getID() + "'!"); return; } curr = ec.retrieve(name + "-AddedOffRampEdge"); incremented.insert(curr); last = curr; moveRampRight(curr, toAdd); if (wasFirst) { first = curr; } } if (curr == prev && dontSplit) { WRITE_WARNING("Could not build off-ramp for edge '" + curr->getID() + "' due to option '--ramps.no-split'"); return; } } // set connections from added ramp to ramp/highway if (!first->addLane2LaneConnections(potRamp->getNumLanes(), potHighway, 0, MIN2(first->getNumLanes() - 1, potHighway->getNumLanes()), NBEdge::L2L_VALIDATED, true)) { throw ProcessError("Could not set connection!"); } if (!first->addLane2LaneConnections(0, potRamp, 0, potRamp->getNumLanes(), NBEdge::L2L_VALIDATED, false)) { throw ProcessError("Could not set connection!"); } // patch ramp geometry PositionVector p = potRamp->getGeometry(); p.pop_front(); p.push_front(first->getLaneShape(0)[-1]); potRamp->setGeometry(p); }
void NBRampsComputer::buildOnRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, SUMOReal rampLength, bool dontSplit, std::set<NBEdge*>& incremented) { NBEdge* potHighway, *potRamp, *cont; getOnRampEdges(cur, &potHighway, &potRamp, &cont); // compute the number of lanes to append const unsigned int firstLaneNumber = potHighway->getNumLanes(); int toAdd = (potRamp->getNumLanes() + firstLaneNumber) - cont->getNumLanes(); NBEdge* first = cont; NBEdge* last = cont; NBEdge* curr = cont; if (toAdd > 0 && find(incremented.begin(), incremented.end(), cont) == incremented.end()) { SUMOReal currLength = 0; while (curr != 0 && currLength + curr->getGeometry().length() - POSITION_EPS < rampLength) { if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) { curr->incLaneNo(toAdd); curr->invalidateConnections(true); incremented.insert(curr); moveRampRight(curr, toAdd); currLength += curr->getLength(); // !!! loaded length? last = curr; } NBNode* nextN = curr->getToNode(); if (nextN->getOutgoingEdges().size() == 1) { curr = nextN->getOutgoingEdges()[0]; if (curr->getNumLanes() != firstLaneNumber) { // the number of lanes changes along the computation; we'll stop... curr = 0; } } else { // ambigous; and, in fact, what should it be? ...stop curr = 0; } } // check whether a further split is necessary if (curr != 0 && !dontSplit && currLength - POSITION_EPS < rampLength && curr->getNumLanes() == firstLaneNumber && find(incremented.begin(), incremented.end(), curr) == incremented.end()) { // there is enough place to build a ramp; do it bool wasFirst = first == curr; NBNode* rn = new NBNode(curr->getID() + "-AddedOnRampNode", curr->getGeometry().positionAtLengthPosition(rampLength - currLength)); if (!nc.insert(rn)) { throw ProcessError("Ups - could not build on-ramp for edge '" + curr->getID() + "' (node could not be build)!"); } std::string name = curr->getID(); bool ok = ec.splitAt(dc, curr, rn, curr->getID() + ADDED_ON_RAMP_EDGE, curr->getID(), curr->getNumLanes() + toAdd, curr->getNumLanes()); if (!ok) { WRITE_ERROR("Ups - could not build on-ramp for edge '" + curr->getID() + "'!"); return; } //ec.retrieve(name)->invalidateConnections(); curr = ec.retrieve(name + ADDED_ON_RAMP_EDGE); curr->invalidateConnections(true); incremented.insert(curr); last = curr; moveRampRight(curr, toAdd); if (wasFirst) { first = curr; } } } // set connections from ramp/highway to added ramp if (!potHighway->addLane2LaneConnections(0, first, potRamp->getNumLanes(), MIN2(first->getNumLanes() - potRamp->getNumLanes(), potHighway->getNumLanes()), NBEdge::L2L_VALIDATED, true, true)) { throw ProcessError("Could not set connection!"); } if (!potRamp->addLane2LaneConnections(0, first, 0, potRamp->getNumLanes(), NBEdge::L2L_VALIDATED, true, true)) { throw ProcessError("Could not set connection!"); } // patch ramp geometry PositionVector p = potRamp->getGeometry(); p.pop_back(); p.push_back(first->getLaneShape(0)[0]); potRamp->setGeometry(p); // set connections from added ramp to following highway NBNode* nextN = last->getToNode(); if (nextN->getOutgoingEdges().size() == 1) { NBEdge* next = nextN->getOutgoingEdges()[0];//const EdgeVector& o1 = cont->getToNode()->getOutgoingEdges(); if (next->getNumLanes() < last->getNumLanes()) { last->addLane2LaneConnections(last->getNumLanes() - next->getNumLanes(), next, 0, next->getNumLanes(), NBEdge::L2L_VALIDATED); } } }