LCOV - code coverage report
Current view: top level - src/netimport/vissim/tempstructs - NIVissimDistrictConnection.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 15 120 12.5 %
Date: 2024-05-01 15:34:42 Functions: 5 15 33.3 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4             : // This program and the accompanying materials are made available under the
       5             : // terms of the Eclipse Public License 2.0 which is available at
       6             : // https://www.eclipse.org/legal/epl-2.0/
       7             : // This Source Code may also be made available under the following Secondary
       8             : // Licenses when the conditions for such availability set forth in the Eclipse
       9             : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10             : // or later which is available at
      11             : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12             : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13             : /****************************************************************************/
      14             : /// @file    NIVissimDistrictConnection.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Jakob Erdmann
      17             : /// @author  Michael Behrisch
      18             : /// @date    Sept 2002
      19             : ///
      20             : // -------------------
      21             : /****************************************************************************/
      22             : #include <config.h>
      23             : 
      24             : #include <map>
      25             : #include <string>
      26             : #include <algorithm>
      27             : #include <cassert>
      28             : #include <utils/common/VectorHelper.h>
      29             : #include <utils/common/ToString.h>
      30             : #include <utils/geom/Position.h>
      31             : #include <utils/geom/GeomHelper.h>
      32             : #include <utils/geom/PositionVector.h>
      33             : #include <utils/options/OptionsCont.h>
      34             : #include "NIVissimAbstractEdge.h"
      35             : #include "NIVissimEdge.h"
      36             : #include <netbuild/NBEdge.h>
      37             : #include <netbuild/NBEdgeCont.h>
      38             : #include <netbuild/NBNode.h>
      39             : #include <netbuild/NBNodeCont.h>
      40             : #include <netbuild/NBDistrict.h>
      41             : #include <netbuild/NBDistrictCont.h>
      42             : #include "NIVissimDistrictConnection.h"
      43             : #include <utils/distribution/DistributionCont.h>
      44             : #include <utils/common/MsgHandler.h>
      45             : 
      46             : 
      47             : // ===========================================================================
      48             : // static member definitions
      49             : // ===========================================================================
      50             : NIVissimDistrictConnection::DictType NIVissimDistrictConnection::myDict;
      51             : std::map<int, std::vector<int> > NIVissimDistrictConnection::myDistrictsConnections;
      52             : 
      53             : 
      54             : // ===========================================================================
      55             : // method definitions
      56             : // ===========================================================================
      57           0 : NIVissimDistrictConnection::NIVissimDistrictConnection(int id,
      58             :         const std::string& name,
      59             :         const std::vector<int>& districts, const std::vector<double>& percentages,
      60             :         int edgeid, double position,
      61           0 :         const std::vector<std::pair<int, int> >& assignedVehicles)
      62           0 :     : myID(id), myName(name), myDistricts(districts),
      63           0 :       myEdgeID(edgeid), myPosition(position),
      64           0 :       myAssignedVehicles(assignedVehicles) {
      65             :     std::vector<int>::iterator i = myDistricts.begin();
      66             :     std::vector<double>::const_iterator j = percentages.begin();
      67           0 :     while (i != myDistricts.end()) {
      68           0 :         myPercentages[*i] = *j;
      69             :         i++;
      70             :         j++;
      71             :     }
      72           0 : }
      73             : 
      74             : 
      75           0 : NIVissimDistrictConnection::~NIVissimDistrictConnection() {}
      76             : 
      77             : 
      78             : 
      79             : bool
      80           0 : NIVissimDistrictConnection::dictionary(int id, const std::string& name,
      81             :                                        const std::vector<int>& districts, const std::vector<double>& percentages,
      82             :                                        int edgeid, double position,
      83             :                                        const std::vector<std::pair<int, int> >& assignedVehicles) {
      84             :     NIVissimDistrictConnection* o =
      85             :         new NIVissimDistrictConnection(id, name, districts, percentages,
      86           0 :                                        edgeid, position, assignedVehicles);
      87           0 :     if (!dictionary(id, o)) {
      88           0 :         delete o;
      89           0 :         return false;
      90             :     }
      91             :     return true;
      92             : }
      93             : 
      94             : 
      95             : bool
      96           0 : NIVissimDistrictConnection::dictionary(int id, NIVissimDistrictConnection* o) {
      97             :     DictType::iterator i = myDict.find(id);
      98           0 :     if (i == myDict.end()) {
      99           0 :         myDict[id] = o;
     100           0 :         return true;
     101             :     }
     102             :     return false;
     103             : }
     104             : 
     105             : 
     106             : NIVissimDistrictConnection*
     107           0 : NIVissimDistrictConnection::dictionary(int id) {
     108             :     DictType::iterator i = myDict.find(id);
     109           0 :     if (i == myDict.end()) {
     110             :         return nullptr;
     111             :     }
     112           0 :     return (*i).second;
     113             : }
     114             : 
     115             : void
     116           9 : NIVissimDistrictConnection::dict_BuildDistrictConnections() {
     117             :     //  pre-assign connections to districts
     118           9 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
     119           0 :         NIVissimDistrictConnection* c = (*i).second;
     120             :         const std::vector<int>& districts = c->myDistricts;
     121           0 :         for (std::vector<int>::const_iterator j = districts.begin(); j != districts.end(); j++) {
     122             :             // assign connection to district
     123           0 :             myDistrictsConnections[*j].push_back((*i).first);
     124             :         }
     125             :     }
     126           9 : }
     127             : 
     128             : 
     129             : void
     130           9 : NIVissimDistrictConnection::dict_CheckEdgeEnds() {
     131           9 :     for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) {
     132             :         const std::vector<int>& connections = (*k).second;
     133           0 :         for (std::vector<int>::const_iterator j = connections.begin(); j != connections.end(); j++) {
     134           0 :             NIVissimDistrictConnection* c = dictionary(*j);
     135           0 :             c->checkEdgeEnd();
     136             :         }
     137             :     }
     138           9 : }
     139             : 
     140             : 
     141             : void
     142           0 : NIVissimDistrictConnection::checkEdgeEnd() {
     143           0 :     NIVissimEdge* edge = NIVissimEdge::dictionary(myEdgeID);
     144             :     assert(edge != 0);
     145           0 :     edge->checkDistrictConnectionExistanceAt(myPosition);
     146           0 : }
     147             : 
     148             : 
     149             : void
     150           9 : NIVissimDistrictConnection::dict_BuildDistrictNodes(NBDistrictCont& dc,
     151             :         NBNodeCont& nc) {
     152           9 :     for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) {
     153             :         // get the connections
     154             :         const std::vector<int>& connections = (*k).second;
     155             :         // retrieve the current district
     156           0 :         std::string dsid = toString<int>((*k).first);
     157           0 :         NBDistrict* district = new NBDistrict(dsid);
     158           0 :         dc.insert(district);
     159             :         // compute the middle of the district
     160           0 :         PositionVector pos;
     161           0 :         for (std::vector<int>::const_iterator j = connections.begin(); j != connections.end(); j++) {
     162           0 :             NIVissimDistrictConnection* c = dictionary(*j);
     163           0 :             pos.push_back(c->geomPosition());
     164             :         }
     165           0 :         Position distCenter = pos.getPolygonCenter();
     166           0 :         if (connections.size() == 1) { // !!! ok, ok, maybe not the best way just to add an offset
     167             :             distCenter.add(10, 10);
     168             :         }
     169           0 :         district->setCenter(distCenter);
     170             :         // build the node
     171           0 :         std::string id = "District" + district->getID();
     172             :         NBNode* districtNode =
     173           0 :             new NBNode(id, district->getPosition(), district);
     174           0 :         if (!nc.insert(districtNode)) {
     175           0 :             throw 1;
     176             :         }
     177           0 :     }
     178           9 : }
     179             : 
     180             : void
     181           9 : NIVissimDistrictConnection::dict_BuildDistricts(NBDistrictCont& dc,
     182             :         NBEdgeCont& ec,
     183             :         NBNodeCont& nc) {
     184             :     // add the sources and sinks
     185             :     //  their normalised probability is computed within NBDistrict
     186             :     //   to avoid double code writing and more securty within the converter
     187             :     //  go through the district table
     188           9 :     for (std::map<int, std::vector<int> >::iterator k = myDistrictsConnections.begin(); k != myDistrictsConnections.end(); k++) {
     189             :         // get the connections
     190             :         const std::vector<int>& connections = (*k).second;
     191             :         // retrieve the current district
     192             :         NBDistrict* district =
     193           0 :             dc.retrieve(toString<int>((*k).first));
     194           0 :         NBNode* districtNode = nc.retrieve("District" + district->getID());
     195             :         assert(district != 0 && districtNode != 0);
     196             : 
     197           0 :         for (std::vector<int>::const_iterator l = connections.begin(); l != connections.end(); l++) {
     198           0 :             NIVissimDistrictConnection* c = dictionary(*l);
     199             :             // get the edge to connect the parking place to
     200           0 :             NBEdge* e = ec.retrieve(toString<int>(c->myEdgeID));
     201           0 :             if (e == nullptr) {
     202           0 :                 e = ec.retrievePossiblySplit(toString<int>(c->myEdgeID), c->myPosition);
     203             :             }
     204           0 :             if (e == nullptr) {
     205           0 :                 WRITE_WARNINGF(TL("Could not build district '%' - edge '%' is missing."), toString<int>((*k).first), toString<int>(c->myEdgeID));
     206           0 :                 continue;
     207             :             }
     208           0 :             std::string id = "ParkingPlace" + toString<int>(*l);
     209           0 :             NBNode* parkingPlace = nc.retrieve(id);
     210           0 :             if (parkingPlace == nullptr) {
     211             :                 double pos = c->getPosition();
     212           0 :                 if (pos < e->getLength() - pos) {
     213             :                     parkingPlace = e->getFromNode();
     214           0 :                     parkingPlace->invalidateIncomingConnections();
     215             :                 } else {
     216             :                     parkingPlace = e->getToNode();
     217           0 :                     parkingPlace->invalidateOutgoingConnections();
     218             :                 }
     219             :             }
     220             :             assert(
     221             :                 e->getToNode() == parkingPlace
     222             :                 ||
     223             :                 e->getFromNode() == parkingPlace);
     224             : 
     225             :             // build the connection to the source
     226           0 :             if (e->getFromNode() == parkingPlace) {
     227           0 :                 id = "VissimFromParkingplace" + toString<int>((*k).first) + "-" + toString<int>(c->myID);
     228             :                 NBEdge* source =
     229             :                     new NBEdge(id, districtNode, parkingPlace,
     230           0 :                                "Connection", c->getMeanSpeed(/*distc*/) / 3.6, NBEdge::UNSPECIFIED_FRICTION, 3, -1,
     231           0 :                                NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, LaneSpreadFunction::RIGHT);
     232           0 :                 if (!ec.insert(source)) { // !!! in den Konstruktor
     233           0 :                     throw 1; // !!!
     234             :                 }
     235             :                 double percNormed =
     236           0 :                     c->myPercentages[(*k).first];
     237           0 :                 if (!district->addSource(source, percNormed)) {
     238           0 :                     throw 1;
     239             :                 }
     240             :             }
     241             : 
     242             :             // build the connection to the destination
     243           0 :             if (e->getToNode() == parkingPlace) {
     244           0 :                 id = "VissimToParkingplace"  + toString<int>((*k).first) + "-" + toString<int>(c->myID);
     245             :                 NBEdge* destination =
     246             :                     new NBEdge(id, parkingPlace, districtNode,
     247             :                                "Connection", 100. / 3.6, NBEdge::UNSPECIFIED_FRICTION, 2, -1,
     248           0 :                                NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, LaneSpreadFunction::RIGHT);
     249           0 :                 if (!ec.insert(destination)) { // !!! (in den Konstruktor)
     250           0 :                     throw 1; // !!!
     251             :                 }
     252             :                 double percNormed2 =
     253           0 :                     c->myPercentages[(*k).first];
     254           0 :                 if (!district->addSink(destination, percNormed2)) {
     255           0 :                     throw 1; // !!!
     256             :                 }
     257             :             }
     258             : 
     259             :             /*
     260             :             if(e->getToNode()==districtNode) {
     261             :             double percNormed =
     262             :                 c->myPercentages[(*k).first];
     263             :             district->addSink(e, percNormed);
     264             :             }
     265             :             if(e->getFromNode()==districtNode) {
     266             :             double percNormed =
     267             :                 c->myPercentages[(*k).first];
     268             :             district->addSource(e, percNormed);
     269             :             }
     270             :             */
     271             :         }
     272             : 
     273             :         /*
     274             :         // add them as sources and sinks to the current district
     275             :         for(std::vector<int>::const_iterator l=connections.begin(); l!=connections.end(); l++) {
     276             :             // get the current connections
     277             :             NIVissimDistrictConnection *c = dictionary(*l);
     278             :             // get the edge to connect the parking place to
     279             :             NBEdge *e = NBEdgeCont::retrieve(toString<int>(c->myEdgeID));
     280             :             Position edgepos = c->geomPosition();
     281             :             NBNode *edgeend = e->tryGetNodeAtPosition(c->myPosition,
     282             :                 e->getLength()/4.0);
     283             :             if(edgeend==0) {
     284             :                 // Edge splitting omitted on build district connections by now
     285             :                 assert(false);
     286             :             }
     287             : 
     288             :             // build the district-node if not yet existing
     289             :             std::string id = "VissimParkingplace" + district->getID();
     290             :             NBNode *districtNode = nc.retrieve(id);
     291             :             assert(districtNode!=0);
     292             : 
     293             :             if(e->getToNode()==edgeend) {
     294             :                 // build the connection to the source
     295             :                 id = std::string("VissimFromParkingplace")
     296             :                     + toString<int>((*k).first) + "-"
     297             :                     + toString<int>(c->myID);
     298             :                 NBEdge *source =
     299             :                     new NBEdge(id, id, districtNode, edgeend,
     300             :                     "Connection", 100/3.6, 2, 100, 0,
     301             :                     NBEdge::EDGEFUNCTION_SOURCE);
     302             :                 NBEdgeCont::insert(source); // !!! (in den Konstruktor)
     303             :                 double percNormed =
     304             :                     c->myPercentages[(*k).first];
     305             :                 district->addSource(source, percNormed);
     306             :             } else {
     307             :                 // build the connection to the destination
     308             :                 id = std::string("VissimToParkingplace")
     309             :                     + toString<int>((*k).first) + "-"
     310             :                     + toString<int>(c->myID);
     311             :                 NBEdge *destination =
     312             :                     new NBEdge(id, id, edgeend, districtNode,
     313             :                     "Connection", 100/3.6, 2, 100, 0,
     314             :                     NBEdge::EDGEFUNCTION_SINK);
     315             :                 NBEdgeCont::insert(destination); // !!! (in den Konstruktor)
     316             : 
     317             :                 // add both the source and the sink to the district
     318             :                 double percNormed =
     319             :                     c->myPercentages[(*k).first];
     320             :                 district->addSink(destination, percNormed);
     321             :             }
     322             :         }
     323             :         */
     324             :     }
     325           9 : }
     326             : 
     327             : 
     328             : 
     329             : Position
     330           0 : NIVissimDistrictConnection::geomPosition() const {
     331           0 :     NIVissimAbstractEdge* e = NIVissimEdge::dictionary(myEdgeID);
     332           0 :     return e->getGeomPosition(myPosition);
     333             : }
     334             : 
     335             : 
     336             : NIVissimDistrictConnection*
     337           0 : NIVissimDistrictConnection::dict_findForEdge(int edgeid) {
     338           0 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
     339           0 :         if ((*i).second->myEdgeID == edgeid) {
     340             :             return (*i).second;
     341             :         }
     342             :     }
     343             :     return nullptr;
     344             : }
     345             : 
     346             : 
     347             : void
     348           9 : NIVissimDistrictConnection::clearDict() {
     349           9 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
     350           0 :         delete (*i).second;
     351             :     }
     352             :     myDict.clear();
     353           9 : }
     354             : 
     355             : 
     356             : double
     357           0 : NIVissimDistrictConnection::getMeanSpeed() const {
     358             :     //assert(myAssignedVehicles.size()!=0);
     359           0 :     if (myAssignedVehicles.size() == 0) {
     360           0 :         WRITE_WARNINGF(TL("No streams assigned at district'%'.\n Using default speed 200km/h"), toString(myID));
     361           0 :         return (double) 200 / (double) 3.6;
     362             :     }
     363             :     double speed = 0;
     364             :     std::vector<std::pair<int, int> >::const_iterator i;
     365           0 :     for (i = myAssignedVehicles.begin(); i != myAssignedVehicles.end(); i++) {
     366           0 :         speed += getRealSpeed((*i).second);
     367             :     }
     368           0 :     return speed / (double) myAssignedVehicles.size();
     369             : }
     370             : 
     371             : 
     372             : double
     373           0 : NIVissimDistrictConnection::getRealSpeed(int distNo) const {
     374           0 :     std::string id = toString<int>(distNo);
     375           0 :     Distribution* dist = DistributionCont::dictionary("speed", id);
     376           0 :     if (dist == nullptr) {
     377           0 :         WRITE_WARNINGF(TL("The referenced speed distribution '%' is not known."), id);
     378           0 :         WRITE_WARNING(TL(". Using default."));
     379           0 :         return OptionsCont::getOptions().getFloat("vissim.default-speed");
     380             :     }
     381             :     assert(dist != 0);
     382           0 :     double speed = dist->getMax();
     383           0 :     if (speed < 0 || speed > 1000) {
     384           0 :         WRITE_WARNING(" False speed at district '" + id);
     385           0 :         WRITE_WARNING(TL(". Using default."));
     386           0 :         speed = OptionsCont::getOptions().getFloat("vissim.default-speed");
     387             :     }
     388             :     return speed;
     389             : }
     390             : 
     391             : 
     392             : /****************************************************************************/

Generated by: LCOV version 1.14