Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netbuild/NBPTStop.cpp
169665 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 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 NBPTStop.cpp
15
/// @author Gregor Laemmel
16
/// @date Tue, 20 Mar 2017
17
///
18
// The representation of a single pt stop
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <utils/iodevices/OutputDevice.h>
23
#include <utils/common/StringUtils.h>
24
#include "NBEdge.h"
25
#include "NBEdgeCont.h"
26
#include "NBPTPlatform.h"
27
#include "NBPTStop.h"
28
29
30
// ===========================================================================
31
// method definitions
32
// ===========================================================================
33
NBPTStop::NBPTStop(std::string ptStopId, Position position, std::string edgeId, std::string origEdgeId, double length,
34
std::string name, SVCPermissions svcPermissions, double parkingLength, const RGBColor color, double givenStartPos) :
35
myPTStopId(ptStopId),
36
myPosition(position),
37
myEdgeId(edgeId),
38
myOrigEdgeId(origEdgeId),
39
myPTStopLength(length),
40
myName(name),
41
myParkingLength(parkingLength),
42
myColor(color),
43
myPermissions(svcPermissions),
44
myStartPos(0),
45
myEndPos(0),
46
myBidiStop(std::weak_ptr<NBPTStop>()),
47
myIsLoose(origEdgeId == ""),
48
myIsPlatform(false),
49
myIsMultipleStopPositions(false),
50
myAreaID(-1),
51
myGivenStartPos(givenStartPos) {
52
}
53
54
55
std::string
56
NBPTStop::getID() const {
57
return myPTStopId;
58
}
59
60
61
const std::string
62
NBPTStop::getOrigEdgeId() const {
63
return myOrigEdgeId;
64
}
65
66
67
const std::string&
68
NBPTStop::getEdgeId() const {
69
return myEdgeId;
70
}
71
72
73
const std::string
74
NBPTStop::getName() const {
75
return myName;
76
}
77
78
79
const Position&
80
NBPTStop::getPosition() const {
81
return myPosition;
82
}
83
84
85
void
86
NBPTStop::mirrorX() {
87
myPosition.mul(1, -1);
88
}
89
90
91
void
92
NBPTStop::addLine(const std::string& line) {
93
const std::string l = StringUtils::escapeXML(line);
94
if (std::find(myLines.begin(), myLines.end(), l) == myLines.end()) {
95
myLines.push_back(l);
96
}
97
}
98
99
100
void
101
NBPTStop::write(OutputDevice& device) {
102
device.openTag(SUMO_TAG_BUS_STOP);
103
device.writeAttr(SUMO_ATTR_ID, myPTStopId);
104
if (!myName.empty()) {
105
device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myName));
106
}
107
device.writeAttr(SUMO_ATTR_LANE, myLaneId);
108
device.writeAttr(SUMO_ATTR_STARTPOS, myStartPos);
109
device.writeAttr(SUMO_ATTR_ENDPOS, myEndPos);
110
device.writeAttr(SUMO_ATTR_FRIENDLY_POS, "true");
111
if (myLines.size() > 0) {
112
device.writeAttr(SUMO_ATTR_LINES, toString(myLines));
113
}
114
if (myParkingLength > 0) {
115
device.writeAttr(SUMO_ATTR_PARKING_LENGTH, myParkingLength);
116
}
117
if (myColor.isValid()) {
118
device.writeAttr(SUMO_ATTR_COLOR, myColor);
119
}
120
if (!myAccesses.empty()) {
121
std::sort(myAccesses.begin(), myAccesses.end());
122
for (auto tuple : myAccesses) {
123
device.openTag(SUMO_TAG_ACCESS);
124
device.writeAttr(SUMO_ATTR_LANE, std::get<0>(tuple));
125
device.writeAttr(SUMO_ATTR_POSITION, std::get<1>(tuple));
126
device.writeAttr(SUMO_ATTR_LENGTH, std::get<2>(tuple));
127
device.writeAttr(SUMO_ATTR_FRIENDLY_POS, true);
128
device.closeTag();
129
}
130
}
131
writeParams(device);
132
device.closeTag();
133
}
134
135
136
void
137
NBPTStop::reshiftPosition(const double offsetX, const double offsetY) {
138
myPosition.add(offsetX, offsetY, 0);
139
for (NBPTPlatform& platformCand : myPlatformCands) {
140
platformCand.reshiftPosition(offsetX, offsetY);
141
}
142
}
143
144
145
SVCPermissions
146
NBPTStop::getPermissions() const {
147
return myPermissions;
148
}
149
150
151
void
152
NBPTStop::addPlatformCand(NBPTPlatform platform) {
153
myPlatformCands.push_back(platform);
154
}
155
156
157
const std::vector<NBPTPlatform>&
158
NBPTStop::getPlatformCands() {
159
return myPlatformCands;
160
}
161
162
163
bool
164
NBPTStop::getIsMultipleStopPositions() const {
165
return myIsMultipleStopPositions;
166
}
167
168
169
void
170
NBPTStop::setIsMultipleStopPositions(bool multipleStopPositions, long long int areaID) {
171
myIsMultipleStopPositions = multipleStopPositions;
172
myAreaID = areaID;
173
}
174
175
176
double
177
NBPTStop::getLength() const {
178
return myPTStopLength;
179
}
180
181
182
bool
183
NBPTStop::setEdgeId(std::string edgeId, const NBEdgeCont& ec) {
184
myEdgeId = edgeId;
185
return findLaneAndComputeBusStopExtent(ec);
186
}
187
188
189
void
190
NBPTStop::registerAdditionalEdge(std::string wayId, std::string edgeId) {
191
myAdditionalEdgeCandidates[wayId] = edgeId;
192
}
193
194
195
bool
196
NBPTStop::findLaneAndComputeBusStopExtent(const NBEdgeCont& ec) {
197
NBEdge* edge = ec.getByID(myEdgeId);
198
return findLaneAndComputeBusStopExtent(edge);
199
}
200
201
202
bool
203
NBPTStop::findLaneAndComputeBusStopExtent(const NBEdge* edge) {
204
if (edge != nullptr) {
205
myEdgeId = edge->getID();
206
int laneNr = -1;
207
for (const auto& it : edge->getLanes()) {
208
if ((it.permissions & getPermissions()) == getPermissions()) {
209
++laneNr;
210
break;
211
}
212
laneNr++;
213
}
214
if (laneNr != -1) {
215
myLaneId = edge->getLaneID(laneNr);
216
const PositionVector& shape = edge->getLaneShape(laneNr);
217
double offset = shape.nearest_offset_to_point2D(getPosition(), false);
218
const double edgeLength = edge->getFinalLength();
219
offset *= edgeLength / shape.length2D();
220
if (wasLoaded()) {
221
myStartPos = myGivenStartPos;
222
myEndPos = myStartPos + myPTStopLength;
223
} else {
224
myStartPos = MAX2(0.0, offset - myPTStopLength / 2.);
225
myEndPos = MIN2(myStartPos + myPTStopLength, edgeLength);
226
double missing = myPTStopLength - (myEndPos - myStartPos);
227
if (missing > 0) {
228
myStartPos = MAX2(0.0, myStartPos - missing);
229
}
230
}
231
return true;
232
}
233
}
234
return myEdgeId == ""; // loose stop. Try later when processing lines
235
}
236
237
238
void
239
NBPTStop::clearAccess() {
240
myAccesses.clear();
241
}
242
243
244
void
245
NBPTStop::addAccess(std::string laneID, double offset, double length) {
246
const std::string newEdgeID = SUMOXMLDefinitions::getEdgeIDFromLane(laneID);
247
// avoid duplicate access
248
for (auto it = myAccesses.begin(); it != myAccesses.end();) {
249
if (SUMOXMLDefinitions::getEdgeIDFromLane(std::get<0>(*it)) == newEdgeID) {
250
it = myAccesses.erase(it);
251
} else {
252
it++;
253
}
254
}
255
myAccesses.push_back(std::make_tuple(laneID, offset, length));
256
}
257
258
259
bool
260
NBPTStop::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
261
if (myEdgeId == edgeID) {
262
// find best edge among replacement edges
263
double bestDist = std::numeric_limits<double>::max();
264
NBEdge* bestEdge = nullptr;
265
for (NBEdge* cand : replacement) {
266
if (myPermissions == 0 || (cand->getPermissions() & myPermissions) != 0) {
267
const double dist = cand->getGeometry().distance2D(myPosition) + MAX2(0., myPTStopLength - cand->getLoadedLength());
268
if (dist < bestDist) {
269
bestDist = dist;
270
bestEdge = cand;
271
}
272
}
273
}
274
if (bestEdge != nullptr) {
275
if ((bestEdge->getPermissions() & SVC_PEDESTRIAN) != 0) {
276
// no need for access
277
clearAccess();
278
}
279
return findLaneAndComputeBusStopExtent(bestEdge);
280
}
281
return false;
282
}
283
return true;
284
}
285
286
287
/****************************************************************************/
288
289