void MELoop::buildSegmentsFor(const MSEdge& e, const OptionsCont& oc) { const SUMOReal length = e.getLength(); int no = numSegmentsFor(length, oc.getFloat("meso-edgelength")); const SUMOReal slength = length / (SUMOReal)no; const SUMOReal lengthGeometryFactor = e.getLanes()[0]->getLengthGeometryFactor(); MESegment* newSegment = 0; MESegment* nextSegment = 0; bool multiQueue = oc.getBool("meso-multi-queue"); bool junctionControl = oc.getBool("meso-junction-control"); for (int s = no - 1; s >= 0; s--) { std::string id = e.getID() + ":" + toString(s); newSegment = new MESegment(id, e, nextSegment, slength, e.getLanes()[0]->getSpeedLimit(), s, string2time(oc.getString("meso-tauff")), string2time(oc.getString("meso-taufj")), string2time(oc.getString("meso-taujf")), string2time(oc.getString("meso-taujj")), oc.getFloat("meso-jam-threshold"), multiQueue, junctionControl, lengthGeometryFactor); multiQueue = false; junctionControl = false; nextSegment = newSegment; } while (e.getNumericalID() >= static_cast<int>(myEdges2FirstSegments.size())) { myEdges2FirstSegments.push_back(0); } myEdges2FirstSegments[e.getNumericalID()] = newSegment; }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // NBRampsComputer // --------------------------------------------------------------------------- void NBRampsComputer::computeRamps(NBNetBuilder& nb, OptionsCont& oc) { SUMOReal minHighwaySpeed = oc.getFloat("ramps.min-highway-speed"); SUMOReal maxRampSpeed = oc.getFloat("ramps.max-ramp-speed"); SUMOReal rampLength = oc.getFloat("ramps.ramp-length"); bool dontSplit = oc.getBool("ramps.no-split"); std::set<NBEdge*> incremented; // check whether on-off ramps shall be guessed if (oc.getBool("ramps.guess")) { NBNodeCont& nc = nb.getNodeCont(); NBEdgeCont& ec = nb.getEdgeCont(); NBDistrictCont& dc = nb.getDistrictCont(); std::set<NBNode*> potOnRamps; std::set<NBNode*> potOffRamps; for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* cur = (*i).second; if (mayNeedOnRamp(cur, minHighwaySpeed, maxRampSpeed)) { potOnRamps.insert(cur); } if (mayNeedOffRamp(cur, minHighwaySpeed, maxRampSpeed)) { potOffRamps.insert(cur); } } for (std::set<NBNode*>::const_iterator i = potOnRamps.begin(); i != potOnRamps.end(); ++i) { buildOnRamp(*i, nc, ec, dc, rampLength, dontSplit, incremented); } for (std::set<NBNode*>::const_iterator i = potOffRamps.begin(); i != potOffRamps.end(); ++i) { buildOffRamp(*i, nc, ec, dc, rampLength, dontSplit, incremented); } } // check whether on-off ramps shall be guessed if (oc.isSet("ramps.set")) { std::vector<std::string> edges = oc.getStringVector("ramps.set"); NBNodeCont& nc = nb.getNodeCont(); NBEdgeCont& ec = nb.getEdgeCont(); NBDistrictCont& dc = nb.getDistrictCont(); for (std::vector<std::string>::iterator i = edges.begin(); i != edges.end(); ++i) { NBEdge* e = ec.retrieve(*i); if (e == 0) { WRITE_WARNING("Can not build on ramp on edge '" + *i + "' - the edge is not known."); continue; } NBNode* from = e->getFromNode(); if (from->getIncomingEdges().size() == 2 && from->getOutgoingEdges().size() == 1) { buildOnRamp(from, nc, ec, dc, rampLength, dontSplit, incremented); } // load edge again to check offramps e = ec.retrieve(*i); if (e == 0) { WRITE_WARNING("Can not build off ramp on edge '" + *i + "' - the edge is not known."); continue; } NBNode* to = e->getToNode(); if (to->getIncomingEdges().size() == 1 && to->getOutgoingEdges().size() == 2) { buildOffRamp(to, nc, ec, dc, rampLength, dontSplit, incremented); } } } }
// =========================================================================== // method definitions // =========================================================================== PCTypeMap::PCTypeMap(const OptionsCont& oc) { myDefaultType.id = oc.getString("type"); myDefaultType.color = RGBColor::parseColor(oc.getString("color")); myDefaultType.layer = oc.getFloat("layer"); myDefaultType.discard = oc.getBool("discard"); myDefaultType.allowFill = oc.getBool("fill"); myDefaultType.prefix = oc.getString("prefix"); }
void NBNetBuilder::applyOptions(OptionsCont& oc) { // apply options to type control myTypeCont.setDefaults(oc.getInt("default.lanenumber"), oc.getFloat("default.lanewidth"), oc.getFloat("default.speed"), oc.getInt("default.priority")); // apply options to edge control myEdgeCont.applyOptions(oc); // apply options to traffic light logics control myTLLCont.applyOptions(oc); }
void ODMatrix::loadMatrix(OptionsCont& oc) { std::vector<std::string> files = oc.getStringVector("od-matrix-files"); for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); ++i) { LineReader lr(*i); if (!lr.good()) { throw ProcessError("Could not open '" + (*i) + "'."); } std::string type = lr.readLine(); // get the type only if (type.find(';') != std::string::npos) { type = type.substr(0, type.find(';')); } // parse type-dependant if (type.length() > 1 && type[1] == 'V') { // process ptv's 'V'-matrices if (type.find('N') != std::string::npos) { throw ProcessError("'" + *i + "' does not contain the needed information about the time described."); } readV(lr, oc.getFloat("scale"), oc.getString("vtype"), type.find('M') != std::string::npos); } else if (type.length() > 1 && type[1] == 'O') { // process ptv's 'O'-matrices if (type.find('N') != std::string::npos) { throw ProcessError("'" + *i + "' does not contain the needed information about the time described."); } readO(lr, oc.getFloat("scale"), oc.getString("vtype"), type.find('M') != std::string::npos); } else { throw ProcessError("'" + *i + "' uses an unknown matrix type '" + type + "'."); } } std::vector<std::string> amitranFiles = oc.getStringVector("od-amitran-files"); for (std::vector<std::string>::iterator i = amitranFiles.begin(); i != amitranFiles.end(); ++i) { if (!FileHelpers::isReadable(*i)) { throw ProcessError("Could not access matrix file '" + *i + "' to load."); } PROGRESS_BEGIN_MESSAGE("Loading matrix in Amitran format from '" + *i + "'"); ODAmitranHandler handler(*this, *i); if (!XMLSubSys::runParser(handler, *i)) { PROGRESS_FAILED_MESSAGE(); } else { PROGRESS_DONE_MESSAGE(); } } }
void MSFrame::setMSGlobals(OptionsCont& oc) { // pre-initialise the network // set whether empty edges shall be printed on dump MSGlobals::gOmitEmptyEdgesOnDump = !oc.getBool("netstate-dump.empty-edges"); #ifdef HAVE_INTERNAL_LANES // set whether internal lanes shall be used MSGlobals::gUsingInternalLanes = !oc.getBool("no-internal-links"); MSGlobals::gIgnoreJunctionBlocker = string2time(oc.getString("ignore-junction-blocker")) < 0 ? std::numeric_limits<SUMOTime>::max() : string2time(oc.getString("ignore-junction-blocker")); #else MSGlobals::gUsingInternalLanes = false; MSGlobals::gIgnoreJunctionBlocker = 0; #endif // set the grid lock time MSGlobals::gTimeToGridlock = string2time(oc.getString("time-to-teleport")) < 0 ? 0 : string2time(oc.getString("time-to-teleport")); MSGlobals::gTimeToGridlockHighways = string2time(oc.getString("time-to-teleport.highways")) < 0 ? 0 : string2time(oc.getString("time-to-teleport.highways")); MSGlobals::gCheck4Accidents = !oc.getBool("ignore-accidents"); MSGlobals::gCheckRoutes = !oc.getBool("ignore-route-errors"); MSGlobals::gLaneChangeDuration = string2time(oc.getString("lanechange.duration")); MSGlobals::gLateralResolution = oc.getFloat("lateral-resolution"); MSGlobals::gStateLoaded = oc.isSet("load-state"); MSGlobals::gUseMesoSim = oc.getBool("mesosim"); MSGlobals::gMesoLimitedJunctionControl = oc.getBool("meso-junction-control.limited"); MSGlobals::gMesoOvertaking = oc.getBool("meso-overtaking"); MSGlobals::gMesoTLSPenalty = oc.getFloat("meso-tls-penalty"); if (MSGlobals::gUseMesoSim) { MSGlobals::gUsingInternalLanes = false; } MSGlobals::gWaitingTimeMemory = string2time(oc.getString("waiting-time-memory")); MSAbstractLaneChangeModel::initGlobalOptions(oc); MSLane::initCollisionOptions(oc); DELTA_T = string2time(oc.getString("step-length")); #ifdef _DEBUG if (oc.isSet("movereminder-output")) { MSBaseVehicle::initMoveReminderOutput(oc); } #endif }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods (interface in this case) // --------------------------------------------------------------------------- void NIImporter_VISUM::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether the option is set (properly) if (!oc.isSet("visum-file")) { return; } // build the handler NIImporter_VISUM loader(nb, oc.getString("visum-file"), NBCapacity2Lanes(oc.getFloat("lanes-from-capacity.norm")), oc.getBool("visum.use-type-priority")); loader.load(); }
bool GeoConvHelper::init(OptionsCont& oc) { std::string proj = "!"; // the default double scale = oc.getFloat("proj.scale"); double rot = oc.getFloat("proj.rotate"); Position offset = Position(oc.getFloat("offset.x"), oc.getFloat("offset.y")); bool inverse = oc.exists("proj.inverse") && oc.getBool("proj.inverse"); bool flatten = oc.exists("flatten") && oc.getBool("flatten"); if (oc.getBool("simple-projection")) { proj = "-"; } #ifdef PROJ_API_FILE if (oc.getBool("proj.inverse") && oc.getString("proj") == "!") { WRITE_ERROR("Inverse projection works only with explicit proj parameters."); return false; } unsigned numProjections = oc.getBool("simple-projection") + oc.getBool("proj.utm") + oc.getBool("proj.dhdn") + oc.getBool("proj.dhdnutm") + (oc.getString("proj").length() > 1); if (numProjections > 1) { WRITE_ERROR("The projection method needs to be uniquely defined."); return false; } if (oc.getBool("proj.utm")) { proj = "UTM"; } else if (oc.getBool("proj.dhdn")) { proj = "DHDN"; } else if (oc.getBool("proj.dhdnutm")) { proj = "DHDN_UTM"; } else if (!oc.isDefault("proj")) { proj = oc.getString("proj"); } #endif myProcessing = GeoConvHelper(proj, offset, Boundary(), Boundary(), scale, rot, inverse, flatten); myFinal = myProcessing; return true; }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_MATSim::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether a matsim-file shall be generated if (!oc.isSet("matsim-output")) { return; } OutputDevice& device = OutputDevice::getDevice(oc.getString("matsim-output")); device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; device << "<!DOCTYPE network SYSTEM \"http://www.matsim.org/files/dtd/network_v1.dtd\">\n\n"; device << "<network name=\"NAME\">\n"; // !!! name // write nodes device << " <nodes>\n"; NBNodeCont& nc = nb.getNodeCont(); for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { device << " <node id=\"" << (*i).first << "\" x=\"" << (*i).second->getPosition().x() << "\" y=\"" << (*i).second->getPosition().y() << "\"/>\n"; } device << " </nodes>\n"; // write edges device << " <links capperiod=\"01:00:00\">\n"; NBEdgeCont& ec = nb.getEdgeCont(); for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { device << " <link id=\"" << (*i).first << "\" from=\"" << (*i).second->getFromNode()->getID() << "\" to=\"" << (*i).second->getToNode()->getID() << "\" length=\"" << (*i).second->getLoadedLength() << "\" capacity=\"" << (oc.getFloat("lanes-from-capacity.norm") * (*i).second->getNumLanes()) << "\" freespeed=\"" << (*i).second->getSpeed() << "\" permlanes=\"" << (*i).second->getNumLanes() << "\"/>\n"; } device << " </links>\n"; // device << "</network>\n"; // !!! name device.close(); }
void NBEdgeCont::applyOptions(OptionsCont& oc) { myAmLeftHanded = oc.getBool("lefthand"); // set edges dismiss/accept options myEdgesMinSpeed = oc.isSet("keep-edges.min-speed") ? oc.getFloat("keep-edges.min-speed") : -1; myRemoveEdgesAfterJoining = oc.exists("keep-edges.postload") && oc.getBool("keep-edges.postload"); if (oc.isSet("keep-edges.explicit")) { const std::vector<std::string> edges = oc.getStringVector("keep-edges.explicit"); myEdges2Keep.insert(edges.begin(), edges.end()); } if (oc.isSet("remove-edges.explicit")) { const std::vector<std::string> edges = oc.getStringVector("remove-edges.explicit"); myEdges2Remove.insert(edges.begin(), edges.end()); } if (oc.exists("keep-edges.by-vclass") && oc.isSet("keep-edges.by-vclass")) { const std::vector<std::string> classes = oc.getStringVector("keep-edges.by-vclass"); for (std::vector<std::string>::const_iterator i = classes.begin(); i != classes.end(); ++i) { myVehicleClasses2Keep |= getVehicleClassID(*i); } } if (oc.exists("remove-edges.by-vclass") && oc.isSet("remove-edges.by-vclass")) { const std::vector<std::string> classes = oc.getStringVector("remove-edges.by-vclass"); for (std::vector<std::string>::const_iterator i = classes.begin(); i != classes.end(); ++i) { myVehicleClasses2Remove |= getVehicleClassID(*i); } } if (oc.exists("keep-edges.by-type") && oc.isSet("keep-edges.by-type")) { const std::vector<std::string> types = oc.getStringVector("keep-edges.by-type"); myTypes2Keep.insert(types.begin(), types.end()); } if (oc.exists("remove-edges.by-type") && oc.isSet("remove-edges.by-type")) { const std::vector<std::string> types = oc.getStringVector("remove-edges.by-type"); myTypes2Remove.insert(types.begin(), types.end()); } if (oc.isSet("keep-edges.in-boundary") || oc.isSet("keep-edges.in-geo-boundary")) { std::vector<std::string> polyS = oc.getStringVector(oc.isSet("keep-edges.in-boundary") ? "keep-edges.in-boundary" : "keep-edges.in-geo-boundary"); // !!! throw something if length<4 || length%2!=0? std::vector<SUMOReal> poly; for (std::vector<std::string>::iterator i = polyS.begin(); i != polyS.end(); ++i) { poly.push_back(TplConvert::_2SUMOReal((*i).c_str())); // !!! may throw something anyhow... } if (poly.size() < 4) { throw ProcessError("Invalid boundary: need at least 2 coordinates"); } else if (poly.size() % 2 != 0) { throw ProcessError("Invalid boundary: malformed coordinate"); } else if (poly.size() == 4) { // prunning boundary (box) myPrunningBoundary.push_back(Position(poly[0], poly[1])); myPrunningBoundary.push_back(Position(poly[2], poly[1])); myPrunningBoundary.push_back(Position(poly[2], poly[3])); myPrunningBoundary.push_back(Position(poly[0], poly[3])); } else { for (std::vector<SUMOReal>::iterator j = poly.begin(); j != poly.end();) { SUMOReal x = *j++; SUMOReal y = *j++; myPrunningBoundary.push_back(Position(x, y)); } } if (oc.isSet("keep-edges.in-geo-boundary")) { NBNetBuilder::transformCoordinates(myPrunningBoundary, false); } } }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_OpenDrive::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether an opendrive-file shall be generated if (!oc.isSet("opendrive-output")) { return; } const NBNodeCont& nc = nb.getNodeCont(); const NBEdgeCont& ec = nb.getEdgeCont(); const bool origNames = oc.getBool("output.original-names"); const SUMOReal straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold")); // some internal mapping containers int nodeID = 1; int edgeID = nc.size() * 10; // distinct from node ids StringBijection<int> edgeMap; StringBijection<int> nodeMap; // OutputDevice& device = OutputDevice::getDevice(oc.getString("opendrive-output")); device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; device.openTag("OpenDRIVE"); time_t now = time(0); std::string dstr(ctime(&now)); const Boundary& b = GeoConvHelper::getFinal().getConvBoundary(); // write header device.openTag("header"); device.writeAttr("revMajor", "1"); device.writeAttr("revMinor", "4"); device.writeAttr("name", ""); device.writeAttr("version", "1.00"); device.writeAttr("date", dstr.substr(0, dstr.length() - 1)); device.writeAttr("north", b.ymax()); device.writeAttr("south", b.ymin()); device.writeAttr("east", b.xmax()); device.writeAttr("west", b.xmin()); /* @note obsolete in 1.4 device.writeAttr("maxRoad", ec.size()); device.writeAttr("maxJunc", nc.size()); device.writeAttr("maxPrg", 0); */ device.closeTag(); // write normal edges (road) for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { const NBEdge* e = (*i).second; // buffer output because some fields are computed out of order OutputDevice_String elevationOSS(false, 3); elevationOSS.setPrecision(8); OutputDevice_String planViewOSS(false, 2); planViewOSS.setPrecision(8); SUMOReal length = 0; planViewOSS.openTag("planView"); planViewOSS.setPrecision(8); // geometry hdg requires higher precision // for the shape we need to use the leftmost border of the leftmost lane const std::vector<NBEdge::Lane>& lanes = e->getLanes(); PositionVector ls = getLeftLaneBorder(e); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << "write planview for edge " << e->getID() << "\n"; } #endif if (ls.size() == 2 || e->getPermissions() == SVC_PEDESTRIAN) { // foot paths may contain sharp angles length = writeGeomLines(ls, planViewOSS, elevationOSS); } else { bool ok = writeGeomSmooth(ls, e->getSpeed(), planViewOSS, elevationOSS, straightThresh, length); if (!ok) { WRITE_WARNING("Could not compute smooth shape for edge '" + e->getID() + "'."); } } planViewOSS.closeTag(); device.openTag("road"); device.writeAttr("name", StringUtils::escapeXML(e->getStreetName())); device.setPrecision(8); // length requires higher precision device.writeAttr("length", MAX2(POSITION_EPS, length)); device.setPrecision(OUTPUT_ACCURACY); device.writeAttr("id", getID(e->getID(), edgeMap, edgeID)); device.writeAttr("junction", -1); const bool hasSucc = e->getConnections().size() > 0; const bool hasPred = e->getIncomingEdges().size() > 0; if (hasPred || hasSucc) { device.openTag("link"); if (hasPred) { device.openTag("predecessor"); device.writeAttr("elementType", "junction"); device.writeAttr("elementId", getID(e->getFromNode()->getID(), nodeMap, nodeID)); device.closeTag(); } if (hasSucc) { device.openTag("successor"); device.writeAttr("elementType", "junction"); device.writeAttr("elementId", getID(e->getToNode()->getID(), nodeMap, nodeID)); device.closeTag(); } device.closeTag(); } device.openTag("type").writeAttr("s", 0).writeAttr("type", "town").closeTag(); device << planViewOSS.getString(); writeElevationProfile(ls, device, elevationOSS); device << " <lateralProfile/>\n"; device << " <lanes>\n"; device << " <laneSection s=\"0\">\n"; writeEmptyCenterLane(device, "solid", 0.13); device << " <right>\n"; for (int j = e->getNumLanes(); --j >= 0;) { device << " <lane id=\"-" << e->getNumLanes() - j << "\" type=\"" << getLaneType(e->getPermissions(j)) << "\" level=\"true\">\n"; device << " <link/>\n"; // this could be used for geometry-link junctions without u-turn, // predecessor and sucessors would be lane indices, // road predecessor / succesfors would be of type 'road' rather than // 'junction' //device << " <predecessor id=\"-1\"/>\n"; //device << " <successor id=\"-1\"/>\n"; //device << " </link>\n"; device << " <width sOffset=\"0\" a=\"" << e->getLaneWidth(j) << "\" b=\"0\" c=\"0\" d=\"0\"/>\n"; std::string markType = "broken"; if (j == 0) { markType = "solid"; } device << " <roadMark sOffset=\"0\" type=\"" << markType << "\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n"; device << " <speed sOffset=\"0\" max=\"" << lanes[j].speed << "\"/>\n"; device << " </lane>\n"; } device << " </right>\n"; device << " </laneSection>\n"; device << " </lanes>\n"; device << " <objects/>\n"; device << " <signals/>\n"; if (origNames) { device << " <userData code=\"sumoId\" value=\"" << e->getID() << "\"/>\n"; } device.closeTag(); checkLaneGeometries(e); } device.lf(); // write junction-internal edges (road). In OpenDRIVE these are called 'paths' or 'connecting roads' for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const std::vector<NBEdge*>& incoming = (*i).second->getIncomingEdges(); for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { const NBEdge* inEdge = *j; const std::vector<NBEdge::Connection>& elv = inEdge->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { const NBEdge::Connection& c = *k; const NBEdge* outEdge = c.toEdge; if (outEdge == 0) { continue; } const SUMOReal width = c.toEdge->getLaneWidth(c.toLane); const PositionVector begShape = getLeftLaneBorder(inEdge, c.fromLane); const PositionVector endShape = getLeftLaneBorder(outEdge, c.toLane); //std::cout << "computing reference line for internal lane " << c.getInternalLaneID() << " begLane=" << inEdge->getLaneShape(c.fromLane) << " endLane=" << outEdge->getLaneShape(c.toLane) << "\n"; SUMOReal length; PositionVector fallBackShape; fallBackShape.push_back(begShape.back()); fallBackShape.push_back(endShape.front()); const bool turnaround = inEdge->isTurningDirectionAt(outEdge); bool ok = true; PositionVector init = NBNode::bezierControlPoints(begShape, endShape, turnaround, 25, 25, ok, 0, straightThresh); if (init.size() == 0) { length = fallBackShape.length2D(); // problem with turnarounds is known, method currently returns 'ok' (#2539) if (!ok) { WRITE_WARNING("Could not compute smooth shape from lane '" + inEdge->getLaneID(c.fromLane) + "' to lane '" + outEdge->getLaneID(c.toLane) + "'. Use option 'junctions.scurve-stretch' or increase radius of junction '" + inEdge->getToNode()->getID() + "' to fix this."); } } else { length = bezier(init, 12).length2D(); } device.openTag("road"); device.writeAttr("name", c.getInternalLaneID()); device.setPrecision(8); // length requires higher precision device.writeAttr("length", MAX2(POSITION_EPS, length)); device.setPrecision(OUTPUT_ACCURACY); device.writeAttr("id", getID(c.getInternalLaneID(), edgeMap, edgeID)); device.writeAttr("junction", getID(n->getID(), nodeMap, nodeID)); device.openTag("link"); device.openTag("predecessor"); device.writeAttr("elementType", "road"); device.writeAttr("elementId", getID(inEdge->getID(), edgeMap, edgeID)); device.writeAttr("contactPoint", "end"); device.closeTag(); device.openTag("successor"); device.writeAttr("elementType", "road"); device.writeAttr("elementId", getID(outEdge->getID(), edgeMap, edgeID)); device.writeAttr("contactPoint", "start"); device.closeTag(); device.closeTag(); device.openTag("type").writeAttr("s", 0).writeAttr("type", "town").closeTag(); device.openTag("planView"); device.setPrecision(8); // geometry hdg requires higher precision OutputDevice_String elevationOSS(false, 3); #ifdef DEBUG_SMOOTH_GEOM if (DEBUGCOND) { std::cout << "write planview for internal edge " << c.getInternalLaneID() << " init=" << init << " fallback=" << fallBackShape << "\n"; } #endif if (init.size() == 0) { writeGeomLines(fallBackShape, device, elevationOSS); } else { writeGeomPP3(device, elevationOSS, init, length); } device.setPrecision(OUTPUT_ACCURACY); device.closeTag(); writeElevationProfile(fallBackShape, device, elevationOSS); device << " <lateralProfile/>\n"; device << " <lanes>\n"; device << " <laneSection s=\"0\">\n"; writeEmptyCenterLane(device, "none", 0); device << " <right>\n"; device << " <lane id=\"-1\" type=\"" << getLaneType(outEdge->getPermissions(c.toLane)) << "\" level=\"true\">\n"; device << " <link>\n"; device << " <predecessor id=\"-" << inEdge->getNumLanes() - c.fromLane << "\"/>\n"; device << " <successor id=\"-" << outEdge->getNumLanes() - c.toLane << "\"/>\n"; device << " </link>\n"; device << " <width sOffset=\"0\" a=\"" << width << "\" b=\"0\" c=\"0\" d=\"0\"/>\n"; device << " <roadMark sOffset=\"0\" type=\"none\" weight=\"standard\" color=\"standard\" width=\"0.13\"/>\n"; device << " </lane>\n"; device << " </right>\n"; device << " </laneSection>\n"; device << " </lanes>\n"; device << " <objects/>\n"; device << " <signals/>\n"; device.closeTag(); } } } // write junctions (junction) for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const std::vector<NBEdge*>& incoming = n->getIncomingEdges(); // check if any connections must be written int numConnections = 0; for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { numConnections += (int)((*j)->getConnections().size()); } if (numConnections == 0) { continue; } device << " <junction name=\"" << n->getID() << "\" id=\"" << getID(n->getID(), nodeMap, nodeID) << "\">\n"; int index = 0; for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { const NBEdge* inEdge = *j; const std::vector<NBEdge::Connection>& elv = inEdge->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { const NBEdge::Connection& c = *k; const NBEdge* outEdge = c.toEdge; if (outEdge == 0) { continue; } device << " <connection id=\"" << index << "\" incomingRoad=\"" << getID(inEdge->getID(), edgeMap, edgeID) << "\" connectingRoad=\"" << getID(c.getInternalLaneID(), edgeMap, edgeID) << "\" contactPoint=\"start\">\n"; device << " <laneLink from=\"-" << inEdge->getNumLanes() - c.fromLane << "\" to=\"-1" // every connection has its own edge << "\"/>\n"; device << " </connection>\n"; ++index; } } device << " </junction>\n"; } device.closeTag(); device.close(); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NWWriter_OpenDrive::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether an opendrive-file shall be generated if (!oc.isSet("opendrive-output")) { return; } const NBNodeCont& nc = nb.getNodeCont(); const NBEdgeCont& ec = nb.getEdgeCont(); const bool origNames = oc.getBool("output.original-names"); const bool lefthand = oc.getBool("lefthand"); const double straightThresh = DEG2RAD(oc.getFloat("opendrive-output.straight-threshold")); // some internal mapping containers int nodeID = 1; int edgeID = nc.size() * 10; // distinct from node ids StringBijection<int> edgeMap; StringBijection<int> nodeMap; // OutputDevice& device = OutputDevice::getDevice(oc.getString("opendrive-output")); device << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; device.openTag("OpenDRIVE"); time_t now = time(0); std::string dstr(ctime(&now)); const Boundary& b = GeoConvHelper::getFinal().getConvBoundary(); // write header device.openTag("header"); device.writeAttr("revMajor", "1"); device.writeAttr("revMinor", "4"); device.writeAttr("name", ""); device.writeAttr("version", "1.00"); device.writeAttr("date", dstr.substr(0, dstr.length() - 1)); device.writeAttr("north", b.ymax()); device.writeAttr("south", b.ymin()); device.writeAttr("east", b.xmax()); device.writeAttr("west", b.xmin()); /* @note obsolete in 1.4 device.writeAttr("maxRoad", ec.size()); device.writeAttr("maxJunc", nc.size()); device.writeAttr("maxPrg", 0); */ device.closeTag(); // write optional geo reference const GeoConvHelper& gch = GeoConvHelper::getFinal(); if (gch.usingGeoProjection()) { if (gch.getOffsetBase() == Position(0,0)) { device.openTag("geoReference"); device.writePreformattedTag(" <![CDATA[\n " + gch.getProjString() + "\n]]>\n"); device.closeTag(); } else { WRITE_WARNING("Could not write OpenDRIVE geoReference. Only unshifted Coordinate systems are supported (offset=" + toString(gch.getOffsetBase()) + ")"); } } // write normal edges (road) for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { const NBEdge* e = (*i).second; const int fromNodeID = e->getIncomingEdges().size() > 0 ? getID(e->getFromNode()->getID(), nodeMap, nodeID) : INVALID_ID; const int toNodeID = e->getConnections().size() > 0 ? getID(e->getToNode()->getID(), nodeMap, nodeID) : INVALID_ID; writeNormalEdge(device, e, getID(e->getID(), edgeMap, edgeID), fromNodeID, toNodeID, origNames, straightThresh); } device.lf(); // write junction-internal edges (road). In OpenDRIVE these are called 'paths' or 'connecting roads' OutputDevice_String junctionOSS(false, 3); for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; int connectionID = 0; // unique within a junction const int nID = getID(n->getID(), nodeMap, nodeID); if (n->numNormalConnections() > 0) { junctionOSS << " <junction name=\"" << n->getID() << "\" id=\"" << nID << "\">\n"; } std::vector<NBEdge*> incoming = (*i).second->getIncomingEdges(); if (lefthand) { std::reverse(incoming.begin(), incoming.end()); } for (NBEdge* inEdge : incoming) { std::string centerMark = "none"; const int inEdgeID = getID(inEdge->getID(), edgeMap, edgeID); // group parallel edges const NBEdge* outEdge = 0; bool isOuterEdge = true; // determine where a solid outer border should be drawn int lastFromLane = -1; std::vector<NBEdge::Connection> parallel; std::vector<NBEdge::Connection> connections = inEdge->getConnections(); if (lefthand) { std::reverse(connections.begin(), connections.end()); } for (const NBEdge::Connection& c : connections) { assert(c.toEdge != 0); if (outEdge != c.toEdge || c.fromLane == lastFromLane) { if (outEdge != 0) { if (isOuterEdge) { addPedestrianConnection(inEdge, outEdge, parallel); } connectionID = writeInternalEdge(device, junctionOSS, inEdge, nID, getID(parallel.back().getInternalLaneID(), edgeMap, edgeID), inEdgeID, getID(outEdge->getID(), edgeMap, edgeID), connectionID, parallel, isOuterEdge, straightThresh, centerMark); parallel.clear(); isOuterEdge = false; } outEdge = c.toEdge; } lastFromLane = c.fromLane; parallel.push_back(c); } if (isOuterEdge) { addPedestrianConnection(inEdge, outEdge, parallel); } if (!parallel.empty()) { if (!lefthand && (n->geometryLike() || inEdge->isTurningDirectionAt(outEdge))) { centerMark = "solid"; } connectionID = writeInternalEdge(device, junctionOSS, inEdge, nID, getID(parallel.back().getInternalLaneID(), edgeMap, edgeID), inEdgeID, getID(outEdge->getID(), edgeMap, edgeID), connectionID, parallel, isOuterEdge, straightThresh, centerMark); parallel.clear(); } } if (n->numNormalConnections() > 0) { junctionOSS << " </junction>\n"; } } device.lf(); // write junctions (junction) device << junctionOSS.getString(); for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { NBNode* n = (*i).second; const std::vector<NBEdge*>& incoming = n->getIncomingEdges(); // check if any connections must be written int numConnections = 0; for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { numConnections += (int)((*j)->getConnections().size()); } if (numConnections == 0) { continue; } for (std::vector<NBEdge*>::const_iterator j = incoming.begin(); j != incoming.end(); ++j) { const NBEdge* inEdge = *j; const std::vector<NBEdge::Connection>& elv = inEdge->getConnections(); for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { const NBEdge::Connection& c = *k; const NBEdge* outEdge = c.toEdge; if (outEdge == 0) { continue; } } } } device.closeTag(); device.close(); }
// =========================================================================== // method definitions // =========================================================================== // --------------------------------------------------------------------------- // static methods // --------------------------------------------------------------------------- void NIImporter_MATSim::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) { // check whether the option is set (properly) if (!oc.isSet("matsim-files")) { return; } /* Parse file(s) * Each file is parsed twice: first for nodes, second for edges. */ std::vector<std::string> files = oc.getStringVector("matsim-files"); // load nodes, first NodesHandler nodesHandler(nb.getNodeCont()); for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { // nodes if (!FileHelpers::isReadable(*file)) { WRITE_ERROR("Could not open matsim-file '" + *file + "'."); return; } nodesHandler.setFileName(*file); PROGRESS_BEGIN_MESSAGE("Parsing nodes from matsim-file '" + *file + "'"); if (!XMLSubSys::runParser(nodesHandler, *file)) { return; } PROGRESS_DONE_MESSAGE(); } // load edges, then EdgesHandler edgesHandler(nb.getNodeCont(), nb.getEdgeCont(), oc.getBool("matsim.keep-length"), oc.getBool("matsim.lanes-from-capacity"), NBCapacity2Lanes(oc.getFloat("lanes-from-capacity.norm"))); for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) { // edges edgesHandler.setFileName(*file); PROGRESS_BEGIN_MESSAGE("Parsing edges from matsim-file '" + *file + "'"); XMLSubSys::runParser(edgesHandler, *file); PROGRESS_DONE_MESSAGE(); } }
void NBNodeCont::guessTLs(OptionsCont& oc, NBTrafficLightLogicCont& tlc) { // build list of definitely not tls-controlled junctions std::vector<NBNode*> ncontrolled; if (oc.isSet("tls.unset")) { std::vector<std::string> notTLControlledNodes = oc.getStringVector("tls.unset"); for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) { NBNode* n = NBNodeCont::retrieve(*i); if (n == 0) { throw ProcessError(" The node '" + *i + "' to set as not-controlled is not known."); } std::set<NBTrafficLightDefinition*> tls = n->getControllingTLS(); for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) { (*j)->removeNode(n); } n->removeTrafficLights(); ncontrolled.push_back(n); } } TrafficLightType type = SUMOXMLDefinitions::TrafficLightTypes.get(OptionsCont::getOptions().getString("tls.default-type")); // loop#1 checking whether the node shall be tls controlled, // because it is assigned to a district if (oc.exists("tls.taz-nodes") && oc.getBool("tls.taz-nodes")) { for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) { NBNode* cur = (*i).second; if (cur->isNearDistrict() && find(ncontrolled.begin(), ncontrolled.end(), cur) == ncontrolled.end()) { setAsTLControlled(cur, tlc, type); } } } // maybe no tls shall be guessed if (!oc.getBool("tls.guess")) { return; } // guess joined tls first, if wished if (oc.getBool("tls.join")) { // get node clusters std::vector<std::set<NBNode*> > cands; generateNodeClusters(oc.getFloat("tls.join-dist"), cands); // check these candidates (clusters) whether they should be controlled by a tls for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end();) { std::set<NBNode*>& c = (*i); // regard only junctions which are not yet controlled and are not // forbidden to be controlled for (std::set<NBNode*>::iterator j = c.begin(); j != c.end();) { if ((*j)->isTLControlled() || find(ncontrolled.begin(), ncontrolled.end(), *j) != ncontrolled.end()) { c.erase(j++); } else { ++j; } } // check whether the cluster should be controlled if (!shouldBeTLSControlled(c)) { i = cands.erase(i); } else { ++i; } } // cands now only contain sets of junctions that shall be joined into being tls-controlled unsigned int index = 0; for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end(); ++i) { std::vector<NBNode*> nodes; for (std::set<NBNode*>::iterator j = (*i).begin(); j != (*i).end(); j++) { nodes.push_back(*j); } std::string id = "joinedG_" + toString(index++); NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, nodes, 0, type); if (!tlc.insert(tlDef)) { // actually, nothing should fail here WRITE_WARNING("Could not build guessed, joined tls"); delete tlDef; return; } } } // guess tls for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) { NBNode* cur = (*i).second; // do nothing if already is tl-controlled if (cur->isTLControlled()) { continue; } // do nothing if in the list of explicit non-controlled junctions if (find(ncontrolled.begin(), ncontrolled.end(), cur) != ncontrolled.end()) { continue; } std::set<NBNode*> c; c.insert(cur); if (!shouldBeTLSControlled(c) || cur->getIncomingEdges().size() < 3) { continue; } setAsTLControlled((*i).second, tlc, type); } }
void NBNodeCont::guessTLs(OptionsCont& oc, NBTrafficLightLogicCont& tlc) { // build list of definitely not tls-controlled junctions std::vector<NBNode*> ncontrolled; if (oc.isSet("tls.unset")) { std::vector<std::string> notTLControlledNodes = oc.getStringVector("tls.unset"); for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) { NBNode* n = NBNodeCont::retrieve(*i); if (n == 0) { throw ProcessError(" The node '" + *i + "' to set as not-controlled is not known."); } std::set<NBTrafficLightDefinition*> tls = n->getControllingTLS(); for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) { (*j)->removeNode(n); } n->removeTrafficLights(); ncontrolled.push_back(n); } } TrafficLightType type = SUMOXMLDefinitions::TrafficLightTypes.get(OptionsCont::getOptions().getString("tls.default-type")); // loop#1 checking whether the node shall be tls controlled, // because it is assigned to a district if (oc.exists("tls.taz-nodes") && oc.getBool("tls.taz-nodes")) { for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) { NBNode* cur = (*i).second; if (cur->isNearDistrict() && find(ncontrolled.begin(), ncontrolled.end(), cur) == ncontrolled.end()) { setAsTLControlled(cur, tlc, type); } } } // figure out which nodes mark the locations of TLS signals // This assumes nodes are already joined if (oc.exists("tls.guess-signals") && oc.getBool("tls.guess-signals")) { // prepare candidate edges const SUMOReal signalDist = oc.getFloat("tls.guess-signals.dist"); for (std::map<std::string, NBNode*>::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) { NBNode* node = (*i).second; if (node->isTLControlled() && node->geometryLike()) { const EdgeVector& outgoing = node->getOutgoingEdges(); for (EdgeVector::const_iterator it_o = outgoing.begin(); it_o != outgoing.end(); ++it_o) { (*it_o)->setSignalOffset((*it_o)->getLength()); } } } // check which nodes should be controlled for (std::map<std::string, NBNode*>::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) { NBNode* node = i->second; const EdgeVector& incoming = node->getIncomingEdges(); if (!node->isTLControlled() && incoming.size() > 1 && !node->geometryLike()) { std::vector<NBNode*> signals; bool isTLS = true; for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) { const NBEdge* inEdge = *it_i; if (inEdge->getSignalOffset() == NBEdge::UNSPECIFIED_SIGNAL_OFFSET || inEdge->getSignalOffset() > signalDist) { isTLS = false; break; } if (inEdge->getSignalOffset() == inEdge->getLength()) { signals.push_back(inEdge->getFromNode()); } } if (isTLS) { for (std::vector<NBNode*>::iterator j = signals.begin(); j != signals.end(); ++j) { std::set<NBTrafficLightDefinition*> tls = (*j)->getControllingTLS(); (*j)->removeTrafficLights(); for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) { tlc.removeFully((*j)->getID()); } } NBTrafficLightDefinition* tlDef = new NBOwnTLDef("GS_" + node->getID(), node, 0, TLTYPE_STATIC); // @todo patch endOffset for all incoming lanes according to the signal positions if (!tlc.insert(tlDef)) { // actually, nothing should fail here WRITE_WARNING("Could not build joined tls '" + node->getID() + "'."); delete tlDef; return; } } } } } // maybe no tls shall be guessed if (!oc.getBool("tls.guess")) { return; } // guess joined tls first, if wished if (oc.getBool("tls.join")) { // get node clusters std::vector<std::set<NBNode*> > cands; generateNodeClusters(oc.getFloat("tls.join-dist"), cands); // check these candidates (clusters) whether they should be controlled by a tls for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end();) { std::set<NBNode*>& c = (*i); // regard only junctions which are not yet controlled and are not // forbidden to be controlled for (std::set<NBNode*>::iterator j = c.begin(); j != c.end();) { if ((*j)->isTLControlled() || find(ncontrolled.begin(), ncontrolled.end(), *j) != ncontrolled.end()) { c.erase(j++); } else { ++j; } } // check whether the cluster should be controlled if (!shouldBeTLSControlled(c)) { i = cands.erase(i); } else { ++i; } } // cands now only contain sets of junctions that shall be joined into being tls-controlled unsigned int index = 0; for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end(); ++i) { std::vector<NBNode*> nodes; for (std::set<NBNode*>::iterator j = (*i).begin(); j != (*i).end(); j++) { nodes.push_back(*j); } std::string id = "joinedG_" + toString(index++); NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, nodes, 0, type); if (!tlc.insert(tlDef)) { // actually, nothing should fail here WRITE_WARNING("Could not build guessed, joined tls"); delete tlDef; return; } } } // guess tls for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) { NBNode* cur = (*i).second; // do nothing if already is tl-controlled if (cur->isTLControlled()) { continue; } // do nothing if in the list of explicit non-controlled junctions if (find(ncontrolled.begin(), ncontrolled.end(), cur) != ncontrolled.end()) { continue; } std::set<NBNode*> c; c.insert(cur); if (!shouldBeTLSControlled(c) || cur->getIncomingEdges().size() < 3) { continue; } setAsTLControlled((*i).second, tlc, type); } }
void NBNetBuilder::compute(OptionsCont& oc, const std::set<std::string>& explicitTurnarounds, bool removeElements) { GeoConvHelper& geoConvHelper = GeoConvHelper::getProcessing(); const bool lefthand = oc.getBool("lefthand"); if (lefthand) { mirrorX(); }; // MODIFYING THE SETS OF NODES AND EDGES // Removes edges that are connecting the same node long before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Removing self-loops"); myNodeCont.removeSelfLoops(myDistrictCont, myEdgeCont, myTLLCont); PROGRESS_TIME_MESSAGE(before); // if (oc.exists("remove-edges.isolated") && oc.getBool("remove-edges.isolated")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Finding isolated roads"); myNodeCont.removeIsolatedRoads(myDistrictCont, myEdgeCont, myTLLCont); PROGRESS_TIME_MESSAGE(before); } // if (oc.exists("keep-edges.postload") && oc.getBool("keep-edges.postload")) { if (oc.isSet("keep-edges.explicit") || oc.isSet("keep-edges.input-file")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Removing unwished edges"); myEdgeCont.removeUnwishedEdges(myDistrictCont); PROGRESS_TIME_MESSAGE(before); } } if (oc.getBool("junctions.join") || (oc.exists("ramps.guess") && oc.getBool("ramps.guess"))) { // preliminary geometry computations to determine the length of edges // This depends on turning directions and sorting of edge list // in case junctions are joined geometry computations have to be repeated // preliminary roundabout computations to avoid damaging roundabouts via junctions.join or ramps.guess NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false); NBNodesEdgesSorter::sortNodesEdges(myNodeCont); myEdgeCont.computeLaneShapes(); myNodeCont.computeNodeShapes(); myEdgeCont.computeEdgeShapes(); if (oc.getBool("roundabouts.guess")) { myEdgeCont.guessRoundabouts(); } const std::set<EdgeSet>& roundabouts = myEdgeCont.getRoundabouts(); for (std::set<EdgeSet>::const_iterator it_round = roundabouts.begin(); it_round != roundabouts.end(); ++it_round) { std::vector<std::string> nodeIDs; for (EdgeSet::const_iterator it_edge = it_round->begin(); it_edge != it_round->end(); ++it_edge) { nodeIDs.push_back((*it_edge)->getToNode()->getID()); } myNodeCont.addJoinExclusion(nodeIDs); } } // join junctions (may create new "geometry"-nodes so it needs to come before removing these if (oc.exists("junctions.join-exclude") && oc.isSet("junctions.join-exclude")) { myNodeCont.addJoinExclusion(oc.getStringVector("junctions.join-exclude")); } unsigned int numJoined = myNodeCont.joinLoadedClusters(myDistrictCont, myEdgeCont, myTLLCont); if (oc.getBool("junctions.join")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Joining junction clusters"); numJoined += myNodeCont.joinJunctions(oc.getFloat("junctions.join-dist"), myDistrictCont, myEdgeCont, myTLLCont); PROGRESS_TIME_MESSAGE(before); } if (oc.getBool("junctions.join") || (oc.exists("ramps.guess") && oc.getBool("ramps.guess"))) { // reset geometry to avoid influencing subsequent steps (ramps.guess) myEdgeCont.computeLaneShapes(); } if (numJoined > 0) { // bit of a misnomer since we're already done WRITE_MESSAGE(" Joined " + toString(numJoined) + " junction cluster(s)."); } // if (removeElements) { unsigned int no = 0; const bool removeGeometryNodes = oc.exists("geometry.remove") && oc.getBool("geometry.remove"); before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Removing empty nodes" + std::string(removeGeometryNodes ? " and geometry nodes" : "")); // removeUnwishedNodes needs turnDirections. @todo: try to call this less often NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false); no = myNodeCont.removeUnwishedNodes(myDistrictCont, myEdgeCont, myTLLCont, removeGeometryNodes); PROGRESS_TIME_MESSAGE(before); WRITE_MESSAGE(" " + toString(no) + " nodes removed."); } // MOVE TO ORIGIN // compute new boundary after network modifications have taken place Boundary boundary; for (std::map<std::string, NBNode*>::const_iterator it = myNodeCont.begin(); it != myNodeCont.end(); ++it) { boundary.add(it->second->getPosition()); } for (std::map<std::string, NBEdge*>::const_iterator it = myEdgeCont.begin(); it != myEdgeCont.end(); ++it) { boundary.add(it->second->getGeometry().getBoxBoundary()); } geoConvHelper.setConvBoundary(boundary); if (!oc.getBool("offset.disable-normalization") && oc.isDefault("offset.x") && oc.isDefault("offset.y")) { moveToOrigin(geoConvHelper, lefthand); } geoConvHelper.computeFinal(lefthand); // information needed for location element fixed at this point if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Reducing geometries"); myEdgeCont.reduceGeometries(oc.getFloat("geometry.min-dist")); PROGRESS_TIME_MESSAGE(before); } // @note: removing geometry can create similar edges so joinSimilarEdges must come afterwards // @note: likewise splitting can destroy similarities so joinSimilarEdges must come before if (removeElements && oc.getBool("edges.join")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Joining similar edges"); myNodeCont.joinSimilarEdges(myDistrictCont, myEdgeCont, myTLLCont); PROGRESS_TIME_MESSAGE(before); } if (oc.getBool("opposites.guess")) { PROGRESS_BEGIN_MESSAGE("guessing opposite direction edges"); myEdgeCont.guessOpposites(); PROGRESS_DONE_MESSAGE(); } // if (oc.exists("geometry.split") && oc.getBool("geometry.split")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Splitting geometry edges"); myEdgeCont.splitGeometry(myNodeCont); PROGRESS_TIME_MESSAGE(before); } // turning direction before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing turning directions"); NBTurningDirectionsComputer::computeTurnDirections(myNodeCont); PROGRESS_TIME_MESSAGE(before); // correct edge geometries to avoid overlap myNodeCont.avoidOverlap(); // guess ramps if ((oc.exists("ramps.guess") && oc.getBool("ramps.guess")) || (oc.exists("ramps.set") && oc.isSet("ramps.set"))) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Guessing and setting on-/off-ramps"); NBNodesEdgesSorter::sortNodesEdges(myNodeCont); NBRampsComputer::computeRamps(*this, oc); PROGRESS_TIME_MESSAGE(before); } // guess sidewalks if (oc.getBool("sidewalks.guess") || oc.getBool("sidewalks.guess.from-permissions")) { const int sidewalks = myEdgeCont.guessSidewalks(oc.getFloat("default.sidewalk-width"), oc.getFloat("sidewalks.guess.min-speed"), oc.getFloat("sidewalks.guess.max-speed"), oc.getBool("sidewalks.guess.from-permissions")); WRITE_MESSAGE("Guessed " + toString(sidewalks) + " sidewalks."); } // check whether any not previously setable connections may be set now myEdgeCont.recheckPostProcessConnections(); // remap ids if wished if (oc.getBool("numerical-ids")) { int numChangedEdges = myEdgeCont.mapToNumericalIDs(); int numChangedNodes = myNodeCont.mapToNumericalIDs(); if (numChangedEdges + numChangedNodes > 0) { WRITE_MESSAGE("Remapped " + toString(numChangedEdges) + " edge IDs and " + toString(numChangedNodes) + " node IDs."); } } // if (oc.exists("geometry.max-angle")) { myEdgeCont.checkGeometries( DEG2RAD(oc.getFloat("geometry.max-angle")), oc.getFloat("geometry.min-radius"), oc.getBool("geometry.min-radius.fix")); } // GEOMETRY COMPUTATION // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Sorting nodes' edges"); NBNodesEdgesSorter::sortNodesEdges(myNodeCont); PROGRESS_TIME_MESSAGE(before); myEdgeCont.computeLaneShapes(); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing node shapes"); if (oc.exists("geometry.junction-mismatch-threshold")) { myNodeCont.computeNodeShapes(oc.getFloat("geometry.junction-mismatch-threshold")); } else { myNodeCont.computeNodeShapes(); } PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing edge shapes"); myEdgeCont.computeEdgeShapes(); PROGRESS_TIME_MESSAGE(before); // resort edges based on the node and edge shapes NBNodesEdgesSorter::sortNodesEdges(myNodeCont, true); NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false); // APPLY SPEED MODIFICATIONS if (oc.exists("speed.offset")) { const SUMOReal speedOffset = oc.getFloat("speed.offset"); const SUMOReal speedFactor = oc.getFloat("speed.factor"); if (speedOffset != 0 || speedFactor != 1 || oc.isSet("speed.minimum")) { const SUMOReal speedMin = oc.isSet("speed.minimum") ? oc.getFloat("speed.minimum") : -std::numeric_limits<SUMOReal>::infinity(); before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Applying speed modifications"); for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) { (*i).second->setSpeed(-1, MAX2((*i).second->getSpeed() * speedFactor + speedOffset, speedMin)); } PROGRESS_TIME_MESSAGE(before); } } // CONNECTIONS COMPUTATION // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing node types"); NBNodeTypeComputer::computeNodeTypes(myNodeCont); PROGRESS_TIME_MESSAGE(before); // bool haveCrossings = false; if (oc.getBool("crossings.guess")) { haveCrossings = true; int crossings = 0; for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) { crossings += (*i).second->guessCrossings(); } WRITE_MESSAGE("Guessed " + toString(crossings) + " pedestrian crossings."); } if (!haveCrossings) { // recheck whether we had crossings in the input for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) { if (i->second->getCrossings().size() > 0) { haveCrossings = true; break; } } } if (oc.isDefault("no-internal-links") && !haveCrossings && myHaveLoadedNetworkWithoutInternalEdges) { oc.set("no-internal-links", "true"); } // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing priorities"); NBEdgePriorityComputer::computeEdgePriorities(myNodeCont); PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing approached edges"); myEdgeCont.computeEdge2Edges(oc.getBool("no-left-connections")); PROGRESS_TIME_MESSAGE(before); // if (oc.getBool("roundabouts.guess")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Guessing and setting roundabouts"); const int numGuessed = myEdgeCont.guessRoundabouts(); if (numGuessed > 0) { WRITE_MESSAGE(" Guessed " + toString(numGuessed) + " roundabout(s)."); } PROGRESS_TIME_MESSAGE(before); } myEdgeCont.markRoundabouts(); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing approaching lanes"); myEdgeCont.computeLanes2Edges(); PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Dividing of lanes on approached lanes"); myNodeCont.computeLanes2Lanes(); myEdgeCont.sortOutgoingLanesConnections(); PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Processing turnarounds"); if (!oc.getBool("no-turnarounds")) { myEdgeCont.appendTurnarounds(oc.getBool("no-turnarounds.tls")); } else { myEdgeCont.appendTurnarounds(explicitTurnarounds, oc.getBool("no-turnarounds.tls")); } PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Rechecking of lane endings"); myEdgeCont.recheckLanes(); PROGRESS_TIME_MESSAGE(before); if (haveCrossings && !oc.getBool("no-internal-links")) { for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) { i->second->buildCrossingsAndWalkingAreas(); } } // GUESS TLS POSITIONS before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Assigning nodes to traffic lights"); if (oc.isSet("tls.set")) { std::vector<std::string> tlControlledNodes = oc.getStringVector("tls.set"); TrafficLightType type = SUMOXMLDefinitions::TrafficLightTypes.get(oc.getString("tls.default-type")); for (std::vector<std::string>::const_iterator i = tlControlledNodes.begin(); i != tlControlledNodes.end(); ++i) { NBNode* node = myNodeCont.retrieve(*i); if (node == 0) { WRITE_WARNING("Building a tl-logic for junction '" + *i + "' is not possible." + "\n The junction '" + *i + "' is not known."); } else { myNodeCont.setAsTLControlled(node, myTLLCont, type); } } } myNodeCont.guessTLs(oc, myTLLCont); PROGRESS_TIME_MESSAGE(before); // if (oc.getBool("tls.join")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Joining traffic light nodes"); myNodeCont.joinTLS(myTLLCont, oc.getFloat("tls.join-dist")); PROGRESS_TIME_MESSAGE(before); } // COMPUTING RIGHT-OF-WAY AND TRAFFIC LIGHT PROGRAMS // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing traffic light control information"); myTLLCont.setTLControllingInformation(myEdgeCont, myNodeCont); PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing node logics"); myNodeCont.computeLogics(myEdgeCont, oc); PROGRESS_TIME_MESSAGE(before); // before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Computing traffic light logics"); std::pair<unsigned int, unsigned int> numbers = myTLLCont.computeLogics(oc); PROGRESS_TIME_MESSAGE(before); std::string progCount = ""; if (numbers.first != numbers.second) { progCount = "(" + toString(numbers.second) + " programs) "; } WRITE_MESSAGE(" " + toString(numbers.first) + " traffic light(s) " + progCount + "computed."); // if (oc.isSet("street-sign-output")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Generating street signs"); myEdgeCont.generateStreetSigns(); PROGRESS_TIME_MESSAGE(before); } // FINISHING INNER EDGES if (!oc.getBool("no-internal-links")) { before = SysUtils::getCurrentMillis(); PROGRESS_BEGIN_MESSAGE("Building inner edges"); for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) { (*i).second->sortOutgoingConnectionsByIndex(); } // walking areas shall only be built if crossings are wished as well for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) { (*i).second->buildInnerEdges(); } PROGRESS_TIME_MESSAGE(before); } if (lefthand) { mirrorX(); }; // report WRITE_MESSAGE("-----------------------------------------------------"); WRITE_MESSAGE("Summary:"); myNodeCont.printBuiltNodesStatistics(); WRITE_MESSAGE(" Network boundaries:"); WRITE_MESSAGE(" Original boundary : " + toString(geoConvHelper.getOrigBoundary())); WRITE_MESSAGE(" Applied offset : " + toString(geoConvHelper.getOffsetBase())); WRITE_MESSAGE(" Converted boundary : " + toString(geoConvHelper.getConvBoundary())); WRITE_MESSAGE("-----------------------------------------------------"); NBRequest::reportWarnings(); // report on very large networks if (MAX2(geoConvHelper.getConvBoundary().xmax(), geoConvHelper.getConvBoundary().ymax()) > 1000000 || MIN2(geoConvHelper.getConvBoundary().xmin(), geoConvHelper.getConvBoundary().ymin()) < -1000000) { WRITE_WARNING("Network contains very large coordinates and will probably flicker in the GUI. Check for outlying nodes and make sure the network is shifted to the coordinate origin"); } }
void startComputation(RODFNet* optNet, RODFDetectorFlows& flows, RODFDetectorCon& detectors, OptionsCont& oc) { if (oc.getBool("print-absolute-flows")) { flows.printAbsolute(); } // if a network was loaded... (mode1) if (optNet != 0) { if (oc.getBool("remove-empty-detectors")) { PROGRESS_BEGIN_MESSAGE("Removing empty detectors"); optNet->removeEmptyDetectors(detectors, flows); PROGRESS_DONE_MESSAGE(); } else if (oc.getBool("report-empty-detectors")) { PROGRESS_BEGIN_MESSAGE("Scanning for empty detectors"); optNet->reportEmptyDetectors(detectors, flows); PROGRESS_DONE_MESSAGE(); } // compute the detector types (optionally) if (!detectors.detectorsHaveCompleteTypes() || oc.getBool("revalidate-detectors")) { optNet->computeTypes(detectors, oc.getBool("strict-sources")); } std::vector<RODFDetector*>::const_iterator i = detectors.getDetectors().begin(); for (; i != detectors.getDetectors().end(); ++i) { if ((*i)->getType() == SOURCE_DETECTOR) { break; } } if (i == detectors.getDetectors().end() && !oc.getBool("routes-for-all")) { throw ProcessError("No source detectors found."); } // compute routes between the detectors (optionally) if (!detectors.detectorsHaveRoutes() || oc.getBool("revalidate-routes") || oc.getBool("guess-empty-flows")) { PROGRESS_BEGIN_MESSAGE("Computing routes"); optNet->buildRoutes(detectors, oc.getBool("all-end-follower"), oc.getBool("keep-unfinished-routes"), oc.getBool("routes-for-all"), !oc.getBool("keep-longer-routes"), oc.getInt("max-search-depth")); PROGRESS_DONE_MESSAGE(); } } // check // whether the detectors are valid if (!detectors.detectorsHaveCompleteTypes()) { throw ProcessError("The detector types are not defined; use in combination with a network"); } // whether the detectors have routes if (!detectors.detectorsHaveRoutes()) { throw ProcessError("The emitters have no routes; use in combination with a network"); } // save the detectors if wished if (oc.isSet("detector-output")) { detectors.save(oc.getString("detector-output")); } // save their positions as POIs if wished if (oc.isSet("detectors-poi-output")) { detectors.saveAsPOIs(oc.getString("detectors-poi-output")); } // save the routes file if it was changed or it's wished if (detectors.detectorsHaveRoutes() && oc.isSet("routes-output")) { detectors.saveRoutes(oc.getString("routes-output")); } // guess flows if wished if (oc.getBool("guess-empty-flows")) { optNet->buildDetectorDependencies(detectors); detectors.guessEmptyFlows(flows); } const SUMOTime begin = string2time(oc.getString("begin")); const SUMOTime end = string2time(oc.getString("end")); const SUMOTime step = string2time(oc.getString("time-step")); // save emitters if wished if (oc.isSet("emitters-output") || oc.isSet("emitters-poi-output")) { optNet->buildEdgeFlowMap(flows, detectors, begin, end, step); // !!! if (oc.getBool("revalidate-flows")) { PROGRESS_BEGIN_MESSAGE("Rechecking loaded flows"); optNet->revalidateFlows(detectors, flows, begin, end, step); PROGRESS_DONE_MESSAGE(); } if (oc.isSet("emitters-output")) { PROGRESS_BEGIN_MESSAGE("Writing emitters"); detectors.writeEmitters(oc.getString("emitters-output"), flows, begin, end, step, *optNet, oc.getBool("calibrator-output"), oc.getBool("include-unused-routes"), oc.getFloat("scale"), // oc.getInt("max-search-depth"), oc.getBool("emissions-only")); PROGRESS_DONE_MESSAGE(); } if (oc.isSet("emitters-poi-output")) { PROGRESS_BEGIN_MESSAGE("Writing emitter pois"); detectors.writeEmitterPOIs(oc.getString("emitters-poi-output"), flows); PROGRESS_DONE_MESSAGE(); } } // save end speed trigger if wished if (oc.isSet("variable-speed-sign-output")) { PROGRESS_BEGIN_MESSAGE("Writing speed triggers"); detectors.writeSpeedTrigger(optNet, oc.getString("variable-speed-sign-output"), flows, begin, end, step); PROGRESS_DONE_MESSAGE(); } // save checking detectors if wished if (oc.isSet("validation-output")) { PROGRESS_BEGIN_MESSAGE("Writing validation detectors"); detectors.writeValidationDetectors(oc.getString("validation-output"), oc.getBool("validation-output.add-sources"), true, true); // !!! PROGRESS_DONE_MESSAGE(); } // build global rerouter on end if wished if (oc.isSet("end-reroute-output")) { PROGRESS_BEGIN_MESSAGE("Writing highway end rerouter"); detectors.writeEndRerouterDetectors(oc.getString("end-reroute-output")); // !!! PROGRESS_DONE_MESSAGE(); } /* // save the insertion definitions if(oc.isSet("flow-definitions")) { buildVehicleEmissions(oc.getString("flow-definitions")); } */ // }