Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/elements/additional/GNEAdditional.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 GNEAdditional.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Dec 2015
17
///
18
// A abstract class for representation of additional elements
19
/****************************************************************************/
20
#include <config.h>
21
22
#include <foreign/fontstash/fontstash.h>
23
#include <netedit/GNENet.h>
24
#include <netedit/GNESegment.h>
25
#include <netedit/GNETagPropertiesDatabase.h>
26
#include <netedit/GNEViewParent.h>
27
#include <netedit/frames/GNEAttributesEditor.h>
28
#include <netedit/frames/GNEPathCreator.h>
29
#include <netedit/frames/GNEPlanCreator.h>
30
#include <netedit/frames/common/GNEInspectorFrame.h>
31
#include <netedit/frames/common/GNEMoveFrame.h>
32
#include <netedit/frames/common/GNESelectorFrame.h>
33
#include <netedit/frames/data/GNETAZRelDataFrame.h>
34
#include <netedit/frames/demand/GNEContainerFrame.h>
35
#include <netedit/frames/demand/GNEContainerPlanFrame.h>
36
#include <netedit/frames/demand/GNEPersonFrame.h>
37
#include <netedit/frames/demand/GNEPersonPlanFrame.h>
38
#include <netedit/frames/demand/GNEVehicleFrame.h>
39
#include <utils/gui/div/GLHelper.h>
40
#include <utils/gui/div/GUIDesigns.h>
41
#include <utils/gui/div/GUIParameterTableWindow.h>
42
#include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
43
44
#include "GNEAdditional.h"
45
#include "GNETAZ.h"
46
47
// ===========================================================================
48
// member method definitions
49
// ===========================================================================
50
51
GNEAdditional::GNEAdditional(const std::string& id, GNENet* net, const std::string& filename,
52
SumoXMLTag tag, const std::string& additionalName) :
53
GNEAttributeCarrier(tag, net, filename, id.empty()),
54
GUIGlObject(net->getTagPropertiesDatabase()->getTagProperty(tag, true)->getGLType(), id,
55
GUIIconSubSys::getIcon(net->getTagPropertiesDatabase()->getTagProperty(tag, true)->getGUIIcon())),
56
GNEPathElement(GNEPathElement::Options::ADDITIONAL_ELEMENT),
57
myAdditionalName(additionalName) {
58
}
59
60
61
GNEAdditional::GNEAdditional(GNEAdditional* additionalParent, SumoXMLTag tag, const std::string& additionalName) :
62
GNEAttributeCarrier(tag, additionalParent->getNet(), additionalParent->getFilename(), false),
63
GUIGlObject(additionalParent->getNet()->getTagPropertiesDatabase()->getTagProperty(tag, true)->getGLType(), additionalParent->getID(),
64
GUIIconSubSys::getIcon(additionalParent->getNet()->getTagPropertiesDatabase()->getTagProperty(tag, true)->getGUIIcon())),
65
GNEPathElement(GNEPathElement::Options::ADDITIONAL_ELEMENT),
66
myAdditionalName(additionalName) {
67
}
68
69
70
GNEAdditional::~GNEAdditional() {}
71
72
73
GNEHierarchicalElement*
74
GNEAdditional::getHierarchicalElement() {
75
return this;
76
}
77
78
79
void
80
GNEAdditional::removeGeometryPoint(const Position /*clickedPosition*/, GNEUndoList* /*undoList*/) {
81
// currently there isn't additionals with removable geometry points
82
}
83
84
85
GUIGlObject*
86
GNEAdditional::getGUIGlObject() {
87
return this;
88
}
89
90
91
const GUIGlObject*
92
GNEAdditional::getGUIGlObject() const {
93
return this;
94
}
95
96
97
const std::string
98
GNEAdditional::getOptionalName() const {
99
try {
100
return getAttribute(SUMO_ATTR_NAME);
101
} catch (InvalidArgument&) {
102
return "";
103
}
104
}
105
106
107
const GUIGeometry&
108
GNEAdditional::getAdditionalGeometry() const {
109
return myAdditionalGeometry;
110
}
111
112
113
void
114
GNEAdditional::setSpecialColor(const RGBColor* color) {
115
mySpecialColor = color;
116
}
117
118
119
void
120
GNEAdditional::resetAdditionalContour() {
121
myAdditionalContour.clearContour();
122
}
123
124
125
bool
126
GNEAdditional::isAdditionalValid() const {
127
return true;
128
}
129
130
131
std::string
132
GNEAdditional::getAdditionalProblem() const {
133
return "";
134
}
135
136
137
void
138
GNEAdditional::fixAdditionalProblem() {
139
throw InvalidArgument(getTagStr() + " cannot fix any problem");
140
}
141
142
143
void
144
GNEAdditional::openAdditionalDialog() {
145
throw InvalidArgument(getTagStr() + " doesn't have an additional dialog");
146
}
147
148
149
double
150
GNEAdditional::getExaggeration(const GUIVisualizationSettings& s) const {
151
return s.addSize.getExaggeration(s, this);
152
}
153
154
155
Boundary
156
GNEAdditional::getCenteringBoundary() const {
157
if (myAdditionalBoundary.isInitialised()) {
158
return myAdditionalBoundary;
159
} else {
160
Boundary contourBoundary = myAdditionalContour.getContourBoundary();
161
if (contourBoundary.isInitialised()) {
162
contourBoundary.grow(5);
163
return contourBoundary;
164
} else if (myAdditionalGeometry.getShape().size() > 0) {
165
Boundary geometryBoundary = myAdditionalGeometry.getShape().getBoxBoundary();
166
geometryBoundary.grow(5);
167
return geometryBoundary;
168
} else if (getParentAdditionals().size() > 0) {
169
return getParentAdditionals().front()->getCenteringBoundary();
170
} else {
171
Boundary centerBoundary(0, 0, 0, 0);
172
centerBoundary.grow(5);
173
return centerBoundary;
174
}
175
}
176
}
177
178
179
bool
180
GNEAdditional::checkDrawFromContour() const {
181
// get modes and viewParent (for code legibility)
182
const auto& modes = myNet->getViewNet()->getEditModes();
183
const auto& viewParent = myNet->getViewNet()->getViewParent();
184
const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
185
// continue depending of current status
186
if (inspectedElements.isInspectingSingleElement()) {
187
const auto inspectedAC = inspectedElements.getFirstAC();
188
// check conditions
189
if (inspectedAC->hasAttribute(SUMO_ATTR_FROM_TAZ)) {
190
return (inspectedAC->getAttribute(SUMO_ATTR_FROM_TAZ) == getID());
191
} else if ((inspectedAC->getTagProperty()->getTag() == SUMO_TAG_TAZREL)) {
192
return (inspectedAC->getAttribute(SUMO_ATTR_FROM) == getID());
193
}
194
} else if (modes.isCurrentSupermodeDemand()) {
195
// get current GNEPlanCreator
196
GNEPlanCreator* planCreator = nullptr;
197
if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
198
planCreator = viewParent->getPersonFrame()->getPlanCreator();
199
} else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
200
planCreator = viewParent->getPersonPlanFrame()->getPlanCreator();
201
} else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
202
planCreator = viewParent->getContainerFrame()->getPlanCreator();
203
} else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
204
planCreator = viewParent->getContainerPlanFrame()->getPlanCreator();
205
}
206
// continue depending of planCreator
207
if (planCreator) {
208
// check if this is the from additional
209
const auto additionalID = getID();
210
if ((planCreator->getPlanParameteres().fromBusStop == additionalID) ||
211
(planCreator->getPlanParameteres().fromTrainStop == additionalID) ||
212
(planCreator->getPlanParameteres().fromContainerStop == additionalID) ||
213
(planCreator->getPlanParameteres().fromChargingStation == additionalID) ||
214
(planCreator->getPlanParameteres().fromParkingArea == additionalID) ||
215
(planCreator->getPlanParameteres().fromTAZ == additionalID)) {
216
return true;
217
}
218
} else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
219
// get selected TAZs
220
const auto& selectedTAZs = viewParent->getVehicleFrame()->getPathCreator()->getSelectedTAZs();
221
// check if this is the first selected TAZ
222
if ((selectedTAZs.size() > 0) && (selectedTAZs.front() == this)) {
223
return true;
224
}
225
}
226
} else if (modes.isCurrentSupermodeData()) {
227
// get TAZRelDataFrame
228
const auto& TAZRelDataFrame = viewParent->getTAZRelDataFrame();
229
if (TAZRelDataFrame->shown() && (TAZRelDataFrame->getFirstTAZ() == this)) {
230
return true;
231
}
232
}
233
// nothing to draw
234
return false;
235
}
236
237
238
bool
239
GNEAdditional::checkDrawToContour() const {
240
// get modes and viewParent (for code legibility)
241
const auto& modes = myNet->getViewNet()->getEditModes();
242
const auto& viewParent = myNet->getViewNet()->getViewParent();
243
const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
244
// check conditions
245
if (myNet->getViewNet()->getViewParent()->getInspectorFrame()->getAttributesEditor()->isReparenting()) {
246
return false;
247
} else if (inspectedElements.isInspectingSingleElement()) {
248
const auto inspectedAC = inspectedElements.getFirstAC();
249
// check conditions
250
if (inspectedAC->hasAttribute(SUMO_ATTR_TO_TAZ)) {
251
return (inspectedAC->getAttribute(SUMO_ATTR_TO_TAZ) == getID());
252
} else if (inspectedAC->getTagProperty()->getTag() == SUMO_TAG_TAZREL) {
253
return (inspectedAC->getAttribute(SUMO_ATTR_TO) == getID());
254
} else if (inspectedAC->hasAttribute(GNE_ATTR_PARENT)) {
255
// check all parent tags
256
const auto& parentTags = inspectedAC->getTagProperty()->getXMLParentTags();
257
if (std::find(parentTags.begin(), parentTags.end(), myTagProperty->getTag()) != parentTags.end()) {
258
return (inspectedAC->getAttribute(GNE_ATTR_PARENT) == getID());
259
}
260
}
261
} else if (modes.isCurrentSupermodeDemand()) {
262
// get current GNEPlanCreator
263
GNEPlanCreator* planCreator = nullptr;
264
if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
265
planCreator = viewParent->getPersonFrame()->getPlanCreator();
266
} else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
267
planCreator = viewParent->getPersonPlanFrame()->getPlanCreator();
268
} else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
269
planCreator = viewParent->getContainerFrame()->getPlanCreator();
270
} else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
271
planCreator = viewParent->getContainerPlanFrame()->getPlanCreator();
272
}
273
// continue depending of planCreator
274
if (planCreator) {
275
// check if this is the from additional
276
const auto additionalID = getID();
277
if ((planCreator->getPlanParameteres().toBusStop == additionalID) ||
278
(planCreator->getPlanParameteres().toTrainStop == additionalID) ||
279
(planCreator->getPlanParameteres().toContainerStop == additionalID) ||
280
(planCreator->getPlanParameteres().toChargingStation == additionalID) ||
281
(planCreator->getPlanParameteres().toParkingArea == additionalID) ||
282
(planCreator->getPlanParameteres().toTAZ == additionalID)) {
283
return true;
284
}
285
} else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
286
// get selected TAZs
287
const auto& selectedTAZs = viewParent->getVehicleFrame()->getPathCreator()->getSelectedTAZs();
288
// check if this is the first selected TAZ
289
if ((selectedTAZs.size() > 1) && (selectedTAZs.back() == this)) {
290
return true;
291
}
292
}
293
} else if (modes.isCurrentSupermodeData()) {
294
// get TAZRelDataFrame
295
const auto& TAZRelDataFrame = viewParent->getTAZRelDataFrame();
296
if (TAZRelDataFrame->shown() && (TAZRelDataFrame->getSecondTAZ() == this)) {
297
return true;
298
}
299
}
300
// nothing to draw
301
return false;
302
}
303
304
305
bool
306
GNEAdditional::checkDrawRelatedContour() const {
307
const auto& neteditAttributesEditor = myNet->getViewNet()->getViewParent()->getInspectorFrame()->getAttributesEditor();
308
if (neteditAttributesEditor->isReparenting()) {
309
return neteditAttributesEditor->checkNewParent(this);
310
}
311
// check opened popup
312
if (myNet->getViewNet()->getPopup()) {
313
return myNet->getViewNet()->getPopup()->getGLObject() == this;
314
}
315
return false;
316
}
317
318
319
bool
320
GNEAdditional::checkDrawOverContour() const {
321
const auto& modes = myNet->getViewNet()->getEditModes();
322
if (myNet->getViewNet()->getViewObjectsSelector().getGUIGlObjectFront() != this) {
323
return false;
324
} else {
325
const auto& viewParent = myNet->getViewNet()->getViewParent();
326
if (modes.isCurrentSupermodeDemand()) {
327
// get current plan selector
328
GNEPlanSelector* planSelector = nullptr;
329
if (modes.demandEditMode == DemandEditMode::DEMAND_PERSON) {
330
planSelector = viewParent->getPersonFrame()->getPlanSelector();
331
} else if (modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) {
332
planSelector = viewParent->getPersonPlanFrame()->getPlanSelector();
333
} else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) {
334
planSelector = viewParent->getContainerFrame()->getPlanSelector();
335
} else if (modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) {
336
planSelector = viewParent->getContainerPlanFrame()->getPlanSelector();
337
}
338
// continue depending of plan selector
339
if (planSelector) {
340
if ((myTagProperty->isStoppingPlace() && planSelector->markStoppingPlaces()) ||
341
(myTagProperty->isTAZElement() && planSelector->markTAZs())) {
342
return true;
343
}
344
} else if (modes.demandEditMode == DemandEditMode::DEMAND_VEHICLE) {
345
// get current vehicle template
346
const auto& vehicleTemplate = viewParent->getVehicleFrame()->getVehicleTagSelector()->getCurrentTemplateAC();
347
// check if vehicle can be placed over from-to TAZs
348
if (vehicleTemplate && vehicleTemplate->getTagProperty()->vehicleTAZs()) {
349
return true;
350
}
351
}
352
} else if (modes.isCurrentSupermodeData()) {
353
// get TAZRelDataFrame
354
const auto& TAZRelDataFrame = viewParent->getTAZRelDataFrame();
355
if (TAZRelDataFrame->shown()) {
356
if (TAZRelDataFrame->getFirstTAZ() && TAZRelDataFrame->getSecondTAZ()) {
357
return false;
358
} else if (TAZRelDataFrame->getFirstTAZ() == this) {
359
return false;
360
} else if (TAZRelDataFrame->getSecondTAZ() == this) {
361
return false;
362
} else {
363
return true;
364
}
365
}
366
}
367
return false;
368
}
369
}
370
371
372
bool
373
GNEAdditional::checkDrawDeleteContour() const {
374
// get edit modes
375
const auto& editModes = myNet->getViewNet()->getEditModes();
376
// check if we're in delete mode
377
if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE)) {
378
return myNet->getViewNet()->checkOverLockedElement(this, mySelected);
379
} else {
380
return false;
381
}
382
}
383
384
385
bool
386
GNEAdditional::checkDrawDeleteContourSmall() const {
387
// get edit modes
388
const auto& editModes = myNet->getViewNet()->getEditModes();
389
// check if we're in delete mode and this additional has a parent
390
if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_DELETE) && (getParentAdditionals().size() > 0)) {
391
const auto additional = myNet->getViewNet()->getViewObjectsSelector().getAdditionalFront();
392
if (additional && (additional == myNet->getViewNet()->getViewObjectsSelector().getAttributeCarrierFront())) {
393
return (getParentAdditionals().front() == additional);
394
}
395
}
396
return false;
397
}
398
399
400
bool
401
GNEAdditional::checkDrawSelectContour() const {
402
// get edit modes
403
const auto& editModes = myNet->getViewNet()->getEditModes();
404
// check if we're in select mode
405
if (editModes.isCurrentSupermodeNetwork() && (editModes.networkEditMode == NetworkEditMode::NETWORK_SELECT)) {
406
return myNet->getViewNet()->checkOverLockedElement(this, mySelected);
407
} else {
408
return false;
409
}
410
}
411
412
413
GUIGLObjectPopupMenu*
414
GNEAdditional::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
415
// create popup
416
GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, this);
417
// build common options
418
buildPopUpMenuCommonOptions(ret, app, myNet->getViewNet(), myTagProperty->getTag(), mySelected);
419
// show option to open additional dialog
420
if (myTagProperty->hasDialog()) {
421
GUIDesigns::buildFXMenuCommand(ret, TL("Open ") + getTagStr() + TL(" Dialog"), getACIcon(), &parent, MID_OPEN_ADDITIONAL_DIALOG);
422
new FXMenuSeparator(ret);
423
}
424
// Show position parameters
425
if (myTagProperty->hasAttribute(SUMO_ATTR_LANE) && (myAdditionalGeometry.getShape().size() > 1)) {
426
const GNELane* lane = myNet->getAttributeCarriers()->retrieveLane(getAttribute(SUMO_ATTR_LANE));
427
// Show menu command inner position
428
const double innerPos = myAdditionalGeometry.getShape().nearest_offset_to_point2D(parent.getPositionInformation());
429
GUIDesigns::buildFXMenuCommand(ret, TL("Cursor position over additional shape: ") + toString(innerPos), nullptr, nullptr, 0);
430
// If shape isn't empty, show menu command lane position
431
if (myAdditionalGeometry.getShape().size() > 0) {
432
const double lanePos = lane->getLaneShape().nearest_offset_to_point2D(myAdditionalGeometry.getShape().front());
433
GUIDesigns::buildFXMenuCommand(ret, TL("Cursor position over lane: ") + toString(innerPos + lanePos), nullptr, nullptr, 0);
434
}
435
} else if (myTagProperty->hasAttribute(SUMO_ATTR_EDGE) && (myAdditionalGeometry.getShape().size() > 1)) {
436
const GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(getAttribute(SUMO_ATTR_EDGE));
437
// Show menu command inner position
438
const double innerPos = myAdditionalGeometry.getShape().nearest_offset_to_point2D(parent.getPositionInformation());
439
GUIDesigns::buildFXMenuCommand(ret, TL("Cursor position over additional shape: ") + toString(innerPos), nullptr, nullptr, 0);
440
// If shape isn't empty, show menu command edge position
441
if (myAdditionalGeometry.getShape().size() > 0) {
442
const double edgePos = edge->getChildLanes().at(0)->getLaneShape().nearest_offset_to_point2D(myAdditionalGeometry.getShape().front());
443
GUIDesigns::buildFXMenuCommand(ret, TL("Mouse position over edge: ") + toString(innerPos + edgePos), nullptr, nullptr, 0);
444
}
445
} else {
446
const auto mousePos = myNet->getViewNet()->getPositionInformation();
447
GUIDesigns::buildFXMenuCommand(ret, TL("Cursor position in view: ") + toString(mousePos.x()) + "," + toString(mousePos.y()), nullptr, nullptr, 0);
448
}
449
return ret;
450
}
451
452
453
GUIParameterTableWindow*
454
GNEAdditional::getParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
455
// Create table
456
GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
457
// Iterate over attributes
458
for (const auto& attributeProperty : myTagProperty->getAttributeProperties()) {
459
// Add attribute and set it dynamic if aren't unique
460
if (attributeProperty->isUnique()) {
461
ret->mkItem(attributeProperty->getAttrStr().c_str(), false, getAttribute(attributeProperty->getAttr()));
462
} else {
463
ret->mkItem(attributeProperty->getAttrStr().c_str(), true, getAttribute(attributeProperty->getAttr()));
464
}
465
}
466
// close building
467
ret->closeBuilding();
468
return ret;
469
}
470
471
472
const std::string&
473
GNEAdditional::getOptionalAdditionalName() const {
474
return myAdditionalName;
475
}
476
477
478
bool
479
GNEAdditional::isGLObjectLocked() const {
480
if (myNet->getViewNet()->getEditModes().isCurrentSupermodeNetwork()) {
481
return myNet->getViewNet()->getLockManager().isObjectLocked(getType(), isAttributeCarrierSelected());
482
} else {
483
return true;
484
}
485
}
486
487
488
void
489
GNEAdditional::markAsFrontElement() {
490
markForDrawingFront();
491
}
492
493
494
void
495
GNEAdditional::deleteGLObject() {
496
myNet->deleteAdditional(this, myNet->getViewNet()->getUndoList());
497
}
498
499
500
void
501
GNEAdditional::selectGLObject() {
502
if (isAttributeCarrierSelected()) {
503
unselectAttributeCarrier();
504
} else {
505
selectAttributeCarrier();
506
}
507
// update information label
508
myNet->getViewNet()->getViewParent()->getSelectorFrame()->getSelectionInformation()->updateInformationLabel();
509
}
510
511
512
void GNEAdditional::updateGLObject() {
513
updateGeometry();
514
}
515
516
517
void
518
GNEAdditional::computePathElement() {
519
// Nothing to compute
520
}
521
522
523
bool
524
GNEAdditional::isPathElementSelected() const {
525
return mySelected;
526
}
527
528
529
void
530
GNEAdditional::drawLanePartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {
531
// Nothing to draw
532
}
533
534
535
void
536
GNEAdditional::drawJunctionPartialGL(const GUIVisualizationSettings& /*s*/, const GNESegment* /*segment*/, const double /*offsetFront*/) const {
537
// Nothing to draw
538
}
539
540
// ---------------------------------------------------------------------------
541
// GNEAdditional - protected methods
542
// ---------------------------------------------------------------------------
543
544
bool
545
GNEAdditional::isValidAdditionalID(const std::string& value) const {
546
if (!isTemplate() && (value == getID())) {
547
return true;
548
} else if (SUMOXMLDefinitions::isValidAdditionalID(value)) {
549
return (myNet->getAttributeCarriers()->retrieveAdditional(myTagProperty->getTag(), value, false) == nullptr);
550
} else {
551
return false;
552
}
553
}
554
555
556
bool
557
GNEAdditional::isValidAdditionalID(const std::vector<SumoXMLTag>& tags, const std::string& value) const {
558
if (isTemplate() && value.empty()) {
559
return true;
560
} else if (!isTemplate() && (value == getID())) {
561
return true;
562
} else if (SUMOXMLDefinitions::isValidAdditionalID(value)) {
563
return (myNet->getAttributeCarriers()->retrieveAdditionals(tags, value, false) == nullptr);
564
} else {
565
return false;
566
}
567
}
568
569
570
bool
571
GNEAdditional::isValidDetectorID(const std::string& value) const {
572
if (isTemplate() && value.empty()) {
573
return true;
574
} else if (!isTemplate() && (value == getID())) {
575
return true;
576
} else if (SUMOXMLDefinitions::isValidDetectorID(value)) {
577
return (myNet->getAttributeCarriers()->retrieveAdditional(myTagProperty->getTag(), value, false) == nullptr);
578
} else {
579
return false;
580
}
581
}
582
583
584
bool
585
GNEAdditional::isValidDetectorID(const std::vector<SumoXMLTag>& tags, const std::string& value) const {
586
if (!isTemplate() && (value == getID())) {
587
return true;
588
} else if (SUMOXMLDefinitions::isValidDetectorID(value)) {
589
return (myNet->getAttributeCarriers()->retrieveAdditionals(tags, value, false) == nullptr);
590
} else {
591
return false;
592
}
593
}
594
595
596
void
597
GNEAdditional::setAdditionalID(const std::string& newID) {
598
// update ID
599
if (isTemplate()) {
600
setMicrosimID(newID);
601
} else if ((myTagProperty->getTag() == SUMO_TAG_VAPORIZER) || !myTagProperty->hasAttribute(SUMO_ATTR_ID)) {
602
setMicrosimID(newID);
603
} else {
604
myNet->getAttributeCarriers()->updateAdditionalID(this, newID);
605
}
606
// change IDs of certain children
607
for (const auto& additionalChild : getChildAdditionals()) {
608
// get tag
609
const auto tag = additionalChild->getTagProperty()->getTag();
610
if ((tag == SUMO_TAG_ACCESS) || (tag == SUMO_TAG_PARKING_SPACE) ||
611
(tag == SUMO_TAG_DET_ENTRY) || (tag == SUMO_TAG_DET_EXIT)) {
612
additionalChild->setAdditionalID(getID());
613
}
614
}
615
// enable save demand elements if this additional has children
616
if (getChildDemandElements().size() > 0) {
617
myNet->getSavingStatus()->requireSaveDemandElements();
618
}
619
// enable save data elements if this additional has children
620
if (getChildGenericDatas().size() > 0) {
621
myNet->getSavingStatus()->requireSaveDataElements();
622
}
623
}
624
625
626
void
627
GNEAdditional::drawAdditionalID(const GUIVisualizationSettings& s) const {
628
if (s.addName.show(this) && (myAdditionalGeometry.getShape().size() > 0)) {
629
// calculate middle point
630
const double middlePoint = (myAdditionalGeometry.getShape().length2D() * 0.5);
631
// calculate position
632
const Position pos = (myAdditionalGeometry.getShape().size() == 1) ? myAdditionalGeometry.getShape().front() : myAdditionalGeometry.getShape().positionAtOffset2D(middlePoint);
633
// calculate rotation
634
const double rot = (myAdditionalGeometry.getShape().size() == 1) ? myAdditionalGeometry.getShapeRotations().front() : myAdditionalGeometry.getShape().rotationDegreeAtOffset(middlePoint);
635
// draw additional ID
636
if (myTagProperty->hasAttribute(SUMO_ATTR_LANE)) {
637
GLHelper::drawText(getMicrosimID(), pos, GLO_MAX - getType(), s.addName.scaledSize(s.scale), s.addName.color, s.getTextAngle(rot - 90));
638
} else {
639
GLHelper::drawText(getMicrosimID(), pos, GLO_MAX - getType(), s.addName.scaledSize(s.scale), s.addName.color, 0);
640
}
641
}
642
}
643
644
645
void
646
GNEAdditional::drawAdditionalName(const GUIVisualizationSettings& s) const {
647
if (s.addFullName.show(this) && (myAdditionalGeometry.getShape().size() > 0) && (myAdditionalName != "")) {
648
// calculate middle point
649
const double middlePoint = (myAdditionalGeometry.getShape().length2D() * 0.5);
650
// calculate position
651
const Position pos = (myAdditionalGeometry.getShape().size() == 1) ? myAdditionalGeometry.getShape().front() : myAdditionalGeometry.getShape().positionAtOffset2D(middlePoint);
652
// calculate rotation
653
const double rot = (myAdditionalGeometry.getShape().size() == 1) ? myAdditionalGeometry.getShapeRotations().front() : myAdditionalGeometry.getShape().rotationDegreeAtOffset(middlePoint);
654
// draw additional name
655
if (myTagProperty->hasAttribute(SUMO_ATTR_LANE)) {
656
GLHelper::drawText(myAdditionalName, pos, GLO_MAX - getType(), s.addFullName.scaledSize(s.scale), s.addFullName.color, s.getTextAngle(rot - 90));
657
} else {
658
GLHelper::drawText(myAdditionalName, pos, GLO_MAX - getType(), s.addFullName.scaledSize(s.scale), s.addFullName.color, 0);
659
}
660
}
661
}
662
663
664
void
665
GNEAdditional::replaceAdditionalParentEdges(const std::string& value) {
666
GNEHierarchicalElement::updateParents(this, parse<GNEHierarchicalContainerParents<GNEEdge*> >(getNet(), value));
667
}
668
669
670
void
671
GNEAdditional::replaceAdditionalParentLanes(const std::string& value) {
672
GNEHierarchicalElement::updateParents(this, parse<GNEHierarchicalContainerParents<GNELane*> >(getNet(), value));
673
674
}
675
676
677
void
678
GNEAdditional::replaceAdditionalChildEdges(const std::string& value) {
679
GNEHierarchicalElement::updateChildren(this, parse<GNEHierarchicalContainerParents<GNEEdge*> >(getNet(), value));
680
}
681
682
683
void
684
GNEAdditional::replaceAdditionalChildLanes(const std::string& value) {
685
GNEHierarchicalElement::updateChildren(this, parse<GNEHierarchicalContainerParents<GNELane*> >(getNet(), value));
686
687
}
688
689
690
void
691
GNEAdditional::replaceAdditionalParent(SumoXMLTag tag, const std::string& value, const int parentIndex) {
692
std::vector<GNEAdditional*> newParentAdditionals;
693
// special case for calibrators and routeprobes
694
if (value.size() > 0) {
695
newParentAdditionals = getParentAdditionals();
696
if ((newParentAdditionals.size() == 0) && (parentIndex == 0)) {
697
newParentAdditionals.push_back(myNet->getAttributeCarriers()->retrieveAdditional(tag, value));
698
} else {
699
newParentAdditionals[parentIndex] = myNet->getAttributeCarriers()->retrieveAdditional(tag, value);
700
}
701
}
702
GNEHierarchicalElement::updateParents(this, newParentAdditionals);
703
}
704
705
706
void
707
GNEAdditional::replaceDemandElementParent(SumoXMLTag tag, const std::string& value, const int parentIndex) {
708
auto newDemandElement = myNet->getAttributeCarriers()->retrieveDemandElement(tag, value);
709
GNEHierarchicalElement::updateParent(this, parentIndex, newDemandElement);
710
}
711
712
713
void
714
GNEAdditional::shiftLaneIndex() {
715
const std::vector<GNELane*> newLanes = {getParentLanes().front()->getParentEdge()->getChildLanes().at(getParentLanes().front()->getIndex() + 1)};
716
GNEHierarchicalElement::updateParents(this, newLanes);
717
}
718
719
720
void
721
GNEAdditional::calculatePerpendicularLine(const double endLaneposition) {
722
if (getParentEdges().empty()) {
723
throw ProcessError(TL("Invalid number of edges"));
724
} else {
725
// get lanes
726
const GNELane* firstLane = getParentEdges().front()->getChildLanes().front();
727
const GNELane* lastLane = getParentEdges().front()->getChildLanes().back();
728
// get first and back lane shapes
729
PositionVector firstLaneShape = firstLane->getLaneShape();
730
PositionVector lastLaneShape = lastLane->getLaneShape();
731
// move shapes
732
firstLaneShape.move2side((firstLane->getParentEdge()->getNBEdge()->getLaneWidth(firstLane->getIndex()) * 0.5) + 1);
733
lastLaneShape.move2side(lastLane->getParentEdge()->getNBEdge()->getLaneWidth(lastLane->getIndex()) * -0.5);
734
// calculate lane postion
735
const double lanePosition = firstLaneShape.length2D() >= endLaneposition ? endLaneposition : firstLaneShape.length2D();
736
// update geometry
737
myAdditionalGeometry.updateGeometry({firstLaneShape.positionAtOffset2D(lanePosition), lastLaneShape.positionAtOffset2D(lanePosition)});
738
}
739
}
740
741
742
void
743
GNEAdditional::drawSquaredAdditional(const GUIVisualizationSettings& s, const Position& pos, const double size, GUITexture texture, GUITexture selectedTexture) const {
744
// draw boundaries
745
GLHelper::drawBoundary(s, getCenteringBoundary());
746
// Obtain drawing exaggeration
747
const double exaggeration = getExaggeration(s);
748
// get detail level
749
const auto d = s.getDetailLevel(exaggeration);
750
// draw geometry only if we'rent in drawForObjectUnderCursor mode
751
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
752
// Add layer matrix
753
GLHelper::pushMatrix();
754
// translate to front
755
drawInLayer(getType());
756
// translate to position
757
glTranslated(pos.x(), pos.y(), 0);
758
// scale
759
glScaled(exaggeration, exaggeration, 1);
760
// set White color
761
glColor3d(1, 1, 1);
762
// rotate
763
glRotated(180, 0, 0, 1);
764
// draw texture
765
if (drawUsingSelectColor()) {
766
GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(selectedTexture), size);
767
} else {
768
GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(texture), size);
769
}
770
// Pop layer matrix
771
GLHelper::popMatrix();
772
// draw lock icon
773
GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), pos, exaggeration, 0.4, 0.5, 0.5);
774
// Draw additional ID
775
drawAdditionalID(s);
776
// draw additional name
777
drawAdditionalName(s);
778
// draw dotted contour
779
myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
780
}
781
// calculate contour
782
myAdditionalContour.calculateContourRectangleShape(s, d, this, pos, size, size, getType(), 0, 0, 0, exaggeration, nullptr);
783
}
784
785
786
void
787
GNEAdditional::drawListedAdditional(const GUIVisualizationSettings& s, const Position& parentPosition, const double offsetX,
788
const double extraOffsetY, const RGBColor baseCol, const RGBColor textCol, GUITexture texture,
789
const std::string text) const {
790
// check if additional has to be drawn
791
if (myNet->getViewNet()->getDataViewOptions().showAdditionals()) {
792
// draw boundaries
793
GLHelper::drawBoundary(s, getCenteringBoundary());
794
// get detail level
795
const auto d = s.getDetailLevel(1);
796
// declare offsets
797
const double lineOffset = 0.1875;
798
const double baseOffsetX = 6.25;
799
const double baseOffsetY = 0.6;
800
// get draw position index
801
const int drawPositionIndex = getDrawPositionIndex();
802
// calculate lineA position (from parent to middle)
803
Position positionLineA = parentPosition;
804
const double positionLineA_Y = (0 - extraOffsetY + baseOffsetY);
805
// set position depending of indexes
806
positionLineA.add(1 + lineOffset + (baseOffsetX * offsetX), positionLineA_Y, 0);
807
// calculate lineC position (From middle until current listenAdditional
808
Position positionLineB = parentPosition;
809
const double positionLineB_Y = ((drawPositionIndex * -1) - extraOffsetY + baseOffsetY);
810
// set position depending of indexes
811
positionLineB.add(1 + lineOffset + (baseOffsetX * offsetX) + (2 * lineOffset), positionLineB_Y, 0);
812
// calculate signPosition position
813
Position signPosition = parentPosition;
814
// draw geometry only if we'rent in drawForObjectUnderCursor mode
815
if (s.checkDrawAdditional(d, isAttributeCarrierSelected())) {
816
// set position depending of indexes
817
signPosition.add(4.5 + (baseOffsetX * offsetX), (drawPositionIndex * -1) - extraOffsetY + 1, 0);
818
// calculate colors
819
const RGBColor baseColor = isAttributeCarrierSelected() ? s.colorSettings.selectedAdditionalColor : baseCol;
820
const RGBColor secondColor = baseColor.changedBrightness(-30);
821
const RGBColor textColor = isAttributeCarrierSelected() ? s.colorSettings.selectedAdditionalColor.changedBrightness(30) : textCol;
822
// Add layer matrix
823
GLHelper::pushMatrix();
824
// translate to front
825
drawInLayer(getType());
826
// set line color
827
GLHelper::setColor(s.additionalSettings.connectionColor);
828
// draw both lines
829
GLHelper::drawBoxLine(positionLineA, 0, 0.1, lineOffset);
830
GLHelper::drawBoxLine(positionLineB, 0, 0.1, lineOffset);
831
// check if draw middle lane
832
if (drawPositionIndex != 0) {
833
// calculate length
834
const double length = std::abs(positionLineA_Y - positionLineB_Y);
835
// push middle lane matrix
836
GLHelper::pushMatrix();
837
//move and rotate
838
glTranslated(positionLineA.x() + lineOffset, positionLineA.y(), 0);
839
glRotated(90, 0, 0, 1);
840
glTranslated((length * -0.5), 0, 0);
841
// draw line
842
GLHelper::drawBoxLine(Position(0, 0), 0, 0.1, length * 0.5);
843
// pop middle lane matrix
844
GLHelper::popMatrix();
845
}
846
// draw extern rectangle
847
GLHelper::setColor(secondColor);
848
GLHelper::drawBoxLine(signPosition, 0, 0.96, 2.75);
849
// move to front
850
glTranslated(0, -0.06, 0.1);
851
// draw intern rectangle
852
GLHelper::setColor(baseColor);
853
GLHelper::drawBoxLine(signPosition, 0, 0.84, 2.69);
854
// move position down
855
signPosition.add(-2, -0.43, 0);
856
// draw interval
857
GLHelper::drawText(adjustListedAdditionalText(text), signPosition, .1, 0.5, textColor, 0, (FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE));
858
// move to icon position
859
signPosition.add(-0.3, 0);
860
// check if draw lock icon or rerouter interval icon
861
if (GNEViewNetHelper::LockIcon::checkDrawing(d, this, getType(), 1)) {
862
// pop layer matrix
863
GLHelper::popMatrix();
864
// draw lock icon
865
GNEViewNetHelper::LockIcon::drawLockIcon(d, this, getType(), signPosition, 1, 0.4, 0.0, -0.05);
866
} else {
867
// translate to front
868
glTranslated(signPosition.x(), signPosition.y(), 0.1);
869
// set White color
870
glColor3d(1, 1, 1);
871
// rotate
872
glRotated(180, 0, 0, 1);
873
// draw texture
874
GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(texture), 0.25);
875
// pop layer matrix
876
GLHelper::popMatrix();
877
}
878
// draw dotted contour
879
myAdditionalContour.drawDottedContours(s, d, this, s.dottedContourSettings.segmentWidth, true);
880
}
881
// calculate contour
882
myAdditionalContour.calculateContourRectangleShape(s, d, this, signPosition, 0.56, 2.75, getType(), 0, -2.3, 0, 1, nullptr);
883
}
884
}
885
886
887
bool
888
GNEAdditional::drawMovingGeometryPoints(const bool ignoreShift) const {
889
// get modes
890
const auto& modes = myNet->getViewNet()->getEditModes();
891
// check conditions
892
if (modes.isCurrentSupermodeNetwork() && (modes.networkEditMode == NetworkEditMode::NETWORK_MOVE) &&
893
(ignoreShift || myNet->getViewNet()->getMouseButtonKeyPressed().shiftKeyPressed())) {
894
return true;
895
} else {
896
return false;
897
}
898
}
899
900
901
void
902
GNEAdditional::drawDemandElementChildren(const GUIVisualizationSettings& s) const {
903
// draw child demand elements
904
for (const auto& demandElement : getChildDemandElements()) {
905
if (!demandElement->getTagProperty()->isPlacedInRTree()) {
906
demandElement->drawGL(s);
907
}
908
}
909
}
910
911
912
GNEMoveOperation*
913
GNEAdditional::getMoveOperationSingleLane(const double startPos, const double endPos) {
914
// get allow change lane
915
const bool allowChangeLane = myNet->getViewNet()->getViewParent()->getMoveFrame()->getCommonMoveOptions()->getAllowChangeLane();
916
// fist check if we're moving only extremes
917
if (myNet->getViewNet()->getMouseButtonKeyPressed().shiftKeyPressed()) {
918
// get snap radius
919
const double snap_radius = myNet->getViewNet()->getVisualisationSettings().neteditSizeSettings.additionalGeometryPointRadius;
920
// get mouse position
921
const Position mousePosition = myNet->getViewNet()->getPositionInformation();
922
// check if we clicked over start or end position
923
if (myAdditionalGeometry.getShape().front().distanceSquaredTo2D(mousePosition) <= (snap_radius * snap_radius)) {
924
// move only start position
925
return new GNEMoveOperation(this, getParentLanes().front(), startPos, endPos,
926
allowChangeLane, GNEMoveOperation::OperationType::SINGLE_LANE_MOVE_FIRST);
927
} else if (myAdditionalGeometry.getShape().back().distanceSquaredTo2D(mousePosition) <= (snap_radius * snap_radius)) {
928
// move only end position
929
return new GNEMoveOperation(this, getParentLanes().front(), startPos, endPos,
930
allowChangeLane, GNEMoveOperation::OperationType::SINGLE_LANE_MOVE_LAST);
931
} else {
932
return nullptr;
933
}
934
} else {
935
// move both start and end positions
936
return new GNEMoveOperation(this, getParentLanes().front(), startPos, endPos,
937
allowChangeLane, GNEMoveOperation::OperationType::SINGLE_LANE_MOVE_BOTH);
938
}
939
}
940
941
942
GNEMoveOperation*
943
GNEAdditional::getMoveOperationMultiLane(const double startPos, const double endPos) {
944
// get snap radius
945
const double snap_radius = myNet->getViewNet()->getVisualisationSettings().neteditSizeSettings.additionalGeometryPointRadius;
946
// get mouse position
947
const Position mousePosition = myNet->getViewNet()->getPositionInformation();
948
// calculate both geometries
949
GUIGeometry fromGeometry, toGeometry;
950
fromGeometry.updateGeometry(getParentLanes().front()->getLaneGeometry().getShape(), startPos, 0);
951
toGeometry.updateGeometry(getParentLanes().back()->getLaneGeometry().getShape(), endPos, 0);
952
// check if we clicked over start or end position
953
if (myNet->getViewNet()->getMouseButtonKeyPressed().shiftKeyPressed()) {
954
if (fromGeometry.getShape().front().distanceSquaredTo2D(mousePosition) <= (snap_radius * snap_radius)) {
955
// move first position
956
return new GNEMoveOperation(this, getParentLanes().front(), startPos, getParentLanes().back(), endPos,
957
false, GNEMoveOperation::OperationType::MULTIPLE_LANES_MOVE_FIRST);
958
} else if (toGeometry.getShape().back().distanceSquaredTo2D(mousePosition) <= (snap_radius * snap_radius)) {
959
// move last position
960
return new GNEMoveOperation(this, getParentLanes().front(), startPos, getParentLanes().back(), endPos,
961
false, GNEMoveOperation::OperationType::MULTIPLE_LANES_MOVE_LAST);
962
}
963
} else {
964
auto segment = gViewObjectsHandler.getSelectedSegment(this);
965
if (segment) {
966
if (segment->getLaneIndex() == 0) {
967
return new GNEMoveOperation(this, getParentLanes().front(), startPos, getParentLanes().back(), endPos,
968
false, GNEMoveOperation::OperationType::MULTIPLE_LANES_MOVE_BOTH_FIRST);
969
} else if (segment->getLaneIndex() == ((int)getParentLanes().size() - 1)) {
970
return new GNEMoveOperation(this, getParentLanes().front(), startPos, getParentLanes().back(), endPos,
971
false, GNEMoveOperation::OperationType::MULTIPLE_LANES_MOVE_BOTH_LAST);
972
}
973
}
974
}
975
return nullptr;
976
}
977
978
979
std::string
980
GNEAdditional::getJuPedSimType(SumoXMLTag tag) {
981
// continue depending of tag
982
switch (tag) {
983
case GNE_TAG_JPS_WALKABLEAREA:
984
return "jupedsim.walkable_area";
985
case GNE_TAG_JPS_OBSTACLE:
986
return "jupedsim.obstacle";
987
default:
988
throw InvalidArgument("Invalid JuPedSim tag");
989
}
990
}
991
992
993
RGBColor
994
GNEAdditional::getJuPedSimColor(SumoXMLTag tag) {
995
// continue depending of tag
996
switch (tag) {
997
case GNE_TAG_JPS_WALKABLEAREA:
998
return RGBColor(179, 217, 255);
999
case GNE_TAG_JPS_OBSTACLE:
1000
return RGBColor(255, 204, 204);
1001
default:
1002
throw InvalidArgument("Invalid JuPedSim tag");
1003
}
1004
}
1005
1006
1007
bool
1008
GNEAdditional::getJuPedSimFill(SumoXMLTag tag) {
1009
// continue depending of tag
1010
switch (tag) {
1011
case GNE_TAG_JPS_WALKABLEAREA:
1012
case GNE_TAG_JPS_OBSTACLE:
1013
return true;
1014
default:
1015
throw InvalidArgument("Invalid JuPedSim tag");
1016
}
1017
}
1018
1019
1020
double
1021
GNEAdditional::getJuPedSimLayer(SumoXMLTag tag) {
1022
// continue depending of tag
1023
switch (tag) {
1024
case GNE_TAG_JPS_WALKABLEAREA:
1025
return 1;
1026
case GNE_TAG_JPS_OBSTACLE:
1027
return 2;
1028
default:
1029
throw InvalidArgument("Invalid JuPedSim tag");
1030
}
1031
}
1032
1033
1034
void
1035
GNEAdditional::calculateContourPolygons(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
1036
const double layer, const double exaggeration, const bool filledShape) const {
1037
// calculate contour depending of contoured shape
1038
if (filledShape) {
1039
myAdditionalContour.calculateContourClosedShape(s, d, this, myAdditionalGeometry.getShape(), layer, 1, nullptr);
1040
} else {
1041
myAdditionalContour.calculateContourExtrudedShape(s, d, this, myAdditionalGeometry.getShape(), layer,
1042
s.neteditSizeSettings.polylineWidth, exaggeration, true, true, 0, nullptr, nullptr);
1043
}
1044
// get edit modes
1045
const auto& editModes = myNet->getViewNet()->getEditModes();
1046
// check if draw geometry points
1047
if (editModes.isCurrentSupermodeNetwork() && !myNet->getViewNet()->getViewParent()->getMoveFrame()->getNetworkMoveOptions()->getMoveWholePolygons()) {
1048
// check if we're in move mode
1049
const bool moveMode = (editModes.networkEditMode == NetworkEditMode::NETWORK_MOVE);
1050
// get geometry point radius (size depends if we're in move mode)
1051
const double geometryPointRaidus = s.neteditSizeSettings.polygonGeometryPointRadius * (moveMode ? 1 : 0.5);
1052
// calculate contour geometry points
1053
myAdditionalContour.calculateContourAllGeometryPoints(s, d, this, myAdditionalGeometry.getShape(), layer, geometryPointRaidus, exaggeration, moveMode);
1054
}
1055
}
1056
1057
1058
GNELane*
1059
GNEAdditional::getFirstPathLane() const {
1060
return getParentLanes().front();
1061
}
1062
1063
1064
GNELane*
1065
GNEAdditional::getLastPathLane() const {
1066
return getParentLanes().back();
1067
}
1068
1069
1070
Position
1071
GNEAdditional::getAttributePosition(SumoXMLAttr key) const {
1072
throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
1073
}
1074
1075
1076
void
1077
GNEAdditional::drawParentChildLines(const GUIVisualizationSettings& s, const RGBColor& color, const bool onlySymbols) const {
1078
const auto& inspectedElements = myNet->getViewNet()->getInspectedElements();
1079
// check if current additional is inspected, front or selected
1080
const bool currentDrawEntire = inspectedElements.isACInspected(this) || myDrawInFront || isAttributeCarrierSelected();
1081
// push layer matrix
1082
GLHelper::pushMatrix();
1083
// translate to parentChildLine layer
1084
glTranslated(0, 0, GLO_PARENTCHILDLINE);
1085
// iterate over parent additionals
1086
for (const auto& parent : getParentAdditionals()) {
1087
// get inspected flag
1088
const bool parentInspected = inspectedElements.isACInspected(parent);
1089
// draw parent lines
1090
GUIGeometry::drawParentLine(s, getPositionInView(), parent->getPositionInView(),
1091
(isAttributeCarrierSelected() || parent->isAttributeCarrierSelected()) ? s.additionalSettings.connectionColorSelected : color,
1092
currentDrawEntire || parentInspected || parent->isAttributeCarrierSelected(), .05);
1093
}
1094
// special case for Parking area reroutes
1095
if (getTagProperty()->getTag() == SUMO_TAG_REROUTER) {
1096
// iterate over rerouter elements
1097
for (const auto& rerouterInterval : getChildAdditionals()) {
1098
for (const auto& rerouterElement : rerouterInterval->getChildAdditionals()) {
1099
if (rerouterElement->getTagProperty()->getTag() == SUMO_TAG_PARKING_AREA_REROUTE) {
1100
// get parking area
1101
const auto parkingArea = rerouterElement->getParentAdditionals().at(1);
1102
// get inspected flag
1103
const bool parkingAreaInspected = inspectedElements.isACInspected(parkingArea);
1104
// draw parent lines
1105
GUIGeometry::drawParentLine(s, getPositionInView(), parkingArea->getPositionInView(),
1106
(isAttributeCarrierSelected() || parkingArea->isAttributeCarrierSelected()) ? s.additionalSettings.connectionColorSelected : color,
1107
currentDrawEntire || parkingAreaInspected || parkingArea->isAttributeCarrierSelected(), .05);
1108
}
1109
}
1110
}
1111
}
1112
// iterate over child additionals
1113
for (const auto& child : getChildAdditionals()) {
1114
// get inspected flag
1115
const bool childInspected = inspectedElements.isACInspected(child);
1116
// special case for parking zone reroute
1117
if (child->getTagProperty()->getTag() == SUMO_TAG_PARKING_AREA_REROUTE) {
1118
// draw child line between parking area and rerouter
1119
GUIGeometry::drawChildLine(s, getPositionInView(), child->getParentAdditionals().front()->getParentAdditionals().front()->getPositionInView(),
1120
(isAttributeCarrierSelected() || child->isAttributeCarrierSelected()) ? s.additionalSettings.connectionColorSelected : color,
1121
currentDrawEntire || childInspected || child->isAttributeCarrierSelected(), .05);
1122
} else if (!onlySymbols || child->getTagProperty()->isSymbol()) {
1123
// draw child line
1124
GUIGeometry::drawChildLine(s, getPositionInView(), child->getPositionInView(),
1125
(isAttributeCarrierSelected() || child->isAttributeCarrierSelected()) ? s.additionalSettings.connectionColorSelected : color,
1126
currentDrawEntire || childInspected || child->isAttributeCarrierSelected(), .05);
1127
}
1128
}
1129
// pop layer matrix
1130
GLHelper::popMatrix();
1131
}
1132
1133
1134
void
1135
GNEAdditional::drawUpGeometryPoint(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d, const Position& pos,
1136
const double rot, const RGBColor& baseColor, const bool ignoreShift) const {
1137
drawSemiCircleGeometryPoint(s, d, pos, rot, baseColor, -90, 90, ignoreShift);
1138
}
1139
1140
void
1141
GNEAdditional::drawDownGeometryPoint(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d, const Position& pos,
1142
const double rot, const RGBColor& baseColor, const bool ignoreShift) const {
1143
drawSemiCircleGeometryPoint(s, d, pos, rot, baseColor, 90, 270, ignoreShift);
1144
}
1145
1146
void
1147
GNEAdditional::drawLeftGeometryPoint(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d, const Position& pos,
1148
const double rot, const RGBColor& baseColor, const bool ignoreShift) const {
1149
drawSemiCircleGeometryPoint(s, d, pos, rot, baseColor, -90, 90, ignoreShift);
1150
}
1151
1152
1153
void
1154
GNEAdditional::drawRightGeometryPoint(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d, const Position& pos,
1155
const double rot, const RGBColor& baseColor, const bool ignoreShift) const {
1156
drawSemiCircleGeometryPoint(s, d, pos, rot, baseColor, 270, 90, ignoreShift);
1157
}
1158
1159
1160
int
1161
GNEAdditional::getDrawPositionIndex() const {
1162
// filter symbols
1163
std::vector<GNEAdditional*> children;
1164
for (const auto& child : getParentAdditionals().front()->getChildAdditionals()) {
1165
if (!child->getTagProperty()->isSymbol()) {
1166
children.push_back(child);
1167
}
1168
}
1169
// now get index
1170
for (int i = 0; i < (int)children.size(); i++) {
1171
if (children.at(i) == this) {
1172
return i;
1173
}
1174
}
1175
return 0;
1176
}
1177
1178
1179
bool
1180
GNEAdditional::areLaneConsecutives(const std::vector<GNELane*>& lanes) {
1181
// declare lane iterator
1182
int laneIt = 0;
1183
// iterate over all lanes
1184
while (laneIt < ((int)lanes.size() - 1)) {
1185
// we assume that lanes aren't consecutive
1186
bool consecutiveFound = false;
1187
// get lanes
1188
const auto lane = lanes.at(laneIt);
1189
const auto nextLane = lanes.at(laneIt + 1);
1190
// if there is a connection between "from" lane and "to" lane of connection, change connectionFound to true
1191
for (const auto& outgoingEdge : lane->getParentEdge()->getToJunction()->getGNEOutgoingEdges()) {
1192
for (const auto& outgoingLane : outgoingEdge->getChildLanes()) {
1193
if (outgoingLane == nextLane) {
1194
consecutiveFound = true;
1195
}
1196
}
1197
}
1198
// abort if consecutiveFound is false
1199
if (!consecutiveFound) {
1200
return false;
1201
}
1202
// update iterator
1203
laneIt++;
1204
}
1205
// lanes are consecutive, then return true
1206
return true;
1207
}
1208
1209
1210
bool
1211
GNEAdditional::areLaneConnected(const std::vector<GNELane*>& lanes) {
1212
// declare lane iterator
1213
int laneIt = 0;
1214
// iterate over all lanes, and stop if myE2valid is false
1215
while (laneIt < ((int)lanes.size() - 1)) {
1216
// we assume that E2 is invalid
1217
bool connectionFound = false;
1218
// get lanes
1219
const auto lane = lanes.at(laneIt);
1220
const auto nextLane = lanes.at(laneIt + 1);
1221
// check if both lanes are sidewalks
1222
if ((lane->getAttribute(SUMO_ATTR_ALLOW) == "pedestrian") && (nextLane->getAttribute(SUMO_ATTR_ALLOW) == "pedestrian")) {
1223
connectionFound = true;
1224
}
1225
// if there is a connection between "from" lane and "to" lane of connection, change connectionFound to true
1226
for (const auto& connection : lane->getParentEdge()->getNBEdge()->getConnections()) {
1227
if ((connection.toEdge == nextLane->getParentEdge()->getNBEdge()) &&
1228
(connection.fromLane == lane->getIndex()) &&
1229
(connection.toLane == nextLane->getIndex())) {
1230
connectionFound = true;
1231
}
1232
}
1233
// abort if connectionFound is false
1234
if (!connectionFound) {
1235
return false;
1236
}
1237
// update iterator
1238
laneIt++;
1239
}
1240
// there are connections between all lanes, then return true
1241
return true;
1242
}
1243
1244
1245
bool
1246
GNEAdditional::checkChildAdditionalRestriction() const {
1247
// throw exception because this function mus be implemented in child (see GNEE3Detector)
1248
throw ProcessError(StringUtils::format("Calling non-implemented function checkChildAdditionalRestriction during saving of %. It muss be reimplemented in child class", getTagStr()));
1249
}
1250
1251
1252
void
1253
GNEAdditional::drawSemiCircleGeometryPoint(const GUIVisualizationSettings& s, const GUIVisualizationSettings::Detail d,
1254
const Position& pos, const double rot, const RGBColor& baseColor, const double fromAngle, const double toAngle,
1255
const bool /* ignoreShift */) const {
1256
// check if draw geometry point
1257
if (!s.drawForViewObjectsHandler && (d <= GUIVisualizationSettings::Detail::GeometryPoint)) {
1258
// push matrix
1259
GLHelper::pushMatrix();
1260
// translated to front
1261
glTranslated(0, 0, 0.1);
1262
// set color depending if check if mouse is over element
1263
GLHelper::setColor(baseColor.changedBrightness(-50));
1264
// translate and rotate
1265
glTranslated(pos.x(), pos.y(), 0.1);
1266
glRotated(rot, 0, 0, 1);
1267
// draw geometry point
1268
GLHelper::drawFilledCircleDetailled(d, s.neteditSizeSettings.additionalGeometryPointRadius, fromAngle, toAngle);
1269
// pop geometry point matrix
1270
GLHelper::popMatrix();
1271
}
1272
}
1273
1274
1275
std::string
1276
GNEAdditional::adjustListedAdditionalText(const std::string& text) const {
1277
// 10 + 3 + 10
1278
if (text.size() <= 23) {
1279
return text;
1280
} else {
1281
// get text size
1282
const int textPosition = (int)text.size() - 10;
1283
// declare strings
1284
std::string partA, partB;
1285
// resize
1286
partA.reserve(10);
1287
partB.reserve(10);
1288
// fill both
1289
for (int i = 0; i < 10; i++) {
1290
partA.push_back(text.at(i));
1291
partB.push_back(text.at(textPosition + i));
1292
}
1293
// return composition
1294
return (partA + "..." + partB);
1295
}
1296
}
1297
1298
/****************************************************************************/
1299
1300