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