LCOV - code coverage report
Current view: top level - src/netimport/vissim/tempstructs - NIVissimDisturbance.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 105 127 82.7 %
Date: 2024-05-01 15:34:42 Functions: 13 13 100.0 %

          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        1245 : 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             : }
     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         264 :         std::string id1 = toString<int>(e1->getID()) + "x" + toString<int>(e2->getID());
     146         264 :         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             :             }
     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             :             }
     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 1.14