Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNEParkingArea.cpp
169684 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 GNEParkingArea.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Feb 2018
17
///
18
// A lane area vehicles can park at (GNE version)
19
/****************************************************************************/
20
21
#include <netedit/GNENet.h>
22
#include <netedit/GNETagProperties.h>
23
#include <netedit/changes/GNEChange_Attribute.h>
24
#include <utils/gui/div/GLHelper.h>
25
#include <utils/options/OptionsCont.h>
26
#include <utils/vehicle/SUMORouteHandler.h>
27
28
#include "GNEParkingArea.h"
29
30
// ===========================================================================
31
// method definitions
32
// ===========================================================================
33
34
GNEParkingArea::GNEParkingArea(GNENet* net) :
35
GNEStoppingPlace(net, SUMO_TAG_PARKING_AREA) {
36
}
37
38
39
GNEParkingArea::GNEParkingArea(const std::string& id, GNENet* net, const std::string& filename, GNELane* lane, const double startPos, const double endPos,
40
const std::string& departPos, const std::string& name, const std::vector<std::string>& badges,
41
const bool friendlyPosition, const int roadSideCapacity, const bool onRoad, const double width,
42
const double length, const double angle, const bool lefthand, const Parameterised::Map& parameters) :
43
GNEStoppingPlace(id, net, filename, SUMO_TAG_PARKING_AREA, lane, startPos,
44
endPos, name, friendlyPosition, RGBColor::INVISIBLE, angle, parameters),
45
myDepartPos(departPos),
46
myRoadSideCapacity(roadSideCapacity),
47
myOnRoad(onRoad),
48
myWidth(width),
49
myLength(length),
50
myLefthand(lefthand),
51
myAcceptedBadges(badges) {
52
// update centering boundary without updating grid
53
updateCenteringBoundary(false);
54
}
55
56
57
GNEParkingArea::~GNEParkingArea() {}
58
59
60
void
61
GNEParkingArea::writeAdditional(OutputDevice& device) const {
62
device.openTag(getTagProperty()->getTag());
63
// write common attributes
64
writeStoppingPlaceAttributes(device);
65
// write specific attributes
66
if (myRoadSideCapacity != myTagProperty->getDefaultIntValue(SUMO_ATTR_ROADSIDE_CAPACITY)) {
67
device.writeAttr(SUMO_ATTR_ROADSIDE_CAPACITY, myRoadSideCapacity);
68
}
69
if (myOnRoad != myTagProperty->getDefaultBoolValue(SUMO_ATTR_ONROAD)) {
70
device.writeAttr(SUMO_ATTR_ONROAD, myOnRoad);
71
}
72
if (myWidth != myTagProperty->getDefaultDoubleValue(SUMO_ATTR_WIDTH)) {
73
device.writeAttr(SUMO_ATTR_WIDTH, myWidth);
74
}
75
if (myLength != myTagProperty->getDefaultDoubleValue(SUMO_ATTR_LENGTH)) {
76
device.writeAttr(SUMO_ATTR_LENGTH, myLength);
77
}
78
if (myDepartPos != myTagProperty->getDefaultStringValue(SUMO_ATTR_DEPARTPOS)) {
79
device.writeAttr(SUMO_ATTR_DEPARTPOS, myDepartPos);
80
}
81
if (myLefthand != myTagProperty->getDefaultBoolValue(SUMO_ATTR_LEFTHAND)) {
82
device.writeAttr(SUMO_ATTR_LEFTHAND, myLefthand);
83
}
84
if (getAttribute(SUMO_ATTR_ACCEPTED_BADGES) != myTagProperty->getDefaultStringValue(SUMO_ATTR_ACCEPTED_BADGES)) {
85
device.writeAttr(SUMO_ATTR_ACCEPTED_BADGES, toString(myAcceptedBadges));
86
}
87
// write all parking spaces
88
for (const auto& space : getChildAdditionals()) {
89
if (space->getTagProperty()->getTag() == SUMO_TAG_PARKING_SPACE) {
90
space->writeAdditional(device);
91
}
92
}
93
// write parameters (Always after children to avoid problems with additionals.xsd)
94
writeParams(device);
95
device.closeTag();
96
}
97
98
99
void
100
GNEParkingArea::updateGeometry() {
101
// Get value of option "lefthand"
102
const double offsetSign = OptionsCont::getOptions().getBool("lefthand") != myLefthand ? -1 : 1;
103
// calculate spaceDim
104
const double spaceDim = myRoadSideCapacity > 0 ? (getAttributeDouble(SUMO_ATTR_ENDPOS) - getAttributeDouble(SUMO_ATTR_STARTPOS)) / myRoadSideCapacity * getParentLanes().front()->getLengthGeometryFactor() : 7.5;
105
// calculate length
106
const double length = (myLength > 0) ? myLength : spaceDim;
107
// Update common geometry of stopping place
108
setStoppingPlaceGeometry(myWidth);
109
// Obtain a copy of the shape
110
PositionVector tmpShape = myAdditionalGeometry.getShape();
111
// Move shape to side
112
tmpShape.move2side(1.5 * offsetSign + myWidth);
113
// Get position of the sign
114
mySymbolPosition = tmpShape.getLineCenter();
115
// clear LotSpaceDefinitions
116
myLotSpaceDefinitions.clear();
117
// iterate over
118
for (int i = 0; i < myRoadSideCapacity; ++i) {
119
// calculate pos
120
const Position pos = GeomHelper::calculateLotSpacePosition(myAdditionalGeometry.getShape(), i, spaceDim, myAngle, myWidth, length);
121
// calculate angle
122
const double angle = GeomHelper::calculateLotSpaceAngle(myAdditionalGeometry.getShape(), i, spaceDim, myAngle);
123
// add GNElotEntry
124
myLotSpaceDefinitions.push_back(GNELotSpaceDefinition(pos.x(), pos.y(), pos.z(), angle, myWidth, length));
125
}
126
}
127
128
129
void
130
GNEParkingArea::drawGL(const GUIVisualizationSettings& s) const {
131
// first check if additional has to be drawn
132
if (myNet->getViewNet()->getDataViewOptions().showAdditionals()) {
133
// Obtain exaggeration of the draw
134
const double parkingAreaExaggeration = getExaggeration(s);
135
// check if draw moving geometry points
136
const bool movingGeometryPoints = drawMovingGeometryPoints(false);
137
// get detail level
138
const auto d = s.getDetailLevel(parkingAreaExaggeration);
139
// draw geometry only if we'rent in drawForObjectUnderCursor mode
140
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
141
// declare colors
142
RGBColor baseColor, signColor;
143
// set colors
144
if (mySpecialColor) {
145
baseColor = *mySpecialColor;
146
signColor = baseColor.changedBrightness(-32);
147
} else if (drawUsingSelectColor()) {
148
baseColor = s.colorSettings.selectedAdditionalColor;
149
signColor = baseColor.changedBrightness(-32);
150
} else {
151
baseColor = s.colorSettings.parkingAreaColor;
152
signColor = s.colorSettings.parkingAreaColorSign;
153
}
154
// draw parent and child lines
155
drawParentChildLines(s, s.additionalSettings.connectionColor);
156
// Add a layer matrix
157
GLHelper::pushMatrix();
158
// translate to front
159
drawInLayer(GLO_PARKING_AREA);
160
// set base color
161
GLHelper::setColor(baseColor);
162
// Draw the area using shape, shapeRotations, shapeLengths and value of exaggeration
163
GUIGeometry::drawGeometry(d, myAdditionalGeometry, myWidth * 0.5 * MIN2(1.0, parkingAreaExaggeration));
164
// draw sign
165
drawSign(s, d, parkingAreaExaggeration, baseColor, signColor, "P");
166
// Traslate to front
167
glTranslated(0, 0, 0.1);
168
// draw lotSpaceDefinitions
169
if (d <= GUIVisualizationSettings::Detail::AdditionalDetails) {
170
for (const auto& lsd : myLotSpaceDefinitions) {
171
GLHelper::drawSpaceOccupancies(parkingAreaExaggeration, lsd.position, lsd.rotation, lsd.width, lsd.length, true);
172
}
173
}
174
// draw geometry points
175
if (movingGeometryPoints && (myStartPosition != INVALID_DOUBLE)) {
176
drawLeftGeometryPoint(s, d, myAdditionalGeometry.getShape().front(), myAdditionalGeometry.getShapeRotations().front(), baseColor);
177
}
178
if (movingGeometryPoints && (myEndPosition != INVALID_DOUBLE)) {
179
drawRightGeometryPoint(s, d, myAdditionalGeometry.getShape().back(), myAdditionalGeometry.getShapeRotations().back(), baseColor);
180
}
181
// pop layer matrix
182
GLHelper::popMatrix();
183
// draw lock icon
184
GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), getPositionInView(), parkingAreaExaggeration);
185
// Draw additional ID
186
drawAdditionalID(s);
187
// draw additional name
188
drawAdditionalName(s);
189
// draw dotted contours
190
if (movingGeometryPoints) {
191
myAdditionalContour.drawDottedContourGeometryPoints(s, d, this, myAdditionalGeometry.getShape(), s.neteditSizeSettings.additionalGeometryPointRadius,
192
1, s.dottedContourSettings.segmentWidthSmall);
193
} else {
194
myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
195
mySymbolContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidthSmall, true);
196
}
197
}
198
// draw demand element children
199
drawDemandElementChildren(s);
200
// calculate contours
201
calculateStoppingPlaceContour(s, d, myWidth * 0.5, parkingAreaExaggeration, movingGeometryPoints);
202
}
203
}
204
205
206
std::string
207
GNEParkingArea::getAttribute(SumoXMLAttr key) const {
208
switch (key) {
209
case SUMO_ATTR_DEPARTPOS:
210
return myDepartPos;
211
case SUMO_ATTR_ACCEPTED_BADGES:
212
return joinToString(myAcceptedBadges, " ");
213
case SUMO_ATTR_ROADSIDE_CAPACITY:
214
return toString(myRoadSideCapacity);
215
case SUMO_ATTR_ONROAD:
216
return toString(myOnRoad);
217
case SUMO_ATTR_WIDTH:
218
return toString(myWidth);
219
case SUMO_ATTR_LENGTH:
220
return toString(myLength);
221
case SUMO_ATTR_LEFTHAND:
222
return toString(myLefthand);
223
default:
224
return getStoppingPlaceAttribute(this, key);
225
}
226
}
227
228
229
double
230
GNEParkingArea::getAttributeDouble(SumoXMLAttr key) const {
231
switch (key) {
232
case SUMO_ATTR_WIDTH:
233
return myWidth;
234
case SUMO_ATTR_LENGTH: {
235
// calculate spaceDim
236
const double spaceDim = myRoadSideCapacity > 0 ? (getAttributeDouble(SUMO_ATTR_ENDPOS) - getAttributeDouble(SUMO_ATTR_STARTPOS)) / myRoadSideCapacity * getParentLanes().front()->getLengthGeometryFactor() : 7.5;
237
return (myLength > 0) ? myLength : spaceDim;
238
}
239
default:
240
return getStoppingPlaceAttributeDouble(key);
241
}
242
}
243
244
245
void
246
GNEParkingArea::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
247
switch (key) {
248
case SUMO_ATTR_DEPARTPOS:
249
case SUMO_ATTR_ACCEPTED_BADGES:
250
case SUMO_ATTR_ROADSIDE_CAPACITY:
251
case SUMO_ATTR_ONROAD:
252
case SUMO_ATTR_WIDTH:
253
case SUMO_ATTR_LENGTH:
254
case SUMO_ATTR_LEFTHAND:
255
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
256
break;
257
default:
258
setStoppingPlaceAttribute(key, value, undoList);
259
break;
260
}
261
}
262
263
264
bool
265
GNEParkingArea::isValid(SumoXMLAttr key, const std::string& value) {
266
switch (key) {
267
case SUMO_ATTR_DEPARTPOS:
268
if (value.empty()) {
269
return true;
270
} else if (canParse<double>(value)) {
271
// parse value
272
const double departPos = parse<double>(value);
273
if (departPos >= 0) {
274
if (isTemplate()) {
275
return true;
276
} else {
277
return (departPos <= getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength());
278
}
279
} else {
280
return false;
281
}
282
} else {
283
return false;
284
}
285
case SUMO_ATTR_ACCEPTED_BADGES:
286
return true;
287
case SUMO_ATTR_ROADSIDE_CAPACITY:
288
return canParse<int>(value) && (parse<int>(value) >= 0);
289
case SUMO_ATTR_ONROAD:
290
return canParse<bool>(value);
291
case SUMO_ATTR_WIDTH:
292
return canParse<double>(value) && (parse<double>(value) > 0);
293
case SUMO_ATTR_LENGTH:
294
if (value.empty()) {
295
return true;
296
} else {
297
return canParse<double>(value) && (parse<double>(value) > 0);
298
}
299
case SUMO_ATTR_LEFTHAND:
300
return canParse<bool>(value);
301
default:
302
return isStoppingPlaceValid(key, value);
303
}
304
}
305
306
// ===========================================================================
307
// protected
308
// ===========================================================================
309
310
GNEParkingArea::GNELotSpaceDefinition::GNELotSpaceDefinition() :
311
rotation(0),
312
width(0),
313
length(0) {
314
}
315
316
317
GNEParkingArea::GNELotSpaceDefinition::GNELotSpaceDefinition(double x, double y, double z, double rotation_, double width_, double length_) :
318
position(Position(x, y, z)),
319
rotation(rotation_),
320
width(width_),
321
length(length_) {
322
}
323
324
// ===========================================================================
325
// private
326
// ===========================================================================
327
328
void
329
GNEParkingArea::setAttribute(SumoXMLAttr key, const std::string& value) {
330
switch (key) {
331
case SUMO_ATTR_DEPARTPOS:
332
myDepartPos = value;
333
break;
334
case SUMO_ATTR_ACCEPTED_BADGES:
335
myAcceptedBadges = GNEAttributeCarrier::parse<std::vector<std::string> >(value);
336
break;
337
case SUMO_ATTR_ROADSIDE_CAPACITY:
338
myRoadSideCapacity = parse<int>(value);
339
updateCenteringBoundary(false);
340
break;
341
case SUMO_ATTR_ONROAD:
342
myOnRoad = parse<bool>(value);
343
break;
344
case SUMO_ATTR_WIDTH:
345
myWidth = parse<double>(value);
346
// update geometry of all spaces
347
for (const auto& space : getChildAdditionals()) {
348
space->updateGeometry();
349
}
350
updateCenteringBoundary(false);
351
if (!isTemplate()) {
352
getParentLanes().front()->getParentEdge()->updateCenteringBoundary(true);
353
}
354
break;
355
case SUMO_ATTR_LENGTH:
356
if (value.empty()) {
357
myLength = 0;
358
} else {
359
myLength = parse<double>(value);
360
}
361
// update geometry of all spaces
362
for (const auto& space : getChildAdditionals()) {
363
space->updateGeometry();
364
}
365
break;
366
case SUMO_ATTR_LEFTHAND:
367
myLefthand = parse<bool>(value);
368
if (!isTemplate()) {
369
updateGeometry();
370
}
371
break;
372
default:
373
setStoppingPlaceAttribute(this, key, value);
374
break;
375
}
376
}
377
378
379
/****************************************************************************/
380
381