Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNEAccess.cpp
193871 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2026 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 GNEAccess.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Jun 2018
17
///
18
//
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <netedit/changes/GNEChange_Attribute.h>
23
#include <netedit/elements/moving/GNEMoveElementLaneSingle.h>
24
#include <netedit/GNENet.h>
25
#include <netedit/GNETagProperties.h>
26
#include <utils/gui/div/GLHelper.h>
27
#include <utils/xml/NamespaceIDs.h>
28
29
#include "GNEAccess.h"
30
#include "GNEAdditionalHandler.h"
31
32
// ===========================================================================
33
// member method definitions
34
// ===========================================================================
35
36
GNEAccess::GNEAccess(GNENet* net) :
37
GNEAdditional(net, SUMO_TAG_ACCESS),
38
myMoveElementLaneSingle(new GNEMoveElementLaneSingle(this, SUMO_ATTR_POSITION, myPosOverLane, myFriendlyPos,
39
GNEMoveElementLaneSingle::PositionType::SINGLE)) {
40
}
41
42
43
GNEAccess::GNEAccess(GNEAdditional* busStop, GNELane* lane, const double pos, const std::string& specialPos,
44
const bool friendlyPos, const double length, const Parameterised::Map& parameters) :
45
GNEAdditional(busStop, SUMO_TAG_ACCESS, ""),
46
Parameterised(parameters),
47
myPosOverLane(pos),
48
myFriendlyPos(friendlyPos),
49
myMoveElementLaneSingle(new GNEMoveElementLaneSingle(this, SUMO_ATTR_POSITION, myPosOverLane, myFriendlyPos,
50
GNEMoveElementLaneSingle::PositionType::SINGLE)),
51
mySpecialPosition(specialPos),
52
myLength(length) {
53
// set parents
54
setParent<GNELane*>(lane);
55
setParent<GNEAdditional*>(busStop);
56
// update centering boundary without updating grid
57
updateCenteringBoundary(false);
58
}
59
60
61
GNEAccess::~GNEAccess() {
62
delete myMoveElementLaneSingle;
63
}
64
65
66
GNEMoveElement*
67
GNEAccess::getMoveElement() const {
68
return myMoveElementLaneSingle;
69
}
70
71
72
Parameterised*
73
GNEAccess::getParameters() {
74
return this;
75
}
76
77
78
const Parameterised*
79
GNEAccess::getParameters() const {
80
return this;
81
}
82
83
84
void
85
GNEAccess::updateGeometry() {
86
// set start position
87
double fixedPositionOverLane;
88
if (myPosOverLane < 0) {
89
fixedPositionOverLane = 0;
90
} else if (myPosOverLane > getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength()) {
91
fixedPositionOverLane = getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength();
92
} else {
93
fixedPositionOverLane = myPosOverLane;
94
}
95
// update geometry
96
myAdditionalGeometry.updateGeometry(getParentLanes().front()->getLaneShape(), fixedPositionOverLane * getParentLanes().front()->getLengthGeometryFactor(), myMoveElementLaneSingle->myMovingLateralOffset);
97
}
98
99
100
Position
101
GNEAccess::getPositionInView() const {
102
return myAdditionalGeometry.getShape().getPolygonCenter();
103
}
104
105
106
void
107
GNEAccess::updateCenteringBoundary(const bool /*updateGrid*/) {
108
// nothing to update
109
}
110
111
112
void
113
GNEAccess::splitEdgeGeometry(const double splitPosition, const GNENetworkElement* /*originalElement*/, const GNENetworkElement* newElement, GNEUndoList* undoList) {
114
if (splitPosition < myPosOverLane) {
115
// change lane
116
setAttribute(SUMO_ATTR_LANE, newElement->getID(), undoList);
117
// now adjust start position
118
setAttribute(SUMO_ATTR_POSITION, toString(myPosOverLane - splitPosition), undoList);
119
}
120
}
121
122
123
bool
124
GNEAccess::isAccessPositionFixed() const {
125
// with friendly position enabled position are "always fixed"
126
if (myFriendlyPos) {
127
return true;
128
} else {
129
if (myPosOverLane != INVALID_DOUBLE) {
130
return (myPosOverLane >= 0) && (myPosOverLane <= getParentLanes().front()->getParentEdge()->getNBEdge()->getFinalLength());
131
} else {
132
return false;
133
}
134
}
135
}
136
137
138
void
139
GNEAccess::writeAdditional(OutputDevice& device) const {
140
device.openTag(SUMO_TAG_ACCESS);
141
// write common additional attributes
142
writeAdditionalAttributes(device);
143
// write move attributes
144
myMoveElementLaneSingle->writeMoveAttributes(device);
145
// write specific attributes
146
if (myLength != -1) {
147
device.writeAttr(SUMO_ATTR_LENGTH, myLength);
148
}
149
device.closeTag();
150
}
151
152
153
bool
154
GNEAccess::isAdditionalValid() const {
155
// only movement problems
156
return myMoveElementLaneSingle->isMoveElementValid();
157
}
158
159
160
std::string
161
GNEAccess::getAdditionalProblem() const {
162
// only movement problems
163
return myMoveElementLaneSingle->getMovingProblem();
164
}
165
166
167
void
168
GNEAccess::fixAdditionalProblem() {
169
// only movement problems
170
myMoveElementLaneSingle->fixMovingProblem();
171
}
172
173
174
bool
175
GNEAccess::checkDrawMoveContour() const {
176
// get edit modes
177
const auto& editModes = myNet->getViewNet()->getEditModes();
178
// check if we're in move mode
179
if (!myNet->getViewNet()->isCurrentlyMovingElements() && editModes.isCurrentSupermodeNetwork() &&
180
!myNet->getViewNet()->getEditNetworkElementShapes().getEditedNetworkElement() &&
181
(editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE) && myNet->getViewNet()->checkOverLockedElement(this, mySelected)) {
182
// only move the first element
183
return myNet->getViewNet()->getViewObjectsSelector().getGUIGlObjectFront() == this;
184
} else {
185
return false;
186
}
187
}
188
189
190
GNEEdge*
191
GNEAccess::getEdge() const {
192
return getParentLanes().front()->getParentEdge();
193
}
194
195
196
std::string
197
GNEAccess::getParentName() const {
198
return getParentAdditionals().at(0)->getID();
199
}
200
201
202
void
203
GNEAccess::drawGL(const GUIVisualizationSettings& s) const {
204
// first check if additional has to be drawn
205
if (myNet->getViewNet()->getDataViewOptions().showAdditionals()) {
206
// Obtain exaggeration
207
const double accessExaggeration = getExaggeration(s);
208
// adjust radius depending of mode and distance to mouse position
209
double radius = 0.5;
210
if (myNet->getViewNet()->getEditModes().isCurrentSupermodeNetwork() &&
211
myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(myAdditionalGeometry.getShape().front()) < 1) {
212
radius = 1;
213
}
214
// get detail level
215
const auto d = s.getDetailLevel(1);
216
// draw geometry only if we'rent in drawForObjectUnderCursor mode
217
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
218
// get color
219
RGBColor accessColor;
220
if (drawUsingSelectColor()) {
221
accessColor = s.colorSettings.selectedAdditionalColor;
222
} else if (!getParentAdditionals().front()->getAttribute(SUMO_ATTR_COLOR).empty()) {
223
accessColor = parse<RGBColor>(getParentAdditionals().front()->getAttribute(SUMO_ATTR_COLOR));
224
} else if (getParentAdditionals().front()->getTagProperty()->getTag() == SUMO_TAG_CONTAINER_STOP) {
225
accessColor = s.colorSettings.containerStopColor;
226
} else {
227
accessColor = s.colorSettings.busStopColor;
228
}
229
// draw parent and child lines
230
drawParentChildLines(s, accessColor);
231
// push layer matrix
232
GLHelper::pushMatrix();
233
// translate to front
234
drawInLayer(GLO_ACCESS);
235
// set color
236
GLHelper::setColor(accessColor);
237
// translate to geometry position
238
glTranslated(myAdditionalGeometry.getShape().front().x(), myAdditionalGeometry.getShape().front().y(), 0);
239
// draw circle
240
GLHelper::drawFilledCircleDetailled(d, radius * accessExaggeration);
241
// pop layer matrix
242
GLHelper::popMatrix();
243
// draw lock icon
244
GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), myAdditionalGeometry.getShape().front(), accessExaggeration, 0.3);
245
// draw dotted contour
246
myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidthSmall, true);
247
}
248
// calculate contour
249
myAdditionalContour.calculateContourCircleShape(s, d, this, myAdditionalGeometry.getShape().front(), radius, getType(),
250
accessExaggeration, getParentLanes().front()->getParentEdge());
251
}
252
}
253
254
255
std::string
256
GNEAccess::getAttribute(SumoXMLAttr key) const {
257
switch (key) {
258
case SUMO_ATTR_ID:
259
return getParentAdditionals().front()->getID();
260
case SUMO_ATTR_POSITION:
261
if (myPosOverLane == INVALID_DOUBLE) {
262
return mySpecialPosition;
263
} else {
264
return myMoveElementLaneSingle->getMovingAttribute(key);
265
}
266
case SUMO_ATTR_LENGTH:
267
if (myLength == -1) {
268
return "";
269
} else {
270
return toString(myLength);
271
}
272
case GNE_ATTR_PARENT:
273
if (isTemplate()) {
274
return "";
275
} else {
276
return getParentAdditionals().at(0)->getID();
277
}
278
case GNE_ATTR_SHIFTLANEINDEX:
279
return "";
280
default:
281
return myMoveElementLaneSingle->getMovingAttribute(key);
282
}
283
}
284
285
286
double
287
GNEAccess::getAttributeDouble(SumoXMLAttr key) const {
288
return myMoveElementLaneSingle->getMovingAttributeDouble(key);
289
}
290
291
292
Position
293
GNEAccess::getAttributePosition(SumoXMLAttr key) const {
294
return myMoveElementLaneSingle->getMovingAttributePosition(key);
295
}
296
297
298
PositionVector
299
GNEAccess::getAttributePositionVector(SumoXMLAttr key) const {
300
return getCommonAttributePositionVector(key);
301
}
302
303
304
void
305
GNEAccess::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
306
switch (key) {
307
case SUMO_ATTR_LENGTH:
308
case GNE_ATTR_PARENT:
309
case GNE_ATTR_SHIFTLANEINDEX:
310
GNEChange_Attribute::changeAttribute(this, key, value, undoList);
311
break;
312
default:
313
myMoveElementLaneSingle->setMovingAttribute(key, value, undoList);
314
break;
315
}
316
}
317
318
319
bool
320
GNEAccess::isValid(SumoXMLAttr key, const std::string& value) {
321
switch (key) {
322
case SUMO_ATTR_LANE: {
323
// check lane
324
if (!myMoveElementLaneSingle->isMovingAttributeValid(key, value)) {
325
return false;
326
} else {
327
// check if exist another access for the same parent in the given edge
328
const auto lane = myNet->getAttributeCarriers()->retrieveLane(value);
329
return GNEAdditionalHandler::accessExists(getParentAdditionals().at(0), lane->getParentEdge());
330
}
331
}
332
case SUMO_ATTR_POSITION:
333
if (value.empty() || (value == "random") || (value == "doors") || (value == "carriage")) {
334
return true;
335
} else {
336
return myMoveElementLaneSingle->isMovingAttributeValid(key, value);
337
}
338
case SUMO_ATTR_LENGTH:
339
if (canParse<double>(value)) {
340
const double valueDouble = parse<double>(value);
341
return (valueDouble == -1) || (valueDouble >= 0);
342
} else {
343
return false;
344
}
345
case GNE_ATTR_PARENT:
346
return (myNet->getAttributeCarriers()->retrieveAdditionals(NamespaceIDs::busStops, value, false) != nullptr);
347
default:
348
return myMoveElementLaneSingle->isMovingAttributeValid(key, value);
349
}
350
}
351
352
353
std::string
354
GNEAccess::getPopUpID() const {
355
return getTagStr();
356
}
357
358
359
std::string
360
GNEAccess::getHierarchyName() const {
361
return getTagStr() + ": " + getParentLanes().front()->getParentEdge()->getID();
362
}
363
364
// ===========================================================================
365
// private
366
// ===========================================================================
367
368
void
369
GNEAccess::setAttribute(SumoXMLAttr key, const std::string& value) {
370
switch (key) {
371
case SUMO_ATTR_LANE:
372
replaceAdditionalParentLanes(value);
373
break;
374
case SUMO_ATTR_POSITION:
375
if (value.empty()) {
376
myPosOverLane = 0;
377
} else if (value == "random" || value == "doors" || value == "carriage") {
378
myPosOverLane = INVALID_DOUBLE;
379
mySpecialPosition = value;
380
} else {
381
myMoveElementLaneSingle->setMovingAttribute(key, value);
382
}
383
break;
384
case SUMO_ATTR_LENGTH:
385
if (value.empty()) {
386
myLength = myTagProperty->getDefaultDoubleValue(key);
387
} else {
388
myLength = parse<double>(value);
389
}
390
break;
391
case GNE_ATTR_PARENT:
392
if (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, value, false) != nullptr) {
393
replaceAdditionalParent(SUMO_TAG_BUS_STOP, value, 0);
394
} else if (myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_TRAIN_STOP, value, false) != nullptr) {
395
replaceAdditionalParent(SUMO_TAG_TRAIN_STOP, value, 0);
396
} else {
397
replaceAdditionalParent(SUMO_TAG_CONTAINER_STOP, value, 0);
398
}
399
break;
400
case GNE_ATTR_SHIFTLANEINDEX:
401
shiftLaneIndex();
402
break;
403
default:
404
myMoveElementLaneSingle->setMovingAttribute(key, value);
405
break;
406
}
407
}
408
409
/****************************************************************************/
410
411