Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/netedit/frames/GNEPathCreator.cpp
169678 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 GNEPathCreator.cpp
15
/// @author Pablo Alvarez Lopez
16
/// @date Mar 2022
17
///
18
// Frame for create paths
19
/****************************************************************************/
20
21
#include <netedit/GNEApplicationWindow.h>
22
#include <netedit/GNENet.h>
23
#include <netedit/GNETagProperties.h>
24
#include <netedit/GNEViewNet.h>
25
#include <netedit/GNEViewParent.h>
26
#include <netedit/elements/additional/GNETAZ.h>
27
#include <netedit/frames/common/GNEInspectorFrame.h>
28
#include <utils/gui/div/GLHelper.h>
29
#include <utils/gui/div/GUIDesigns.h>
30
#include <utils/gui/windows/GUIAppEnum.h>
31
32
#include "GNEPathCreator.h"
33
34
// ===========================================================================
35
// FOX callback mapping
36
// ===========================================================================
37
38
FXDEFMAP(GNEPathCreator) PathCreatorMap[] = {
39
FXMAPFUNC(SEL_COMMAND, MID_GNE_PATHCREATOR_ABORT, GNEPathCreator::onCmdAbortPathCreation),
40
FXMAPFUNC(SEL_COMMAND, MID_GNE_PATHCREATOR_FINISH, GNEPathCreator::onCmdCreatePath),
41
FXMAPFUNC(SEL_COMMAND, MID_GNE_PATHCREATOR_USELASTROUTE, GNEPathCreator::onCmdUseLastRoute),
42
FXMAPFUNC(SEL_UPDATE, MID_GNE_PATHCREATOR_USELASTROUTE, GNEPathCreator::onUpdUseLastRoute),
43
FXMAPFUNC(SEL_COMMAND, MID_GNE_PATHCREATOR_REMOVELAST, GNEPathCreator::onCmdRemoveLastElement),
44
FXMAPFUNC(SEL_COMMAND, MID_GNE_PATHCREATOR_SHOWCANDIDATES, GNEPathCreator::onCmdShowCandidateEdges)
45
};
46
47
// Object implementation
48
FXIMPLEMENT(GNEPathCreator, MFXGroupBoxModule, PathCreatorMap, ARRAYNUMBER(PathCreatorMap))
49
50
51
// ===========================================================================
52
// method definitions
53
// ===========================================================================
54
55
GNEPathCreator::Path::Path(const SUMOVehicleClass vClass, GNEEdge* edge) :
56
mySubPath({edge}),
57
myConflictVClass(false),
58
myConflictDisconnected(false) {
59
// check if we have to change vClass flag
60
if (edge->getNBEdge()->getNumLanesThatAllow(vClass) == 0) {
61
myConflictVClass = true;
62
}
63
}
64
65
66
GNEPathCreator::Path::Path(GNEPathManager* pathManager, const SUMOVehicleClass vClass, GNEEdge* edgeFrom, GNEEdge* edgeTo) :
67
myConflictVClass(false),
68
myConflictDisconnected(false) {
69
// calculate subpath
70
mySubPath = pathManager->getPathCalculator()->calculateDijkstraPath(vClass, {edgeFrom, edgeTo});
71
// if subPath is empty, try it with pedestrian (i.e. ignoring vCass)
72
if (mySubPath.empty()) {
73
mySubPath = pathManager->getPathCalculator()->calculateDijkstraPath(SVC_PEDESTRIAN, {edgeFrom, edgeTo});
74
if (mySubPath.empty()) {
75
mySubPath = { edgeFrom, edgeTo };
76
myConflictDisconnected = true;
77
} else {
78
myConflictVClass = true;
79
}
80
}
81
}
82
83
84
GNEPathCreator::Path::Path(GNEPathManager* pathManager, const SUMOVehicleClass vClass, GNEJunction* junctionFrom, GNEJunction* junctionTo) :
85
myConflictVClass(false),
86
myConflictDisconnected(false) {
87
// calculate subpath
88
mySubPath = pathManager->getPathCalculator()->calculateDijkstraPath(vClass, junctionFrom, junctionTo);
89
// if subPath is empty, try it with pedestrian (i.e. ignoring vCass)
90
if (mySubPath.empty()) {
91
mySubPath = pathManager->getPathCalculator()->calculateDijkstraPath(SVC_PEDESTRIAN, junctionFrom, junctionTo);
92
if (mySubPath.empty()) {
93
myConflictDisconnected = true;
94
} else {
95
myConflictVClass = true;
96
}
97
}
98
}
99
100
101
const std::vector<GNEEdge*>&
102
GNEPathCreator::Path::getSubPath() const {
103
return mySubPath;
104
}
105
106
107
bool
108
GNEPathCreator::Path::isConflictVClass() const {
109
return myConflictVClass;
110
}
111
112
113
bool
114
GNEPathCreator::Path::isConflictDisconnected() const {
115
return myConflictDisconnected;
116
}
117
118
119
GNEPathCreator::Path::Path() :
120
myConflictVClass(false),
121
myConflictDisconnected(false) {
122
}
123
124
125
GNEPathCreator::GNEPathCreator(GNEFrame* frameParent, GNEPathManager* pathManager) :
126
MFXGroupBoxModule(frameParent, TL("Route creator")),
127
myFrameParent(frameParent),
128
myPathManager(pathManager),
129
myVClass(SVC_PASSENGER),
130
myCreationMode(0),
131
myRoute(nullptr) {
132
// create label for route info
133
myInfoRouteLabel = new FXLabel(getCollapsableFrame(), TL("No edges selected"), 0, GUIDesignLabelFrameInformation);
134
// create button for use last route
135
myUseLastRoute = GUIDesigns::buildFXButton(getCollapsableFrame(), TL("Use last route"), "", "", GUIIconSubSys::getIcon(GUIIcon::ROUTE), this, MID_GNE_PATHCREATOR_USELASTROUTE, GUIDesignButton);
136
myUseLastRoute->disable();
137
// create button for finish route creation
138
myFinishCreationButton = GUIDesigns::buildFXButton(getCollapsableFrame(), TL("Finish route creation"), "", "", nullptr, this, MID_GNE_PATHCREATOR_FINISH, GUIDesignButton);
139
myFinishCreationButton->disable();
140
// create button for abort route creation
141
myAbortCreationButton = GUIDesigns::buildFXButton(getCollapsableFrame(), TL("Abort route creation"), "", "", nullptr, this, MID_GNE_PATHCREATOR_ABORT, GUIDesignButton);
142
myAbortCreationButton->disable();
143
// create button for remove last inserted edge
144
myRemoveLastInsertedElement = GUIDesigns::buildFXButton(getCollapsableFrame(), TL("Remove last edge"), "", "", nullptr, this, MID_GNE_PATHCREATOR_REMOVELAST, GUIDesignButton);
145
myRemoveLastInsertedElement->disable();
146
// create check button
147
myShowCandidateEdges = new FXCheckButton(getCollapsableFrame(), TL("Show candidate edges"), this, MID_GNE_PATHCREATOR_SHOWCANDIDATES, GUIDesignCheckButton);
148
myShowCandidateEdges->setCheck(TRUE);
149
// create shift label
150
myShiftLabel = new FXLabel(this,
151
TL("SHIFT-click: ignore vClass"),
152
0, GUIDesignLabelFrameInformation);
153
// create control label
154
myControlLabel = new FXLabel(this,
155
TL("CTRL-click: force add"),
156
0, GUIDesignLabelFrameInformation);
157
// create backspace label (always shown)
158
myBackSpaceLabel = new FXLabel(this,
159
TL("BACKSPACE: undo click"),
160
0, GUIDesignLabelFrameInformation);
161
}
162
163
164
GNEPathCreator::~GNEPathCreator() {}
165
166
167
void
168
GNEPathCreator::showPathCreatorModule(const GNETagProperties* tagProperty, const bool consecutives) {
169
// declare flag
170
bool showPathCreator = true;
171
// first abort creation
172
abortPathCreation();
173
// hide use last inserted route
174
myUseLastRoute->hide();
175
// disable buttons
176
myFinishCreationButton->disable();
177
myAbortCreationButton->disable();
178
myRemoveLastInsertedElement->disable();
179
// show info label
180
myInfoRouteLabel->show();
181
myShowCandidateEdges->show();
182
myShiftLabel->show();
183
myControlLabel->show();
184
myBackSpaceLabel->show();
185
// reset creation mode
186
myCreationMode = 0;
187
// set consecutive or non consecuives
188
if (consecutives) {
189
myCreationMode |= CONSECUTIVE_EDGES;
190
} else {
191
myCreationMode |= NONCONSECUTIVE_EDGES;
192
}
193
// continue depending of tag
194
if (tagProperty->isRoute() || tagProperty->vehicleRouteEmbedded()) {
195
myCreationMode |= SHOW_CANDIDATE_EDGES;
196
myCreationMode |= START_EDGE;
197
myCreationMode |= END_EDGE;
198
} else if (tagProperty->vehicleRoute()) {
199
myCreationMode |= ROUTE;
200
// show use last inserted route
201
myUseLastRoute->show();
202
// disable other elements
203
myFinishCreationButton->hide();
204
myAbortCreationButton->hide();
205
myRemoveLastInsertedElement->hide();
206
myInfoRouteLabel->hide();
207
myShowCandidateEdges->hide();
208
myShiftLabel->hide();
209
myControlLabel->hide();
210
myBackSpaceLabel->hide();
211
} else if (tagProperty->vehicleEdges() || (tagProperty->getTag() == SUMO_TAG_EDGEREL)) {
212
myCreationMode |= SHOW_CANDIDATE_EDGES;
213
myCreationMode |= START_EDGE;
214
myCreationMode |= END_EDGE;
215
} else if (tagProperty->vehicleJunctions()) {
216
myCreationMode |= SHOW_CANDIDATE_JUNCTIONS;
217
myCreationMode |= START_JUNCTION;
218
myCreationMode |= END_JUNCTION;
219
myCreationMode |= ONLY_FROMTO;
220
} else if (tagProperty->vehicleTAZs()) {
221
myCreationMode |= START_TAZ;
222
myCreationMode |= END_TAZ;
223
myCreationMode |= ONLY_FROMTO;
224
} else {
225
showPathCreator = false;
226
}
227
// update colors
228
updateEdgeColors();
229
updateJunctionColors();
230
// check if show path creator
231
if (showPathCreator) {
232
// recalc before show (to avoid graphic problems)
233
recalc();
234
// show modul
235
show();
236
} else {
237
// hide modul
238
hide();
239
}
240
}
241
242
243
void
244
GNEPathCreator::hidePathCreatorModule() {
245
// clear path
246
clearPath();
247
// hide modul
248
hide();
249
}
250
251
252
SUMOVehicleClass
253
GNEPathCreator::getVClass() const {
254
return myVClass;
255
}
256
257
258
void
259
GNEPathCreator::setVClass(SUMOVehicleClass vClass) {
260
myVClass = vClass;
261
// update edge colors
262
updateEdgeColors();
263
}
264
265
266
bool
267
GNEPathCreator::addJunction(GNEJunction* junction) {
268
// check if junctions are allowed
269
if (((myCreationMode & START_JUNCTION) == 0) && ((myCreationMode & END_JUNCTION) == 0)) {
270
return false;
271
}
272
// continue depending of number of selected edge
273
if (mySelectedJunctions.size() > 0) {
274
// check double junctions
275
if (mySelectedJunctions.back() == junction) {
276
// Write warning
277
WRITE_WARNING(TL("Double junctions aren't allowed"));
278
// abort add junction
279
return false;
280
}
281
}
282
// check number of junctions
283
if (mySelectedJunctions.size() == 2 && (myCreationMode & Mode::ONLY_FROMTO)) {
284
// Write warning
285
WRITE_WARNING(TL("Only two junctions are allowed"));
286
// abort add junction
287
return false;
288
}
289
// All checks ok, then add it in selected elements
290
mySelectedJunctions.push_back(junction);
291
// enable abort route button
292
myAbortCreationButton->enable();
293
// enable finish button
294
myFinishCreationButton->enable();
295
// disable undo/redo
296
myFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->disableUndoRedoTemporally(TL("creation of path between junctions"));
297
// enable or disable remove last junction button
298
if (mySelectedJunctions.size() > 1) {
299
myRemoveLastInsertedElement->enable();
300
} else {
301
myRemoveLastInsertedElement->disable();
302
}
303
// recalculate path
304
recalculatePath();
305
// update info route label
306
updateInfoRouteLabel();
307
// update junction colors
308
updateJunctionColors();
309
return true;
310
}
311
312
313
bool
314
GNEPathCreator::addTAZ(GNETAZ* TAZ) {
315
// check if TAZs are allowed
316
if (((myCreationMode & START_TAZ) == 0) && ((myCreationMode & END_TAZ) == 0)) {
317
return false;
318
}
319
// continue depending of number of selected edge
320
if (mySelectedTAZs.size() > 0) {
321
// check double TAZs
322
if (mySelectedTAZs.back() == TAZ) {
323
// Write warning
324
WRITE_WARNING(TL("Double TAZs aren't allowed"));
325
// abort add TAZ
326
return false;
327
}
328
}
329
// check number of TAZs
330
if ((mySelectedTAZs.size() == 2) && (myCreationMode & Mode::ONLY_FROMTO)) {
331
// Write warning
332
WRITE_WARNING(TL("Only two TAZs are allowed"));
333
// abort add TAZ
334
return false;
335
}
336
// All checks ok, then add it in selected elements
337
mySelectedTAZs.push_back(TAZ);
338
// enable abort route button
339
myAbortCreationButton->enable();
340
// enable finish button
341
myFinishCreationButton->enable();
342
// disable undo/redo
343
myFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->disableUndoRedoTemporally(TL("creation of path between TAZs"));
344
// enable or disable remove last TAZ button
345
if (mySelectedTAZs.size() > 1) {
346
myRemoveLastInsertedElement->enable();
347
} else {
348
myRemoveLastInsertedElement->disable();
349
}
350
// update info route label
351
updateInfoRouteLabel();
352
return true;
353
}
354
355
356
bool
357
GNEPathCreator::addEdge(GNEEdge* edge, const bool shiftKeyPressed, const bool controlKeyPressed) {
358
// check if edges are allowed
359
if (((myCreationMode & START_EDGE) == 0) && ((myCreationMode & END_EDGE) == 0)) {
360
return false;
361
}
362
// continue depending of number of selected eges
363
if (mySelectedEdges.size() > 0) {
364
// check double edges
365
if (mySelectedEdges.back() == edge) {
366
// Write warning
367
WRITE_WARNING(TL("Double edges aren't allowed"));
368
// abort add edge
369
return false;
370
}
371
// check consecutive edges
372
if (myCreationMode & Mode::CONSECUTIVE_EDGES) {
373
// check that new edge is consecutive
374
const auto& outgoingEdges = mySelectedEdges.back()->getToJunction()->getGNEOutgoingEdges();
375
if (std::find(outgoingEdges.begin(), outgoingEdges.end(), edge) == outgoingEdges.end()) {
376
// Write warning
377
WRITE_WARNING(TL("Only consecutives edges are allowed"));
378
// abort add edge
379
return false;
380
}
381
}
382
}
383
// check number of edges
384
if (mySelectedEdges.size() == 2 && (myCreationMode & Mode::ONLY_FROMTO)) {
385
// Write warning
386
WRITE_WARNING(TL("Only two edges are allowed"));
387
// abort add edge
388
return false;
389
}
390
// check candidate edge
391
if ((myShowCandidateEdges->getCheck() == TRUE) && !edge->isPossibleCandidate()) {
392
if (edge->isSpecialCandidate()) {
393
if (!shiftKeyPressed) {
394
// Write warning
395
WRITE_WARNING(TL("Invalid edge (SHIFT + click to add an invalid vClass edge)"));
396
// abort add edge
397
return false;
398
}
399
} else if (edge->isConflictedCandidate()) {
400
if (!controlKeyPressed) {
401
// Write warning
402
WRITE_WARNING(TL("Invalid edge (CONTROL + click to add a disconnected edge)"));
403
// abort add edge
404
return false;
405
}
406
}
407
}
408
// All checks ok, then add it in selected elements
409
mySelectedEdges.push_back(edge);
410
// enable abort route button
411
myAbortCreationButton->enable();
412
// enable finish button
413
myFinishCreationButton->enable();
414
// disable undo/redo
415
myFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->disableUndoRedoTemporally(TL("creation of path between edges"));
416
// enable or disable remove last edge button
417
if (mySelectedEdges.size() > 1) {
418
myRemoveLastInsertedElement->enable();
419
} else {
420
myRemoveLastInsertedElement->disable();
421
}
422
// recalculate path
423
recalculatePath();
424
// update info route label
425
updateInfoRouteLabel();
426
// update edge colors
427
updateEdgeColors();
428
// add edge ok, then return true
429
return true;
430
}
431
432
433
const std::vector<GNEEdge*>&
434
GNEPathCreator::getSelectedEdges() const {
435
return mySelectedEdges;
436
}
437
438
439
const std::vector<GNEJunction*>&
440
GNEPathCreator::getSelectedJunctions() const {
441
return mySelectedJunctions;
442
}
443
444
445
const std::vector<GNETAZ*>&
446
GNEPathCreator::getSelectedTAZs() const {
447
return mySelectedTAZs;
448
}
449
450
451
bool
452
GNEPathCreator::addRoute(GNEDemandElement* route) {
453
// check if routes aren allowed
454
if ((myCreationMode & ROUTE) == 0) {
455
return false;
456
}
457
// check if previously a route was added
458
if (myRoute) {
459
return false;
460
}
461
// set route and create path
462
myRoute = route;
463
createPath(false);
464
myRoute = nullptr;
465
// recalculate path
466
recalculatePath();
467
updateInfoRouteLabel();
468
updateEdgeColors();
469
return true;
470
}
471
472
473
GNEDemandElement*
474
GNEPathCreator::getRoute() const {
475
return myRoute;
476
}
477
478
479
const std::vector<GNEPathCreator::Path>&
480
GNEPathCreator::getPath() const {
481
return myPath;
482
}
483
484
485
bool
486
GNEPathCreator::drawCandidateEdgesWithSpecialColor() const {
487
return (myShowCandidateEdges->getCheck() == TRUE);
488
}
489
490
491
void
492
GNEPathCreator::updateJunctionColors() {
493
// clear junction colors
494
clearJunctionColors();
495
// check if show possible candidates
496
if (myCreationMode & SHOW_CANDIDATE_JUNCTIONS) {
497
// set candidate flags
498
for (const auto& junction : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getJunctions()) {
499
junction.second->resetCandidateFlags();
500
junction.second->setPossibleCandidate(true);
501
}
502
}
503
// set selected junctions
504
if (mySelectedJunctions.size() > 0) {
505
// mark selected eges
506
for (const auto& junction : mySelectedJunctions) {
507
junction->resetCandidateFlags();
508
junction->setSourceCandidate(true);
509
}
510
// finally mark last selected element as target
511
mySelectedJunctions.back()->resetCandidateFlags();
512
mySelectedJunctions.back()->setTargetCandidate(true);
513
}
514
// update view net
515
myFrameParent->getViewNet()->updateViewNet();
516
}
517
518
519
void
520
GNEPathCreator::updateEdgeColors() {
521
// clear edge colors
522
clearEdgeColors();
523
// first check if show candidate edges
524
if (myShowCandidateEdges->getCheck() == TRUE && (myCreationMode & SHOW_CANDIDATE_EDGES)) {
525
// mark all edges that have at least one lane that allow given vClass
526
for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
527
if (edge.second->getNBEdge()->getNumLanesThatAllow(myVClass) > 0) {
528
edge.second->setPossibleCandidate(true);
529
} else {
530
edge.second->setSpecialCandidate(true);
531
}
532
}
533
}
534
// set reachability
535
if (mySelectedEdges.size() > 0) {
536
// only coloring edges if checkbox "show candidate edges" is enabled
537
if ((myShowCandidateEdges->getCheck() == TRUE) && (myCreationMode & SHOW_CANDIDATE_EDGES)) {
538
// mark all edges as conflicted (to mark special candidates)
539
for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
540
edge.second->resetCandidateFlags();
541
edge.second->setConflictedCandidate(true);
542
}
543
// set special candidates (Edges that are connected but aren't compatibles with current vClass
544
setSpecialCandidates(mySelectedEdges.back());
545
// mark again all edges as conflicted (to mark possible candidates)
546
for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
547
edge.second->setConflictedCandidate(true);
548
}
549
// set possible candidates (Edges that are connected AND are compatibles with current vClass
550
setPossibleCandidates(mySelectedEdges.back(), myVClass);
551
}
552
// now mark selected eges
553
for (const auto& edge : mySelectedEdges) {
554
edge->resetCandidateFlags();
555
edge->setSourceCandidate(true);
556
}
557
// finally mark last selected element as target
558
mySelectedEdges.back()->resetCandidateFlags();
559
mySelectedEdges.back()->setTargetCandidate(true);
560
}
561
// update view net
562
myFrameParent->getViewNet()->updateViewNet();
563
}
564
565
566
void
567
GNEPathCreator::clearJunctionColors() {
568
// reset all junction flags
569
for (const auto& junction : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getJunctions()) {
570
junction.second->resetCandidateFlags();
571
}
572
}
573
574
575
void
576
GNEPathCreator::clearEdgeColors() {
577
// reset all junction flags
578
for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
579
edge.second->resetCandidateFlags();
580
}
581
}
582
583
584
void
585
GNEPathCreator::drawTemporalRoute(const GUIVisualizationSettings& s) const {
586
const double lineWidth = 0.35;
587
const double lineWidthin = 0.25;
588
// Add a draw matrix
589
GLHelper::pushMatrix();
590
// Start with the drawing of the area traslating matrix to origin
591
glTranslated(0, 0, GLO_MAX - 0.1);
592
// check if draw bewteen junction or edges
593
if (myPath.size() > 0) {
594
// set first color
595
GLHelper::setColor(RGBColor::GREY);
596
// iterate over path
597
for (int i = 0; i < (int)myPath.size(); i++) {
598
// get path
599
const GNEPathCreator::Path& path = myPath.at(i);
600
// draw line over
601
for (int j = 0; j < (int)path.getSubPath().size(); j++) {
602
const GNELane* lane = path.getSubPath().at(j)->getChildLanes().back();
603
if (((i == 0) && (j == 0)) || (j > 0)) {
604
GLHelper::drawBoxLines(lane->getLaneShape(), lineWidth);
605
}
606
// draw connection between lanes
607
if ((j + 1) < (int)path.getSubPath().size()) {
608
const GNELane* nextLane = path.getSubPath().at(j + 1)->getChildLanes().back();
609
if (lane->getLane2laneConnections().exist(nextLane)) {
610
GLHelper::drawBoxLines(lane->getLane2laneConnections().getLane2laneGeometry(nextLane).getShape(), lineWidth);
611
} else {
612
GLHelper::drawBoxLines({lane->getLaneShape().back(), nextLane->getLaneShape().front()}, lineWidth);
613
}
614
}
615
}
616
}
617
glTranslated(0, 0, 0.1);
618
// iterate over path again
619
for (int i = 0; i < (int)myPath.size(); i++) {
620
// get path
621
const GNEPathCreator::Path& path = myPath.at(i);
622
// set path color color
623
if ((myCreationMode & SHOW_CANDIDATE_EDGES) == 0) {
624
GLHelper::setColor(RGBColor::ORANGE);
625
} else if (path.isConflictDisconnected()) {
626
GLHelper::setColor(s.candidateColorSettings.conflict);
627
} else if (path.isConflictVClass()) {
628
GLHelper::setColor(s.candidateColorSettings.special);
629
} else {
630
GLHelper::setColor(RGBColor::ORANGE);
631
}
632
// draw line over
633
for (int j = 0; j < (int)path.getSubPath().size(); j++) {
634
const GNELane* lane = path.getSubPath().at(j)->getChildLanes().back();
635
if (((i == 0) && (j == 0)) || (j > 0)) {
636
GLHelper::drawBoxLines(lane->getLaneShape(), lineWidthin);
637
}
638
// draw connection between lanes
639
if ((j + 1) < (int)path.getSubPath().size()) {
640
const GNELane* nextLane = path.getSubPath().at(j + 1)->getChildLanes().back();
641
if (lane->getLane2laneConnections().exist(nextLane)) {
642
GLHelper::drawBoxLines(lane->getLane2laneConnections().getLane2laneGeometry(nextLane).getShape(), lineWidthin);
643
} else {
644
GLHelper::drawBoxLines({ lane->getLaneShape().back(), nextLane->getLaneShape().front() }, lineWidthin);
645
}
646
}
647
}
648
}
649
} else if (mySelectedJunctions.size() > 0) {
650
// set color
651
GLHelper::setColor(RGBColor::ORANGE);
652
// draw line between junctions
653
for (int i = 0; i < (int)mySelectedJunctions.size() - 1; i++) {
654
// get two points
655
const Position posA = mySelectedJunctions.at(i)->getPositionInView();
656
const Position posB = mySelectedJunctions.at(i + 1)->getPositionInView();
657
const double rot = ((double)atan2((posB.x() - posA.x()), (posA.y() - posB.y())) * (double) 180.0 / (double)M_PI);
658
const double len = posA.distanceTo2D(posB);
659
// draw line
660
GLHelper::drawBoxLine(posA, rot, len, 0.25);
661
}
662
} else if (mySelectedTAZs.size() > 0) {
663
// set color
664
GLHelper::setColor(RGBColor::ORANGE);
665
// draw line between TAZs
666
for (int i = 0; i < (int)mySelectedTAZs.size() - 1; i++) {
667
// get two points
668
const Position posA = mySelectedTAZs.at(i)->getPositionInView();
669
const Position posB = mySelectedTAZs.at(i + 1)->getPositionInView();
670
const double rot = ((double)atan2((posB.x() - posA.x()), (posA.y() - posB.y())) * (double) 180.0 / (double)M_PI);
671
const double len = posA.distanceTo2D(posB);
672
// draw line
673
GLHelper::drawBoxLine(posA, rot, len, 0.25);
674
}
675
}
676
// Pop last matrix
677
GLHelper::popMatrix();
678
}
679
680
681
bool
682
GNEPathCreator::createPath(const bool useLastRoute) {
683
// call create path implemented in frame parent
684
return myFrameParent->createPath(useLastRoute);
685
}
686
687
688
void
689
GNEPathCreator::abortPathCreation() {
690
// first check that there is elements
691
if ((mySelectedJunctions.size() > 0) || (mySelectedTAZs.size() > 0) || (mySelectedEdges.size() > 0) || myRoute) {
692
// unblock undo/redo
693
myFrameParent->getViewNet()->getViewParent()->getGNEAppWindows()->enableUndoRedoTemporally();
694
// clear edges
695
clearPath();
696
// disable buttons
697
myFinishCreationButton->disable();
698
myAbortCreationButton->disable();
699
myRemoveLastInsertedElement->disable();
700
// update info route label
701
updateInfoRouteLabel();
702
// update junction colors
703
updateJunctionColors();
704
// update edge colors
705
updateEdgeColors();
706
// update view (to see the new route)
707
myFrameParent->getViewNet()->updateViewNet();
708
}
709
}
710
711
712
void
713
GNEPathCreator::removeLastElement() {
714
if (mySelectedEdges.size() > 1) {
715
// remove special color of last selected edge
716
mySelectedEdges.back()->resetCandidateFlags();
717
// remove last edge
718
mySelectedEdges.pop_back();
719
// change last edge flag
720
if ((mySelectedEdges.size() > 0) && mySelectedEdges.back()->isSourceCandidate()) {
721
mySelectedEdges.back()->setSourceCandidate(false);
722
mySelectedEdges.back()->setTargetCandidate(true);
723
}
724
// enable or disable remove last edge button
725
if (mySelectedEdges.size() > 1) {
726
myRemoveLastInsertedElement->enable();
727
} else {
728
myRemoveLastInsertedElement->disable();
729
}
730
// recalculate path
731
recalculatePath();
732
// update info route label
733
updateInfoRouteLabel();
734
// update junction colors
735
updateJunctionColors();
736
// update edge colors
737
updateEdgeColors();
738
// update view
739
myFrameParent->getViewNet()->updateViewNet();
740
}
741
}
742
743
744
long
745
GNEPathCreator::onCmdCreatePath(FXObject*, FXSelector, void*) {
746
// call create path
747
return createPath(false);
748
}
749
750
751
long
752
GNEPathCreator::onCmdUseLastRoute(FXObject*, FXSelector, void*) {
753
// call create path with useLastRoute = true
754
return createPath(true);
755
}
756
757
long
758
GNEPathCreator::onUpdUseLastRoute(FXObject* sender, FXSelector, void*) {
759
if ((myCreationMode & ROUTE) && myFrameParent->getViewNet()->getLastCreatedRoute()) {
760
return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), nullptr);
761
} else {
762
return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), nullptr);
763
}
764
}
765
766
long
767
GNEPathCreator::onCmdAbortPathCreation(FXObject*, FXSelector, void*) {
768
// just call abort path creation
769
abortPathCreation();
770
return 1;
771
}
772
773
774
long
775
GNEPathCreator::onCmdRemoveLastElement(FXObject*, FXSelector, void*) {
776
// just call remove last element
777
removeLastElement();
778
return 1;
779
}
780
781
782
long
783
GNEPathCreator::onCmdShowCandidateEdges(FXObject*, FXSelector, void*) {
784
// update labels
785
if (myShowCandidateEdges->getCheck() == TRUE) {
786
myShiftLabel->show();
787
myControlLabel->show();
788
} else {
789
myShiftLabel->hide();
790
myControlLabel->hide();
791
}
792
// recalc frame
793
recalc();
794
// update edge colors (view will be updated within function)
795
updateEdgeColors();
796
return 1;
797
}
798
799
800
void
801
GNEPathCreator::updateInfoRouteLabel() {
802
if (myPath.size() > 0) {
803
// declare variables for route info
804
double length = 0;
805
double speed = 0;
806
int pathSize = 0;
807
for (const auto& path : myPath) {
808
for (const auto& edge : path.getSubPath()) {
809
length += edge->getNBEdge()->getLength();
810
speed += edge->getNBEdge()->getSpeed();
811
}
812
pathSize += (int)path.getSubPath().size();
813
}
814
// declare ostringstream for label and fill it
815
std::ostringstream information;
816
information
817
<< TL("- Selected edges: ") << toString(mySelectedEdges.size()) << "\n"
818
<< TL("- Path edges: ") << toString(pathSize) << "\n"
819
<< TL("- Length: ") << toString(length) << "\n"
820
<< TL("- Average speed: ") << toString(speed / pathSize);
821
// set new label
822
myInfoRouteLabel->setText(information.str().c_str());
823
} else {
824
myInfoRouteLabel->setText(TL("No edges selected"));
825
}
826
}
827
828
829
void
830
GNEPathCreator::clearPath() {
831
/// reset flags
832
clearJunctionColors();
833
clearEdgeColors();
834
// clear junction, TAZs, edges, additionals and route
835
mySelectedJunctions.clear();
836
mySelectedTAZs.clear();
837
mySelectedEdges.clear();
838
myRoute = nullptr;
839
// clear path
840
myPath.clear();
841
// update info route label
842
updateInfoRouteLabel();
843
}
844
845
846
void
847
GNEPathCreator::recalculatePath() {
848
// first clear path
849
myPath.clear();
850
// set edges
851
std::vector<GNEEdge*> edges;
852
// add route edges
853
if (myRoute) {
854
edges = myRoute->getParentEdges();
855
} else {
856
// add selected edges
857
for (const auto& edge : mySelectedEdges) {
858
edges.push_back(edge);
859
}
860
}
861
// fill paths
862
if (edges.size() == 1) {
863
myPath.push_back(Path(myVClass, edges.front()));
864
} else if (mySelectedJunctions.size() == 2) {
865
// add path between two junctions
866
myPath.push_back(Path(myPathManager, myVClass, mySelectedJunctions.front(), mySelectedJunctions.back()));
867
} else {
868
// add every segment
869
for (int i = 1; i < (int)edges.size(); i++) {
870
myPath.push_back(Path(myPathManager, myVClass, edges.at(i - 1), edges.at(i)));
871
}
872
}
873
}
874
875
876
void
877
GNEPathCreator::setSpecialCandidates(GNEEdge* originEdge) {
878
// first calculate reachability for pedestrians (we use it, because pedestran can walk in almost all edges)
879
myPathManager->getPathCalculator()->calculateReachability(SVC_PEDESTRIAN, originEdge);
880
// change flags
881
for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
882
for (const auto& lane : edge.second->getChildLanes()) {
883
if (lane->getReachability() > 0) {
884
lane->getParentEdge()->resetCandidateFlags();
885
lane->getParentEdge()->setSpecialCandidate(true);
886
}
887
}
888
}
889
}
890
891
void
892
GNEPathCreator::setPossibleCandidates(GNEEdge* originEdge, const SUMOVehicleClass vClass) {
893
// first calculate reachability for pedestrians
894
myPathManager->getPathCalculator()->calculateReachability(vClass, originEdge);
895
// change flags
896
for (const auto& edge : myFrameParent->getViewNet()->getNet()->getAttributeCarriers()->getEdges()) {
897
for (const auto& lane : edge.second->getChildLanes()) {
898
if (lane->getReachability() > 0) {
899
lane->getParentEdge()->resetCandidateFlags();
900
lane->getParentEdge()->setPossibleCandidate(true);
901
}
902
}
903
}
904
}
905
906
/****************************************************************************/
907
908