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 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 2116 : NBPTStop::NBPTStop(std::string ptStopId, Position position, std::string edgeId, std::string origEdgeId, double length,
34 2116 : std::string name, SVCPermissions svcPermissions, double parkingLength, const RGBColor color, double givenStartPos) :
35 2116 : myPTStopId(ptStopId),
36 2116 : myPosition(position),
37 2116 : myEdgeId(edgeId),
38 2116 : myOrigEdgeId(origEdgeId),
39 2116 : myPTStopLength(length),
40 2116 : myName(name),
41 2116 : myParkingLength(parkingLength),
42 2116 : myColor(color),
43 2116 : myPermissions(svcPermissions),
44 2116 : myStartPos(0),
45 2116 : myEndPos(0),
46 : myBidiStop(std::weak_ptr<NBPTStop>()),
47 2116 : myIsLoose(origEdgeId == ""),
48 2116 : myIsPlatform(false),
49 2116 : myIsMultipleStopPositions(false),
50 2116 : myAreaID(-1),
51 2116 : myGivenStartPos(givenStartPos) {
52 2116 : }
53 :
54 :
55 : std::string
56 14227 : NBPTStop::getID() const {
57 14227 : return myPTStopId;
58 : }
59 :
60 :
61 : const std::string
62 38157 : NBPTStop::getOrigEdgeId() const {
63 38157 : return myOrigEdgeId;
64 : }
65 :
66 :
67 : const std::string&
68 24500 : NBPTStop::getEdgeId() const {
69 24500 : return myEdgeId;
70 : }
71 :
72 :
73 : const std::string
74 8637 : NBPTStop::getName() const {
75 8637 : return myName;
76 : }
77 :
78 :
79 : const Position&
80 7075 : NBPTStop::getPosition() const {
81 7075 : return myPosition;
82 : }
83 :
84 :
85 : void
86 59 : NBPTStop::mirrorX() {
87 : myPosition.mul(1, -1);
88 59 : }
89 :
90 :
91 : void
92 2522 : NBPTStop::addLine(const std::string& line) {
93 2522 : const std::string l = StringUtils::escapeXML(line);
94 2522 : if (std::find(myLines.begin(), myLines.end(), l) == myLines.end()) {
95 2122 : myLines.push_back(l);
96 : }
97 2522 : }
98 :
99 :
100 : void
101 765 : NBPTStop::write(OutputDevice& device) {
102 765 : device.openTag(SUMO_TAG_BUS_STOP);
103 765 : device.writeAttr(SUMO_ATTR_ID, myPTStopId);
104 765 : if (!myName.empty()) {
105 1496 : device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myName));
106 : }
107 765 : device.writeAttr(SUMO_ATTR_LANE, myLaneId);
108 765 : device.writeAttr(SUMO_ATTR_STARTPOS, myStartPos);
109 765 : device.writeAttr(SUMO_ATTR_ENDPOS, myEndPos);
110 : device.writeAttr(SUMO_ATTR_FRIENDLY_POS, "true");
111 765 : if (myLines.size() > 0) {
112 958 : device.writeAttr(SUMO_ATTR_LINES, toString(myLines));
113 : }
114 765 : if (myParkingLength > 0) {
115 0 : device.writeAttr(SUMO_ATTR_PARKING_LENGTH, myParkingLength);
116 : }
117 765 : if (myColor.isValid()) {
118 : device.writeAttr(SUMO_ATTR_COLOR, myColor);
119 : }
120 765 : if (!myAccesses.empty()) {
121 221 : std::sort(myAccesses.begin(), myAccesses.end());
122 1252 : for (auto tuple : myAccesses) {
123 1031 : 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 1031 : device.writeAttr(SUMO_ATTR_FRIENDLY_POS, true);
128 2062 : device.closeTag();
129 : }
130 : }
131 765 : writeParams(device);
132 765 : device.closeTag();
133 765 : }
134 :
135 :
136 : void
137 1650 : NBPTStop::reshiftPosition(const double offsetX, const double offsetY) {
138 : myPosition.add(offsetX, offsetY, 0);
139 2655 : for (NBPTPlatform& platformCand : myPlatformCands) {
140 1005 : platformCand.reshiftPosition(offsetX, offsetY);
141 : }
142 1650 : }
143 :
144 :
145 : SVCPermissions
146 10387 : NBPTStop::getPermissions() const {
147 10387 : return myPermissions;
148 : }
149 :
150 :
151 : void
152 1058 : NBPTStop::addPlatformCand(NBPTPlatform platform) {
153 1058 : myPlatformCands.push_back(platform);
154 1058 : }
155 :
156 :
157 : const std::vector<NBPTPlatform>&
158 1399 : NBPTStop::getPlatformCands() {
159 1399 : return myPlatformCands;
160 : }
161 :
162 :
163 : bool
164 1115 : NBPTStop::getIsMultipleStopPositions() const {
165 1115 : return myIsMultipleStopPositions;
166 : }
167 :
168 :
169 : void
170 901 : NBPTStop::setIsMultipleStopPositions(bool multipleStopPositions, long long int areaID) {
171 901 : myIsMultipleStopPositions = multipleStopPositions;
172 901 : myAreaID = areaID;
173 901 : }
174 :
175 :
176 : double
177 370 : NBPTStop::getLength() const {
178 370 : return myPTStopLength;
179 : }
180 :
181 :
182 : bool
183 336 : NBPTStop::setEdgeId(std::string edgeId, const NBEdgeCont& ec) {
184 336 : myEdgeId = edgeId;
185 336 : return findLaneAndComputeBusStopExtent(ec);
186 : }
187 :
188 :
189 : void
190 188 : NBPTStop::registerAdditionalEdge(std::string wayId, std::string edgeId) {
191 188 : myAdditionalEdgeCandidates[wayId] = edgeId;
192 188 : }
193 :
194 :
195 : bool
196 3957 : NBPTStop::findLaneAndComputeBusStopExtent(const NBEdgeCont& ec) {
197 3957 : NBEdge* edge = ec.getByID(myEdgeId);
198 3957 : return findLaneAndComputeBusStopExtent(edge);
199 : }
200 :
201 :
202 : bool
203 4421 : NBPTStop::findLaneAndComputeBusStopExtent(const NBEdge* edge) {
204 4421 : if (edge != nullptr) {
205 4280 : myEdgeId = edge->getID();
206 : int laneNr = -1;
207 5525 : for (const auto& it : edge->getLanes()) {
208 4931 : if ((it.permissions & getPermissions()) == getPermissions()) {
209 3686 : ++laneNr;
210 3686 : break;
211 : }
212 1245 : laneNr++;
213 : }
214 4280 : if (laneNr != -1) {
215 4280 : myLaneId = edge->getLaneID(laneNr);
216 4280 : const PositionVector& shape = edge->getLaneShape(laneNr);
217 4280 : double offset = shape.nearest_offset_to_point2D(getPosition(), false);
218 4280 : const double edgeLength = edge->getFinalLength();
219 4280 : offset *= edgeLength / shape.length2D();
220 4280 : if (myGivenStartPos >= 0) {
221 144 : myStartPos = myGivenStartPos;
222 144 : myEndPos = myStartPos + myPTStopLength;
223 : } else {
224 4136 : myStartPos = MAX2(0.0, offset - myPTStopLength / 2.);
225 4136 : myEndPos = MIN2(myStartPos + myPTStopLength, edgeLength);
226 4136 : double missing = myPTStopLength - (myEndPos - myStartPos);
227 4136 : if (missing > 0) {
228 2914 : myStartPos = MAX2(0.0, myStartPos - missing);
229 : }
230 : }
231 4280 : return true;
232 : }
233 : }
234 141 : return myEdgeId == ""; // loose stop. Try later when processing lines
235 : }
236 :
237 :
238 : void
239 217 : NBPTStop::clearAccess() {
240 : myAccesses.clear();
241 217 : }
242 :
243 :
244 : void
245 2784 : NBPTStop::addAccess(std::string laneID, double offset, double length) {
246 5568 : const std::string newEdgeID = SUMOXMLDefinitions::getEdgeIDFromLane(laneID);
247 : // avoid duplicate access
248 8216 : for (auto it = myAccesses.begin(); it != myAccesses.end();) {
249 10864 : if (SUMOXMLDefinitions::getEdgeIDFromLane(std::get<0>(*it)) == newEdgeID) {
250 5 : it = myAccesses.erase(it);
251 : } else {
252 : it++;
253 : }
254 : }
255 5568 : myAccesses.push_back(std::make_tuple(laneID, offset, length));
256 2784 : }
257 :
258 :
259 : bool
260 464 : NBPTStop::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
261 464 : if (myEdgeId == edgeID) {
262 : // find best edge among replacement edges
263 : double bestDist = std::numeric_limits<double>::max();
264 : NBEdge* bestEdge = nullptr;
265 1076 : for (NBEdge* cand : replacement) {
266 612 : if (myPermissions == 0 || (cand->getPermissions() & myPermissions) != 0) {
267 1224 : const double dist = cand->getGeometry().distance2D(myPosition) + MAX2(0., myPTStopLength - cand->getLoadedLength());
268 612 : if (dist < bestDist) {
269 : bestDist = dist;
270 : bestEdge = cand;
271 : }
272 : }
273 : }
274 464 : if (bestEdge != nullptr) {
275 464 : if ((bestEdge->getPermissions() & SVC_PEDESTRIAN) != 0) {
276 : // no need for access
277 217 : clearAccess();
278 : }
279 464 : return findLaneAndComputeBusStopExtent(bestEdge);
280 : }
281 : return false;
282 : }
283 : return true;
284 : }
285 :
286 :
287 : /****************************************************************************/
|