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