Path: blob/main/src/netimport/vissim/tempstructs/NIVissimDistrictConnection.cpp
169684 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file NIVissimDistrictConnection.cpp14/// @author Daniel Krajzewicz15/// @author Jakob Erdmann16/// @author Michael Behrisch17/// @date Sept 200218///19// -------------------20/****************************************************************************/21#include <config.h>2223#include <map>24#include <string>25#include <algorithm>26#include <cassert>27#include <utils/common/VectorHelper.h>28#include <utils/common/ToString.h>29#include <utils/geom/Position.h>30#include <utils/geom/GeomHelper.h>31#include <utils/geom/PositionVector.h>32#include <utils/options/OptionsCont.h>33#include "NIVissimAbstractEdge.h"34#include "NIVissimEdge.h"35#include <netbuild/NBEdge.h>36#include <netbuild/NBEdgeCont.h>37#include <netbuild/NBNode.h>38#include <netbuild/NBNodeCont.h>39#include <netbuild/NBDistrict.h>40#include <netbuild/NBDistrictCont.h>41#include "NIVissimDistrictConnection.h"42#include <utils/distribution/DistributionCont.h>43#include <utils/common/MsgHandler.h>444546// ===========================================================================47// static member definitions48// ===========================================================================49NIVissimDistrictConnection::DictType NIVissimDistrictConnection::myDict;50std::map<int, std::vector<int> > NIVissimDistrictConnection::myDistrictsConnections;515253// ===========================================================================54// method definitions55// ===========================================================================56NIVissimDistrictConnection::NIVissimDistrictConnection(int id,57const std::string& name,58const std::vector<int>& districts, const std::vector<double>& percentages,59int edgeid, double position,60const std::vector<std::pair<int, int> >& assignedVehicles)61: myID(id), myName(name), myDistricts(districts),62myEdgeID(edgeid), myPosition(position),63myAssignedVehicles(assignedVehicles) {64std::vector<int>::iterator i = myDistricts.begin();65std::vector<double>::const_iterator j = percentages.begin();66while (i != myDistricts.end()) {67myPercentages[*i] = *j;68i++;69j++;70}71}727374NIVissimDistrictConnection::~NIVissimDistrictConnection() {}75767778bool79NIVissimDistrictConnection::dictionary(int id, const std::string& name,80const std::vector<int>& districts, const std::vector<double>& percentages,81int edgeid, double position,82const std::vector<std::pair<int, int> >& assignedVehicles) {83NIVissimDistrictConnection* o =84new NIVissimDistrictConnection(id, name, districts, percentages,85edgeid, position, assignedVehicles);86if (!dictionary(id, o)) {87delete o;88return false;89}90return true;91}929394bool95NIVissimDistrictConnection::dictionary(int id, NIVissimDistrictConnection* o) {96DictType::iterator i = myDict.find(id);97if (i == myDict.end()) {98myDict[id] = o;99return true;100}101return false;102}103104105NIVissimDistrictConnection*106NIVissimDistrictConnection::dictionary(int id) {107DictType::iterator i = myDict.find(id);108if (i == myDict.end()) {109return nullptr;110}111return (*i).second;112}113114void115NIVissimDistrictConnection::dict_BuildDistrictConnections() {116// pre-assign connections to districts117for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {118NIVissimDistrictConnection* c = (*i).second;119const std::vector<int>& districts = c->myDistricts;120for (std::vector<int>::const_iterator j = districts.begin(); j != districts.end(); j++) {121// assign connection to district122myDistrictsConnections[*j].push_back((*i).first);123}124}125}126127128void129NIVissimDistrictConnection::dict_CheckEdgeEnds() {130for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) {131const std::vector<int>& connections = (*k).second;132for (std::vector<int>::const_iterator j = connections.begin(); j != connections.end(); j++) {133NIVissimDistrictConnection* c = dictionary(*j);134c->checkEdgeEnd();135}136}137}138139140void141NIVissimDistrictConnection::checkEdgeEnd() {142NIVissimEdge* edge = NIVissimEdge::dictionary(myEdgeID);143assert(edge != 0);144edge->checkDistrictConnectionExistanceAt(myPosition);145}146147148void149NIVissimDistrictConnection::dict_BuildDistrictNodes(NBDistrictCont& dc,150NBNodeCont& nc) {151for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) {152// get the connections153const std::vector<int>& connections = (*k).second;154// retrieve the current district155std::string dsid = toString<int>((*k).first);156NBDistrict* district = new NBDistrict(dsid);157dc.insert(district);158// compute the middle of the district159PositionVector pos;160for (std::vector<int>::const_iterator j = connections.begin(); j != connections.end(); j++) {161NIVissimDistrictConnection* c = dictionary(*j);162pos.push_back(c->geomPosition());163}164Position distCenter = pos.getPolygonCenter();165if (connections.size() == 1) { // !!! ok, ok, maybe not the best way just to add an offset166distCenter.add(10, 10);167}168district->setCenter(distCenter);169// build the node170std::string id = "District" + district->getID();171NBNode* districtNode =172new NBNode(id, district->getPosition(), district);173if (!nc.insert(districtNode)) {174throw 1;175}176}177}178179void180NIVissimDistrictConnection::dict_BuildDistricts(NBDistrictCont& dc,181NBEdgeCont& ec,182NBNodeCont& nc) {183// add the sources and sinks184// their normalised probability is computed within NBDistrict185// to avoid double code writing and more securty within the converter186// go through the district table187for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) {188// get the connections189const std::vector<int>& connections = (*k).second;190// retrieve the current district191NBDistrict* district =192dc.retrieve(toString<int>((*k).first));193NBNode* districtNode = nc.retrieve("District" + district->getID());194assert(district != 0 && districtNode != 0);195196for (std::vector<int>::const_iterator l = connections.begin(); l != connections.end(); l++) {197NIVissimDistrictConnection* c = dictionary(*l);198// get the edge to connect the parking place to199NBEdge* e = ec.retrieve(toString<int>(c->myEdgeID));200if (e == nullptr) {201e = ec.retrievePossiblySplit(toString<int>(c->myEdgeID), c->myPosition);202}203if (e == nullptr) {204WRITE_WARNINGF(TL("Could not build district '%' - edge '%' is missing."), toString<int>((*k).first), toString<int>(c->myEdgeID));205continue;206}207std::string id = "ParkingPlace" + toString<int>(*l);208NBNode* parkingPlace = nc.retrieve(id);209if (parkingPlace == nullptr) {210double pos = c->getPosition();211if (pos < e->getLength() - pos) {212parkingPlace = e->getFromNode();213parkingPlace->invalidateIncomingConnections();214} else {215parkingPlace = e->getToNode();216parkingPlace->invalidateOutgoingConnections();217}218}219assert(220e->getToNode() == parkingPlace221||222e->getFromNode() == parkingPlace);223224// build the connection to the source225if (e->getFromNode() == parkingPlace) {226id = "VissimFromParkingplace" + toString<int>((*k).first) + "-" + toString<int>(c->myID);227NBEdge* source =228new NBEdge(id, districtNode, parkingPlace,229"Connection", c->getMeanSpeed(/*distc*/) / 3.6, NBEdge::UNSPECIFIED_FRICTION, 3, -1,230NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, LaneSpreadFunction::RIGHT);231if (!ec.insert(source)) { // !!! in den Konstruktor232throw 1; // !!!233}234double percNormed =235c->myPercentages[(*k).first];236if (!district->addSource(source, percNormed)) {237throw 1;238}239}240241// build the connection to the destination242if (e->getToNode() == parkingPlace) {243id = "VissimToParkingplace" + toString<int>((*k).first) + "-" + toString<int>(c->myID);244NBEdge* destination =245new NBEdge(id, parkingPlace, districtNode,246"Connection", 100. / 3.6, NBEdge::UNSPECIFIED_FRICTION, 2, -1,247NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, LaneSpreadFunction::RIGHT);248if (!ec.insert(destination)) { // !!! (in den Konstruktor)249throw 1; // !!!250}251double percNormed2 =252c->myPercentages[(*k).first];253if (!district->addSink(destination, percNormed2)) {254throw 1; // !!!255}256}257258/*259if(e->getToNode()==districtNode) {260double percNormed =261c->myPercentages[(*k).first];262district->addSink(e, percNormed);263}264if(e->getFromNode()==districtNode) {265double percNormed =266c->myPercentages[(*k).first];267district->addSource(e, percNormed);268}269*/270}271272/*273// add them as sources and sinks to the current district274for(std::vector<int>::const_iterator l=connections.begin(); l!=connections.end(); l++) {275// get the current connections276NIVissimDistrictConnection *c = dictionary(*l);277// get the edge to connect the parking place to278NBEdge *e = NBEdgeCont::retrieve(toString<int>(c->myEdgeID));279Position edgepos = c->geomPosition();280NBNode *edgeend = e->tryGetNodeAtPosition(c->myPosition,281e->getLength()/4.0);282if(edgeend==0) {283// Edge splitting omitted on build district connections by now284assert(false);285}286287// build the district-node if not yet existing288std::string id = "VissimParkingplace" + district->getID();289NBNode *districtNode = nc.retrieve(id);290assert(districtNode!=0);291292if(e->getToNode()==edgeend) {293// build the connection to the source294id = std::string("VissimFromParkingplace")295+ toString<int>((*k).first) + "-"296+ toString<int>(c->myID);297NBEdge *source =298new NBEdge(id, id, districtNode, edgeend,299"Connection", 100/3.6, 2, 100, 0,300NBEdge::EDGEFUNCTION_SOURCE);301NBEdgeCont::insert(source); // !!! (in den Konstruktor)302double percNormed =303c->myPercentages[(*k).first];304district->addSource(source, percNormed);305} else {306// build the connection to the destination307id = std::string("VissimToParkingplace")308+ toString<int>((*k).first) + "-"309+ toString<int>(c->myID);310NBEdge *destination =311new NBEdge(id, id, edgeend, districtNode,312"Connection", 100/3.6, 2, 100, 0,313NBEdge::EDGEFUNCTION_SINK);314NBEdgeCont::insert(destination); // !!! (in den Konstruktor)315316// add both the source and the sink to the district317double percNormed =318c->myPercentages[(*k).first];319district->addSink(destination, percNormed);320}321}322*/323}324}325326327328Position329NIVissimDistrictConnection::geomPosition() const {330NIVissimAbstractEdge* e = NIVissimEdge::dictionary(myEdgeID);331return e->getGeomPosition(myPosition);332}333334335NIVissimDistrictConnection*336NIVissimDistrictConnection::dict_findForEdge(int edgeid) {337for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {338if ((*i).second->myEdgeID == edgeid) {339return (*i).second;340}341}342return nullptr;343}344345346void347NIVissimDistrictConnection::clearDict() {348for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {349delete (*i).second;350}351myDict.clear();352}353354355double356NIVissimDistrictConnection::getMeanSpeed() const {357//assert(myAssignedVehicles.size()!=0);358if (myAssignedVehicles.size() == 0) {359WRITE_WARNINGF(TL("No streams assigned at district'%'.\n Using default speed 200km/h"), toString(myID));360return (double) 200 / (double) 3.6;361}362double speed = 0;363std::vector<std::pair<int, int> >::const_iterator i;364for (i = myAssignedVehicles.begin(); i != myAssignedVehicles.end(); i++) {365speed += getRealSpeed((*i).second);366}367return speed / (double) myAssignedVehicles.size();368}369370371double372NIVissimDistrictConnection::getRealSpeed(int distNo) const {373std::string id = toString<int>(distNo);374Distribution* dist = DistributionCont::dictionary("speed", id);375if (dist == nullptr) {376WRITE_WARNINGF(TL("The referenced speed distribution '%' is not known."), id);377WRITE_WARNING(TL(". Using default."));378return OptionsCont::getOptions().getFloat("vissim.default-speed");379}380assert(dist != 0);381double speed = dist->getMax();382if (speed < 0 || speed > 1000) {383WRITE_WARNING(" False speed at district '" + id);384WRITE_WARNING(TL(". Using default."));385speed = OptionsCont::getOptions().getFloat("vissim.default-speed");386}387return speed;388}389390391/****************************************************************************/392393394