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 : /****************************************************************************/
|