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 NWWriter_DlrNavteq::writeTrafficSignals(const OptionsCont& oc, NBNodeCont& nc) { OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_traffic_signals.txt"); writeHeader(device, oc); const GeoConvHelper& gch = GeoConvHelper::getFinal(); const bool haveGeo = gch.usingGeoProjection(); const SUMOReal geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE device.setPrecision(0); // write format specifier device << "#Traffic signal related to LINK_ID and NODE_ID with location relative to driving direction.\n#column format like pointcollection.\n#DESCRIPTION->LOCATION: 1-rechts von LINK; 2-links von LINK; 3-oberhalb LINK -1-keineAngabe\n#RELATREC_ID\tPOICOL_TYPE\tDESCRIPTION\tLONGITUDE\tLATITUDE\tLINK_ID\n"; // write record for every edge incoming to a tls controlled node for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; if (n->isTLControlled()) { Position pos = n->getPosition(); gch.cartesian2geo(pos); pos.mul(geoScale); const EdgeVector& incoming = n->getIncomingEdges(); for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) { NBEdge* e = *it; device << e->getID() << "\t" << "12\t" // POICOL_TYPE << "LSA;NODEIDS#" << n->getID() << "#;LOCATION#-1#;\t" << pos.x() << "\t" << pos.y() << "\t" << e->getID() << "\n"; } } } }
void NWWriter_DlrNavteq::writeConnectedLanes(const OptionsCont& oc, NBNodeCont& nc) { OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_connected_lanes.txt"); writeHeader(device, oc); // write format specifier device << "#Lane connections related to LINK-IDs and NODE-ID.\n"; device << "#column format like pointcollection.\n"; device << "#NODE-ID\tVEHICLE-TYPE\tFROM_LANE\tTO_LANE\tTHROUGH_TRAFFIC\tLINK_IDs[2..*]\n"; // write record for every connection for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const EdgeVector& incoming = n->getIncomingEdges(); for (EdgeVector::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { NBEdge* from = *j; const SVCPermissions fromPerm = from->getPermissions(); const std::vector<NBEdge::Connection>& connections = from->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) { const NBEdge::Connection& c = *it_c; device << n->getID() << "\t" << getAllowedTypes(fromPerm & c.toEdge->getPermissions()) << "\t" << c.fromLane + 1 << "\t" // one-based << c.toLane + 1 << "\t" // one-based << 1 << "\t" // no information regarding permissibility of through traffic << from->getID() << "\t" << c.toEdge->getID() << "\t" << "\n"; } } } device.close(); }
void NWWriter_XML::writeNodes(const OptionsCont& oc, NBNodeCont& nc) { const GeoConvHelper& gch = GeoConvHelper::getFinal(); bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo"); if (useGeo && !gch.usingGeoProjection()) { WRITE_WARNING("Ignoring option \"proj.plain-geo\" because no geo-conversion has been defined"); useGeo = false; } const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection(); OutputDevice& device = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".nod.xml"); device.writeXMLHeader("nodes", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/nodes_file.xsd\""); // write network offsets and projection to allow reconstruction of original coordinates if (!useGeo) { NWWriter_SUMO::writeLocation(device); } // write nodes for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; device.openTag(SUMO_TAG_NODE); device.writeAttr(SUMO_ATTR_ID, n->getID()); // write position Position pos = n->getPosition(); if (useGeo) { gch.cartesian2geo(pos); } if (geoAccuracy) { device.setPrecision(GEO_OUTPUT_ACCURACY); } NWFrame::writePositionLong(pos, device); if (geoAccuracy) { device.setPrecision(); } device.writeAttr(SUMO_ATTR_TYPE, toString(n->getType())); if (n->isTLControlled()) { const std::set<NBTrafficLightDefinition*>& tlss = n->getControllingTLS(); // set may contain multiple programs for the same id. // make sure ids are unique and sorted std::set<std::string> tlsIDs; for (std::set<NBTrafficLightDefinition*>::const_iterator it_tl = tlss.begin(); it_tl != tlss.end(); it_tl++) { tlsIDs.insert((*it_tl)->getID()); } std::vector<std::string> sortedIDs(tlsIDs.begin(), tlsIDs.end()); sort(sortedIDs.begin(), sortedIDs.end()); device.writeAttr(SUMO_ATTR_TLID, sortedIDs); } device.closeTag(); } device.close(); }
void NWWriter_DlrNavteq::writeNodesUnsplitted(const OptionsCont& oc, NBNodeCont& nc, NBEdgeCont& ec) { // For "real" nodes we simply use the node id. // For internal nodes (geometry vectors describing edge geometry in the parlance of this format) // we use the id of the edge and do not bother with // compression (each direction gets its own internal node). // XXX add option for generating numerical ids in case the input network has string ids and the target process needs integers OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_nodes_unsplitted.txt"); writeHeader(device, oc); const GeoConvHelper& gch = GeoConvHelper::getFinal(); const bool haveGeo = gch.usingGeoProjection(); const SUMOReal geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE device.setPrecision(0); if (!haveGeo) { WRITE_WARNING("DlrNavteq node data will be written in (floating point) cartesian coordinates"); } // write format specifier device << "# NODE_ID\tIS_BETWEEN_NODE\tamount_of_geocoordinates\tx1\ty1\t[x2 y2 ... xn yn]\n"; // write normal nodes for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; Position pos = n->getPosition(); gch.cartesian2geo(pos); pos.mul(geoScale); device << n->getID() << "\t0\t1\t" << pos.x() << "\t" << pos.y() << "\n"; } // write "internal" nodes for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { NBEdge* e = (*i).second; const PositionVector& geom = e->getGeometry(); if (geom.size() > 2) { std::string internalNodeID = e->getID(); if (internalNodeID == UNDEFINED || (nc.retrieve(internalNodeID) != 0)) { // need to invent a new name to avoid clashing with the id of a 'real' node or a reserved name internalNodeID += "_geometry"; } device << internalNodeID << "\t1\t" << geom.size() - 2; for (size_t ii = 1; ii < geom.size() - 1; ++ii) { Position pos = geom[(int)ii]; gch.cartesian2geo(pos); pos.mul(geoScale); device << "\t" << pos.x() << "\t" << pos.y(); } device << "\n"; } } device.close(); }
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()); } */ }
// --------------------------------------------------------------------------- // NBEdgePriorityComputer // --------------------------------------------------------------------------- void NBEdgePriorityComputer::computeEdgePriorities(NBNodeCont& nc) { for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; // preset all junction's edge priorities to zero for (EdgeVector::iterator j = n->myAllEdges.begin(); j != n->myAllEdges.end(); ++j) { (*j)->setJunctionPriority(n, 0); } // check if the junction is not a real junction if (n->myIncomingEdges.size() == 1 && n->myOutgoingEdges.size() == 1) { continue; } // compute the priorities on junction when needed if (n->myType != NODETYPE_RIGHT_BEFORE_LEFT) { setPriorityJunctionPriorities(*n); } } }
// --------------------------------------------------------------------------- // NBNodeTypeComputer // --------------------------------------------------------------------------- void NBNodeTypeComputer::computeNodeTypes(NBNodeCont& nc) { for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; // the type may already be set from the data if (n->myType != NODETYPE_UNKNOWN) { continue; } // check whether the junction is not a real junction if (n->myIncomingEdges.size() == 1) { n->myType = NODETYPE_PRIORITY; continue; } // @todo "isSimpleContinuation" should be revalidated if (n->isSimpleContinuation()) { n->myType = NODETYPE_PRIORITY; continue; } // determine the type SumoXMLNodeType type = NODETYPE_RIGHT_BEFORE_LEFT; for (EdgeVector::const_iterator i = n->myIncomingEdges.begin(); i != n->myIncomingEdges.end(); i++) { for (EdgeVector::const_iterator j = i + 1; j != n->myIncomingEdges.end(); j++) { // @todo "getOppositeIncoming" should probably be refactored into something the edge knows if (n->getOppositeIncoming(*j) == *i && n->myIncomingEdges.size() > 2) { continue; } // @todo check against a legal document // @todo figure out when NODETYPE_PRIORITY_STOP is appropriate const SUMOReal s1 = (*i)->getSpeed() * (SUMOReal) 3.6; const SUMOReal s2 = (*j)->getSpeed() * (SUMOReal) 3.6; const int p1 = (*i)->getPriority(); const int p2 = (*j)->getPriority(); if (fabs(s1 - s2) > (SUMOReal) 9.5 || MAX2(s1, s2) >= (SUMOReal) 49. || p1 != p2) { type = NODETYPE_PRIORITY; break; } } } // save type n->myType = type; } }
void NWWriter_DlrNavteq::writeProhibitedManoeuvres(const OptionsCont& oc, const NBNodeCont& nc, const NBEdgeCont& ec) { OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_prohibited_manoeuvres.txt"); writeHeader(device, oc); // need to invent id for relation std::set<std::string> reservedRelIDs; if (oc.isSet("reserved-ids")) { NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "rel:", reservedRelIDs); } std::vector<std::string> avoid = ec.getAllNames(); // already used for tls RELATREC_ID avoid.insert(avoid.end(), reservedRelIDs.begin(), reservedRelIDs.end()); IDSupplier idSupplier("", avoid); // @note: use a global relRecIDsupplier if this is used more often // write format specifier device << "#No driving allowed from ID1 to ID2 or the complete chain from ID1 to IDn\n"; device << "#RELATREC_ID\tPERMANENT_ID_INFO\tVALIDITY_PERIOD\tTHROUGH_TRAFFIC\tVEHICLE_TYPE\tNAVTEQ_LINK_ID1\t[NAVTEQ_LINK_ID2 ...]\n"; // write record for every pair of incoming/outgoing edge that are not connected despite having common permissions for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const EdgeVector& incoming = n->getIncomingEdges(); const EdgeVector& outgoing = n->getOutgoingEdges(); for (EdgeVector::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { NBEdge* inEdge = *j; const SVCPermissions inPerm = inEdge->getPermissions(); for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); ++k) { NBEdge* outEdge = *k; const SVCPermissions outPerm = outEdge->getPermissions(); const SVCPermissions commonPerm = inPerm & outPerm; if (commonPerm != 0 && commonPerm != SVC_PEDESTRIAN && !inEdge->isConnectedTo(outEdge)) { device << idSupplier.getNext() << "\t" << 1 << "\t" // permanent id << UNDEFINED << "\t" << 1 << "\t" << getAllowedTypes(SVCAll) << "\t" << inEdge->getID() << "\t" << outEdge->getID() << "\n"; } } } } device.close(); }
void NIVissimNodeCluster::dict_addDisturbances(NBDistrictCont& dc, NBNodeCont& nc, NBEdgeCont& ec) { for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) { const IntVector& disturbances = (*i).second->myDisturbances; NBNode* node = nc.retrieve((*i).second->getNodeName()); for (IntVector::const_iterator j = disturbances.begin(); j != disturbances.end(); j++) { NIVissimDisturbance* disturbance = NIVissimDisturbance::dictionary(*j); disturbance->addToNode(node, dc, nc, ec); } } NIVissimDisturbance::reportRefused(); }
// --------------------------------------------------------------------------- // NBNodesEdgesSorter // --------------------------------------------------------------------------- void NBNodesEdgesSorter::sortNodesEdges(NBNodeCont& nc, bool leftHand) { for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; if (n->myAllEdges.size() == 0) { continue; } std::vector<NBEdge*>& allEdges = (*i).second->myAllEdges; std::vector<NBEdge*>& incoming = (*i).second->myIncomingEdges; std::vector<NBEdge*>& outgoing = (*i).second->myOutgoingEdges; // sort the edges std::sort(allEdges.begin(), allEdges.end(), edge_by_junction_angle_sorter(n)); std::sort(incoming.begin(), incoming.end(), edge_by_junction_angle_sorter(n)); std::sort(outgoing.begin(), outgoing.end(), edge_by_junction_angle_sorter(n)); std::vector<NBEdge*>::iterator j; for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) { swapWhenReversed(n, leftHand, j, j + 1); } if (allEdges.size() > 1 && j != allEdges.end()) { swapWhenReversed(n, leftHand, allEdges.end() - 1, allEdges.begin()); } } }
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); } }
void NBTrafficLightLogicCont::setTLControllingInformation(const NBEdgeCont& ec, const NBNodeCont& nc) { Definitions definitions = getDefinitions(); // set the information about all participants, first for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) { (*it)->setParticipantsInformation(); } // clear previous information because tlDefs may have been removed in NETEDIT ec.clearControllingTLInformation(); // insert the information about the tl-controlling for (Definitions::iterator it = definitions.begin(); it != definitions.end(); it++) { (*it)->setTLControllingInformation(); } // handle rail signals which are not instantiated as normal definitions for (std::map<std::string, NBNode*>::const_iterator it = nc.begin(); it != nc.end(); it ++) { NBNode* n = it->second; if (n->getType() == NODETYPE_RAIL_SIGNAL || n->getType() == NODETYPE_RAIL_CROSSING) { NBOwnTLDef dummy(n->getID(), n, 0, TLTYPE_STATIC); dummy.setParticipantsInformation(); dummy.setTLControllingInformation(); n->removeTrafficLight(&dummy); } } }
void NIImporter_OpenDrive::setNodeSecure(NBNodeCont &nc, OpenDriveEdge &e, const std::string &nodeID, NIImporter_OpenDrive::LinkType lt) throw(ProcessError) { NBNode *n = nc.retrieve(nodeID); if (n==0) { throw ProcessError("Could not find node '" + nodeID + "'."); } if (lt==OPENDRIVE_LT_SUCCESSOR) { if (e.to!=0&&e.to!=n) { throw ProcessError("Edge '" + e.id + "' has two end nodes."); } e.to = n; } else { if (e.from!=0&&e.from!=n) { throw ProcessError("Edge '" + e.id + "' has two start nodes."); } e.from = n; } }
void NWWriter_XML::writeJoinedJunctions(const OptionsCont& oc, NBNodeCont& nc) { OutputDevice& device = OutputDevice::getDevice(oc.getString("junctions.join-output")); device.writeXMLHeader("nodes", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/nodes_file.xsd\""); const std::vector<std::set<std::string> >& clusters = nc.getJoinedClusters(); for (std::vector<std::set<std::string> >::const_iterator it = clusters.begin(); it != clusters.end(); it++) { assert((*it).size() > 0); device.openTag(SUMO_TAG_JOIN); // prepare string std::ostringstream oss; for (std::set<std::string>::const_iterator it_id = it->begin(); it_id != it->end(); it_id++) { oss << *it_id << " "; } // remove final space std::string ids = oss.str(); device.writeAttr(SUMO_ATTR_NODES, ids.substr(0, ids.size() - 1)); device.closeTag(); } device.close(); }
void NWWriter_DlrNavteq::writeNodesUnsplitted(const OptionsCont& oc, NBNodeCont& nc, NBEdgeCont& ec, std::map<NBEdge*, std::string>& internalNodes) { // For "real" nodes we simply use the node id. // For internal nodes (geometry vectors describing edge geometry in the parlance of this format) // we use the id of the edge and do not bother with // compression (each direction gets its own internal node). OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_nodes_unsplitted.txt"); writeHeader(device, oc); const GeoConvHelper& gch = GeoConvHelper::getFinal(); const bool haveGeo = gch.usingGeoProjection(); const double geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE device.setPrecision(oc.getInt("dlr-navteq.precision")); if (!haveGeo) { WRITE_WARNING("DlrNavteq node data will be written in (floating point) cartesian coordinates"); } // write format specifier device << "# NODE_ID\tIS_BETWEEN_NODE\tamount_of_geocoordinates\tx1\ty1\t[x2 y2 ... xn yn]\n"; // write header Boundary boundary = gch.getConvBoundary(); Position min(boundary.xmin(), boundary.ymin()); Position max(boundary.xmax(), boundary.ymax()); gch.cartesian2geo(min); min.mul(geoScale); gch.cartesian2geo(max); max.mul(geoScale); int multinodes = 0; for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { if ((*i).second->getGeometry().size() > 2) { multinodes++; } } device << "# [xmin_region] " << min.x() << "\n"; device << "# [xmax_region] " << max.x() << "\n"; device << "# [ymin_region] " << min.y() << "\n"; device << "# [ymax_region] " << max.y() << "\n"; device << "# [elements_multinode] " << multinodes << "\n"; device << "# [elements_normalnode] " << nc.size() << "\n"; device << "# [xmin] " << min.x() << "\n"; device << "# [xmax] " << max.x() << "\n"; device << "# [ymin] " << min.y() << "\n"; device << "# [ymax] " << max.y() << "\n"; // write normal nodes for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; Position pos = n->getPosition(); gch.cartesian2geo(pos); pos.mul(geoScale); device << n->getID() << "\t0\t1\t" << pos.x() << "\t" << pos.y() << "\n"; } // write "internal" nodes std::vector<std::string> avoid; std::set<std::string> reservedNodeIDs; const bool numericalIDs = oc.getBool("numerical-ids"); if (oc.isSet("reserved-ids")) { NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "node:", reservedNodeIDs); // backward compatibility NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "junction:", reservedNodeIDs); // selection format } if (numericalIDs) { avoid = nc.getAllNames(); std::vector<std::string> avoid2 = ec.getAllNames(); avoid.insert(avoid.end(), avoid2.begin(), avoid2.end()); avoid.insert(avoid.end(), reservedNodeIDs.begin(), reservedNodeIDs.end()); } IDSupplier idSupplier("", avoid); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { NBEdge* e = (*i).second; PositionVector geom = e->getGeometry(); if (geom.size() > 2) { // the import NIImporter_DlrNavteq checks for the presence of a // negated edge id to determine spread type. We may need to do some // shifting to make this consistent const bool hasOppositeID = ec.getOppositeByID(e->getID()) != nullptr; if (e->getLaneSpreadFunction() == LANESPREAD_RIGHT && !hasOppositeID) { // need to write center-line geometry instead try { geom.move2side(e->getTotalWidth() / 2); } catch (InvalidArgument& exception) { WRITE_WARNING("Could not reconstruct shape for edge:'" + e->getID() + "' (" + exception.what() + ")."); } } else if (e->getLaneSpreadFunction() == LANESPREAD_CENTER && hasOppositeID) { // need to write left-border geometry instead try { geom.move2side(-e->getTotalWidth() / 2); } catch (InvalidArgument& exception) { WRITE_WARNING("Could not reconstruct shape for edge:'" + e->getID() + "' (" + exception.what() + ")."); } } std::string internalNodeID = e->getID(); if (internalNodeID == UNDEFINED || (nc.retrieve(internalNodeID) != nullptr) || reservedNodeIDs.count(internalNodeID) > 0 ) { // need to invent a new name to avoid clashing with the id of a 'real' node or a reserved name if (numericalIDs) { internalNodeID = idSupplier.getNext(); } else { internalNodeID += "_geometry"; } } internalNodes[e] = internalNodeID; device << internalNodeID << "\t1\t" << geom.size() - 2; for (int ii = 1; ii < (int)geom.size() - 1; ++ii) { Position pos = geom[(int)ii]; gch.cartesian2geo(pos); pos.mul(geoScale); device << "\t" << pos.x() << "\t" << pos.y(); } device << "\n"; } } device.close(); }
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); } } }
bool NIVissimDisturbance::addToNode(NBNode* node, NBDistrictCont& dc, NBNodeCont& nc, NBEdgeCont& ec) { myNode = 0; NIVissimConnection* pc = NIVissimConnection::dictionary(myEdge.getEdgeID()); NIVissimConnection* bc = NIVissimConnection::dictionary(myDisturbance.getEdgeID()); if (pc == nullptr && bc == nullptr) { // This has not been tested completely, yet // Both competing abstract edges are normal edges // We have to find a crossing point, build a node here, // split both edges and add the connections NIVissimEdge* e1 = NIVissimEdge::dictionary(myEdge.getEdgeID()); NIVissimEdge* e2 = NIVissimEdge::dictionary(myDisturbance.getEdgeID()); WRITE_WARNING("Ugly split to prohibit '" + toString<int>(e1->getID()) + "' by '" + toString<int>(e2->getID()) + "'."); Position pos = e1->crossesEdgeAtPoint(e2); std::string id1 = toString<int>(e1->getID()) + "x" + toString<int>(e2->getID()); std::string id2 = toString<int>(e2->getID()) + "x" + toString<int>(e1->getID()); NBNode* node1 = nc.retrieve(id1); NBNode* node2 = nc.retrieve(id2); NBNode* node = nullptr; assert(node1 == 0 || node2 == 0); if (node1 == nullptr && node2 == nullptr) { refusedProhibits++; return false; /* node = new NBNode(id1, pos.x(), pos.y(), "priority"); if(!myNodeCont.insert(node)) { "nope, NIVissimDisturbance" << endl; throw 1; }*/ } else { node = node1 == nullptr ? node2 : node1; } ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e1->getID()), myEdge.getPosition()), node); ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e2->getID()), myDisturbance.getPosition()), node); // !!! in some cases, one of the edges is not being build because it's too short // !!! what to do in these cases? NBEdge* mayDriveFrom = ec.retrieve(toString<int>(e1->getID()) + "[0]"); NBEdge* mayDriveTo = ec.retrieve(toString<int>(e1->getID()) + "[1]"); NBEdge* mustStopFrom = ec.retrieve(toString<int>(e2->getID()) + "[0]"); NBEdge* mustStopTo = ec.retrieve(toString<int>(e2->getID()) + "[1]"); if (mayDriveFrom != nullptr && mayDriveTo != nullptr && mustStopFrom != nullptr && mustStopTo != nullptr) { node->addSortedLinkFoes( NBConnection(mayDriveFrom, mayDriveTo), NBConnection(mayDriveFrom, mayDriveTo)); } else { refusedProhibits++; return false; // !!! warning } // } } else if (pc != nullptr && bc == nullptr) { // The prohibited abstract edge is a connection, the other // is not; // The connection will be prohibitesd by all connections // outgoing from the "real" edge NBEdge* e = ec.retrievePossiblySplit(toString<int>(myDisturbance.getEdgeID()), myDisturbance.getPosition()); if (e == nullptr) { WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' by '" + toString<int>(myDisturbance.getEdgeID()) + "'. Have not found disturbance."); refusedProhibits++; return false; } if (e->getFromNode() == e->getToNode()) { WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' by '" + toString<int>(myDisturbance.getEdgeID()) + "'. Disturbance connects same node."); refusedProhibits++; // What to do with self-looping edges? return false; } // get the begin of the prohibited connection std::string id_pcoe = toString<int>(pc->getFromEdgeID()); std::string id_pcie = toString<int>(pc->getToEdgeID()); NBEdge* pcoe = ec.retrievePossiblySplit(id_pcoe, id_pcie, true); NBEdge* pcie = ec.retrievePossiblySplit(id_pcie, id_pcoe, false); // check whether it's ending node is the node the prohibited // edge end at if (pcoe != nullptr && pcie != nullptr && pcoe->getToNode() == e->getToNode()) { // if so, simply prohibit the connections NBNode* node = e->getToNode(); const EdgeVector& connected = e->getConnectedEdges(); for (EdgeVector::const_iterator i = connected.begin(); i != connected.end(); i++) { node->addSortedLinkFoes( NBConnection(e, *i), NBConnection(pcoe, pcie)); } } else { WRITE_WARNING("Would have to split edge '" + e->getID() + "' to build a prohibition"); refusedProhibits++; // quite ugly - why was it not build? return false; /* std::string nid1 = e->getID() + "[0]"; std::string nid2 = e->getID() + "[1]"; if(ec.splitAt(e, node)) { node->addSortedLinkFoes( NBConnection( ec.retrieve(nid1), ec.retrieve(nid2) ), getConnection(node, myEdge.getEdgeID()) ); } */ } } else if (bc != nullptr && pc == nullptr) { // The prohibiting abstract edge is a connection, the other // is not; // We have to split the other one and add the prohibition // description NBEdge* e = ec.retrievePossiblySplit(toString<int>(myEdge.getEdgeID()), myEdge.getPosition()); if (e == nullptr) { WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' - it was not built."); return false; } std::string nid1 = e->getID() + "[0]"; std::string nid2 = e->getID() + "[1]"; if (e->getFromNode() == e->getToNode()) { WRITE_WARNING("Could not prohibit '" + toString<int>(myEdge.getEdgeID()) + "' by '" + toString<int>(myDisturbance.getEdgeID()) + "'."); refusedProhibits++; // What to do with self-looping edges? return false; } // get the begin of the prohibiting connection std::string id_bcoe = toString<int>(bc->getFromEdgeID()); std::string id_bcie = toString<int>(bc->getToEdgeID()); NBEdge* bcoe = ec.retrievePossiblySplit(id_bcoe, id_bcie, true); NBEdge* bcie = ec.retrievePossiblySplit(id_bcie, id_bcoe, false); // check whether it's ending node is the node the prohibited // edge end at if (bcoe != nullptr && bcie != nullptr && bcoe->getToNode() == e->getToNode()) { // if so, simply prohibit the connections NBNode* node = e->getToNode(); const EdgeVector& connected = e->getConnectedEdges(); for (EdgeVector::const_iterator i = connected.begin(); i != connected.end(); i++) { node->addSortedLinkFoes( NBConnection(bcoe, bcie), NBConnection(e, *i)); } } else { WRITE_WARNING("Would have to split edge '" + e->getID() + "' to build a prohibition"); refusedProhibits++; return false; /* // quite ugly - why was it not build? if(ec.splitAt(e, node)) { node->addSortedLinkFoes( getConnection(node, myDisturbance.getEdgeID()), NBConnection( ec.retrieve(nid1), ec.retrieve(nid2) ) ); } */ } } else { // both the prohibiting and the prohibited abstract edges // are connections // We can retrieve the conected edges and add the desription NBConnection conn1 = getConnection(node, myDisturbance.getEdgeID()); NBConnection conn2 = getConnection(node, myEdge.getEdgeID()); if (!conn1.check(ec) || !conn2.check(ec)) { refusedProhibits++; return false; } node->addSortedLinkFoes(conn1, conn2); } return true; }
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 NIVissimDistrictConnection::dict_BuildDistricts(NBDistrictCont& dc, NBEdgeCont& ec, NBNodeCont& nc/*, NBDistribution &distc*/) { // add the sources and sinks // their normalised probability is computed within NBDistrict // to avoid SUMOReal code writing and more securty within the converter // go through the district table 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 NBDistrict* district = dc.retrieve(toString<int>((*k).first)); NBNode* districtNode = nc.retrieve("District" + district->getID()); assert(district != 0 && districtNode != 0); for (std::vector<int>::const_iterator l = connections.begin(); l != connections.end(); l++) { NIVissimDistrictConnection* c = dictionary(*l); // get the edge to connect the parking place to NBEdge* e = ec.retrieve(toString<int>(c->myEdgeID)); if (e == 0) { e = ec.retrievePossiblySplit(toString<int>(c->myEdgeID), c->myPosition); } if (e == 0) { WRITE_WARNING("Could not build district '" + toString<int>((*k).first) + "' - edge '" + toString<int>(c->myEdgeID) + "' is missing."); continue; } std::string id = "ParkingPlace" + toString<int>(*l); NBNode* parkingPlace = nc.retrieve(id); if (parkingPlace == 0) { SUMOReal pos = c->getPosition(); if (pos < e->getLength() - pos) { parkingPlace = e->getFromNode(); parkingPlace->invalidateIncomingConnections(); } else { parkingPlace = e->getToNode(); parkingPlace->invalidateOutgoingConnections(); } } assert( e->getToNode() == parkingPlace || e->getFromNode() == parkingPlace); // build the connection to the source if (e->getFromNode() == parkingPlace) { id = "VissimFromParkingplace" + toString<int>((*k).first) + "-" + toString<int>(c->myID); NBEdge* source = new NBEdge(id, districtNode, parkingPlace, "Connection", c->getMeanSpeed(/*distc*/) / (SUMOReal) 3.6, 3, -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET); if (!ec.insert(source)) { // !!! in den Konstruktor throw 1; // !!! } SUMOReal percNormed = c->myPercentages[(*k).first]; if (!district->addSource(source, percNormed)) { throw 1; } } // build the connection to the destination if (e->getToNode() == parkingPlace) { id = "VissimToParkingplace" + toString<int>((*k).first) + "-" + toString<int>(c->myID); NBEdge* destination = new NBEdge(id, parkingPlace, districtNode, "Connection", (SUMOReal) 100 / (SUMOReal) 3.6, 2, -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET); if (!ec.insert(destination)) { // !!! (in den Konstruktor) throw 1; // !!! } SUMOReal percNormed2 = c->myPercentages[(*k).first]; if (!district->addSink(destination, percNormed2)) { throw 1; // !!! } } /* if(e->getToNode()==districtNode) { SUMOReal percNormed = c->myPercentages[(*k).first]; district->addSink(e, percNormed); } if(e->getFromNode()==districtNode) { SUMOReal percNormed = c->myPercentages[(*k).first]; district->addSource(e, percNormed); } */ } /* // add them as sources and sinks to the current district for(std::vector<int>::const_iterator l=connections.begin(); l!=connections.end(); l++) { // get the current connections NIVissimDistrictConnection *c = dictionary(*l); // get the edge to connect the parking place to NBEdge *e = NBEdgeCont::retrieve(toString<int>(c->myEdgeID)); Position edgepos = c->geomPosition(); NBNode *edgeend = e->tryGetNodeAtPosition(c->myPosition, e->getLength()/4.0); if(edgeend==0) { // Edge splitting omitted on build district connections by now assert(false); } // build the district-node if not yet existing std::string id = "VissimParkingplace" + district->getID(); NBNode *districtNode = nc.retrieve(id); assert(districtNode!=0); if(e->getToNode()==edgeend) { // build the connection to the source id = std::string("VissimFromParkingplace") + toString<int>((*k).first) + "-" + toString<int>(c->myID); NBEdge *source = new NBEdge(id, id, districtNode, edgeend, "Connection", 100/3.6, 2, 100, 0, NBEdge::EDGEFUNCTION_SOURCE); NBEdgeCont::insert(source); // !!! (in den Konstruktor) SUMOReal percNormed = c->myPercentages[(*k).first]; district->addSource(source, percNormed); } else { // build the connection to the destination id = std::string("VissimToParkingplace") + toString<int>((*k).first) + "-" + toString<int>(c->myID); NBEdge *destination = new NBEdge(id, id, edgeend, districtNode, "Connection", 100/3.6, 2, 100, 0, NBEdge::EDGEFUNCTION_SINK); NBEdgeCont::insert(destination); // !!! (in den Konstruktor) // add both the source and the sink to the district SUMOReal percNormed = c->myPercentages[(*k).first]; district->addSink(destination, percNormed); } } */ } }
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); } } }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // NBTurningDirectionsComputer // --------------------------------------------------------------------------- void NBTurningDirectionsComputer::computeTurnDirections(NBNodeCont& nc) { for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { computeTurnDirectionsForNode(i->second); } }
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 NWWriter_XML::writeEdgesAndConnections(const OptionsCont& oc, NBNodeCont& nc, NBEdgeCont& ec) { const GeoConvHelper& gch = GeoConvHelper::getFinal(); bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo"); const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection(); OutputDevice& edevice = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".edg.xml"); edevice.writeXMLHeader("edges", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/edges_file.xsd\""); OutputDevice& cdevice = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".con.xml"); cdevice.writeXMLHeader("connections", NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo-sim.org/xsd/connections_file.xsd\""); bool noNames = !oc.getBool("output.street-names"); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { // write the edge itself to the edges-files NBEdge* e = (*i).second; edevice.openTag(SUMO_TAG_EDGE); edevice.writeAttr(SUMO_ATTR_ID, e->getID()); edevice.writeAttr(SUMO_ATTR_FROM, e->getFromNode()->getID()); edevice.writeAttr(SUMO_ATTR_TO, e->getToNode()->getID()); if (!noNames && e->getStreetName() != "") { edevice.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e->getStreetName())); } edevice.writeAttr(SUMO_ATTR_PRIORITY, e->getPriority()); // write the type if given if (e->getTypeID() != "") { edevice.writeAttr(SUMO_ATTR_TYPE, e->getTypeID()); } edevice.writeAttr(SUMO_ATTR_NUMLANES, e->getNumLanes()); if (!e->hasLaneSpecificSpeed()) { edevice.writeAttr(SUMO_ATTR_SPEED, e->getSpeed()); } // write non-default geometry if (!e->hasDefaultGeometry()) { PositionVector geom = e->getGeometry(); if (useGeo) { for (int i = 0; i < (int) geom.size(); i++) { gch.cartesian2geo(geom[i]); } } if (geoAccuracy) { edevice.setPrecision(GEO_OUTPUT_ACCURACY); } edevice.writeAttr(SUMO_ATTR_SHAPE, geom); if (geoAccuracy) { edevice.setPrecision(); } } // write the spread type if not default ("right") if (e->getLaneSpreadFunction() != LANESPREAD_RIGHT) { edevice.writeAttr(SUMO_ATTR_SPREADTYPE, toString(e->getLaneSpreadFunction())); } // write the length if it was specified if (e->hasLoadedLength()) { edevice.writeAttr(SUMO_ATTR_LENGTH, e->getLoadedLength()); } // some attributes can be set by edge default or per lane. Write as default if possible (efficiency) if (e->getLaneWidth() != NBEdge::UNSPECIFIED_WIDTH && !e->hasLaneSpecificWidth()) { edevice.writeAttr(SUMO_ATTR_WIDTH, e->getLaneWidth()); } if (e->getOffset() != NBEdge::UNSPECIFIED_OFFSET && !e->hasLaneSpecificOffset()) { edevice.writeAttr(SUMO_ATTR_OFFSET, e->getOffset()); } if (!e->needsLaneSpecificOutput()) { edevice.closeTag(); } else { for (unsigned int i = 0; i < e->getLanes().size(); ++i) { const NBEdge::Lane& lane = e->getLanes()[i]; edevice.openTag(SUMO_TAG_LANE); edevice.writeAttr(SUMO_ATTR_INDEX, i); // write allowed lanes NWWriter_SUMO::writePermissions(edevice, lane.permissions); NWWriter_SUMO::writePreferences(edevice, lane.preferred); // write other attributes if (lane.width != NBEdge::UNSPECIFIED_WIDTH && e->hasLaneSpecificWidth()) { edevice.writeAttr(SUMO_ATTR_WIDTH, lane.width); } if (lane.offset != NBEdge::UNSPECIFIED_OFFSET && e->hasLaneSpecificOffset()) { edevice.writeAttr(SUMO_ATTR_OFFSET, lane.offset); } if (e->hasLaneSpecificSpeed()) { edevice.writeAttr(SUMO_ATTR_SPEED, lane.speed); } edevice.closeTag(); } edevice.closeTag(); } // write this edge's connections to the connections-files e->sortOutgoingConnectionsByIndex(); const std::vector<NBEdge::Connection> connections = e->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) { NWWriter_SUMO::writeConnection(cdevice, *e, *c, false, NWWriter_SUMO::PLAIN); } if (connections.size() > 0) { cdevice << "\n"; } } // write loaded prohibitions to the connections-file for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NWWriter_SUMO::writeProhibitions(cdevice, i->second->getProhibitions()); } edevice.close(); cdevice.close(); }