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(); }
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 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; } }
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); }
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 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 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(); }