Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2015-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 MSParkingArea.cpp
15 : /// @author Mirco Sturari
16 : /// @author Jakob Erdmann
17 : /// @author Mirko Barthauer
18 : /// @date Tue, 19.01.2016
19 : ///
20 : // A area where vehicles can park next to the road
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <cassert>
25 : #include <utils/common/WrappingCommand.h>
26 : #include <utils/vehicle/SUMOVehicle.h>
27 : #include <utils/geom/Position.h>
28 : #include <utils/geom/GeomHelper.h>
29 : #include <microsim/MSEventControl.h>
30 : #include <microsim/MSNet.h>
31 : #include <microsim/MSVehicle.h>
32 : #include <microsim/MSVehicleType.h>
33 : #include "MSLane.h"
34 : #include <microsim/transportables/MSTransportable.h>
35 : #include "MSParkingArea.h"
36 : #include "MSGlobals.h"
37 :
38 : //#define DEBUG_RESERVATIONS
39 : //#define DEBUG_GET_LAST_FREE_POS
40 : //#define DEBUG_COND2(obj) (obj.getID() == "v.3")
41 : #define DEBUG_COND2(obj) (obj.isSelected())
42 :
43 :
44 : // ===========================================================================
45 : // method definitions
46 : // ===========================================================================
47 13247 : MSParkingArea::MSParkingArea(const std::string& id, const std::vector<std::string>& lines,
48 : const std::vector<std::string>& badges, MSLane& lane,
49 : double begPos, double endPos, int capacity, double width, double length,
50 : double angle, const std::string& name, bool onRoad,
51 13247 : const std::string& departPos, bool lefthand) :
52 : MSStoppingPlace(id, SUMO_TAG_PARKING_AREA, lines, lane, begPos, endPos, name),
53 13247 : myRoadSideCapacity(capacity),
54 13247 : myCapacity(0),
55 13247 : myOnRoad(onRoad),
56 13247 : myWidth(width),
57 13247 : myLength(length),
58 13247 : myAngle(lefthand ? -angle : angle),
59 13247 : myAcceptedBadges(badges.begin(), badges.end()),
60 13247 : myEgressBlocked(false),
61 13247 : myReservationTime(-1),
62 13247 : myReservations(0),
63 13247 : myReservationMaxLength(0),
64 13247 : myNumAlternatives(0),
65 13247 : myLastStepOccupancy(0),
66 13247 : myDepartPos(-1),
67 13247 : myDepartPosDefinition(DepartPosDefinition::DEFAULT),
68 26508 : myUpdateEvent(nullptr) {
69 : // initialize unspecified defaults
70 13247 : if (myWidth == 0) {
71 11276 : myWidth = SUMO_const_laneWidth;
72 : }
73 :
74 13247 : if (departPos != "") {
75 : std::string error;
76 58 : if (!SUMOVehicleParameter::parseDepartPos(departPos, toString(myElement), getID(), myDepartPos, myDepartPosDefinition, error)) {
77 0 : throw ProcessError(error);
78 : }
79 29 : if (myDepartPosDefinition != DepartPosDefinition::GIVEN) {
80 : // maybe allow other methods at a later time
81 0 : throw ProcessError("Only a numerical departPos is supported for " + toString(myElement) + " '" + getID() + "'");
82 29 : } else if (myDepartPos < 0 || myDepartPos > lane.getLength()) {
83 0 : throw ProcessError("Invalid departPos for " + toString(myElement) + " '" + getID() + "'");
84 : }
85 : }
86 :
87 13247 : const double offset = (MSGlobals::gLefthand != lefthand) ? -1 : 1;
88 26494 : myShape = lane.getShape().getSubpart(
89 : lane.interpolateLanePosToGeometryPos(begPos),
90 : lane.interpolateLanePosToGeometryPos(endPos));
91 13247 : if (!myOnRoad) {
92 13186 : myShape.move2side((lane.getWidth() / 2. + myWidth / 2.) * offset);
93 : }
94 13247 : setRoadsideCapacity(capacity);
95 13247 : }
96 :
97 :
98 25756 : MSParkingArea::~MSParkingArea() {}
99 :
100 :
101 : void
102 48499 : MSParkingArea::addLotEntry(double x, double y, double z, double width, double length, double angle, double slope) {
103 : // create LotSpaceDefinition
104 48499 : LotSpaceDefinition lsd((int)mySpaceOccupancies.size(), nullptr, x, y, z, angle, slope, width, length);
105 : // If we are modelling parking set the end position to the lot position relative to the lane
106 : // rather than the end of the parking area - this results in vehicles stopping nearer the space
107 : // and re-entering the lane nearer the space. (If we are not modelling parking the vehicle will usually
108 : // enter the space and re-enter at the end of the parking area.)
109 48499 : if (MSGlobals::gModelParkingManoeuver) {
110 30 : const double offset = this->getLane().getShape().nearest_offset_to_point2D(lsd.position);
111 30 : if (offset < getBeginLanePosition()) {
112 0 : lsd.endPos = getBeginLanePosition() + POSITION_EPS;
113 : } else {
114 30 : if (this->getLane().getLength() > offset) {
115 30 : lsd.endPos = offset;
116 : } else {
117 0 : lsd.endPos = this->getLane().getLength() - POSITION_EPS;
118 : }
119 : }
120 : // Work out the angle of the lot relative to the lane (-90 adjusts for the way the bay is drawn )
121 30 : double relativeAngle = fmod(lsd.rotation - 90., 360) - fmod(RAD2DEG(this->getLane().getShape().rotationAtOffset(lsd.endPos)), 360) + 0.5;
122 30 : if (relativeAngle < 0.) {
123 10 : relativeAngle += 360.;
124 : }
125 30 : lsd.manoeuverAngle = relativeAngle;
126 :
127 : // if p2.y is -ve the lot is on LHS of lane relative to lane direction
128 : // we need to know this because it inverts the complexity of the parking manoeuver
129 30 : Position p2 = this->getLane().getShape().transformToVectorCoordinates(lsd.position);
130 30 : if (p2.y() < (0. + POSITION_EPS)) {
131 30 : lsd.sideIsLHS = true;
132 : } else {
133 0 : lsd.sideIsLHS = false;
134 : }
135 : } else {
136 48469 : lsd.endPos = myEndPos;
137 48469 : lsd.manoeuverAngle = int(angle); // unused unless gModelParkingManoeuver is true
138 48469 : lsd.sideIsLHS = true;
139 : }
140 48499 : mySpaceOccupancies.push_back(lsd);
141 48499 : myCapacity++;
142 48499 : computeLastFreePos();
143 48499 : }
144 :
145 : int
146 30 : MSParkingArea::getLastFreeLotAngle() const {
147 : assert(myLastFreeLot >= 0);
148 : assert(myLastFreeLot < (int)mySpaceOccupancies.size());
149 :
150 30 : const LotSpaceDefinition& lsd = mySpaceOccupancies[myLastFreeLot];
151 30 : if (lsd.sideIsLHS) {
152 30 : return abs(int(lsd.manoeuverAngle)) % 180;
153 : } else {
154 0 : return abs(abs(int(lsd.manoeuverAngle)) % 180 - 180) % 180;
155 : }
156 : }
157 :
158 : double
159 30 : MSParkingArea::getLastFreeLotGUIAngle() const {
160 : assert(myLastFreeLot >= 0);
161 : assert(myLastFreeLot < (int)mySpaceOccupancies.size());
162 :
163 30 : const LotSpaceDefinition& lsd = mySpaceOccupancies[myLastFreeLot];
164 30 : if (lsd.manoeuverAngle > 180.) {
165 15 : return DEG2RAD(lsd.manoeuverAngle - 360.);
166 : } else {
167 15 : return DEG2RAD(lsd.manoeuverAngle);
168 : }
169 : }
170 :
171 :
172 : double
173 1322654 : MSParkingArea::getLastFreePos(const SUMOVehicle& forVehicle, double brakePos) const {
174 1322654 : if (myCapacity == (int)myEndPositions.size()) {
175 : // keep enough space so that parking vehicles can leave
176 : #ifdef DEBUG_GET_LAST_FREE_POS
177 : if (DEBUG_COND2(forVehicle)) {
178 : std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " allOccupied\n";
179 : }
180 : #endif
181 762629 : return myLastFreePos - forVehicle.getVehicleType().getMinGap() - POSITION_EPS;
182 : } else {
183 560025 : const double minPos = MIN2(myEndPos, brakePos);
184 560025 : if (myLastFreePos >= minPos) {
185 : #ifdef DEBUG_GET_LAST_FREE_POS
186 : if (DEBUG_COND2(forVehicle)) {
187 : std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " brakePos=" << brakePos << " myEndPos=" << myEndPos << " using myLastFreePos=" << myLastFreePos << "\n";
188 : }
189 : #endif
190 : return myLastFreePos;
191 : } else {
192 : // find free pos after minPos
193 39490 : for (const auto& lsd : mySpaceOccupancies) {
194 38773 : if (lsd.vehicle == nullptr && lsd.endPos >= minPos) {
195 : #ifdef DEBUG_GET_LAST_FREE_POS
196 : if (DEBUG_COND2(forVehicle)) {
197 : std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " brakePos=" << brakePos << " myEndPos=" << myEndPos << " nextFreePos=" << lsd.endPos << "\n";
198 : }
199 : #endif
200 : return lsd.endPos;
201 : }
202 : }
203 : // shouldn't happen. No good solution seems possible
204 : #ifdef DEBUG_GET_LAST_FREE_POS
205 : if (DEBUG_COND2(forVehicle)) {
206 : std::cout << SIMTIME << " getLastFreePos veh=" << forVehicle.getID() << " brakePos=" << brakePos << " myEndPos=" << myEndPos << " noGoodFreePos blockedAt=" << brakePos << "\n";
207 : }
208 : #endif
209 : return brakePos;
210 : }
211 : }
212 : }
213 :
214 : Position
215 14022 : MSParkingArea::getVehiclePosition(const SUMOVehicle& forVehicle) const {
216 34080 : for (const auto& lsd : mySpaceOccupancies) {
217 34080 : if (lsd.vehicle == &forVehicle) {
218 14022 : return lsd.position;
219 : }
220 : }
221 0 : return Position::INVALID;
222 : }
223 :
224 :
225 : double
226 69055 : MSParkingArea::getInsertionPosition(const SUMOVehicle& forVehicle) const {
227 69055 : if (myDepartPosDefinition == DepartPosDefinition::GIVEN) {
228 250 : return myDepartPos;
229 : }
230 193991 : for (const auto& lsd : mySpaceOccupancies) {
231 193983 : if (lsd.vehicle == &forVehicle) {
232 68797 : return lsd.endPos;
233 : }
234 : }
235 : return -1;
236 : }
237 :
238 :
239 : double
240 12588 : MSParkingArea::getVehicleAngle(const SUMOVehicle& forVehicle) const {
241 34386 : for (const auto& lsd : mySpaceOccupancies) {
242 34369 : if (lsd.vehicle == &forVehicle) {
243 12571 : return (lsd.rotation - 90.) * (double) M_PI / (double) 180.0;
244 : }
245 : }
246 : return 0;
247 : }
248 :
249 : double
250 3621 : MSParkingArea::getVehicleSlope(const SUMOVehicle& forVehicle) const {
251 12171 : for (const auto& lsd : mySpaceOccupancies) {
252 12171 : if (lsd.vehicle == &forVehicle) {
253 3621 : return lsd.slope;
254 : }
255 : }
256 : return 0;
257 : }
258 :
259 : double
260 30 : MSParkingArea::getGUIAngle(const SUMOVehicle& forVehicle) const {
261 60 : for (const auto& lsd : mySpaceOccupancies) {
262 60 : if (lsd.vehicle == &forVehicle) {
263 30 : if (lsd.manoeuverAngle > 180.) {
264 15 : return DEG2RAD(lsd.manoeuverAngle - 360.);
265 : } else {
266 15 : return DEG2RAD(lsd.manoeuverAngle);
267 : }
268 : }
269 : }
270 : return 0.;
271 : }
272 :
273 : int
274 30 : MSParkingArea::getManoeuverAngle(const SUMOVehicle& forVehicle) const {
275 60 : for (const auto& lsd : mySpaceOccupancies) {
276 60 : if (lsd.vehicle == &forVehicle) {
277 30 : if (lsd.sideIsLHS) {
278 30 : return abs(int(lsd.manoeuverAngle)) % 180;
279 : } else {
280 0 : return abs(abs(int(lsd.manoeuverAngle)) % 180 - 180) % 180;
281 : }
282 : }
283 : }
284 : return 0;
285 : }
286 :
287 : int
288 46612 : MSParkingArea::getLotIndex(const SUMOVehicle* veh) const {
289 46612 : if (veh->getPositionOnLane() > myLastFreePos) {
290 : // vehicle has gone past myLastFreePos and we need to find the actual lot
291 : int closestLot = -1;
292 10030 : for (int i = 0; i < (int)mySpaceOccupancies.size(); i++) {
293 9695 : const LotSpaceDefinition lsd = mySpaceOccupancies[i];
294 9695 : if (lsd.vehicle == nullptr) {
295 : closestLot = i;
296 3770 : if (lsd.endPos >= veh->getPositionOnLane()) {
297 : return i;
298 : }
299 : }
300 : }
301 335 : return closestLot;
302 : }
303 44891 : if (myOnRoad && myLastFreePos - veh->getPositionOnLane() > POSITION_EPS) {
304 : // for on-road parking we need to be precise
305 : return -1;
306 : }
307 7138 : return myLastFreeLot;
308 : }
309 :
310 : void
311 7318 : MSParkingArea::enter(SUMOVehicle* veh) {
312 7318 : double beg = veh->getPositionOnLane() + veh->getVehicleType().getMinGap();
313 7318 : double end = veh->getPositionOnLane() - veh->getVehicleType().getLength();
314 7318 : if (myUpdateEvent == nullptr) {
315 6915 : myUpdateEvent = new WrappingCommand<MSParkingArea>(this, &MSParkingArea::updateOccupancy);
316 6915 : MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(myUpdateEvent);
317 : }
318 7318 : int lotIndex = getLotIndex(veh);
319 7318 : if (lotIndex < 0) {
320 0 : WRITE_WARNING("Unsuitable parking position for vehicle '" + veh->getID() + "' at parkingArea '" + getID() + "' time=" + time2string(SIMSTEP));
321 0 : lotIndex = myLastFreeLot;
322 : }
323 : #ifdef DEBUG_GET_LAST_FREE_POS
324 : ((SUMOVehicleParameter&)veh->getParameter()).setParameter("lotIndex", toString(lotIndex));
325 : #endif
326 : assert(myLastFreePos >= 0);
327 : assert(lotIndex < (int)mySpaceOccupancies.size());
328 7318 : mySpaceOccupancies[lotIndex].vehicle = veh;
329 7318 : myEndPositions[veh] = std::pair<double, double>(beg, end);
330 7318 : computeLastFreePos();
331 : // current search ends here
332 7318 : veh->setNumberParkingReroutes(0);
333 7318 : }
334 :
335 :
336 : void
337 6073 : MSParkingArea::leaveFrom(SUMOVehicle* what) {
338 : assert(myEndPositions.find(what) != myEndPositions.end());
339 6073 : if (myUpdateEvent == nullptr) {
340 5998 : myUpdateEvent = new WrappingCommand<MSParkingArea>(this, &MSParkingArea::updateOccupancy);
341 5998 : MSNet::getInstance()->getEndOfTimestepEvents()->addEvent(myUpdateEvent);
342 : }
343 17874 : for (auto& lsd : mySpaceOccupancies) {
344 17874 : if (lsd.vehicle == what) {
345 6073 : lsd.vehicle = nullptr;
346 6073 : break;
347 : }
348 : }
349 : myEndPositions.erase(myEndPositions.find(what));
350 6073 : computeLastFreePos();
351 6073 : }
352 :
353 :
354 : SUMOTime
355 12913 : MSParkingArea::updateOccupancy(SUMOTime /* currentTime */) {
356 12913 : myLastStepOccupancy = getOccupancy();
357 12913 : myUpdateEvent = nullptr;
358 12913 : return 0;
359 : }
360 :
361 :
362 0 : MSParkingArea::LotSpaceDefinition::LotSpaceDefinition() :
363 0 : index(-1),
364 0 : vehicle(nullptr),
365 0 : rotation(0),
366 0 : slope(0),
367 0 : width(0),
368 0 : length(0),
369 0 : endPos(0),
370 0 : manoeuverAngle(0),
371 0 : sideIsLHS(false) {
372 0 : }
373 :
374 :
375 48499 : MSParkingArea::LotSpaceDefinition::LotSpaceDefinition(int index_, SUMOVehicle* vehicle_, double x, double y, double z, double rotation_, double slope_, double width_, double length_) :
376 48499 : index(index_),
377 48499 : vehicle(vehicle_),
378 : position(Position(x, y, z)),
379 48499 : rotation(rotation_),
380 48499 : slope(slope_),
381 48499 : width(width_),
382 48499 : length(length_),
383 48499 : endPos(0),
384 48499 : manoeuverAngle(0),
385 48499 : sideIsLHS(false) {
386 48499 : }
387 :
388 :
389 : void
390 63005 : MSParkingArea::computeLastFreePos() {
391 63005 : myLastFreeLot = -1;
392 63005 : myLastFreePos = myBegPos;
393 63005 : myEgressBlocked = false;
394 89710 : for (auto& lsd : mySpaceOccupancies) {
395 87240 : if (lsd.vehicle == nullptr
396 87240 : || (getOccupancy() == getCapacity()
397 8156 : && lsd.vehicle->remainingStopDuration() <= 0
398 959 : && !lsd.vehicle->isStoppedTriggered())) {
399 60535 : if (lsd.vehicle == nullptr) {
400 59679 : myLastFreeLot = lsd.index;
401 59679 : myLastFreePos = lsd.endPos;
402 : } else {
403 : // vehicle wants to exit the parking area
404 856 : myLastFreeLot = lsd.index;
405 856 : myLastFreePos = lsd.endPos - lsd.vehicle->getVehicleType().getLength() - POSITION_EPS;
406 856 : myEgressBlocked = true;
407 : }
408 : break;
409 : } else {
410 26705 : myLastFreePos = MIN2(myLastFreePos,
411 26705 : lsd.endPos - lsd.vehicle->getVehicleType().getLength() - NUMERICAL_EPS);
412 : }
413 : }
414 63005 : }
415 :
416 :
417 : double
418 731865 : MSParkingArea::getLastFreePosWithReservation(SUMOTime t, const SUMOVehicle& forVehicle, double brakePos) {
419 731865 : if (forVehicle.getLane() != &myLane) {
420 : // for different lanes, do not consider reservations to avoid lane-order
421 : // dependency in parallel simulation
422 : #ifdef DEBUG_RESERVATIONS
423 : if (DEBUG_COND2(forVehicle)) {
424 : std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID() << " other lane\n";
425 : }
426 : #endif
427 559426 : if (myNumAlternatives > 0 && getOccupancy() == getCapacity()) {
428 : // ensure that the vehicle reaches the rerouter lane
429 154687 : return MAX2(myBegPos, MIN2(POSITION_EPS, myEndPos));
430 : } else {
431 404739 : return getLastFreePos(forVehicle, brakePos);
432 : }
433 : }
434 172439 : if (t > myReservationTime) {
435 : #ifdef DEBUG_RESERVATIONS
436 : if (DEBUG_COND2(forVehicle)) {
437 : std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID() << " first reservation\n";
438 : }
439 : #endif
440 91782 : myReservationTime = t;
441 91782 : myReservations = 1;
442 91782 : myReservationMaxLength = forVehicle.getVehicleType().getLength();
443 868629 : for (const auto& lsd : mySpaceOccupancies) {
444 776847 : if (lsd.vehicle != nullptr) {
445 456202 : myReservationMaxLength = MAX2(myReservationMaxLength, lsd.vehicle->getVehicleType().getLength());
446 : }
447 : }
448 91782 : return getLastFreePos(forVehicle, brakePos);
449 : } else {
450 80657 : if (myCapacity > getOccupancy() + myReservations) {
451 : #ifdef DEBUG_RESERVATIONS
452 : if (DEBUG_COND2(forVehicle)) {
453 : std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID() << " res=" << myReservations << " enough space\n";
454 : }
455 : #endif
456 34823 : myReservations++;
457 34823 : myReservationMaxLength = MAX2(myReservationMaxLength, forVehicle.getVehicleType().getLength());
458 34823 : return getLastFreePos(forVehicle, brakePos);
459 : } else {
460 45834 : if (myCapacity == 0) {
461 620 : return getLastFreePos(forVehicle, brakePos);
462 : } else {
463 : #ifdef DEBUG_RESERVATIONS
464 : if (DEBUG_COND2(forVehicle)) std::cout << SIMTIME << " pa=" << getID() << " freePosRes veh=" << forVehicle.getID()
465 : << " res=" << myReservations << " resTime=" << myReservationTime << " reserved full, maxLen=" << myReservationMaxLength << " endPos=" << mySpaceOccupancies[0].endPos << "\n";
466 : #endif
467 45214 : return (mySpaceOccupancies[0].endPos
468 45214 : - myReservationMaxLength
469 45214 : - forVehicle.getVehicleType().getMinGap()
470 45214 : - NUMERICAL_EPS);
471 : }
472 : }
473 : }
474 : }
475 :
476 :
477 : double
478 600 : MSParkingArea::getWidth() const {
479 600 : return myWidth;
480 : }
481 :
482 :
483 : double
484 600 : MSParkingArea::getLength() const {
485 600 : return myLength;
486 : }
487 :
488 :
489 : double
490 600 : MSParkingArea::getAngle() const {
491 600 : return myAngle;
492 : }
493 :
494 :
495 : int
496 741889 : MSParkingArea::getCapacity() const {
497 741889 : return myCapacity;
498 : }
499 :
500 :
501 : bool
502 381089 : MSParkingArea::parkOnRoad() const {
503 381089 : return myOnRoad;
504 : }
505 :
506 :
507 : int
508 583114 : MSParkingArea::getOccupancy() const {
509 583114 : return (int)myEndPositions.size() - (myEgressBlocked ? 1 : 0);
510 : }
511 :
512 :
513 : int
514 139520 : MSParkingArea::getOccupancyIncludingBlocked() const {
515 139520 : return (int)myEndPositions.size();
516 : }
517 :
518 :
519 : int
520 49280 : MSParkingArea::getLastStepOccupancy() const {
521 49280 : return myLastStepOccupancy;
522 : }
523 :
524 :
525 : void
526 0 : MSParkingArea::accept(std::string badge) {
527 : myAcceptedBadges.insert(badge);
528 0 : }
529 :
530 :
531 : void
532 0 : MSParkingArea::accept(std::vector<std::string> badges) {
533 : myAcceptedBadges.insert(badges.begin(), badges.end());
534 0 : }
535 :
536 :
537 : void
538 0 : MSParkingArea::refuse(std::string badge) {
539 : myAcceptedBadges.erase(badge);
540 0 : }
541 :
542 :
543 : bool
544 16338 : MSParkingArea::accepts(MSBaseVehicle* veh) const {
545 16338 : if (myAcceptedBadges.size() == 0) {
546 : return true;
547 : } else {
548 21 : std::vector<std::string> vehicleBadges = veh->getParkingBadges();
549 21 : for (auto badge : vehicleBadges) {
550 : if (myAcceptedBadges.count(badge) != 0) {
551 : return true;
552 : }
553 : }
554 7 : return false;
555 21 : }
556 : }
557 :
558 :
559 : void
560 1115 : MSParkingArea::notifyEgressBlocked() {
561 1115 : computeLastFreePos();
562 1115 : }
563 :
564 :
565 : int
566 0 : MSParkingArea::getNumAlternatives() const {
567 0 : return myNumAlternatives;
568 : }
569 :
570 :
571 : void
572 12087 : MSParkingArea::setNumAlternatives(int alternatives) {
573 12087 : myNumAlternatives = MAX2(myNumAlternatives, alternatives);
574 12087 : }
575 :
576 :
577 : std::vector<std::string>
578 20 : MSParkingArea::getAcceptedBadges() const {
579 20 : std::vector<std::string> result(myAcceptedBadges.begin(), myAcceptedBadges.end());
580 20 : return result;
581 : }
582 :
583 :
584 : void
585 10 : MSParkingArea::setAcceptedBadges(const std::vector<std::string>& badges) {
586 : myAcceptedBadges.clear();
587 : myAcceptedBadges.insert(badges.begin(), badges.end());
588 10 : }
589 :
590 :
591 : void
592 22872 : MSParkingArea::setRoadsideCapacity(int capacity) {
593 : // reinit parking lot generation process
594 22872 : myRoadSideCapacity = capacity;
595 :
596 : // Initialize space occupancies if there is a road-side capacity
597 : // The overall number of lots is fixed and each lot accepts one vehicle regardless of size
598 22872 : const double spaceDim = myRoadSideCapacity > 0 ? myLane.interpolateLanePosToGeometryPos((myEndPos - myBegPos) / myRoadSideCapacity) : 7.5;
599 22872 : if (myLength == 0) {
600 10547 : myLength = spaceDim;
601 : }
602 : mySpaceOccupancies.clear();
603 22872 : myCapacity = 0;
604 70771 : for (int i = 0; i < myRoadSideCapacity; ++i) {
605 : // calculate pos, angle and slope of parking lot space
606 47899 : const Position pos = GeomHelper::calculateLotSpacePosition(myShape, i, spaceDim, myAngle, myWidth, myLength);
607 47899 : double spaceAngle = GeomHelper::calculateLotSpaceAngle(myShape, i, spaceDim, myAngle);
608 47899 : double spaceSlope = GeomHelper::calculateLotSpaceSlope(myShape, i, spaceDim);
609 : // add lotEntry
610 47899 : addLotEntry(pos.x(), pos.y(), pos.z(), myWidth, myLength, spaceAngle, spaceSlope);
611 : // update endPos
612 141715 : mySpaceOccupancies.back().endPos = MIN2(myEndPos, myBegPos + MAX2(POSITION_EPS, spaceDim * (i + 1)));
613 : }
614 22872 : }
615 :
616 : /****************************************************************************/
|