Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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>
26
28#include "GNERoute.h"
29
30// ===========================================================================
31// static definitions
32// ===========================================================================
33
35
36// ===========================================================================
37// GNEDemandElement method definitions
38// ===========================================================================
39
40GNEDemandElementPlan::GNEDemandElementPlan(GNEDemandElement* planElement, const double departPosition, const double arrivalPosition) :
41 myMoveElementPlan(new GNEMoveElementPlan(planElement, myDepartPosition)),
42 myDepartPosition(departPosition),
43 myArrivalPosition(arrivalPosition),
44 myPlanElement(planElement) {
45}
46
47
48void
50 const auto tagProperty = myPlanElement->getTagProperty();
51 // write attributes depending of parent elements
52 if (tagProperty->planConsecutiveEdges()) {
54 } else if (tagProperty->planRoute()) {
56 } else if (tagProperty->planEdge()) {
57 device.writeAttr(SUMO_ATTR_EDGE, myPlanElement->getParentEdges().front()->getID());
58 } else if (tagProperty->planBusStop()) {
60 } else if (tagProperty->planTrainStop()) {
62 } else if (tagProperty->planContainerStop()) {
64 } else if (tagProperty->planChargingStation()) {
66 } else if (tagProperty->planParkingArea()) {
68 } else {
69 // write from attribute (if this is the first element)
70 if (myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement) == nullptr) {
71 // check if write edge or junction
72 if (tagProperty->planFromEdge()) {
73 device.writeAttr(SUMO_ATTR_FROM, myPlanElement->getParentEdges().front()->getID());
74 } else if (tagProperty->planFromTAZ()) {
75 device.writeAttr(SUMO_ATTR_FROM_TAZ, myPlanElement->getParentTAZs().front()->getID());
76 } else if (tagProperty->planFromJunction()) {
78 }
79 // origin stopping places are transformed into an intial stop stage (see writeOriginStop)
80 }
81 // continue writting to attribute
82 if (tagProperty->planToEdge()) {
83 device.writeAttr(SUMO_ATTR_TO, myPlanElement->getParentEdges().back()->getID());
84 } else if (tagProperty->planToJunction()) {
86 } else if (tagProperty->planToTAZ()) {
87 device.writeAttr(SUMO_ATTR_TO_TAZ, myPlanElement->getParentTAZs().back()->getID());
88 } else if (tagProperty->planToBusStop()) {
90 } else if (tagProperty->planToTrainStop()) {
92 } else if (tagProperty->planToContainerStop()) {
94 } else if (tagProperty->planToChargingStation()) {
96 } else if (tagProperty->planToParkingArea()) {
98 }
99 }
100 // check if write depart position
101 if (tagProperty->hasAttribute(SUMO_ATTR_DEPARTPOS) && (myDepartPosition > 0)) {
103 }
104 // check if write arrival position
105 if (tagProperty->hasAttribute(SUMO_ATTR_ARRIVALPOS) && (myArrivalPosition > 0)) {
107 }
108 // check if write end position
109 if (tagProperty->hasAttribute(SUMO_ATTR_ENDPOS)) {
111 }
112}
113
114
115void
117 const auto tagProperty = myPlanElement->getTagProperty();
118 // write an extra stop element with duration 0 over a stopping place (if this is the first element)
119 if (tagProperty->planFromStoppingPlace()
120 && myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement) == nullptr) {
121 device.openTag(SUMO_TAG_STOP);
122 const std::string stopID = myPlanElement->getParentStoppingPlaces().front()->getID();
123 if (tagProperty->planFromBusStop()) {
124 device.writeAttr(SUMO_ATTR_BUS_STOP, stopID);
125 } else if (tagProperty->planFromTrainStop()) {
126 device.writeAttr(SUMO_ATTR_TRAIN_STOP, stopID);
127 } else if (tagProperty->planFromContainerStop()) {
128 device.writeAttr(SUMO_ATTR_CONTAINER_STOP, stopID);
129 } else if (tagProperty->planFromChargingStation()) {
131 } else if (tagProperty->planFromParkingArea()) {
132 device.writeAttr(SUMO_ATTR_PARKING_AREA, stopID);
133 }
134 device.writeAttr(SUMO_ATTR_DURATION, 0);
135 device.closeTag();
136 }
137}
138
139
142 // create popup
144 // build common options
146 GUIDesigns::buildFXMenuCommand(ret, ("Cursor position in view: " + toString(getPlanPositionInView().x()) + "," + toString(getPlanPositionInView().y())).c_str(), nullptr, nullptr, 0);
147 return ret;
148}
149
150
151GNELane*
153 // get tag property
154 const auto tagProperty = myPlanElement->getTagProperty();
155 // get vclass
156 auto vClass = myPlanElement->getVClass();
157 // continue depending of parents
158 if (tagProperty->planRoute()) {
159 // route
160 return myPlanElement->getParentDemandElements().at(1)->getParentEdges().front()->getLaneByAllowedVClass(vClass);
161 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planFromEdge() || tagProperty->planEdge()) {
162 // edges
163 return myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
164 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace() || tagProperty->planToStoppingPlace()) {
165 // additional
166 return myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
167 } else {
168 // in other cases (TAZ, junctions, etc.) return null
169 return nullptr;
170 }
171}
172
173
174GNELane*
176 // get tag property
177 const auto tagProperty = myPlanElement->getTagProperty();
178 // get vclass
179 auto vClass = myPlanElement->getVClass();
180 // check parents
181 if (tagProperty->planRoute()) {
182 // route
183 return myPlanElement->getParentDemandElements().at(1)->getParentEdges().back()->getLaneByAllowedVClass(vClass);
184 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planToEdge() || tagProperty->planEdge()) {
185 // edges
186 return myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
187 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace() || tagProperty->planToStoppingPlace()) {
188 // additional
189 return myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getParentEdge()->getLaneByAllowedVClass(vClass);
190 } else {
191 // in other cases (TAZ, junctions, etc.) return null
192 return nullptr;
193 }
194}
195
196
197void
199 // get tag property
200 const auto tagProperty = myPlanElement->getTagProperty();
201 // get vClass
202 auto vClass = myPlanElement->getVClass();
203 // get path manager
204 auto pathManager = myPlanElement->getNet()->getDemandPathManager();
205 // continue depending of parents
206 if (tagProperty->planRoute()) {
207 // calculate consecutive path using route edges
208 pathManager->calculateConsecutivePathEdges(myPlanElement, vClass, myPlanElement->getParentDemandElements().at(1)->getParentEdges());
209 } else if (tagProperty->planConsecutiveEdges()) {
210 // calculate consecutive path using edges
211 pathManager->calculateConsecutivePathEdges(myPlanElement, vClass, myPlanElement->getParentEdges());
213 // calculate path using junctions
214 pathManager->calculatePath(myPlanElement, vClass, myPlanElement->getParentJunctions().front(), myPlanElement->getParentJunctions().back());
216 // declare last lane
217 GNELane* lastLane = nullptr;
219 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().back();
221 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front();
222 } else if (myPlanElement->myTagProperty->planToEdge()) {
223 lastLane = myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
224 }
225 // calculate path
226 if (lastLane) {
227 pathManager->calculatePath(myPlanElement, vClass, myPlanElement->getParentJunctions().front(), lastLane);
228 }
230 // declare first lane
231 GNELane* firstLane = nullptr;
233 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().back();
235 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
237 firstLane = myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
238 }
239 // calculate path
240 if (firstLane) {
241 pathManager->calculatePath(myPlanElement, vClass, firstLane, myPlanElement->getParentJunctions().back());
242 }
243 } else {
244 // declare first edge
245 GNELane* firstLane = nullptr;
247 firstLane = myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
249 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().back();
251 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
252 }
253 // declare last lane
254 GNELane* lastLane = nullptr;
256 lastLane = myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
258 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().back();
260 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front();
261 }
262 if (firstLane && lastLane) {
263 pathManager->calculatePath(myPlanElement, vClass, firstLane, lastLane);
264 } else if (firstLane) {
265 pathManager->calculateConsecutivePathLanes(myPlanElement, {firstLane});
266 } else if (lastLane) {
267 pathManager->calculateConsecutivePathLanes(myPlanElement, {lastLane});
268 }
269 }
270 // update geometry
272}
273
274
275void
277 // get tag property
278 const auto tagProperty = myPlanElement->getTagProperty();
279 // check if plan start or end in a TAZ (becase in this case has to be inserted in RTREE
280 if (tagProperty->planFromTAZ() || tagProperty->planToTAZ()) {
281 // declare first and last positions
282 Position firstPos = Position::INVALID;
283 Position lastPos = Position::INVALID;
284 // set first position
285 if (tagProperty->planFromEdge()) {
286 // from junction
287 firstPos = myPlanElement->getFirstPathLane()->getLaneShape().back();
288 } else if (tagProperty->planFromJunction()) {
289 // from junction
290 firstPos = myPlanElement->getParentJunctions().front()->getPositionInView();
291 } else if (tagProperty->planFromStoppingPlace()) {
292 // end of stoppingPlace lane shape
293 firstPos = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLaneShape().back();
294 } else if (tagProperty->planFromTAZ()) {
295 // from TAZ
296 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
297 firstPos = myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
298 } else {
299 firstPos = myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
300 }
301 }
302 // set last position
303 if (tagProperty->planToEdge()) {
304 // from junction
305 lastPos = myPlanElement->getLastPathLane()->getLaneShape().back();
306 } else if (tagProperty->planToJunction()) {
307 // from junction
308 lastPos = myPlanElement->getParentJunctions().back()->getPositionInView();
309 } else if (tagProperty->planToStoppingPlace()) {
310 // end of stoppingPlace lane shape
311 lastPos = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLaneShape().front();
312 } else if (tagProperty->planToTAZ()) {
313 // from TAZ
314 if (myPlanElement->getParentTAZs().back()->getAttribute(SUMO_ATTR_CENTER).empty()) {
315 lastPos = myPlanElement->getParentTAZs().back()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
316 } else {
317 lastPos = myPlanElement->getParentTAZs().back()->getAttributePosition(SUMO_ATTR_CENTER);
318 }
319 }
320 // use both position to calculate a line
321 if ((firstPos != Position::INVALID) && (lastPos != Position::INVALID)) {
323 } else {
325 }
326 }
327 // update centering boundary
329 // update child demand elements
330 for (const auto& demandElement : myPlanElement->getChildDemandElements()) {
331 demandElement->updateGeometry();
332 }
333}
334
335
340
341
342void
344 // remove additional from grid
345 if (myPlanBoundary.isInitialised() && updateGrid) {
347 }
349 // if this element is over route, add their boundary
350 if (myPlanElement->getParentDemandElements().size() > 1) {
351 myPlanBoundary.add(myPlanElement->getParentDemandElements().at(1)->getCenteringBoundary());
352 }
353 // add the combination of all parent edges's boundaries
354 for (const auto& edge : myPlanElement->getParentEdges()) {
355 myPlanBoundary.add(edge->getCenteringBoundary());
356 }
357 // add the combination of all parent edges's boundaries
358 for (const auto& junction : myPlanElement->getParentJunctions()) {
359 myPlanBoundary.add(junction->getCenteringBoundary());
360 }
361 // add the combination of all parent additional's boundaries (stoppingPlaces and TAZs)
362 for (const auto& additional : myPlanElement->getParentAdditionals()) {
363 if (additional->getTagProperty()->getTag() == SUMO_TAG_TAZ) {
364 if (additional->getAttribute(SUMO_ATTR_CENTER).empty()) {
365 myPlanBoundary.add(additional->getAttributePosition(GNE_ATTR_TAZ_CENTROID));
366 } else {
367 myPlanBoundary.add(additional->getAttributePosition(SUMO_ATTR_CENTER));
368 }
369 } else {
370 myPlanBoundary.add(additional->getCenteringBoundary());
371 }
372 }
373 // check if is valid
376 }
377 // add additional into RTREE again
378 if (myPlanBoundary.isInitialised() && updateGrid) {
380 }
381}
382
383
386 // get tag property
387 const auto tagProperty = myPlanElement->getTagProperty();
388 // continue depending of parents
389 if (tagProperty->planRoute()) {
390 // route
391 return myPlanElement->getParentDemandElements().at(1)->getPositionInView();
392 } else if (tagProperty->isPlanStop()) {
394 } else if (tagProperty->planFromEdge() || tagProperty->planConsecutiveEdges() || tagProperty->planEdge()) {
395 // first edge
396 return myPlanElement->getParentEdges().front()->getPositionInView();
397 } else if (tagProperty->planFromJunction()) {
398 // first junction
399 return myPlanElement->getParentJunctions().front()->getPositionInView();
400 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace()) {
401 // first additional
402 return myPlanElement->getParentStoppingPlaces().front()->getPositionInView();
403 } else if (tagProperty->planFromTAZ()) {
404 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
405 return myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
406 } else {
407 return myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
408 }
409 } else {
410 // return parent position
411 return Position(0, 0);
412 }
413}
414
415
416std::string
418 // continue depending of key
419 switch (key) {
420 // Common plan attributes
421 case SUMO_ATTR_ID:
422 case GNE_ATTR_PARENT:
423 return myPlanElement->getParentDemandElements().at(0)->getID();
425 if (myDepartPosition < 0) {
426 return "";
427 } else {
429 }
430 case SUMO_ATTR_ENDPOS:
432 if (myArrivalPosition < 0) {
433 return "";
434 } else {
436 }
437 // route
438 case SUMO_ATTR_ROUTE:
439 return myPlanElement->getParentDemandElements().at(1)->getID();
440 // edges
441 case SUMO_ATTR_EDGE:
442 case SUMO_ATTR_EDGES:
444 // stoppingPlaces (single and back)
450 return myPlanElement->getParentStoppingPlaces().back()->getID();
451 // from elements
452 case SUMO_ATTR_FROM:
453 return myPlanElement->getParentEdges().front()->getID();
455 return myPlanElement->getParentJunctions().front()->getID();
457 return myPlanElement->getParentTAZs().front()->getID();
463 return myPlanElement->getParentStoppingPlaces().front()->getID();
464 // to elements
465 case SUMO_ATTR_TO:
466 return myPlanElement->getParentEdges().back()->getID();
468 return myPlanElement->getParentJunctions().back()->getID();
469 case SUMO_ATTR_TO_TAZ:
470 return myPlanElement->getParentTAZs().back()->getID();
471 default:
473 }
474}
475
476
477double
479 // get tag property
480 const auto tagProperty = myPlanElement->getTagProperty();
481 // declare plan parent
482 const auto planParent = myPlanElement->getParentDemandElements().at(0);
483 // continue depending of key
484 switch (key) {
486 if (tagProperty->planStoppingPlace()) {
487 // use startpos of stoppingPlace parent (stops)
488 const auto factor = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLengthGeometryFactor();
489 return myPlanElement->getParentStoppingPlaces().front()->getAttributeDouble(SUMO_ATTR_STARTPOS) * factor;
490 } else if (tagProperty->planFromStoppingPlace()) {
491 // use end position of stoppingPlace parent (for plans that starts in stoppingPlaces)
492 const auto factor = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLengthGeometryFactor();
493 return myPlanElement->getParentStoppingPlaces().front()->getAttributeDouble(SUMO_ATTR_ENDPOS) * factor;
494 } else if (tagProperty->planFromTAZ()) {
495 return 0;
496 } else if (tagProperty->planFromJunction()) {
497 return -1;
498 } else {
499 // get previous plan element
500 const auto previousPlan = planParent->getPreviousChildDemandElement(myPlanElement);
501 // continue depending of previous plan
502 if (previousPlan) {
503 // use previous plan end position (normally the arrival position)
504 const auto posOverLane = previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
505 // if posOverLane is -1, means that previousPlan ends in the end of lane.
506 if (posOverLane == -1) {
507 // INVALID_DOUBLE will put the startPositio at the end of line
508 return INVALID_DOUBLE;
509 } else {
510 return previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
511 }
512 } else {
513 // use depart position defined in parent (person or container)
514 return planParent->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
515 }
516 }
517 }
519 // continue depending of parents
520 if (tagProperty->planStoppingPlace()) {
521 // use end position of the stoppingPlace (stops)
522 const auto factor = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLengthGeometryFactor();
523 return myPlanElement->getParentStoppingPlaces().back()->getAttributeDouble(SUMO_ATTR_ENDPOS) * factor;
524 } else if (tagProperty->planToStoppingPlace()) {
525 // use start position of the stoppingPlace (for elements that ends in stoppingPlaces)
526 const auto factor = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLengthGeometryFactor();
527 return myPlanElement->getParentStoppingPlaces().back()->getAttributeDouble(SUMO_ATTR_STARTPOS) * factor;
528 } else if (tagProperty->planToJunction() || tagProperty->planToTAZ()) {
529 // junctions and TAZs return always -1
530 return -1;
531 } else if ((tagProperty->isPlanStopPerson() || tagProperty->isPlanStopContainer()) && tagProperty->planEdge()) {
532 // elements that ends in stop always uses the end (arrival) position of the stops over edges
533 return myArrivalPosition;
534 } else {
535 // check if next plan is a stop over edge
536 const auto nextPlan = planParent->getNextChildDemandElement(myPlanElement);
537 if (nextPlan && (nextPlan->getTagProperty()->isPlanStopPerson() ||
538 nextPlan->getTagProperty()->isPlanStopContainer()) &&
539 nextPlan->getTagProperty()->planEdge()) {
540 // if next plan is an stop over stoppingPlaces, use ends of stoppingPlace
541 return nextPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
542 } else {
543 // use arrival position
544 return myArrivalPosition;
545 }
546 }
548 return myDepartPosition;
549 case SUMO_ATTR_ENDPOS:
551 return myArrivalPosition;
552 default:
553 throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have a doubleattribute of type '" + toString(key) + "'");
554 }
555}
556
557
560 // get tag property
561 const auto tagProperty = myPlanElement->getTagProperty();
562 // declare plan parent
563 const auto planParent = myPlanElement->getParentDemandElements().at(0);
564 // continue depending of key
565 switch (key) {
567 // get previous plan
568 const auto previousPlan = planParent->getPreviousChildDemandElement(myPlanElement);
569 if (previousPlan && previousPlan->getTagProperty()->isPlanStop() && previousPlan->getTagProperty()->planStoppingPlace()) {
570 return previousPlan->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().back();
571 }
572 // continue depending of from element
573 if (tagProperty->planStoppingPlace()) {
574 return myPlanElement->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().front();
575 } else if (tagProperty->planFromStoppingPlace()) {
576 return myPlanElement->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().back();
577 } else if (tagProperty->planFromJunction()) {
578 // junction view position
579 return myPlanElement->getParentJunctions().front()->getPositionInView();
580 } else if (tagProperty->planFromTAZ()) {
581 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
582 return myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
583 } else {
584 return myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
585 }
586 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planRoute() || tagProperty->planFromEdge()) {
587 // get first path lane
588 const auto firstLane = myPlanElement->getFirstPathLane();
589 // check if first lane exists
590 if (firstLane == nullptr) {
591 return Position::INVALID;
592 }
593 // declare lane position
594 double lanePosition = 0;
595 // continue depending of conditions
596 if (previousPlan) {
597 // use previous geometry end position
598 lanePosition = previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
599 } else {
600 // use departPos defined in planParent
601 lanePosition = planParent->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
602 }
603 // get lane shape
604 const auto& laneShape = firstLane->getLaneShape();
605 // continue depending of lane position
606 if (lanePosition <= 0) {
607 return laneShape.front();
608 } else if (lanePosition >= laneShape.length2D()) {
609 return laneShape.back();
610 } else {
611 return laneShape.positionAtOffset2D(lanePosition);
612 }
613 } else {
614 return Position::INVALID;
615 }
616 }
618 // check parents
619 if (tagProperty->planToJunction()) {
620 // junctions
621 return myPlanElement->getParentJunctions().back()->getPositionInView();
622 } else if (tagProperty->planStoppingPlace()) {
623 // get additional back shape (stops)
624 return myPlanElement->getParentStoppingPlaces().back()->getAdditionalGeometry().getShape().back();
625 } else if (tagProperty->planToStoppingPlace()) {
626 // get additional front shape
627 return myPlanElement->getParentStoppingPlaces().back()->getAdditionalGeometry().getShape().front();
628 } else if (tagProperty->planToTAZ()) {
629 // taz
630 if (myPlanElement->getParentTAZs().back()->getAttribute(SUMO_ATTR_CENTER).empty()) {
631 return myPlanElement->getParentTAZs().back()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
632 } else {
633 return myPlanElement->getParentTAZs().back()->getAttributePosition(SUMO_ATTR_CENTER);
634 }
635 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planRoute() || tagProperty->planFromEdge()) {
636 // get next plan
637 const auto nextPlan = planParent->getNextChildDemandElement(myPlanElement);
638 // if next plan exist, then use their first lane (needed to maintain connectivity with rides)
639 const auto lastLane = nextPlan ? nextPlan->getFirstPathLane() : myPlanElement->getLastPathLane();
640 // check if last lane exists
641 if (lastLane == nullptr) {
642 return Position::INVALID;
643 }
644 // get lane shape
645 const auto& laneShape = lastLane->getLaneShape();
646 // continue depending of arrival position
647 if (nextPlan && nextPlan->getTagProperty()->isPlanStop()) {
648 return nextPlan->getAttributePosition(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
649 } else if (myArrivalPosition == 0) {
650 return laneShape.front();
651 } else if ((myArrivalPosition == -1) || (myArrivalPosition >= laneShape.length2D())) {
652 return laneShape.back();
653 } else {
654 return laneShape.positionAtOffset2D(myArrivalPosition);
655 }
656 } else {
657 return Position::INVALID;
658 }
659 }
660 default:
661 throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have a position attribute of type '" + toString(key) + "'");
662 }
663}
664
665
666void
667GNEDemandElementPlan::setPlanAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
668 // continue depending of key
669 switch (key) {
670 // common attributes
673 case SUMO_ATTR_ENDPOS:
674 case GNE_ATTR_PARENT:
676 break;
677 default:
678 myPlanElement->setCommonAttribute(key, value, undoList);
679 break;
680 }
681}
682
683
684bool
685GNEDemandElementPlan::isPlanValid(SumoXMLAttr key, const std::string& value) {
686 // continue depending of key
687 switch (key) {
688 // common attributes
689 case GNE_ATTR_PARENT:
690 return false;
693 if (value.empty()) {
694 return true;
695 } else if (GNEAttributeCarrier::canParse<double>(value)) {
696 return GNEAttributeCarrier::parse<double>(value) >= 0;
697 } else {
698 return false;
699 }
700 case SUMO_ATTR_ENDPOS:
701 return GNEAttributeCarrier::canParse<double>(value);
702 default:
703 return myPlanElement->isCommonAttributeValid(key, value);
704 }
705}
706
707
708bool
710 switch (key) {
711 // edges
712 case SUMO_ATTR_EDGES:
713 // edge
714 case SUMO_ATTR_EDGE:
715 // route
716 case SUMO_ATTR_ROUTE:
717 // from
718 case SUMO_ATTR_FROM:
726 // to
727 case SUMO_ATTR_TO:
729 case SUMO_ATTR_TO_TAZ:
735 // depart pos (temporal, probably will be removed)
737 return false;
738 default:
739 return true;
740 }
741}
742
743
744void
746 bool recompute = false;
747 switch (key) {
748 // from-to attributes (needed if we're replacing junction by geometry points and similar operations)
749 case SUMO_ATTR_FROM:
751 recompute = true;
752 break;
753 case SUMO_ATTR_TO:
755 recompute = true;
756 break;
757 // Common plan attributes
758 case GNE_ATTR_PARENT:
759 replacePlanParent(value);
760 break;
762 if (value.empty()) {
763 myDepartPosition = -1;
764 } else {
765 myDepartPosition = GNEAttributeCarrier::parse<double>(value);
766 }
767 recompute = true;
768 break;
769 case SUMO_ATTR_ENDPOS:
771 if (value.empty()) {
773 } else {
774 myArrivalPosition = GNEAttributeCarrier::parse<double>(value);
775 }
776 recompute = true;
777 break;
778 default:
780 break;
781 }
782 // check if compute geometry and path
783 if (recompute && !myPlanElement->isTemplate()) {
786 }
787}
788
789
790std::string
792 // get tag property
793 const auto tagProperty = myPlanElement->getTagProperty();
794 // declare result
795 std::string result;
796 // clear result
797 int index = 0;
798 while (tagProperty->getTagStr().at(index) != ':') {
799 result.push_back(tagProperty->getTagStr().at(index));
800 index++;
801 }
802 result += ": ";
803 // continue depending of attributes
804 if (tagProperty->planConsecutiveEdges()) {
805 // edges
806 return result + myPlanElement->getParentEdges().front()->getID() + " ... " + myPlanElement->getParentEdges().back()->getID();
807 } else if (tagProperty->planRoute()) {
808 // route
809 return result + myPlanElement->getParentDemandElements().at(1)->getID();
810 } else if (tagProperty->planEdge()) {
811 // edge
812 return result + myPlanElement->getParentEdges().front()->getID();
813 } else if (tagProperty->planStoppingPlace()) {
814 // stoppingPlace
815 return myPlanElement->getParentStoppingPlaces().front()->getID();
816 } else {
817 // stoppingPlace
818 if (tagProperty->planFromStoppingPlace()) {
819 result += myPlanElement->getParentStoppingPlaces().front()->getID();
820 }
821 // TAZ
822 if (tagProperty->planFromTAZ()) {
823 result += myPlanElement->getParentTAZs().front()->getID();
824 }
825 // junction
826 if (tagProperty->planFromJunction()) {
827 result += myPlanElement->getParentJunctions().front()->getID();
828 }
829 // edge
830 if (tagProperty->planFromEdge()) {
831 result += myPlanElement->getParentEdges().front()->getID();
832 }
833 // arrow
834 result += " -> ";
835 // stoppingPlace
836 if (tagProperty->planToStoppingPlace()) {
837 result += myPlanElement->getParentStoppingPlaces().back()->getID();
838 }
839 // TAZ
840 if (tagProperty->planToTAZ()) {
841 result += myPlanElement->getParentTAZs().back()->getID();
842 }
843 // junction
844 if (tagProperty->planToJunction()) {
845 result += myPlanElement->getParentJunctions().back()->getID();
846 }
847 // edge
848 if (tagProperty->planToEdge()) {
849 result += myPlanElement->getParentEdges().back()->getID();
850 }
851 return result;
852 }
853}
854
855
856bool
858 const auto viewNet = myPlanElement->getNet()->getViewNet();
859 const auto& inspectedElements = viewNet->getInspectedElements();
860 // check conditions
861 if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
862 viewNet->getNetworkViewOptions().showDemandElements() &&
863 viewNet->getDemandViewOptions().showAllPersonPlans()) {
864 // show all person plans in network mode
865 return true;
866 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
867 viewNet->getDemandViewOptions().showAllPersonPlans()) {
868 // show all person plans
869 return true;
870 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() && myPlanElement->isAttributeCarrierSelected()) {
871 // show selected
872 return true;
873 } else if (inspectedElements.isACInspected(myPlanElement->getParentDemandElements().front())) {
874 // person parent is inspected
875 return true;
876 } else if (viewNet->getDemandViewOptions().getLockedPerson() == myPlanElement->getParentDemandElements().front()) {
877 // person parent is locked
878 return true;
879 } else {
880 // check if parent
881 if (inspectedElements.getFirstAC() && inspectedElements.getFirstAC()->getTagProperty()->isPlanPerson() &&
882 (inspectedElements.getFirstAC()->getAttribute(GNE_ATTR_PARENT) == myPlanElement->getAttribute(GNE_ATTR_PARENT))) {
883 // common person parent
884 return true;
885 } else {
886 // all conditions are false
887 return false;
888 }
889 }
890}
891
892
893bool
895 const auto viewNet = myPlanElement->getNet()->getViewNet();
896 const auto& inspectedElements = viewNet->getInspectedElements();
897 // check conditions
898 if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
899 viewNet->getNetworkViewOptions().showDemandElements() &&
900 viewNet->getDemandViewOptions().showAllContainerPlans()) {
901 // show all container plans in network mode
902 return true;
903 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
904 viewNet->getDemandViewOptions().showAllContainerPlans()) {
905 // show all container plans
906 return true;
907 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() && myPlanElement->isAttributeCarrierSelected()) {
908 // show selected
909 return true;
910 } else if (inspectedElements.isACInspected(myPlanElement->getParentDemandElements().front())) {
911 // container parent is inspected
912 return true;
913 } else if (viewNet->getDemandViewOptions().getLockedContainer() == myPlanElement->getParentDemandElements().front()) {
914 // container parent is locked
915 return true;
916 } else {
917 // check if parent is inspected
918 if (inspectedElements.getFirstAC() && inspectedElements.getFirstAC()->getTagProperty()->isPlanContainer() &&
919 (inspectedElements.getFirstAC()->getAttribute(GNE_ATTR_PARENT) == myPlanElement->getAttribute(GNE_ATTR_PARENT))) {
920 // common container parent
921 return true;
922 } else {
923 // all conditions are false
924 return false;
925 }
926 }
927}
928
929
930void
931GNEDemandElementPlan::drawPlanGL(const bool drawPlan, const GUIVisualizationSettings& s, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
932 const auto viewNet = myPlanElement->getNet()->getViewNet();
933 const auto& inspectedElements = viewNet->getInspectedElements();
934 // get plan parent
935 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
936 // get tag property
937 const auto tagProperty = myPlanElement->getTagProperty();
938 // get plan geometry
939 auto& planGeometry = myPlanElement->myDemandElementGeometry;
940 // draw relations between TAZs
941 if (drawPlan && (planGeometry.getShape().size() > 0)) {
942 // draw boundary
943 if (s.drawBoundaries) {
945 }
946 // get detail level
947 const auto d = s.getDetailLevel(1);
948 // check if draw with double width
949 const bool drawHalfWidth = ((inspectedElements.getFirstAC() != myPlanElement) && (inspectedElements.getFirstAC() != planParent) && !gViewObjectsHandler.isObjectSelected(myPlanElement));
950 // calculate path width
951 double pathWidth = s.widthSettings.walkWidth;
952 if (tagProperty->isPlanRide()) {
953 pathWidth = s.widthSettings.rideWidth;
954 } else if (tagProperty->isPlanPersonTrip()) {
955 pathWidth = s.widthSettings.personTripWidth;
956 }
957 // draw geometry only if we'rent in drawForObjectUnderCursor mode
958 if ((tagProperty->isPlanPerson() && s.checkDrawPerson(d, myPlanElement->isAttributeCarrierSelected())) ||
959 (tagProperty->isPlanContainer() && s.checkDrawContainer(d, myPlanElement->isAttributeCarrierSelected()))) {
960 // push matrix
962 // translate to front
964 // set color
965 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
966 // draw line
967 GUIGeometry::drawGeometry(d, planGeometry, pathWidth * (drawHalfWidth ? 1 : 2));
968 if (drawHalfWidth) {
969 GLHelper::drawTriangleAtEnd(planGeometry.getShape().front(), planGeometry.getShape().back(), 0.5, 0.5, 0.5);
970 } else {
971 GLHelper::drawTriangleAtEnd(planGeometry.getShape().front(), planGeometry.getShape().back(), 1, 1, 1);
972 }
973 // pop matrix
975 // draw dotted contour
977 }
978 // calculate contour and draw dotted geometry
979 myPlanContour.calculateContourExtrudedShape(s, d, myPlanElement, planGeometry.getShape(), myPlanElement->getType(), pathWidth * 2,
980 1, true, true, 0, nullptr, nullptr);
981 // calculate contour for end
982 myPlanContourEnd.calculateContourCircleShape(s, d, myPlanElement, planGeometry.getShape().back(), 1, myPlanElement->getType(), 1, nullptr);
983 }
984 // check if draw plan parent
985 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
986 planParent->drawGL(s);
987 }
988}
989
990
991void
993 const double offsetFront, const double planWidth, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
994 const auto viewNet = myPlanElement->getNet()->getViewNet();
995 const auto& inspectedElements = viewNet->getInspectedElements();
996 // get tag property
997 const auto tagProperty = myPlanElement->getTagProperty();
998 // get plan parent
999 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1000 // check if draw plan element can be drawn
1001 if (drawPlan && segment->getLane() && myPlanElement->getNet()->getDemandPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment->getLane(), tagProperty->getTag(), true)) {
1002 // draw boundary
1003 if (tagProperty->isPlacedInRTree() && s.drawBoundaries) {
1005 }
1006 // get detail level
1007 const auto d = s.getDetailLevel(1);
1008 // declare path geometry
1009 GUIGeometry planGeometry;
1010 // update pathGeometry depending of first and last segment
1011 if (segment->isFirstSegment() && segment->isLastSegment()) {
1012 if (tagProperty->planFromTAZ()) {
1013 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1018 } else if (tagProperty->planToTAZ()) {
1019 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1024 } else {
1025 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1030 }
1031 } else if (segment->isFirstSegment()) {
1032 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1035 -1,
1037 } else if (segment->isLastSegment()) {
1038 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1039 -1,
1043 } else {
1044 planGeometry = segment->getLane()->getLaneGeometry();
1045 }
1046 // calculate path width double
1047 const double drawingWidth = s.addSize.getExaggeration(s, segment->getLane()) * planWidth * 2;
1048 // check if draw with double width
1049 const bool drawHalfWidth = ((inspectedElements.getFirstAC() != myPlanElement) && (inspectedElements.getFirstAC() != planParent) && !gViewObjectsHandler.isObjectSelected(myPlanElement));
1050 // get end pos radius
1051 const double endPosRadius = getEndPosRadius(s, segment, drawHalfWidth);
1052 // draw geometry only if we'rent in drawForObjectUnderCursor mode
1053 if ((tagProperty->isPlanPerson() && s.checkDrawPerson(d, myPlanElement->isAttributeCarrierSelected())) ||
1054 (tagProperty->isPlanContainer() && s.checkDrawContainer(d, myPlanElement->isAttributeCarrierSelected()))) {
1055 // Add a draw matrix
1057 // Start with the drawing of the area traslating matrix to origin
1059 // Set color
1060 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1061 // draw geometry depending of drawWithDoubleWidth
1062 GUIGeometry::drawGeometry(d, planGeometry, drawingWidth * (drawHalfWidth ? 0.5 : 1));
1063 // draw red arrows
1064 drawFromArrow(s, segment->getLane(), segment);
1065 drawToArrow(s, segment->getLane(), segment);
1066 // Pop last matrix
1068 // Draw name if isn't being drawn for selecting
1070 // draw dotted contour
1072 // draw TAZ Center dotted contour
1074 }
1075 // declare trim geometry to draw
1076 const auto& shape = (segment->isFirstSegment() || segment->isLastSegment()) ? planGeometry.getShape() : segment->getLane()->getLaneShape();
1077 // calculate contour and draw dotted geometry (always with double width)
1078 if (segment->isFirstSegment()) {
1079 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, true, false,
1080 0, segment, segment->getLane()->getParentEdge());
1081 } else if (segment->isLastSegment()) {
1082 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, false, false,
1083 0, segment, segment->getLane()->getParentEdge());
1084 // calculate contour for end
1086 myPlanElement->getType(), 1, segment->getLane());
1087 } else {
1088 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, false, false, 0,
1089 segment, segment->getLane()->getParentEdge());
1090 }
1091 // check if add this path element to redraw buffer
1094 }
1095 }
1096 // check if draw plan parent
1097 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1098 planParent->drawGL(s);
1099 }
1100}
1101
1102
1103void
1105 const double offsetFront, const double planWidth, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
1106 const auto viewNet = myPlanElement->getNet()->getViewNet();
1107 const auto& inspectedElements = viewNet->getInspectedElements();
1108 // get tag property
1109 const auto tagProperty = myPlanElement->getTagProperty();
1110 // get plan parent
1111 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1112 // check if draw plan elements can be drawn
1113 if (drawPlan && myPlanElement->getNet()->getDemandPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment, tagProperty->getTag(), false)) {
1114 // draw boundary
1115 if (tagProperty->isPlacedInRTree() && s.drawBoundaries) {
1117 }
1118 // get detail level
1119 const auto d = s.getDetailLevel(1);
1120 // calculate path width double
1121 const double pathWidthDouble = s.addSize.getExaggeration(s, segment->getLane()) * planWidth * 2;
1122 // check if draw with double width
1123 const bool drawWithDoubleWidth = ((inspectedElements.getFirstAC() == myPlanElement) || (inspectedElements.getFirstAC() == planParent) || gViewObjectsHandler.isObjectSelected(myPlanElement));
1124 // draw geometry only if we'rent in drawForObjectUnderCursor mode
1126 // push a draw matrix
1128 // Start with the drawing of the area traslating matrix to origin
1130 // Set plan color
1131 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1132 // check if draw lane2lane connection or a red line
1133 if (segment->getPreviousLane() && segment->getNextLane()) {
1134 if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
1135 // obtain lane2lane geometry
1136 const GUIGeometry& lane2laneGeometry = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane());
1137 // draw lane2lane
1138 GUIGeometry::drawGeometry(d, lane2laneGeometry, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1139 } else {
1140 // Set invalid plan color
1142 // draw line between end of first shape and first position of second shape
1143 GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), segment->getNextLane()->getLaneShape().front()}, (0.5 * pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5)));
1144 }
1145 } else if (segment->getPreviousLane()) {
1146 // draw line between center of junction and last lane shape
1147 GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), myPlanElement->getParentJunctions().back()->getPositionInView()}, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1148 } else if (segment->getNextLane()) {
1149 // draw line between center of junction and first lane shape
1150 GLHelper::drawBoxLines({myPlanElement->getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()}, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1151 }
1152 // Pop last matrix
1154 // draw lock icon
1156 // draw dotted contour
1158 }
1159 // check if shape dotted contour has to be drawn
1160 if (segment->getPreviousLane() && segment->getNextLane()) {
1161 if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
1162 // get shape
1163 const auto& shape = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()).getShape();
1164 // calculate contour and draw dotted geometry (always with double width)
1165 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), pathWidthDouble, 1, false, false, 0, segment, segment->getJunction());
1166 }
1167 } else if (segment->getPreviousLane()) {
1168 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, {segment->getPreviousLane()->getLaneShape().back(), myPlanElement->getParentJunctions().back()->getPositionInView()},
1169 myPlanElement->getType(), pathWidthDouble, 1, false, true, 0, segment, segment->getJunction());
1170 } else if (segment->getNextLane()) {
1171 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, {myPlanElement->getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()},
1172 myPlanElement->getType(), pathWidthDouble, 1, true, false, 0, segment, segment->getJunction());
1173 }
1174 // check if add this path element to redraw buffer
1177 }
1178 }
1179 // check if draw plan parent
1180 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1181 planParent->drawGL(s);
1182 }
1183}
1184
1185
1188 // get previous plan
1189 const auto previousPlan = myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement);
1190 if (previousPlan) {
1191 // get previous lane
1192 const auto previousLastLane = previousPlan->getLastPathLane();
1193 // get first lane
1194 const auto firstLane = myPlanElement->getFirstPathLane();
1195 // compare edges
1196 if (previousLastLane && firstLane && (previousLastLane->getParentEdge() != firstLane->getParentEdge())) {
1198 }
1199 // in the future, check more elements
1200 }
1201 // get next child
1202 const auto nextPlan = myPlanElement->getParentDemandElements().at(0)->getNextChildDemandElement(myPlanElement);
1203 if (nextPlan) {
1204 // get previous lane
1205 const auto nextFirstLane = nextPlan->getFirstPathLane();
1206 // get first lane
1207 const auto lastLane = myPlanElement->getLastPathLane();
1208 // compare edges
1209 if (nextFirstLane && lastLane && (nextFirstLane->getParentEdge() != lastLane->getParentEdge())) {
1211 }
1212 // in the future, check more elements
1213 }
1214 // all ok, then return true
1216}
1217
1218
1219std::string
1221 // get previous plan
1222 const auto previousPlan = myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement);
1223 if (previousPlan) {
1224 // get previous lane
1225 const auto previousLastLane = previousPlan->getLastPathLane();
1226 // get first lane
1227 const auto firstLane = myPlanElement->getLastPathLane();
1228 // compare edges
1229 if (previousLastLane && firstLane && (previousLastLane->getParentEdge() != firstLane->getParentEdge())) {
1230 return TLF("Edge '%' is not consecutive with edge '%'", previousLastLane->getParentEdge()->getID(), firstLane->getParentEdge()->getID());
1231 }
1232 // in the future, check more elements
1233 }
1234 // get next child
1235 const auto nextPlan = myPlanElement->getParentDemandElements().at(0)->getNextChildDemandElement(myPlanElement);
1236 if (nextPlan) {
1237 // get previous lane
1238 const auto nextFirstLane = nextPlan->getFirstPathLane();
1239 // get first lane
1240 const auto lastLane = myPlanElement->getLastPathLane();
1241 // compare edges
1242 if (nextFirstLane && lastLane && (nextFirstLane->getParentEdge() != lastLane->getParentEdge())) {
1243 return TLF("Edge '%' is not consecutive with edge '%'", nextFirstLane->getParentEdge()->getID(), lastLane->getParentEdge()->getID());
1244 }
1245 // in the future, check more elements
1246 }
1247 // undefined problem
1248 return "undefined problem";
1249}
1250
1251
1252double
1253GNEDemandElementPlan::getEndPosRadius(const GUIVisualizationSettings& s, const GNESegment* segment, const bool drawHalfWidth) const {
1254 // check if myPlanElement is the last segment
1255 if (segment->isLastSegment()) {
1256 // calculate circle width
1257 const double circleRadius = (drawHalfWidth ? myArrivalPositionDiameter * 0.5 : myArrivalPositionDiameter);
1258 return circleRadius * MIN2((double)0.5, s.laneWidthExaggeration);
1259 } else {
1260 return -1;
1261 }
1262}
1263
1264
1265void
1267 // draw ifcurrent amd next segment is placed over lanes
1268 if (segment->getNextLane()) {
1269 // get firstPosition (last position of current lane shape)
1270 const Position from = lane->getLaneShape().back();
1271 // get lastPosition (first position of next lane shape)
1272 const Position to = segment->getNextLane()->getLaneShape().front();
1273 // push draw matrix
1275 // move front
1276 glTranslated(0, 0, 4);
1277 // draw child line
1279 // pop draw matrix
1281 }
1282}
1283
1284
1285void
1287 // draw the line if previos segment and current segment is placed over lanes
1288 if (segment->getPreviousLane()) {
1289 // get firstPosition (last position of current lane shape)
1290 const Position from = lane->getLaneShape().front();
1291 // get lastPosition (first position of next lane shape)
1292 const Position to = segment->getPreviousLane()->getLaneShape().back();
1293 // push draw matrix
1295 // move front
1296 glTranslated(0, 0, 4);
1297 // draw child line
1299 // pop draw matrix
1301 }
1302}
1303
1304
1305void
1307 // check if myPlanElement is the last segment
1308 if (endPosRadius > 0) {
1310 // push draw matrix
1312 // translate to pos and move to
1313 glTranslated(geometryEndPos.x(), geometryEndPos.y(), 4);
1314 // resolution of drawn circle depending of the zoom (To improve smothness)
1315 GLHelper::drawFilledCircleDetailled(d, endPosRadius);
1316 // pop draw matrix
1318 }
1319}
1320
1321
1322bool
1323GNEDemandElementPlan::replacePlanParent(const std::string& newParentID) {
1324 std::vector<SumoXMLTag> tags;
1326 tags.push_back(SUMO_TAG_PERSON);
1327 tags.push_back(SUMO_TAG_PERSONFLOW);
1328 } else {
1329 tags.push_back(SUMO_TAG_CONTAINER);
1330 tags.push_back(SUMO_TAG_CONTAINERFLOW);
1331 }
1332 // search new parent and set it
1333 for (const auto& tag : tags) {
1334 if (myPlanElement->getNet()->getAttributeCarriers()->retrieveDemandElement(tag, newParentID, false) != nullptr) {
1335 myPlanElement->replaceDemandElementParent(tag, newParentID, 0);
1336 return true;
1337 }
1338 }
1339 throw ProcessError("Invalid new parent ID");
1340}
1341
1342/****************************************************************************/
@ GLO_TAZ
Traffic Assignment Zones (TAZs)
GUIViewObjectsHandler gViewObjectsHandler
#define TLF(string,...)
Definition MsgHandler.h:306
@ 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:68
T MIN2(T a, T b)
Definition StdDefs.h:80
const double SUMO_const_halfLaneWidth
Definition StdDefs.h:53
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:952
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
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
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
bool isCommonAttributeValid(SumoXMLAttr key, const std::string &value) const
virtual void updateGeometry()=0
update pre-computed geometry information
virtual std::string getAttribute(SumoXMLAttr key) const =0
std::string getCommonAttribute(SumoXMLAttr key) const
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 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
GUIGeometry myDemandElementGeometry
demand element geometry (also called "stacked geometry")
void replaceLastParentEdge(const std::string &value)
replace the last parent edge
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
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
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
const PositionVector & getLaneShape() const
get elements shape
Definition GNELane.cpp:232
const GNELane2laneConnection & getLane2laneConnections() const
get Lane2laneConnection struct
Definition GNELane.cpp:666
const GUIGeometry & getLaneGeometry() const
get lane geometry
Definition GNELane.cpp:226
GNEEdge * getParentEdge() const
get parent edge
Definition GNELane.cpp:214
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:1440
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1450
GNEPathManager * getDemandPathManager()
get demand path manager
Definition GNENet.cpp:174
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition GNENet.cpp:144
GNEViewNet * getViewNet() const
get view net
Definition GNENet.cpp:2193
virtual GNELane * getLastPathLane() const =0
get last path lane
virtual void computePathElement()=0
implement in children+
virtual GNELane * getFirstPathLane() const =0
get first path lane
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)
virtual void drawGL(const GUIVisualizationSettings &s) const =0
Draws the object.
void drawName(const Position &pos, const double scale, const GUIVisualizationTextSettings &settings, const double angle=0, bool forceShow=false) const
draw name of item
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.
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
static const Position INVALID
used to indicate that a position is valid
Definition Position.h:323
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