Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
GNEDemandElementPlan.cpp
Go to the documentation of this file.
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/****************************************************************************/
18// An auxiliar, asbtract class for plan elements
19/****************************************************************************/
20
21#include <netedit/GNENet.h>
22#include <netedit/GNESegment.h>
23#include <netedit/GNEUndoList.h>
24#include <netedit/GNEViewNet.h>
29
31#include "GNERoute.h"
32
33// ===========================================================================
34// static definitions
35// ===========================================================================
36
38
39// ===========================================================================
40// GNEDemandElement method definitions
41// ===========================================================================
42
43GNEDemandElementPlan::GNEDemandElementPlan(GNEDemandElement* planElement, const double departPosition, const double arrivalPosition) :
44 myDepartPosition(departPosition),
45 myArrivalPosition(arrivalPosition),
46 myPlanElement(planElement) {
47}
48
49
52 // get tag property
53 const auto tagProperty = myPlanElement->getTagProperty();
54 // only move personTrips defined over edges
55 if (tagProperty->planToEdge() || tagProperty->planConsecutiveEdges() || tagProperty->planEdge()) {
56 // get geometry end pos
58 // calculate circle width squared
59 const double circleWidthSquared = myArrivalPositionDiameter * myArrivalPositionDiameter;
60 // check if we clicked over a geometry end pos
61 if (myPlanElement->myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(geometryEndPos) <= ((circleWidthSquared + 2))) {
62 // continue depending of parent edges
63 if (myPlanElement->getParentEdges().size() > 0) {
64 return new GNEMoveOperation(myPlanElement, myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(myPlanElement->getVClass()), myArrivalPosition, false);
65 } else {
66 return new GNEMoveOperation(myPlanElement, myPlanElement->getParentDemandElements().at(1)->getParentEdges().back()->getLaneByAllowedVClass(myPlanElement->getVClass()), myArrivalPosition, false);
67 }
68 }
69 }
70 return nullptr;
71}
72
73
74void
76 const auto tagProperty = myPlanElement->getTagProperty();
77 // write attributes depending of parent elements
78 if (tagProperty->planConsecutiveEdges()) {
80 } else if (tagProperty->planRoute()) {
82 } else if (tagProperty->planEdge()) {
83 device.writeAttr(SUMO_ATTR_EDGE, myPlanElement->getParentEdges().front()->getID());
84 } else if (tagProperty->planBusStop()) {
86 } else if (tagProperty->planTrainStop()) {
88 } else if (tagProperty->planContainerStop()) {
90 } else if (tagProperty->planChargingStation()) {
92 } else if (tagProperty->planParkingArea()) {
94 } else {
95 // write from attribute (if this is the first element)
96 if (myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement) == nullptr) {
97 // check if write edge or junction
98 if (tagProperty->planFromEdge()) {
99 device.writeAttr(SUMO_ATTR_FROM, myPlanElement->getParentEdges().front()->getID());
100 } else if (tagProperty->planFromTAZ()) {
101 device.writeAttr(SUMO_ATTR_FROM_TAZ, myPlanElement->getParentTAZs().front()->getID());
102 } else if (tagProperty->planFromJunction()) {
104 }
105 // origin stopping places are transformed into an intial stop stage (see writeOriginStop)
106 }
107 // continue writting to attribute
108 if (tagProperty->planToEdge()) {
109 device.writeAttr(SUMO_ATTR_TO, myPlanElement->getParentEdges().back()->getID());
110 } else if (tagProperty->planToJunction()) {
112 } else if (tagProperty->planToTAZ()) {
113 device.writeAttr(SUMO_ATTR_TO_TAZ, myPlanElement->getParentTAZs().back()->getID());
114 } else if (tagProperty->planToBusStop()) {
116 } else if (tagProperty->planToTrainStop()) {
118 } else if (tagProperty->planToContainerStop()) {
120 } else if (tagProperty->planToChargingStation()) {
122 } else if (tagProperty->planToParkingArea()) {
124 }
125 }
126 // check if write depart position
127 if (tagProperty->hasAttribute(SUMO_ATTR_DEPARTPOS) && (myDepartPosition > 0)) {
129 }
130 // check if write arrival position
131 if (tagProperty->hasAttribute(SUMO_ATTR_ARRIVALPOS) && (myArrivalPosition > 0)) {
133 }
134 // check if write end position
135 if (tagProperty->hasAttribute(SUMO_ATTR_ENDPOS)) {
137 }
138}
139
140
141void
143 const auto tagProperty = myPlanElement->getTagProperty();
144 // write an extra stop element with duration 0 over a stopping place (if this is the first element)
145 if (tagProperty->planFromStoppingPlace()
146 && myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement) == nullptr) {
147 device.openTag(SUMO_TAG_STOP);
148 const std::string stopID = myPlanElement->getParentStoppingPlaces().front()->getID();
149 if (tagProperty->planFromBusStop()) {
150 device.writeAttr(SUMO_ATTR_BUS_STOP, stopID);
151 } else if (tagProperty->planFromTrainStop()) {
152 device.writeAttr(SUMO_ATTR_TRAIN_STOP, stopID);
153 } else if (tagProperty->planFromContainerStop()) {
154 device.writeAttr(SUMO_ATTR_CONTAINER_STOP, stopID);
155 } else if (tagProperty->planFromChargingStation()) {
157 } else if (tagProperty->planFromParkingArea()) {
158 device.writeAttr(SUMO_ATTR_PARKING_AREA, stopID);
159 }
160 device.writeAttr(SUMO_ATTR_DURATION, 0);
161 device.closeTag();
162 }
163}
164
165
168 // create popup
170 // build common options
172 GUIDesigns::buildFXMenuCommand(ret, ("Cursor position in view: " + toString(getPlanPositionInView().x()) + "," + toString(getPlanPositionInView().y())).c_str(), nullptr, nullptr, 0);
173 return ret;
174}
175
176
177GNELane*
179 // get tag property
180 const auto tagProperty = myPlanElement->getTagProperty();
181 // get vclass
182 auto vClass = myPlanElement->getVClass();
183 // continue depending of parents
184 if (tagProperty->planRoute()) {
185 // route
186 return myPlanElement->getParentDemandElements().at(1)->getParentEdges().front()->getLaneByAllowedVClass(vClass);
187 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planFromEdge() || tagProperty->planEdge()) {
188 // edges
189 return myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
190 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace() || tagProperty->planToStoppingPlace()) {
191 // additional
192 return myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
193 } else {
194 // in other cases (TAZ, junctions, etc.) return null
195 return nullptr;
196 }
197}
198
199
200GNELane*
202 // get tag property
203 const auto tagProperty = myPlanElement->getTagProperty();
204 // get vclass
205 auto vClass = myPlanElement->getVClass();
206 // check parents
207 if (tagProperty->planRoute()) {
208 // route
209 return myPlanElement->getParentDemandElements().at(1)->getParentEdges().back()->getLaneByAllowedVClass(vClass);
210 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planToEdge() || tagProperty->planEdge()) {
211 // edges
212 return myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
213 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace() || tagProperty->planToStoppingPlace()) {
214 // additional
215 return myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getParentEdge()->getLaneByAllowedVClass(vClass);
216 } else {
217 // in other cases (TAZ, junctions, etc.) return null
218 return nullptr;
219 }
220}
221
222
223void
225 // get tag property
226 const auto tagProperty = myPlanElement->getTagProperty();
227 // get vClass
228 auto vClass = myPlanElement->getVClass();
229 // get path manager
230 auto pathManager = myPlanElement->getNet()->getDemandPathManager();
231 // continue depending of parents
232 if (tagProperty->planRoute()) {
233 // calculate consecutive path using route edges
234 pathManager->calculateConsecutivePathEdges(myPlanElement, vClass, myPlanElement->getParentDemandElements().at(1)->getParentEdges());
235 } else if (tagProperty->planConsecutiveEdges()) {
236 // calculate consecutive path using edges
237 pathManager->calculateConsecutivePathEdges(myPlanElement, vClass, myPlanElement->getParentEdges());
239 // calculate path using junctions
240 pathManager->calculatePath(myPlanElement, vClass, myPlanElement->getParentJunctions().front(), myPlanElement->getParentJunctions().back());
242 // declare last lane
243 GNELane* lastLane = nullptr;
245 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().back();
247 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front();
248 } else if (myPlanElement->myTagProperty->planToEdge()) {
249 lastLane = myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
250 }
251 // calculate path
252 if (lastLane) {
253 pathManager->calculatePath(myPlanElement, vClass, myPlanElement->getParentJunctions().front(), lastLane);
254 }
256 // declare first lane
257 GNELane* firstLane = nullptr;
259 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().back();
261 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
263 firstLane = myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
264 }
265 // calculate path
266 if (firstLane) {
267 pathManager->calculatePath(myPlanElement, vClass, firstLane, myPlanElement->getParentJunctions().back());
268 }
269 } else {
270 // declare first edge
271 GNELane* firstLane = nullptr;
273 firstLane = myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
275 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().back();
277 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
278 }
279 // declare last lane
280 GNELane* lastLane = nullptr;
282 lastLane = myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
284 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().back();
286 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front();
287 }
288 if (firstLane && lastLane) {
289 pathManager->calculatePath(myPlanElement, vClass, firstLane, lastLane);
290 } else if (firstLane) {
291 pathManager->calculateConsecutivePathLanes(myPlanElement, {firstLane});
292 } else if (lastLane) {
293 pathManager->calculateConsecutivePathLanes(myPlanElement, {lastLane});
294 }
295 }
296 // update geometry
298}
299
300
301void
303 // get tag property
304 const auto tagProperty = myPlanElement->getTagProperty();
305 // check if plan start or end in a TAZ (becase in this case has to be inserted in RTREE
306 if (tagProperty->planFromTAZ() || tagProperty->planToTAZ()) {
307 // declare first and last positions
308 Position firstPos = Position::INVALID;
309 Position lastPos = Position::INVALID;
310 // set first position
311 if (tagProperty->planFromEdge()) {
312 // from junction
313 firstPos = myPlanElement->getFirstPathLane()->getLaneShape().back();
314 } else if (tagProperty->planFromJunction()) {
315 // from junction
316 firstPos = myPlanElement->getParentJunctions().front()->getPositionInView();
317 } else if (tagProperty->planFromStoppingPlace()) {
318 // end of stoppingPlace lane shape
319 firstPos = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLaneShape().back();
320 } else if (tagProperty->planFromTAZ()) {
321 // from TAZ
322 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
323 firstPos = myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
324 } else {
325 firstPos = myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
326 }
327 }
328 // set last position
329 if (tagProperty->planToEdge()) {
330 // from junction
331 lastPos = myPlanElement->getLastPathLane()->getLaneShape().back();
332 } else if (tagProperty->planToJunction()) {
333 // from junction
334 lastPos = myPlanElement->getParentJunctions().back()->getPositionInView();
335 } else if (tagProperty->planToStoppingPlace()) {
336 // end of stoppingPlace lane shape
337 lastPos = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLaneShape().front();
338 } else if (tagProperty->planToTAZ()) {
339 // from TAZ
340 if (myPlanElement->getParentTAZs().back()->getAttribute(SUMO_ATTR_CENTER).empty()) {
341 lastPos = myPlanElement->getParentTAZs().back()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
342 } else {
343 lastPos = myPlanElement->getParentTAZs().back()->getAttributePosition(SUMO_ATTR_CENTER);
344 }
345 }
346 // use both position to calculate a line
347 if ((firstPos != Position::INVALID) && (lastPos != Position::INVALID)) {
349 } else {
351 }
352 }
353 // update centering boundary
355 // update child demand elements
356 for (const auto& demandElement : myPlanElement->getChildDemandElements()) {
357 demandElement->updateGeometry();
358 }
359}
360
361
366
367
368void
370 // remove additional from grid
371 if (myPlanBoundary.isInitialised() && updateGrid) {
373 }
375 // if this element is over route, add their boundary
376 if (myPlanElement->getParentDemandElements().size() > 1) {
377 myPlanBoundary.add(myPlanElement->getParentDemandElements().at(1)->getCenteringBoundary());
378 }
379 // add the combination of all parent edges's boundaries
380 for (const auto& edge : myPlanElement->getParentEdges()) {
381 myPlanBoundary.add(edge->getCenteringBoundary());
382 }
383 // add the combination of all parent edges's boundaries
384 for (const auto& junction : myPlanElement->getParentJunctions()) {
385 myPlanBoundary.add(junction->getCenteringBoundary());
386 }
387 // add the combination of all parent additional's boundaries (stoppingPlaces and TAZs)
388 for (const auto& additional : myPlanElement->getParentAdditionals()) {
389 if (additional->getTagProperty()->getTag() == SUMO_TAG_TAZ) {
390 if (additional->getAttribute(SUMO_ATTR_CENTER).empty()) {
391 myPlanBoundary.add(additional->getAttributePosition(GNE_ATTR_TAZ_CENTROID));
392 } else {
393 myPlanBoundary.add(additional->getAttributePosition(SUMO_ATTR_CENTER));
394 }
395 } else {
396 myPlanBoundary.add(additional->getCenteringBoundary());
397 }
398 }
399 // check if is valid
402 }
403 // add additional into RTREE again
404 if (myPlanBoundary.isInitialised() && updateGrid) {
406 }
407}
408
409
412 // get tag property
413 const auto tagProperty = myPlanElement->getTagProperty();
414 // continue depending of parents
415 if (tagProperty->planRoute()) {
416 // route
417 return myPlanElement->getParentDemandElements().at(1)->getPositionInView();
418 } else if (tagProperty->isPlanStop()) {
420 } else if (tagProperty->planFromEdge() || tagProperty->planConsecutiveEdges() || tagProperty->planEdge()) {
421 // first edge
422 return myPlanElement->getParentEdges().front()->getPositionInView();
423 } else if (tagProperty->planFromJunction()) {
424 // first junction
425 return myPlanElement->getParentJunctions().front()->getPositionInView();
426 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace()) {
427 // first additional
428 return myPlanElement->getParentStoppingPlaces().front()->getPositionInView();
429 } else if (tagProperty->planFromTAZ()) {
430 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
431 return myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
432 } else {
433 return myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
434 }
435 } else {
436 // return parent position
437 return Position(0, 0);
438 }
439}
440
441
442std::string
444 // continue depending of key
445 switch (key) {
446 // Common plan attributes
447 case SUMO_ATTR_ID:
448 case GNE_ATTR_PARENT:
449 return myPlanElement->getParentDemandElements().at(0)->getID();
451 if (myDepartPosition < 0) {
452 return "";
453 } else {
455 }
456 case SUMO_ATTR_ENDPOS:
458 if (myArrivalPosition < 0) {
459 return "";
460 } else {
462 }
463 // route
464 case SUMO_ATTR_ROUTE:
465 return myPlanElement->getParentDemandElements().at(1)->getID();
466 // edges
467 case SUMO_ATTR_EDGE:
468 case SUMO_ATTR_EDGES:
470 // stoppingPlaces (single and back)
476 return myPlanElement->getParentStoppingPlaces().back()->getID();
477 // from elements
478 case SUMO_ATTR_FROM:
479 return myPlanElement->getParentEdges().front()->getID();
481 return myPlanElement->getParentJunctions().front()->getID();
483 return myPlanElement->getParentTAZs().front()->getID();
489 return myPlanElement->getParentStoppingPlaces().front()->getID();
490 // to elements
491 case SUMO_ATTR_TO:
492 return myPlanElement->getParentEdges().back()->getID();
494 return myPlanElement->getParentJunctions().back()->getID();
495 case SUMO_ATTR_TO_TAZ:
496 return myPlanElement->getParentTAZs().back()->getID();
497 default:
498 return myPlanElement->getCommonAttribute(dynamic_cast<Parameterised*>(myPlanElement), key);
499 }
500}
501
502
503double
505 // get tag property
506 const auto tagProperty = myPlanElement->getTagProperty();
507 // declare plan parent
508 const auto planParent = myPlanElement->getParentDemandElements().at(0);
509 // continue depending of key
510 switch (key) {
512 if (tagProperty->planStoppingPlace()) {
513 // use startpos of stoppingPlace parent (stops)
514 const auto factor = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLengthGeometryFactor();
515 return myPlanElement->getParentStoppingPlaces().front()->getAttributeDouble(SUMO_ATTR_STARTPOS) * factor;
516 } else if (tagProperty->planFromStoppingPlace()) {
517 // use end position of stoppingPlace parent (for plans that starts in stoppingPlaces)
518 const auto factor = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLengthGeometryFactor();
519 return myPlanElement->getParentStoppingPlaces().front()->getAttributeDouble(SUMO_ATTR_ENDPOS) * factor;
520 } else if (tagProperty->planFromTAZ()) {
521 return 0;
522 } else if (tagProperty->planFromJunction()) {
523 return -1;
524 } else {
525 // get previous plan element
526 const auto previousPlan = planParent->getPreviousChildDemandElement(myPlanElement);
527 // continue depending of previous plan
528 if (previousPlan) {
529 // use previous plan end position (normally the arrival position)
530 const auto posOverLane = previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
531 // if posOverLane is -1, means that previousPlan ends in the end of lane.
532 if (posOverLane == -1) {
533 // INVALID_DOUBLE will put the startPositio at the end of line
534 return INVALID_DOUBLE;
535 } else {
536 return previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
537 }
538 } else {
539 // use depart position defined in parent (person or container)
540 return planParent->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
541 }
542 }
543 }
545 // continue depending of parents
546 if (tagProperty->planStoppingPlace()) {
547 // use end position of the stoppingPlace (stops)
548 const auto factor = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLengthGeometryFactor();
549 return myPlanElement->getParentStoppingPlaces().back()->getAttributeDouble(SUMO_ATTR_ENDPOS) * factor;
550 } else if (tagProperty->planToStoppingPlace()) {
551 // use start position of the stoppingPlace (for elements that ends in stoppingPlaces)
552 const auto factor = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLengthGeometryFactor();
553 return myPlanElement->getParentStoppingPlaces().back()->getAttributeDouble(SUMO_ATTR_STARTPOS) * factor;
554 } else if (tagProperty->planToJunction() || tagProperty->planToTAZ()) {
555 // junctions and TAZs return always -1
556 return -1;
557 } else if ((tagProperty->isPlanStopPerson() || tagProperty->isPlanStopContainer()) && tagProperty->planEdge()) {
558 // elements that ends in stop always uses the end (arrival) position of the stops over edges
559 return myArrivalPosition;
560 } else {
561 // check if next plan is a stop over edge
562 const auto nextPlan = planParent->getNextChildDemandElement(myPlanElement);
563 if (nextPlan && (nextPlan->getTagProperty()->isPlanStopPerson() ||
564 nextPlan->getTagProperty()->isPlanStopContainer()) &&
565 nextPlan->getTagProperty()->planEdge()) {
566 // if next plan is an stop over stoppingPlaces, use ends of stoppingPlace
567 return nextPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
568 } else {
569 // use arrival position
570 return myArrivalPosition;
571 }
572 }
574 return myDepartPosition;
575 case SUMO_ATTR_ENDPOS:
577 return myArrivalPosition;
578 default:
579 throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have a doubleattribute of type '" + toString(key) + "'");
580 }
581}
582
583
586 // get tag property
587 const auto tagProperty = myPlanElement->getTagProperty();
588 // declare plan parent
589 const auto planParent = myPlanElement->getParentDemandElements().at(0);
590 // continue depending of key
591 switch (key) {
593 // get previous plan
594 const auto previousPlan = planParent->getPreviousChildDemandElement(myPlanElement);
595 if (previousPlan && previousPlan->getTagProperty()->isPlanStop() && previousPlan->getTagProperty()->planStoppingPlace()) {
596 return previousPlan->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().back();
597 }
598 // continue depending of from element
599 if (tagProperty->planStoppingPlace()) {
600 return myPlanElement->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().front();
601 } else if (tagProperty->planFromStoppingPlace()) {
602 return myPlanElement->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().back();
603 } else if (tagProperty->planFromJunction()) {
604 // junction view position
605 return myPlanElement->getParentJunctions().front()->getPositionInView();
606 } else if (tagProperty->planFromTAZ()) {
607 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
608 return myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
609 } else {
610 return myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
611 }
612 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planRoute() || tagProperty->planFromEdge()) {
613 // get first path lane
614 const auto firstLane = myPlanElement->getFirstPathLane();
615 // check if first lane exists
616 if (firstLane == nullptr) {
617 return Position::INVALID;
618 }
619 // declare lane position
620 double lanePosition = 0;
621 // continue depending of conditions
622 if (previousPlan) {
623 // use previous geometry end position
624 lanePosition = previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
625 } else {
626 // use departPos defined in planParent
627 lanePosition = planParent->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
628 }
629 // get lane shape
630 const auto& laneShape = firstLane->getLaneShape();
631 // continue depending of lane position
632 if (lanePosition <= 0) {
633 return laneShape.front();
634 } else if (lanePosition >= laneShape.length2D()) {
635 return laneShape.back();
636 } else {
637 return laneShape.positionAtOffset2D(lanePosition);
638 }
639 } else {
640 return Position::INVALID;
641 }
642 }
644 // check parents
645 if (tagProperty->planToJunction()) {
646 // junctions
647 return myPlanElement->getParentJunctions().back()->getPositionInView();
648 } else if (tagProperty->planStoppingPlace()) {
649 // get additional back shape (stops)
650 return myPlanElement->getParentStoppingPlaces().back()->getAdditionalGeometry().getShape().back();
651 } else if (tagProperty->planToStoppingPlace()) {
652 // get additional front shape
653 return myPlanElement->getParentStoppingPlaces().back()->getAdditionalGeometry().getShape().front();
654 } else if (tagProperty->planToTAZ()) {
655 // taz
656 if (myPlanElement->getParentTAZs().back()->getAttribute(SUMO_ATTR_CENTER).empty()) {
657 return myPlanElement->getParentTAZs().back()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
658 } else {
659 return myPlanElement->getParentTAZs().back()->getAttributePosition(SUMO_ATTR_CENTER);
660 }
661 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planRoute() || tagProperty->planFromEdge()) {
662 // get next plan
663 const auto nextPlan = planParent->getNextChildDemandElement(myPlanElement);
664 // if next plan exist, then use their first lane (needed to maintain connectivity with rides)
665 const auto lastLane = nextPlan ? nextPlan->getFirstPathLane() : myPlanElement->getLastPathLane();
666 // check if last lane exists
667 if (lastLane == nullptr) {
668 return Position::INVALID;
669 }
670 // get lane shape
671 const auto& laneShape = lastLane->getLaneShape();
672 // continue depending of arrival position
673 if (nextPlan && nextPlan->getTagProperty()->isPlanStop()) {
674 return nextPlan->getAttributePosition(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
675 } else if (myArrivalPosition == 0) {
676 return laneShape.front();
677 } else if ((myArrivalPosition == -1) || (myArrivalPosition >= laneShape.length2D())) {
678 return laneShape.back();
679 } else {
680 return laneShape.positionAtOffset2D(myArrivalPosition);
681 }
682 } else {
683 return Position::INVALID;
684 }
685 }
686 default:
687 throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have a position attribute of type '" + toString(key) + "'");
688 }
689}
690
691
692void
693GNEDemandElementPlan::setPlanAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
694 // continue depending of key
695 switch (key) {
696 // common attributes
699 case SUMO_ATTR_ENDPOS:
700 case GNE_ATTR_PARENT:
702 break;
703 default:
704 myPlanElement->setCommonAttribute(key, value, undoList);
705 break;
706 }
707}
708
709
710bool
711GNEDemandElementPlan::isPlanValid(SumoXMLAttr key, const std::string& value) {
712 // continue depending of key
713 switch (key) {
714 // common attributes
715 case GNE_ATTR_PARENT:
716 return false;
719 if (value.empty()) {
720 return true;
721 } else if (GNEAttributeCarrier::canParse<double>(value)) {
722 return GNEAttributeCarrier::parse<double>(value) >= 0;
723 } else {
724 return false;
725 }
726 case SUMO_ATTR_ENDPOS:
727 return GNEAttributeCarrier::canParse<double>(value);
728 default:
729 return myPlanElement->isCommonValid(key, value);
730 }
731}
732
733
734bool
736 switch (key) {
737 // edges
738 case SUMO_ATTR_EDGES:
739 // edge
740 case SUMO_ATTR_EDGE:
741 // route
742 case SUMO_ATTR_ROUTE:
743 // from
744 case SUMO_ATTR_FROM:
752 // to
753 case SUMO_ATTR_TO:
755 case SUMO_ATTR_TO_TAZ:
761 // depart pos (temporal, probably will be removed)
763 return false;
764 default:
765 return true;
766 }
767}
768
769
770void
772 bool recompute = false;
773 switch (key) {
774 // from-to attributes (needed if we're replacing junction by geometry points and similar operations)
775 case SUMO_ATTR_FROM:
777 recompute = true;
778 break;
779 case SUMO_ATTR_TO:
781 recompute = true;
782 break;
783 // Common plan attributes
784 case GNE_ATTR_PARENT:
785 replacePlanParent(value);
786 break;
788 if (value.empty()) {
789 myDepartPosition = -1;
790 } else {
791 myDepartPosition = GNEAttributeCarrier::parse<double>(value);
792 }
793 recompute = true;
794 break;
795 case SUMO_ATTR_ENDPOS:
797 if (value.empty()) {
799 } else {
800 myArrivalPosition = GNEAttributeCarrier::parse<double>(value);
801 }
802 recompute = true;
803 break;
804 default:
805 myPlanElement->setCommonAttribute(dynamic_cast<Parameterised*>(myPlanElement), key, value);
806 break;
807 }
808 // check if compute geometry and path
809 if (recompute && !myPlanElement->isTemplate()) {
812 }
813}
814
815
816std::string
818 // get tag property
819 const auto tagProperty = myPlanElement->getTagProperty();
820 // declare result
821 std::string result;
822 // clear result
823 int index = 0;
824 while (tagProperty->getTagStr().at(index) != ':') {
825 result.push_back(tagProperty->getTagStr().at(index));
826 index++;
827 }
828 result += ": ";
829 // continue depending of attributes
830 if (tagProperty->planConsecutiveEdges()) {
831 // edges
832 return result + myPlanElement->getParentEdges().front()->getID() + " ... " + myPlanElement->getParentEdges().back()->getID();
833 } else if (tagProperty->planRoute()) {
834 // route
835 return result + myPlanElement->getParentDemandElements().at(1)->getID();
836 } else if (tagProperty->planEdge()) {
837 // edge
838 return result + myPlanElement->getParentEdges().front()->getID();
839 } else if (tagProperty->planStoppingPlace()) {
840 // stoppingPlace
841 return myPlanElement->getParentStoppingPlaces().front()->getID();
842 } else {
843 // stoppingPlace
844 if (tagProperty->planFromStoppingPlace()) {
845 result += myPlanElement->getParentStoppingPlaces().front()->getID();
846 }
847 // TAZ
848 if (tagProperty->planFromTAZ()) {
849 result += myPlanElement->getParentTAZs().front()->getID();
850 }
851 // junction
852 if (tagProperty->planFromJunction()) {
853 result += myPlanElement->getParentJunctions().front()->getID();
854 }
855 // edge
856 if (tagProperty->planFromEdge()) {
857 result += myPlanElement->getParentEdges().front()->getID();
858 }
859 // arrow
860 result += " -> ";
861 // stoppingPlace
862 if (tagProperty->planToStoppingPlace()) {
863 result += myPlanElement->getParentStoppingPlaces().back()->getID();
864 }
865 // TAZ
866 if (tagProperty->planToTAZ()) {
867 result += myPlanElement->getParentTAZs().back()->getID();
868 }
869 // junction
870 if (tagProperty->planToJunction()) {
871 result += myPlanElement->getParentJunctions().back()->getID();
872 }
873 // edge
874 if (tagProperty->planToEdge()) {
875 result += myPlanElement->getParentEdges().back()->getID();
876 }
877 return result;
878 }
879}
880
881
882bool
884 const auto viewNet = myPlanElement->getNet()->getViewNet();
885 const auto& inspectedElements = viewNet->getInspectedElements();
886 // check conditions
887 if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
888 viewNet->getNetworkViewOptions().showDemandElements() &&
889 viewNet->getDemandViewOptions().showAllPersonPlans()) {
890 // show all person plans in network mode
891 return true;
892 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
893 viewNet->getDemandViewOptions().showAllPersonPlans()) {
894 // show all person plans
895 return true;
896 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() && myPlanElement->isAttributeCarrierSelected()) {
897 // show selected
898 return true;
899 } else if (inspectedElements.isACInspected(myPlanElement->getParentDemandElements().front())) {
900 // person parent is inspected
901 return true;
902 } else if (viewNet->getDemandViewOptions().getLockedPerson() == myPlanElement->getParentDemandElements().front()) {
903 // person parent is locked
904 return true;
905 } else {
906 // check if parent
907 if (inspectedElements.getFirstAC() && inspectedElements.getFirstAC()->getTagProperty()->isPlanPerson() &&
908 (inspectedElements.getFirstAC()->getAttribute(GNE_ATTR_PARENT) == myPlanElement->getAttribute(GNE_ATTR_PARENT))) {
909 // common person parent
910 return true;
911 } else {
912 // all conditions are false
913 return false;
914 }
915 }
916}
917
918
919bool
921 const auto viewNet = myPlanElement->getNet()->getViewNet();
922 const auto& inspectedElements = viewNet->getInspectedElements();
923 // check conditions
924 if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
925 viewNet->getNetworkViewOptions().showDemandElements() &&
926 viewNet->getDemandViewOptions().showAllContainerPlans()) {
927 // show all container plans in network mode
928 return true;
929 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
930 viewNet->getDemandViewOptions().showAllContainerPlans()) {
931 // show all container plans
932 return true;
933 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() && myPlanElement->isAttributeCarrierSelected()) {
934 // show selected
935 return true;
936 } else if (inspectedElements.isACInspected(myPlanElement->getParentDemandElements().front())) {
937 // container parent is inspected
938 return true;
939 } else if (viewNet->getDemandViewOptions().getLockedContainer() == myPlanElement->getParentDemandElements().front()) {
940 // container parent is locked
941 return true;
942 } else {
943 // check if parent is inspected
944 if (inspectedElements.getFirstAC() && inspectedElements.getFirstAC()->getTagProperty()->isPlanContainer() &&
945 (inspectedElements.getFirstAC()->getAttribute(GNE_ATTR_PARENT) == myPlanElement->getAttribute(GNE_ATTR_PARENT))) {
946 // common container parent
947 return true;
948 } else {
949 // all conditions are false
950 return false;
951 }
952 }
953}
954
955
956void
957GNEDemandElementPlan::drawPlanGL(const bool drawPlan, const GUIVisualizationSettings& s, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
958 const auto viewNet = myPlanElement->getNet()->getViewNet();
959 const auto& inspectedElements = viewNet->getInspectedElements();
960 // get plan parent
961 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
962 // get tag property
963 const auto tagProperty = myPlanElement->getTagProperty();
964 // get plan geometry
965 auto& planGeometry = myPlanElement->myDemandElementGeometry;
966 // draw relations between TAZs
967 if (drawPlan && (planGeometry.getShape().size() > 0)) {
968 // draw boundary
969 if (s.drawBoundaries) {
971 }
972 // get detail level
973 const auto d = s.getDetailLevel(1);
974 // check if draw with double width
975 const bool drawHalfWidth = ((inspectedElements.getFirstAC() != myPlanElement) && (inspectedElements.getFirstAC() != planParent) && !gViewObjectsHandler.isObjectSelected(myPlanElement));
976 // calculate path width
977 double pathWidth = s.widthSettings.walkWidth;
978 if (tagProperty->isPlanRide()) {
979 pathWidth = s.widthSettings.rideWidth;
980 } else if (tagProperty->isPlanPersonTrip()) {
981 pathWidth = s.widthSettings.personTripWidth;
982 }
983 // draw geometry only if we'rent in drawForObjectUnderCursor mode
984 if ((tagProperty->isPlanPerson() && s.checkDrawPerson(d, myPlanElement->isAttributeCarrierSelected())) ||
985 (tagProperty->isPlanContainer() && s.checkDrawContainer(d, myPlanElement->isAttributeCarrierSelected()))) {
986 // push matrix
988 // translate to front
990 // set color
991 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
992 // draw line
993 GUIGeometry::drawGeometry(d, planGeometry, pathWidth * (drawHalfWidth ? 1 : 2));
994 if (drawHalfWidth) {
995 GLHelper::drawTriangleAtEnd(planGeometry.getShape().front(), planGeometry.getShape().back(), 0.5, 0.5, 0.5);
996 } else {
997 GLHelper::drawTriangleAtEnd(planGeometry.getShape().front(), planGeometry.getShape().back(), 1, 1, 1);
998 }
999 // pop matrix
1001 // draw dotted contour
1003 }
1004 // calculate contour and draw dotted geometry
1005 myPlanContour.calculateContourExtrudedShape(s, d, myPlanElement, planGeometry.getShape(), myPlanElement->getType(), pathWidth * 2,
1006 1, true, true, 0, nullptr, nullptr);
1007 // calculate contour for end
1008 myPlanContourEnd.calculateContourCircleShape(s, d, myPlanElement, planGeometry.getShape().back(), 1, myPlanElement->getType(), 1, nullptr);
1009 }
1010 // check if draw plan parent
1011 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1012 planParent->drawGL(s);
1013 }
1014}
1015
1016
1017void
1019 const double offsetFront, const double planWidth, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
1020 const auto viewNet = myPlanElement->getNet()->getViewNet();
1021 const auto& inspectedElements = viewNet->getInspectedElements();
1022 // get tag property
1023 const auto tagProperty = myPlanElement->getTagProperty();
1024 // get plan parent
1025 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1026 // check if draw plan element can be drawn
1027 if (drawPlan && segment->getLane() && myPlanElement->getNet()->getDemandPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment->getLane(), tagProperty->getTag(), true)) {
1028 // draw boundary
1029 if (tagProperty->isPlacedInRTree() && s.drawBoundaries) {
1031 }
1032 // get detail level
1033 const auto d = s.getDetailLevel(1);
1034 // declare path geometry
1035 GUIGeometry planGeometry;
1036 // update pathGeometry depending of first and last segment
1037 if (segment->isFirstSegment() && segment->isLastSegment()) {
1038 if (tagProperty->planFromTAZ()) {
1039 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1044 } else if (tagProperty->planToTAZ()) {
1045 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1050 } else {
1051 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1056 }
1057 } else if (segment->isFirstSegment()) {
1058 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1061 -1,
1063 } else if (segment->isLastSegment()) {
1064 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1065 -1,
1069 } else {
1070 planGeometry = segment->getLane()->getLaneGeometry();
1071 }
1072 // calculate path width double
1073 const double drawingWidth = s.addSize.getExaggeration(s, segment->getLane()) * planWidth * 2;
1074 // check if draw with double width
1075 const bool drawHalfWidth = ((inspectedElements.getFirstAC() != myPlanElement) && (inspectedElements.getFirstAC() != planParent) && !gViewObjectsHandler.isObjectSelected(myPlanElement));
1076 // get end pos radius
1077 const double endPosRadius = getEndPosRadius(s, segment, drawHalfWidth);
1078 // draw geometry only if we'rent in drawForObjectUnderCursor mode
1079 if ((tagProperty->isPlanPerson() && s.checkDrawPerson(d, myPlanElement->isAttributeCarrierSelected())) ||
1080 (tagProperty->isPlanContainer() && s.checkDrawContainer(d, myPlanElement->isAttributeCarrierSelected()))) {
1081 // Add a draw matrix
1083 // Start with the drawing of the area traslating matrix to origin
1085 // Set color
1086 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1087 // draw geometry depending of drawWithDoubleWidth
1088 GUIGeometry::drawGeometry(d, planGeometry, drawingWidth * (drawHalfWidth ? 0.5 : 1));
1089 // draw red arrows
1090 drawFromArrow(s, segment->getLane(), segment);
1091 drawToArrow(s, segment->getLane(), segment);
1092 // Pop last matrix
1094 // Draw name if isn't being drawn for selecting
1096 // draw dotted contour
1098 // draw TAZ Center dotted contour
1100 }
1101 // declare trim geometry to draw
1102 const auto& shape = (segment->isFirstSegment() || segment->isLastSegment()) ? planGeometry.getShape() : segment->getLane()->getLaneShape();
1103 // calculate contour and draw dotted geometry (always with double width)
1104 if (segment->isFirstSegment()) {
1105 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, true, false,
1106 0, segment, segment->getLane()->getParentEdge());
1107 } else if (segment->isLastSegment()) {
1108 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, false, false,
1109 0, segment, segment->getLane()->getParentEdge());
1110 // calculate contour for end
1112 myPlanElement->getType(), 1, segment->getLane());
1113 } else {
1114 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, false, false, 0,
1115 segment, segment->getLane()->getParentEdge());
1116 }
1117 // check if add this path element to redraw buffer
1120 }
1121 }
1122 // check if draw plan parent
1123 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1124 planParent->drawGL(s);
1125 }
1126}
1127
1128
1129void
1131 const double offsetFront, const double planWidth, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
1132 const auto viewNet = myPlanElement->getNet()->getViewNet();
1133 const auto& inspectedElements = viewNet->getInspectedElements();
1134 // get tag property
1135 const auto tagProperty = myPlanElement->getTagProperty();
1136 // get plan parent
1137 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1138 // check if draw plan elements can be drawn
1139 if (drawPlan && myPlanElement->getNet()->getDemandPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment, tagProperty->getTag(), false)) {
1140 // draw boundary
1141 if (tagProperty->isPlacedInRTree() && s.drawBoundaries) {
1143 }
1144 // get detail level
1145 const auto d = s.getDetailLevel(1);
1146 // calculate path width double
1147 const double pathWidthDouble = s.addSize.getExaggeration(s, segment->getLane()) * planWidth * 2;
1148 // check if draw with double width
1149 const bool drawWithDoubleWidth = ((inspectedElements.getFirstAC() == myPlanElement) || (inspectedElements.getFirstAC() == planParent) || gViewObjectsHandler.isObjectSelected(myPlanElement));
1150 // draw geometry only if we'rent in drawForObjectUnderCursor mode
1152 // push a draw matrix
1154 // Start with the drawing of the area traslating matrix to origin
1156 // Set plan color
1157 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1158 // check if draw lane2lane connection or a red line
1159 if (segment->getPreviousLane() && segment->getNextLane()) {
1160 if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
1161 // obtain lane2lane geometry
1162 const GUIGeometry& lane2laneGeometry = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane());
1163 // draw lane2lane
1164 GUIGeometry::drawGeometry(d, lane2laneGeometry, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1165 } else {
1166 // Set invalid plan color
1168 // draw line between end of first shape and first position of second shape
1169 GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), segment->getNextLane()->getLaneShape().front()}, (0.5 * pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5)));
1170 }
1171 } else if (segment->getPreviousLane()) {
1172 // draw line between center of junction and last lane shape
1173 GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), myPlanElement->getParentJunctions().back()->getPositionInView()}, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1174 } else if (segment->getNextLane()) {
1175 // draw line between center of junction and first lane shape
1176 GLHelper::drawBoxLines({myPlanElement->getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()}, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1177 }
1178 // Pop last matrix
1180 // draw lock icon
1182 // draw dotted contour
1184 }
1185 // check if shape dotted contour has to be drawn
1186 if (segment->getPreviousLane() && segment->getNextLane()) {
1187 if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
1188 // get shape
1189 const auto& shape = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()).getShape();
1190 // calculate contour and draw dotted geometry (always with double width)
1191 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), pathWidthDouble, 1, false, false, 0, segment, segment->getJunction());
1192 }
1193 } else if (segment->getPreviousLane()) {
1194 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, {segment->getPreviousLane()->getLaneShape().back(), myPlanElement->getParentJunctions().back()->getPositionInView()},
1195 myPlanElement->getType(), pathWidthDouble, 1, false, true, 0, segment, segment->getJunction());
1196 } else if (segment->getNextLane()) {
1197 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, {myPlanElement->getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()},
1198 myPlanElement->getType(), pathWidthDouble, 1, true, false, 0, segment, segment->getJunction());
1199 }
1200 // check if add this path element to redraw buffer
1203 }
1204 }
1205 // check if draw plan parent
1206 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1207 planParent->drawGL(s);
1208 }
1209}
1210
1211
1214 // get previous plan
1215 const auto previousPlan = myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement);
1216 if (previousPlan) {
1217 // get previous lane
1218 const auto previousLastLane = previousPlan->getLastPathLane();
1219 // get first lane
1220 const auto firstLane = myPlanElement->getFirstPathLane();
1221 // compare edges
1222 if (previousLastLane && firstLane && (previousLastLane->getParentEdge() != firstLane->getParentEdge())) {
1224 }
1225 // in the future, check more elements
1226 }
1227 // get next child
1228 const auto nextPlan = myPlanElement->getParentDemandElements().at(0)->getNextChildDemandElement(myPlanElement);
1229 if (nextPlan) {
1230 // get previous lane
1231 const auto nextFirstLane = nextPlan->getFirstPathLane();
1232 // get first lane
1233 const auto lastLane = myPlanElement->getLastPathLane();
1234 // compare edges
1235 if (nextFirstLane && lastLane && (nextFirstLane->getParentEdge() != lastLane->getParentEdge())) {
1237 }
1238 // in the future, check more elements
1239 }
1240 // all ok, then return true
1242}
1243
1244
1245std::string
1247 // get previous plan
1248 const auto previousPlan = myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement);
1249 if (previousPlan) {
1250 // get previous lane
1251 const auto previousLastLane = previousPlan->getLastPathLane();
1252 // get first lane
1253 const auto firstLane = myPlanElement->getLastPathLane();
1254 // compare edges
1255 if (previousLastLane && firstLane && (previousLastLane->getParentEdge() != firstLane->getParentEdge())) {
1256 return TLF("Edge '%' is not consecutive with edge '%'", previousLastLane->getParentEdge()->getID(), firstLane->getParentEdge()->getID());
1257 }
1258 // in the future, check more elements
1259 }
1260 // get next child
1261 const auto nextPlan = myPlanElement->getParentDemandElements().at(0)->getNextChildDemandElement(myPlanElement);
1262 if (nextPlan) {
1263 // get previous lane
1264 const auto nextFirstLane = nextPlan->getFirstPathLane();
1265 // get first lane
1266 const auto lastLane = myPlanElement->getLastPathLane();
1267 // compare edges
1268 if (nextFirstLane && lastLane && (nextFirstLane->getParentEdge() != lastLane->getParentEdge())) {
1269 return TLF("Edge '%' is not consecutive with edge '%'", nextFirstLane->getParentEdge()->getID(), lastLane->getParentEdge()->getID());
1270 }
1271 // in the future, check more elements
1272 }
1273 // undefined problem
1274 return "undefined problem";
1275}
1276
1277
1278double
1279GNEDemandElementPlan::getEndPosRadius(const GUIVisualizationSettings& s, const GNESegment* segment, const bool drawHalfWidth) const {
1280 // check if myPlanElement is the last segment
1281 if (segment->isLastSegment()) {
1282 // calculate circle width
1283 const double circleRadius = (drawHalfWidth ? myArrivalPositionDiameter * 0.5 : myArrivalPositionDiameter);
1284 return circleRadius * MIN2((double)0.5, s.laneWidthExaggeration);
1285 } else {
1286 return -1;
1287 }
1288}
1289
1290
1291void
1293 // draw ifcurrent amd next segment is placed over lanes
1294 if (segment->getNextLane()) {
1295 // get firstPosition (last position of current lane shape)
1296 const Position from = lane->getLaneShape().back();
1297 // get lastPosition (first position of next lane shape)
1298 const Position to = segment->getNextLane()->getLaneShape().front();
1299 // push draw matrix
1301 // move front
1302 glTranslated(0, 0, 4);
1303 // draw child line
1305 // pop draw matrix
1307 }
1308}
1309
1310
1311void
1313 // draw the line if previos segment and current segment is placed over lanes
1314 if (segment->getPreviousLane()) {
1315 // get firstPosition (last position of current lane shape)
1316 const Position from = lane->getLaneShape().front();
1317 // get lastPosition (first position of next lane shape)
1318 const Position to = segment->getPreviousLane()->getLaneShape().back();
1319 // push draw matrix
1321 // move front
1322 glTranslated(0, 0, 4);
1323 // draw child line
1325 // pop draw matrix
1327 }
1328}
1329
1330
1331void
1333 // check if myPlanElement is the last segment
1334 if (endPosRadius > 0) {
1336 // push draw matrix
1338 // translate to pos and move to
1339 glTranslated(geometryEndPos.x(), geometryEndPos.y(), 4);
1340 // resolution of drawn circle depending of the zoom (To improve smothness)
1341 GLHelper::drawFilledCircleDetailled(d, endPosRadius);
1342 // pop draw matrix
1344 }
1345}
1346
1347
1348bool
1349GNEDemandElementPlan::replacePlanParent(const std::string& newParentID) {
1350 std::vector<SumoXMLTag> tags;
1352 tags.push_back(SUMO_TAG_PERSON);
1353 tags.push_back(SUMO_TAG_PERSONFLOW);
1354 } else {
1355 tags.push_back(SUMO_TAG_CONTAINER);
1356 tags.push_back(SUMO_TAG_CONTAINERFLOW);
1357 }
1358 // search new parent and set it
1359 for (const auto& tag : tags) {
1360 if (myPlanElement->getNet()->getAttributeCarriers()->retrieveDemandElement(tag, newParentID, false) != nullptr) {
1361 myPlanElement->replaceDemandElementParent(tag, newParentID, 0);
1362 return true;
1363 }
1364 }
1365 throw ProcessError("Invalid new parent ID");
1366}
1367
1368/****************************************************************************/
@ GLO_TAZ
Traffic Assignment Zones (TAZs)
GUIViewObjectsHandler gViewObjectsHandler
#define TLF(string,...)
Definition MsgHandler.h:307
@ SUMO_TAG_TAZ
a traffic assignment zone
@ SUMO_TAG_CONTAINERFLOW
@ SUMO_TAG_STOP
stop for vehicles
@ SUMO_TAG_CONTAINER
@ SUMO_TAG_PERSON
@ SUMO_TAG_PERSONFLOW
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_STARTPOS
@ GNE_ATTR_FROM_TRAINSTOP
@ GNE_ATTR_FROM_BUSSTOP
@ GNE_ATTR_PLAN_GEOMETRY_STARTPOS
person/container geometry start position
@ SUMO_ATTR_FROM_JUNCTION
@ SUMO_ATTR_CONTAINER_STOP
@ SUMO_ATTR_PARKING_AREA
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_BUS_STOP
@ SUMO_ATTR_TRAIN_STOP
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_TO_JUNCTION
@ GNE_ATTR_PARENT
parent of an additional element
@ SUMO_ATTR_ARRIVALPOS
@ GNE_ATTR_TAZ_CENTROID
TAZ Center (uses to return the TAZ centroid if center is not defined)
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_CHARGING_STATION
@ SUMO_ATTR_DEPARTPOS
@ GNE_ATTR_FROM_PARKINGAREA
@ GNE_ATTR_FROM_CONTAINERSTOP
@ SUMO_ATTR_TO_TAZ
@ SUMO_ATTR_CENTER
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_FROM_TAZ
@ GNE_ATTR_FROM_CHARGINGSTATION
@ GNE_ATTR_PLAN_GEOMETRY_ENDPOS
person/container geometry end position
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_ID
@ SUMO_ATTR_DURATION
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:64
T MIN2(T a, T b)
Definition StdDefs.h:76
const double SUMO_const_halfLaneWidth
Definition StdDefs.h:49
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A class that stores a 2D geometrical boundary.
Definition Boundary.h:39
Position getCenter() const
Returns the center of the boundary.
Definition Boundary.cpp:109
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition Boundary.cpp:75
bool isInitialised() const
check if Boundary is Initialised
Definition Boundary.cpp:256
Boundary & grow(double by)
extends the boundary by the given amount
Definition Boundary.cpp:340
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:649
static void drawTriangleAtEnd(const Position &p1, const Position &p2, double tLength, double tWidth, const double extraOffset=0)
Draws a triangle at the end of the given line.
Definition GLHelper.cpp:624
static void popMatrix()
pop matrix
Definition GLHelper.cpp:131
static void drawBoxLines(const PositionVector &geom, const std::vector< double > &rots, const std::vector< double > &lengths, double width, int cornerDetail=0, double offset=0)
Draws thick lines.
Definition GLHelper.cpp:348
static void drawBoundary(const GUIVisualizationSettings &s, const Boundary &b)
Draw a boundary (used for debugging)
Definition GLHelper.cpp:958
static void drawFilledCircleDetailled(const GUIVisualizationSettings::Detail d, const double radius)
Draws a filled circle around (0,0) depending of level of detail.
Definition GLHelper.cpp:534
static void pushMatrix()
push matrix
Definition GLHelper.cpp:118
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
std::string getCommonAttribute(const Parameterised *parameterised, SumoXMLAttr key) const
void setCommonAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
const std::string & getTagStr() const
get tag assigned to this object in string format
bool isTemplate() const
check if this AC is template
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
void drawInLayer(const double typeOrLayer, const double extraOffset=0) const
draw element in the given layer, or in front if corresponding flag is enabled
const GNETagProperties * getTagProperty() const
get tagProperty associated with this Attribute Carrier
GNENet * myNet
pointer to net
bool isCommonValid(SumoXMLAttr key, const std::string &value) const
GNENet * getNet() const
get pointer to net
static std::string parseIDs(const std::vector< T > &ACs)
parses a list of specific Attribute Carriers into a string of IDs
const GNETagProperties * myTagProperty
reference to tagProperty associated with this attribute carrier
static void changeAttribute(GNEAttributeCarrier *AC, SumoXMLAttr key, const std::string &value, GNEUndoList *undoList, const bool force=false)
change attribute
void calculateContourExtrudedShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *glObject, const PositionVector &shape, const double layer, const double extrusionWidth, const double scale, const bool closeFirstExtrem, const bool closeLastExtrem, const double offset, const GNESegment *segment, const GUIGlObject *boundaryParent, const bool addToSelectedObjects=true) const
calculate contour extruded (used in elements formed by a central shape)
void calculateContourCircleShape(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GUIGlObject *glObject, const Position &pos, double radius, const double layer, const double scale, const GUIGlObject *boundaryParent) const
calculate contour (circle elements)
bool drawDottedContours(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, const double lineWidth, const bool addOffset) const
draw dotted contours (basics, select, delete, inspect...)
bool checkDrawPathContour(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC) const
drawing contour functions
virtual void updateGeometry()=0
update pre-computed geometry information
virtual SUMOVehicleClass getVClass() const =0
obtain VClass related with this demand element
void replaceDemandElementParent(SumoXMLTag tag, const std::string &value, const int parentIndex)
replace demand element parent
virtual GNELane * getLastPathLane() const =0
get last path lane
virtual GNELane * getFirstPathLane() const =0
get first path lane
GUIGeometry myDemandElementGeometry
demand element geometry (also called "stacked geometry")
void replaceLastParentEdge(const std::string &value)
replace the last parent edge
virtual std::string getAttribute(SumoXMLAttr key) const =0
virtual void computePathElement()=0
implement in children+
void replaceFirstParentEdge(const std::string &value)
replace the first parent edge
virtual Position getPositionInView() const =0
Returns position of demand element in view.
const GUIGeometry & getDemandElementGeometry()
get demand element geometry (stacked)
Problem
enum class for demandElement problems
GNEDemandElement * getPreviousChildDemandElement(const GNEDemandElement *demandElement) const
get previous child demand element to the given demand element
virtual void drawGL(const GUIVisualizationSettings &s) const =0
Draws the object.
Boundary myPlanBoundary
plan boundary
bool isPlanValid(SumoXMLAttr key, const std::string &value)
check if plan attribute is valid
Boundary getPlanCenteringBoundary() const
get plan centering boundary
Position getPlanPositionInView() const
Returns position of additional in view.
std::string getPersonPlanProblem() const
get plan problem
void computePlanPathElement()
compute plan pathElement
Position getPlanAttributePosition(SumoXMLAttr key) const
get plan attribute position
GNEDemandElement::Problem isPlanPersonValid() const
check if plan is valid
GNEContour myPlanContourEnd
variable used for draw contour end
GUIGLObjectPopupMenu * getPlanPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
GNEDemandElementPlan(GNEDemandElement *planElement, const double departPosition, const double arrivalPosition)
constructor
std::string getPlanHierarchyName() const
get plan Hierarchy Name (Used in AC Hierarchy)
void drawEndPosition(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const double endPosRadius) const
draw to arrow
void drawFromArrow(const GUIVisualizationSettings &s, const GNELane *lane, const GNESegment *segment) const
draw from arrow
void writeLocationAttributes(OutputDevice &device) const
write plan element common attributes
bool checkDrawPersonPlan() const
check if person plan can be drawn
GNEContour myPlanContour
variable used for draw central contour
double getEndPosRadius(const GUIVisualizationSettings &s, const GNESegment *segment, const bool drawHalfWidth) const
get end position radius
GNEMoveOperation * getPlanMoveOperation()
get move operation
double getPlanAttributeDouble(SumoXMLAttr key) const
get plan attribute double
void setPlanAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
set plan attribute
double myArrivalPosition
arrival position (used in all plans over edges)
double myDepartPosition
depart position (used in tranships)
static const double myArrivalPositionDiameter
arrival position diameter
void drawToArrow(const GUIVisualizationSettings &s, const GNELane *lane, const GNESegment *segment) const
draw to arrow
std::string getPlanAttribute(SumoXMLAttr key) const
get plan attribute string
bool isPlanAttributeEnabled(SumoXMLAttr key) const
check if plan attribute is enabled
bool checkDrawContainerPlan() const
check if container plan can be drawn
GNELane * getLastPlanPathLane() const
get last plan path lane
GNEDemandElement * myPlanElement
pointer to plan element
void updatePlanCenteringBoundary(const bool updateGrid)
update plan centering boundary
void drawPlanGL(const bool drawPlan, const GUIVisualizationSettings &s, const RGBColor &planColor, const RGBColor &planSelectedColor) const
draw plan
void updatePlanGeometry()
update pre-computed geometry information
GNELane * getFirstPlanPathLane() const
get first plan path lane
void drawPlanLanePartial(const bool drawPlan, const GUIVisualizationSettings &s, const GNESegment *segment, const double offsetFront, const double planWidth, const RGBColor &planColor, const RGBColor &planSelectedColor) const
draw plan partial lane
void drawPlanJunctionPartial(const bool drawPlan, const GUIVisualizationSettings &s, const GNESegment *segment, const double offsetFront, const double planWidth, const RGBColor &planColor, const RGBColor &planSelectedColor) const
draw plan partial junction
void writeOriginStop(OutputDevice &device) const
write initial stop stage if plan starts at a stopping place
bool replacePlanParent(const std::string &newParentID)
replace plan parent
const GNEHierarchicalContainerParents< GNEAdditional * > & getParentAdditionals() const
get parent additionals
const GNEHierarchicalContainerParents< GNEDemandElement * > & getParentDemandElements() const
get parent demand elements
const GNEHierarchicalContainerParents< GNEEdge * > & getParentEdges() const
get parent edges
const GNEHierarchicalContainerParents< GNEJunction * > & getParentJunctions() const
get parent junctions
const GNEHierarchicalContainerParents< GNEAdditional * > getParentStoppingPlaces() const
get parent stoppingPlaces (used by plans)
const GNEHierarchicalContainerChildren< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
const GNEHierarchicalContainerParents< GNEAdditional * > getParentTAZs() const
get parent TAZs (used by plans)
bool exist(const GNELane *toLane) const
check if exist a lane2lane geometry for the given toLane
const GUIGeometry & getLane2laneGeometry(const GNELane *toLane) const
get lane2lane geometry
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition GNELane.h:46
const PositionVector & getLaneShape() const
get elements shape
Definition GNELane.cpp:220
const GNELane2laneConnection & getLane2laneConnections() const
get Lane2laneConnection struct
Definition GNELane.cpp:692
const GUIGeometry & getLaneGeometry() const
get lane geometry
Definition GNELane.cpp:214
GNEEdge * getParentEdge() const
get parent edge
Definition GNELane.cpp:202
move operation
GNEDemandElement * retrieveDemandElement(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named demand element.
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1442
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1452
GNEPathManager * getDemandPathManager()
get demand path manager
Definition GNENet.cpp:176
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition GNENet.cpp:146
GNEViewNet * getViewNet() const
get view net
Definition GNENet.cpp:2194
bool checkDrawPathGeometry(const GUIVisualizationSettings &s, const GNELane *lane, const SumoXMLTag tag, const bool isPlan)
check if path element geometry must be drawn in the given lane
PathDraw * getPathDraw()
obtain instance of PathDraw
void calculateConsecutivePathEdges(GNEPathElement *pathElement, SUMOVehicleClass vClass, const std::vector< GNEEdge * > &edges, const int firstLaneIndex=-1, const int lastLaneIndex=-1)
calculate consecutive path edges
const GNELane * getLane() const
get lane associated with this segment
const GNEJunction * getJunction() const
get junction associated with this segment
const GNELane * getNextLane() const
get next lane
const GNELane * getPreviousLane() const
get previous lane
bool isFirstSegment() const
check if segment is the first path's segment
GNEContour * getContour() const
bool isLastSegment() const
check if segment is the last path's segment
bool planFromJunction() const
return true if tag correspond to a plan that starts in junction
bool planToStoppingPlace() const
return true if tag correspond to a plan that ends in stoppingPlace
bool planStoppingPlace() const
return true if tag correspond to a plan placed in stoppingPlace
bool planToJunction() const
return true if tag correspond to a plan that starts in junction
bool planFromStoppingPlace() const
return true if tag correspond to a plan that starts in stoppingPlace
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
bool planFromEdge() const
return true if tag correspond to a plan that starts in edge
bool isPlanPerson() const
return true if tag correspond to a person plan
bool planToEdge() const
return true if tag correspond to a plan that starts in edge
GNEViewNetHelper::InspectedElements & getInspectedElements()
get inspected elements
static FXMenuCommand * buildFXMenuCommand(FXComposite *p, const std::string &text, FXIcon *icon, FXObject *tgt, FXSelector sel, const bool disable=false)
build menu command
The popup menu of a globject.
void clearGeometry()
clear geometry
static void drawGeometry(const GUIVisualizationSettings::Detail d, const GUIGeometry &geometry, const double width, double offset=0)
draw geometry
static void drawChildLine(const GUIVisualizationSettings &s, const Position &child, const Position &parent, const RGBColor &color, const bool drawEntire, const double lineWidth)
draw line between child and parent (used in netedit)
const PositionVector & getShape() const
The shape of the additional element.
void updateGeometry(const PositionVector &shape)
update entire geometry
virtual Boundary getCenteringBoundary() const =0
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
void buildPopUpMenuCommonOptions(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, GUISUMOAbstractView *parent, const SumoXMLTag tag, const bool selected, bool addSeparator=true)
void drawName(const Position &pos, const double scale, const GUIVisualizationTextSettings &settings, const double angle=0, bool forceShow=false) const
draw name of item
virtual Position getPositionInformation() const
Returns the cursor's x/y position within the network.
void addToRedrawPathElements(const GNEPathElement *pathElement)
add path element to redrawing set
bool isPathElementMarkForRedraw(const GNEPathElement *pathElement) const
check if the given path element has to be redraw again
bool isObjectSelected(const GUIGlObject *GLObject) const
check if element was already selected
Stores the information about how to visualize structures.
GUIVisualizationTextSettings addName
bool drawBoundaries
enable or disable draw boundaries
GUIVisualizationSizeSettings addSize
GUIVisualizationWidthSettings widthSettings
width settings
Detail getDetailLevel(const double exaggeration) const
return the detail level
double laneWidthExaggeration
The lane exaggeration (upscale thickness)
bool checkDrawContainer(Detail d, const bool selected) const
check if draw container
GUIVisualizationDottedContourSettings dottedContourSettings
dotted contour settings
double scale
information about a lane's width (temporary, used for a single view)
bool drawForViewObjectsHandler
whether drawing is performed for the purpose of selecting objects in view using ViewObjectsHandler
bool checkDrawPerson(Detail d, const bool selected) const
check if draw person
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
An upper class for objects with additional parameters.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition Position.h:278
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:319
double x() const
Returns the x-position.
Definition Position.h:52
double y() const
Returns the y-position.
Definition Position.h:57
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
static const RGBColor RED
named colors
Definition RGBColor.h:188
static void drawLockIcon(const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, GUIGlObjectType type, const Position position, const double exaggeration, const double size=0.5, const double offsetx=0, const double offsety=0)
draw lock icon
static const double segmentWidth
width of dotted contour segments
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values
double personTripWidth
width for person trips