LCOV - code coverage report
Current view: top level - src/netimport/vissim/tempstructs - NIVissimDisturbance.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 82.3 % 130 107
Test Date: 2024-11-22 15:46:21 Functions: 100.0 % 13 13

            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    NIVissimDisturbance.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Michael Behrisch
      17              : /// @date    Sept 2002
      18              : ///
      19              : // -------------------
      20              : /****************************************************************************/
      21              : #include <config.h>
      22              : 
      23              : 
      24              : #include <map>
      25              : #include <string>
      26              : #include <iostream>
      27              : #include <cassert>
      28              : #include <utils/common/ToString.h>
      29              : #include <utils/common/MsgHandler.h>
      30              : #include <utils/geom/GeomHelper.h>
      31              : #include <utils/geom/Boundary.h>
      32              : #include <netbuild/NBEdge.h>
      33              : #include <netbuild/NBNode.h>
      34              : #include <netbuild/NBEdgeCont.h>
      35              : #include <netbuild/NBNodeCont.h>
      36              : #include "NIVissimEdge.h"
      37              : #include "NIVissimConnection.h"
      38              : #include "NIVissimNodeDef.h"
      39              : #include "NIVissimDisturbance.h"
      40              : #include "NIVissimNodeParticipatingEdgeVector.h"
      41              : 
      42              : 
      43              : // ===========================================================================
      44              : // static member variables
      45              : // ===========================================================================
      46              : NIVissimDisturbance::DictType NIVissimDisturbance::myDict;
      47              : int NIVissimDisturbance::myRunningID = 100000000;
      48              : 
      49              : int NIVissimDisturbance::refusedProhibits = 0;
      50              : 
      51              : 
      52              : // ===========================================================================
      53              : // method definitions
      54              : // ===========================================================================
      55          415 : NIVissimDisturbance::NIVissimDisturbance(int id,
      56              :         const std::string& name,
      57              :         const NIVissimExtendedEdgePoint& edge,
      58          415 :         const NIVissimExtendedEdgePoint& by)
      59          830 :     : myID(id), myNode(-1), myName(name), myEdge(edge), myDisturbance(by) {}
      60              : 
      61              : 
      62          830 : NIVissimDisturbance::~NIVissimDisturbance() {}
      63              : 
      64              : 
      65              : 
      66              : bool
      67          415 : NIVissimDisturbance::dictionary(const std::string& name,
      68              :                                 const NIVissimExtendedEdgePoint& edge,
      69              :                                 const NIVissimExtendedEdgePoint& by) {
      70          415 :     int nid = myRunningID++;
      71              :     NIVissimDisturbance* o =
      72          415 :         new NIVissimDisturbance(nid, name, edge, by);
      73          415 :     if (!dictionary(nid, o)) {
      74            0 :         delete o;
      75              :     }
      76          415 :     return true;
      77              : }
      78              : 
      79              : 
      80              : bool
      81          415 : NIVissimDisturbance::dictionary(int id, NIVissimDisturbance* o) {
      82              :     DictType::iterator i = myDict.find(id);
      83          415 :     if (i == myDict.end()) {
      84          415 :         myDict[id] = o;
      85          415 :         return true;
      86              :     }
      87              :     return false;
      88              : }
      89              : 
      90              : 
      91              : NIVissimDisturbance*
      92         4439 : NIVissimDisturbance::dictionary(int id) {
      93              :     DictType::iterator i = myDict.find(id);
      94         4439 :     if (i == myDict.end()) {
      95              :         return nullptr;
      96              :     }
      97         4439 :     return (*i).second;
      98              : }
      99              : 
     100              : std::vector<int>
     101          348 : NIVissimDisturbance::getWithin(const AbstractPoly& poly) {
     102              :     std::vector<int> ret;
     103        26146 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
     104        25798 :         if ((*i).second->crosses(poly)) {
     105          421 :             ret.push_back((*i).second->myID);
     106              :         }
     107              :     }
     108          348 :     return ret;
     109            0 : }
     110              : 
     111              : 
     112              : void
     113          415 : NIVissimDisturbance::computeBounding() {
     114              :     assert(myBoundary == 0);
     115          415 :     Boundary* bound = new Boundary();
     116          415 :     if (NIVissimAbstractEdge::dictionary(myEdge.getEdgeID()) != nullptr) {
     117          415 :         bound->add(myEdge.getGeomPosition());
     118              :     }
     119          415 :     if (NIVissimAbstractEdge::dictionary(myDisturbance.getEdgeID()) != nullptr) {
     120          415 :         bound->add(myDisturbance.getGeomPosition());
     121              :     }
     122          415 :     myBoundary = bound;
     123              :     assert(myBoundary != 0 && myBoundary->xmax() >= myBoundary->xmin());
     124          415 : }
     125              : 
     126              : 
     127              : 
     128              : bool
     129          421 : NIVissimDisturbance::addToNode(NBNode* node, NBDistrictCont& dc,
     130              :                                NBNodeCont& nc, NBEdgeCont& ec) {
     131          421 :     myNode = 0;
     132              :     NIVissimConnection* pc =
     133          421 :         NIVissimConnection::dictionary(myEdge.getEdgeID());
     134              :     NIVissimConnection* bc =
     135          421 :         NIVissimConnection::dictionary(myDisturbance.getEdgeID());
     136          421 :     if (pc == nullptr && bc == nullptr) {
     137              :         // This has not been tested completely, yet
     138              :         // Both competing abstract edges are normal edges
     139              :         // We have to find a crossing point, build a node here,
     140              :         //  split both edges and add the connections
     141          132 :         NIVissimEdge* e1 = NIVissimEdge::dictionary(myEdge.getEdgeID());
     142          132 :         NIVissimEdge* e2 = NIVissimEdge::dictionary(myDisturbance.getEdgeID());
     143          264 :         WRITE_WARNINGF(TL("Ugly split to prohibit '%' by '%'."), toString<int>(e1->getID()), toString<int>(e2->getID()));
     144          132 :         Position pos = e1->crossesEdgeAtPoint(e2);
     145          396 :         std::string id1 = toString<int>(e1->getID()) + "x" + toString<int>(e2->getID());
     146          396 :         std::string id2 = toString<int>(e2->getID()) + "x" + toString<int>(e1->getID());
     147          132 :         NBNode* node1 = nc.retrieve(id1);
     148          132 :         NBNode* node2 = nc.retrieve(id2);
     149          132 :         NBNode* splitNode = node1 == nullptr ? node2 : node1;
     150              :         assert(node1 == nullptr || node2 == nullptr);
     151          132 :         if (splitNode == nullptr) {
     152          132 :             refusedProhibits++;
     153          132 :             return false;
     154              :             /*            node = new NBNode(id1, pos.x(), pos.y(), "priority");
     155              :                         if(!myNodeCont.insert(node)) {
     156              :                              "nope, NIVissimDisturbance" << endl;
     157              :                             throw 1;
     158              :                         }*/
     159              :         }
     160            0 :         ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e1->getID()), myEdge.getPosition()), splitNode);
     161            0 :         ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e2->getID()), myDisturbance.getPosition()), splitNode);
     162              :         // !!! in some cases, one of the edges is not being build because it's too short
     163              :         // !!! what to do in these cases?
     164            0 :         NBEdge* mayDriveFrom = ec.retrieve(toString<int>(e1->getID()) + "[0]");
     165            0 :         NBEdge* mayDriveTo = ec.retrieve(toString<int>(e1->getID()) + "[1]");
     166            0 :         NBEdge* mustStopFrom = ec.retrieve(toString<int>(e2->getID()) + "[0]");
     167            0 :         NBEdge* mustStopTo = ec.retrieve(toString<int>(e2->getID()) + "[1]");
     168            0 :         if (mayDriveFrom != nullptr && mayDriveTo != nullptr && mustStopFrom != nullptr && mustStopTo != nullptr) {
     169            0 :             node->addSortedLinkFoes(
     170            0 :                 NBConnection(mayDriveFrom, mayDriveTo),
     171            0 :                 NBConnection(mayDriveFrom, mayDriveTo));
     172              :         } else {
     173            0 :             refusedProhibits++;
     174            0 :             return false;
     175              :             // !!! warning
     176              :         }
     177              : //        }
     178          289 :     } else if (pc != nullptr && bc == nullptr) {
     179              :         // The prohibited abstract edge is a connection, the other
     180              :         //  is not;
     181              :         // The connection will be prohibitesd by all connections
     182              :         //  outgoing from the "real" edge
     183              : 
     184           81 :         NBEdge* e = ec.retrievePossiblySplit(toString<int>(myDisturbance.getEdgeID()), myDisturbance.getPosition());
     185           81 :         if (e == nullptr) {
     186           12 :             WRITE_WARNINGF(TL("Could not prohibit '%' by '%'. Have not found disturbance."), toString<int>(myEdge.getEdgeID()), toString<int>(myDisturbance.getEdgeID()));
     187            6 :             refusedProhibits++;
     188           75 :             return false;
     189              :         }
     190           75 :         if (e->getFromNode() == e->getToNode()) {
     191            0 :             WRITE_WARNINGF(TL("Could not prohibit '%' by '%'. Disturbance connects same node."), toString<int>(myEdge.getEdgeID()), toString<int>(myDisturbance.getEdgeID()));
     192            0 :             refusedProhibits++;
     193              :             // What to do with self-looping edges?
     194            0 :             return false;
     195              :         }
     196              :         // get the begin of the prohibited connection
     197           75 :         std::string id_pcoe = toString<int>(pc->getFromEdgeID());
     198           75 :         std::string id_pcie = toString<int>(pc->getToEdgeID());
     199           75 :         NBEdge* const pcoe = ec.retrievePossiblySplit(id_pcoe, id_pcie, true);
     200           75 :         NBEdge* const pcie = ec.retrievePossiblySplit(id_pcie, id_pcoe, false);
     201              :         // check whether its ending node is the node the prohibited
     202              :         //  edge end at
     203           75 :         if (pcoe != nullptr && pcie != nullptr && pcoe->getToNode() == e->getToNode()) {
     204              :             // if so, simply prohibit the connections
     205              :             NBNode* const toNode = e->getToNode();
     206           12 :             for (NBEdge* const edge : e->getConnectedEdges()) {
     207            6 :                 toNode->addSortedLinkFoes(NBConnection(e, edge), NBConnection(pcoe, pcie));
     208            6 :             }
     209              :         } else {
     210          207 :             WRITE_WARNINGF(TL("Would have to split edge '%' to build a prohibition"), e->getID());
     211           69 :             refusedProhibits++;
     212              :             // quite ugly - why was it not build?
     213              :             return false;
     214              :             /*
     215              :             std::string nid1 = e->getID() + "[0]";
     216              :             std::string nid2 = e->getID() + "[1]";
     217              : 
     218              :             if(ec.splitAt(e, node)) {
     219              :                 node->addSortedLinkFoes(
     220              :                         NBConnection(
     221              :                             ec.retrieve(nid1),
     222              :                             ec.retrieve(nid2)
     223              :                         ),
     224              :                         getConnection(node, myEdge.getEdgeID())
     225              :                     );
     226              :             }
     227              :             */
     228              :         }
     229          208 :     } else if (bc != nullptr && pc == nullptr) {
     230              :         // The prohibiting abstract edge is a connection, the other
     231              :         //  is not;
     232              :         // We have to split the other one and add the prohibition
     233              :         //  description
     234              : 
     235           75 :         NBEdge* e = ec.retrievePossiblySplit(toString<int>(myEdge.getEdgeID()), myEdge.getPosition());
     236           75 :         if (e == nullptr) {
     237            0 :             WRITE_WARNINGF(TL("Could not prohibit '%' - it was not built."), toString<int>(myEdge.getEdgeID()));
     238           45 :             return false;
     239              :         }
     240           75 :         std::string nid1 = e->getID() + "[0]";
     241           75 :         std::string nid2 = e->getID() + "[1]";
     242           75 :         if (e->getFromNode() == e->getToNode()) {
     243            0 :             WRITE_WARNINGF(TL("Could not prohibit '%' by '%'."), toString<int>(myEdge.getEdgeID()), toString<int>(myDisturbance.getEdgeID()));
     244            0 :             refusedProhibits++;
     245              :             // What to do with self-looping edges?
     246            0 :             return false;
     247              :         }
     248              :         // get the begin of the prohibiting connection
     249           75 :         std::string id_bcoe = toString<int>(bc->getFromEdgeID());
     250           75 :         std::string id_bcie = toString<int>(bc->getToEdgeID());
     251           75 :         NBEdge* const bcoe = ec.retrievePossiblySplit(id_bcoe, id_bcie, true);
     252           75 :         NBEdge* const bcie = ec.retrievePossiblySplit(id_bcie, id_bcoe, false);
     253              :         // check whether its ending node is the node the prohibited
     254              :         //  edge end at
     255           75 :         if (bcoe != nullptr && bcie != nullptr && bcoe->getToNode() == e->getToNode()) {
     256              :             // if so, simply prohibit the connections
     257              :             NBNode* const toNode = e->getToNode();
     258           78 :             for (NBEdge* const edge : e->getConnectedEdges()) {
     259           48 :                 toNode->addSortedLinkFoes(NBConnection(bcoe, bcie), NBConnection(e, edge));
     260           30 :             }
     261              :         } else {
     262          135 :             WRITE_WARNINGF(TL("Would have to split edge '%' to build a prohibition"), e->getID());
     263           45 :             refusedProhibits++;
     264              :             return false;
     265              :             /*
     266              :             // quite ugly - why was it not build?
     267              :             if(ec.splitAt(e, node)) {
     268              :                 node->addSortedLinkFoes(
     269              :                         getConnection(node, myDisturbance.getEdgeID()),
     270              :                         NBConnection(
     271              :                             ec.retrieve(nid1),
     272              :                             ec.retrieve(nid2)
     273              :                         )
     274              :                     );
     275              :             }
     276              :             */
     277              :         }
     278              :     } else {
     279              :         // both the prohibiting and the prohibited abstract edges
     280              :         //  are connections
     281              :         // We can retrieve the conected edges and add the desription
     282          133 :         NBConnection conn1 = getConnection(node, myDisturbance.getEdgeID());
     283          133 :         NBConnection conn2 = getConnection(node, myEdge.getEdgeID());
     284          133 :         if (!conn1.check(ec) || !conn2.check(ec)) {
     285           36 :             refusedProhibits++;
     286              :             return false;
     287              :         }
     288           97 :         node->addSortedLinkFoes(conn1, conn2);
     289          133 :     }
     290              :     return true;
     291              : }
     292              : 
     293              : 
     294              : NBConnection
     295          266 : NIVissimDisturbance::getConnection(NBNode* node, int aedgeid) {
     296          266 :     if (NIVissimEdge::dictionary(myEdge.getEdgeID()) == nullptr) {
     297          266 :         NIVissimConnection* c = NIVissimConnection::dictionary(aedgeid);
     298              :         NBEdge* from =
     299          266 :             node->getPossiblySplittedIncoming(toString<int>(c->getFromEdgeID()));
     300              :         NBEdge* to =
     301          266 :             node->getPossiblySplittedOutgoing(toString<int>(c->getToEdgeID()));
     302              : 
     303              :         // source is a connection
     304          532 :         return NBConnection(toString<int>(c->getFromEdgeID()), from,
     305          798 :                             toString<int>(c->getToEdgeID()), to);
     306              :     } else {
     307            0 :         WRITE_WARNING(TL("NIVissimDisturbance: no connection"));
     308            0 :         return NBConnection::InvalidConnection;
     309              : //        throw 1; // !!! what to do?
     310              :     }
     311              : 
     312              : }
     313              : 
     314              : void
     315            9 : NIVissimDisturbance::clearDict() {
     316          424 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
     317          415 :         delete (*i).second;
     318              :     }
     319              :     myDict.clear();
     320            9 : }
     321              : 
     322              : 
     323              : void
     324            9 : NIVissimDisturbance::dict_SetDisturbances() {
     325          424 :     for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {
     326          415 :         NIVissimDisturbance* d = (*i).second;
     327          415 :         NIVissimAbstractEdge::dictionary(d->myEdge.getEdgeID())->addDisturbance((*i).first);
     328          415 :         NIVissimAbstractEdge::dictionary(d->myDisturbance.getEdgeID())->addDisturbance((*i).first);
     329              :     }
     330              :     /*    for(DictType::iterator i=myDict.begin(); i!=myDict.end(); i++) {
     331              :             delete (*i).second;
     332              :         }
     333              :         */
     334            9 : }
     335              : 
     336              : 
     337              : void
     338            9 : NIVissimDisturbance::reportRefused() {
     339            9 :     if (refusedProhibits > 0) {
     340            8 :         WRITE_WARNINGF(TL("Could not build % of % disturbances."), toString<int>(refusedProhibits), toString<int>((int)myDict.size()));
     341              :     }
     342            9 : }
     343              : 
     344              : 
     345              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1