Path: blob/main/src/netimport/vissim/tempstructs/NIVissimDisturbance.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 NIVissimDisturbance.cpp14/// @author Daniel Krajzewicz15/// @author Michael Behrisch16/// @date Sept 200217///18// -------------------19/****************************************************************************/20#include <config.h>212223#include <map>24#include <string>25#include <iostream>26#include <cassert>27#include <utils/common/ToString.h>28#include <utils/common/MsgHandler.h>29#include <utils/geom/GeomHelper.h>30#include <utils/geom/Boundary.h>31#include <netbuild/NBEdge.h>32#include <netbuild/NBNode.h>33#include <netbuild/NBEdgeCont.h>34#include <netbuild/NBNodeCont.h>35#include "NIVissimEdge.h"36#include "NIVissimConnection.h"37#include "NIVissimNodeDef.h"38#include "NIVissimDisturbance.h"39#include "NIVissimNodeParticipatingEdgeVector.h"404142// ===========================================================================43// static member variables44// ===========================================================================45NIVissimDisturbance::DictType NIVissimDisturbance::myDict;46int NIVissimDisturbance::myRunningID = 100000000;4748int NIVissimDisturbance::refusedProhibits = 0;495051// ===========================================================================52// method definitions53// ===========================================================================54NIVissimDisturbance::NIVissimDisturbance(int id,55const std::string& name,56const NIVissimExtendedEdgePoint& edge,57const NIVissimExtendedEdgePoint& by)58: myID(id), myNode(-1), myName(name), myEdge(edge), myDisturbance(by) {}596061NIVissimDisturbance::~NIVissimDisturbance() {}62636465bool66NIVissimDisturbance::dictionary(const std::string& name,67const NIVissimExtendedEdgePoint& edge,68const NIVissimExtendedEdgePoint& by) {69int nid = myRunningID++;70NIVissimDisturbance* o =71new NIVissimDisturbance(nid, name, edge, by);72if (!dictionary(nid, o)) {73delete o;74}75return true;76}777879bool80NIVissimDisturbance::dictionary(int id, NIVissimDisturbance* o) {81DictType::iterator i = myDict.find(id);82if (i == myDict.end()) {83myDict[id] = o;84return true;85}86return false;87}888990NIVissimDisturbance*91NIVissimDisturbance::dictionary(int id) {92DictType::iterator i = myDict.find(id);93if (i == myDict.end()) {94return nullptr;95}96return (*i).second;97}9899std::vector<int>100NIVissimDisturbance::getWithin(const AbstractPoly& poly) {101std::vector<int> ret;102for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {103if ((*i).second->crosses(poly)) {104ret.push_back((*i).second->myID);105}106}107return ret;108}109110111void112NIVissimDisturbance::computeBounding() {113assert(myBoundary == 0);114Boundary* bound = new Boundary();115if (NIVissimAbstractEdge::dictionary(myEdge.getEdgeID()) != nullptr) {116bound->add(myEdge.getGeomPosition());117}118if (NIVissimAbstractEdge::dictionary(myDisturbance.getEdgeID()) != nullptr) {119bound->add(myDisturbance.getGeomPosition());120}121myBoundary = bound;122assert(myBoundary != 0 && myBoundary->xmax() >= myBoundary->xmin());123}124125126127bool128NIVissimDisturbance::addToNode(NBNode* node, NBDistrictCont& dc,129NBNodeCont& nc, NBEdgeCont& ec) {130myNode = 0;131NIVissimConnection* pc =132NIVissimConnection::dictionary(myEdge.getEdgeID());133NIVissimConnection* bc =134NIVissimConnection::dictionary(myDisturbance.getEdgeID());135if (pc == nullptr && bc == nullptr) {136// This has not been tested completely, yet137// Both competing abstract edges are normal edges138// We have to find a crossing point, build a node here,139// split both edges and add the connections140NIVissimEdge* e1 = NIVissimEdge::dictionary(myEdge.getEdgeID());141NIVissimEdge* e2 = NIVissimEdge::dictionary(myDisturbance.getEdgeID());142WRITE_WARNINGF(TL("Ugly split to prohibit '%' by '%'."), toString<int>(e1->getID()), toString<int>(e2->getID()));143//Position pos = e1->crossesEdgeAtPoint(e2);144std::string id1 = toString<int>(e1->getID()) + "x" + toString<int>(e2->getID());145std::string id2 = toString<int>(e2->getID()) + "x" + toString<int>(e1->getID());146NBNode* node1 = nc.retrieve(id1);147NBNode* node2 = nc.retrieve(id2);148NBNode* splitNode = node1 == nullptr ? node2 : node1;149assert(node1 == nullptr || node2 == nullptr);150if (splitNode == nullptr) {151refusedProhibits++;152return false;153/* node = new NBNode(id1, pos.x(), pos.y(), "priority");154if(!myNodeCont.insert(node)) {155"nope, NIVissimDisturbance" << endl;156throw 1;157}*/158}159ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e1->getID()), myEdge.getPosition()), splitNode);160ec.splitAt(dc, ec.retrievePossiblySplit(toString<int>(e2->getID()), myDisturbance.getPosition()), splitNode);161// !!! in some cases, one of the edges is not being build because it's too short162// !!! what to do in these cases?163NBEdge* mayDriveFrom = ec.retrieve(toString<int>(e1->getID()) + "[0]");164NBEdge* mayDriveTo = ec.retrieve(toString<int>(e1->getID()) + "[1]");165NBEdge* mustStopFrom = ec.retrieve(toString<int>(e2->getID()) + "[0]");166NBEdge* mustStopTo = ec.retrieve(toString<int>(e2->getID()) + "[1]");167if (mayDriveFrom != nullptr && mayDriveTo != nullptr && mustStopFrom != nullptr && mustStopTo != nullptr) {168node->addSortedLinkFoes(169NBConnection(mayDriveFrom, mayDriveTo),170NBConnection(mayDriveFrom, mayDriveTo));171} else {172refusedProhibits++;173return false;174// !!! warning175}176// }177} else if (pc != nullptr && bc == nullptr) {178// The prohibited abstract edge is a connection, the other179// is not;180// The connection will be prohibitesd by all connections181// outgoing from the "real" edge182183NBEdge* e = ec.retrievePossiblySplit(toString<int>(myDisturbance.getEdgeID()), myDisturbance.getPosition());184if (e == nullptr) {185WRITE_WARNINGF(TL("Could not prohibit '%' by '%'. Have not found disturbance."), toString<int>(myEdge.getEdgeID()), toString<int>(myDisturbance.getEdgeID()));186refusedProhibits++;187return false;188}189if (e->getFromNode() == e->getToNode()) {190WRITE_WARNINGF(TL("Could not prohibit '%' by '%'. Disturbance connects same node."), toString<int>(myEdge.getEdgeID()), toString<int>(myDisturbance.getEdgeID()));191refusedProhibits++;192// What to do with self-looping edges?193return false;194}195// get the begin of the prohibited connection196std::string id_pcoe = toString<int>(pc->getFromEdgeID());197std::string id_pcie = toString<int>(pc->getToEdgeID());198NBEdge* const pcoe = ec.retrievePossiblySplit(id_pcoe, id_pcie, true);199NBEdge* const pcie = ec.retrievePossiblySplit(id_pcie, id_pcoe, false);200// check whether its ending node is the node the prohibited201// edge end at202if (pcoe != nullptr && pcie != nullptr && pcoe->getToNode() == e->getToNode()) {203// if so, simply prohibit the connections204NBNode* const toNode = e->getToNode();205for (NBEdge* const edge : e->getConnectedEdges()) {206toNode->addSortedLinkFoes(NBConnection(e, edge), NBConnection(pcoe, pcie));207}208} else {209WRITE_WARNINGF(TL("Would have to split edge '%' to build a prohibition"), e->getID());210refusedProhibits++;211// quite ugly - why was it not build?212return false;213/*214std::string nid1 = e->getID() + "[0]";215std::string nid2 = e->getID() + "[1]";216217if(ec.splitAt(e, node)) {218node->addSortedLinkFoes(219NBConnection(220ec.retrieve(nid1),221ec.retrieve(nid2)222),223getConnection(node, myEdge.getEdgeID())224);225}226*/227}228} else if (bc != nullptr && pc == nullptr) {229// The prohibiting abstract edge is a connection, the other230// is not;231// We have to split the other one and add the prohibition232// description233234NBEdge* e = ec.retrievePossiblySplit(toString<int>(myEdge.getEdgeID()), myEdge.getPosition());235if (e == nullptr) {236WRITE_WARNINGF(TL("Could not prohibit '%' - it was not built."), toString<int>(myEdge.getEdgeID()));237return false;238}239std::string nid1 = e->getID() + "[0]";240std::string nid2 = e->getID() + "[1]";241if (e->getFromNode() == e->getToNode()) {242WRITE_WARNINGF(TL("Could not prohibit '%' by '%'."), toString<int>(myEdge.getEdgeID()), toString<int>(myDisturbance.getEdgeID()));243refusedProhibits++;244// What to do with self-looping edges?245return false;246}247// get the begin of the prohibiting connection248std::string id_bcoe = toString<int>(bc->getFromEdgeID());249std::string id_bcie = toString<int>(bc->getToEdgeID());250NBEdge* const bcoe = ec.retrievePossiblySplit(id_bcoe, id_bcie, true);251NBEdge* const bcie = ec.retrievePossiblySplit(id_bcie, id_bcoe, false);252// check whether its ending node is the node the prohibited253// edge end at254if (bcoe != nullptr && bcie != nullptr && bcoe->getToNode() == e->getToNode()) {255// if so, simply prohibit the connections256NBNode* const toNode = e->getToNode();257for (NBEdge* const edge : e->getConnectedEdges()) {258toNode->addSortedLinkFoes(NBConnection(bcoe, bcie), NBConnection(e, edge));259}260} else {261WRITE_WARNINGF(TL("Would have to split edge '%' to build a prohibition"), e->getID());262refusedProhibits++;263return false;264/*265// quite ugly - why was it not build?266if(ec.splitAt(e, node)) {267node->addSortedLinkFoes(268getConnection(node, myDisturbance.getEdgeID()),269NBConnection(270ec.retrieve(nid1),271ec.retrieve(nid2)272)273);274}275*/276}277} else {278// both the prohibiting and the prohibited abstract edges279// are connections280// We can retrieve the conected edges and add the desription281NBConnection conn1 = getConnection(node, myDisturbance.getEdgeID());282NBConnection conn2 = getConnection(node, myEdge.getEdgeID());283if (!conn1.check(ec) || !conn2.check(ec)) {284refusedProhibits++;285return false;286}287node->addSortedLinkFoes(conn1, conn2);288}289return true;290}291292293NBConnection294NIVissimDisturbance::getConnection(NBNode* node, int aedgeid) {295if (NIVissimEdge::dictionary(myEdge.getEdgeID()) == nullptr) {296NIVissimConnection* c = NIVissimConnection::dictionary(aedgeid);297NBEdge* from =298node->getPossiblySplittedIncoming(toString<int>(c->getFromEdgeID()));299NBEdge* to =300node->getPossiblySplittedOutgoing(toString<int>(c->getToEdgeID()));301302// source is a connection303return NBConnection(toString<int>(c->getFromEdgeID()), from,304toString<int>(c->getToEdgeID()), to);305} else {306WRITE_WARNING(TL("NIVissimDisturbance: no connection"));307return NBConnection::InvalidConnection;308// throw 1; // !!! what to do?309}310311}312313void314NIVissimDisturbance::clearDict() {315for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {316delete (*i).second;317}318myDict.clear();319}320321322void323NIVissimDisturbance::dict_SetDisturbances() {324for (DictType::iterator i = myDict.begin(); i != myDict.end(); i++) {325NIVissimDisturbance* d = (*i).second;326NIVissimAbstractEdge::dictionary(d->myEdge.getEdgeID())->addDisturbance((*i).first);327NIVissimAbstractEdge::dictionary(d->myDisturbance.getEdgeID())->addDisturbance((*i).first);328}329/* for(DictType::iterator i=myDict.begin(); i!=myDict.end(); i++) {330delete (*i).second;331}332*/333}334335336void337NIVissimDisturbance::reportRefused() {338if (refusedProhibits > 0) {339WRITE_WARNINGF(TL("Could not build % of % disturbances."), toString<int>(refusedProhibits), toString<int>((int)myDict.size()));340}341}342343344/****************************************************************************/345346347