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-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
18// An auxiliar, asbtract class for plan elements
19/****************************************************************************/
20
22#include <netedit/GNENet.h>
23#include <netedit/GNESegment.h>
27
29#include "GNERoute.h"
30
31// ===========================================================================
32// static definitions
33// ===========================================================================
34
36
37// ===========================================================================
38// GNEDemandElement method definitions
39// ===========================================================================
40
41GNEDemandElementPlan::GNEDemandElementPlan(GNEDemandElement* planElement, const double departPosition, const double arrivalPosition) :
42 myMoveElementPlan(new GNEMoveElementPlan(planElement, myDepartPosition)),
43 myDepartPosition(departPosition),
44 myArrivalPosition(arrivalPosition),
45 myPlanElement(planElement) {
46}
47
48
49void
51 const auto tagProperty = myPlanElement->getTagProperty();
52 // write attributes depending of parent elements
53 if (tagProperty->planConsecutiveEdges()) {
55 } else if (tagProperty->planRoute()) {
57 } else if (tagProperty->planEdge()) {
58 device.writeAttr(SUMO_ATTR_EDGE, myPlanElement->getParentEdges().front()->getID());
59 } else if (tagProperty->planBusStop()) {
61 } else if (tagProperty->planTrainStop()) {
63 } else if (tagProperty->planContainerStop()) {
65 } else if (tagProperty->planChargingStation()) {
67 } else if (tagProperty->planParkingArea()) {
69 } else {
70 // write from attribute (if this is the first element)
71 if (myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement) == nullptr) {
72 // check if write edge or junction
73 if (tagProperty->planFromEdge()) {
74 device.writeAttr(SUMO_ATTR_FROM, myPlanElement->getParentEdges().front()->getID());
75 } else if (tagProperty->planFromTAZ()) {
76 device.writeAttr(SUMO_ATTR_FROM_TAZ, myPlanElement->getParentTAZs().front()->getID());
77 } else if (tagProperty->planFromJunction()) {
79 }
80 // origin stopping places are transformed into an intial stop stage (see writeOriginStop)
81 }
82 // continue writting to attribute
83 if (tagProperty->planToEdge()) {
84 device.writeAttr(SUMO_ATTR_TO, myPlanElement->getParentEdges().back()->getID());
85 } else if (tagProperty->planToJunction()) {
87 } else if (tagProperty->planToTAZ()) {
88 device.writeAttr(SUMO_ATTR_TO_TAZ, myPlanElement->getParentTAZs().back()->getID());
89 } else if (tagProperty->planToBusStop()) {
91 } else if (tagProperty->planToTrainStop()) {
93 } else if (tagProperty->planToContainerStop()) {
95 } else if (tagProperty->planToChargingStation()) {
97 } else if (tagProperty->planToParkingArea()) {
99 }
100 }
101 // check if write depart position
102 if (tagProperty->hasAttribute(SUMO_ATTR_DEPARTPOS) && (myDepartPosition > 0)) {
104 }
105 // check if write arrival position
106 if (tagProperty->hasAttribute(SUMO_ATTR_ARRIVALPOS) && (myArrivalPosition > 0)) {
108 }
109 // check if write end position
110 if (tagProperty->hasAttribute(SUMO_ATTR_ENDPOS)) {
112 }
113}
114
115
116void
118 const auto tagProperty = myPlanElement->getTagProperty();
119 // write an extra stop element with duration 0 over a stopping place (if this is the first element)
120 if (tagProperty->planFromStoppingPlace()
121 && myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement) == nullptr) {
122 device.openTag(SUMO_TAG_STOP);
123 const std::string stopID = myPlanElement->getParentStoppingPlaces().front()->getID();
124 if (tagProperty->planFromBusStop()) {
125 device.writeAttr(SUMO_ATTR_BUS_STOP, stopID);
126 } else if (tagProperty->planFromTrainStop()) {
127 device.writeAttr(SUMO_ATTR_TRAIN_STOP, stopID);
128 } else if (tagProperty->planFromContainerStop()) {
129 device.writeAttr(SUMO_ATTR_CONTAINER_STOP, stopID);
130 } else if (tagProperty->planFromChargingStation()) {
132 } else if (tagProperty->planFromParkingArea()) {
133 device.writeAttr(SUMO_ATTR_PARKING_AREA, stopID);
134 }
135 device.writeAttr(SUMO_ATTR_DURATION, 0);
136 device.closeTag();
137 }
138}
139
140
143 // create popup
145 // build common options
148 GUIDesigns::buildFXMenuCommand(ret, ("Cursor position in view: " + toString(getPlanPositionInView().x()) + "," + toString(getPlanPositionInView().y())).c_str(), nullptr, nullptr, 0);
149 return ret;
150}
151
152
153GNELane*
155 // get tag property
156 const auto tagProperty = myPlanElement->getTagProperty();
157 // get vclass
158 auto vClass = myPlanElement->getVClass();
159 // continue depending of parents
160 if (tagProperty->planRoute()) {
161 // route
162 return myPlanElement->getParentDemandElements().at(1)->getParentEdges().front()->getLaneByAllowedVClass(vClass);
163 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planFromEdge() || tagProperty->planEdge()) {
164 // edges
165 return myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
166 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace() || tagProperty->planToStoppingPlace()) {
167 // additional
168 return myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
169 } else {
170 // in other cases (TAZ, junctions, etc.) return null
171 return nullptr;
172 }
173}
174
175
176GNELane*
178 // get tag property
179 const auto tagProperty = myPlanElement->getTagProperty();
180 // get vclass
181 auto vClass = myPlanElement->getVClass();
182 // check parents
183 if (tagProperty->planRoute()) {
184 // route
185 return myPlanElement->getParentDemandElements().at(1)->getParentEdges().back()->getLaneByAllowedVClass(vClass);
186 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planToEdge() || tagProperty->planEdge()) {
187 // edges
188 return myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
189 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace() || tagProperty->planToStoppingPlace()) {
190 // additional
191 return myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getParentEdge()->getLaneByAllowedVClass(vClass);
192 } else {
193 // in other cases (TAZ, junctions, etc.) return null
194 return nullptr;
195 }
196}
197
198
199void
201 // get tag property
202 const auto tagProperty = myPlanElement->getTagProperty();
203 // get vClass
204 auto vClass = myPlanElement->getVClass();
205 // get path manager
206 auto pathManager = myPlanElement->getNet()->getDemandPathManager();
207 // continue depending of parents
208 if (tagProperty->planRoute()) {
209 // calculate consecutive path using route edges
210 pathManager->calculateConsecutivePathEdges(myPlanElement, vClass, myPlanElement->getParentDemandElements().at(1)->getParentEdges());
211 } else if (tagProperty->planConsecutiveEdges()) {
212 // calculate consecutive path using edges
213 pathManager->calculateConsecutivePathEdges(myPlanElement, vClass, myPlanElement->getParentEdges());
215 // calculate path using junctions
216 pathManager->calculatePath(myPlanElement, vClass, myPlanElement->getParentJunctions().front(), myPlanElement->getParentJunctions().back());
218 // declare last lane
219 GNELane* lastLane = nullptr;
221 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().back();
223 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front();
224 } else if (myPlanElement->myTagProperty->planToEdge()) {
225 lastLane = myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
226 }
227 // calculate path
228 if (lastLane) {
229 pathManager->calculatePath(myPlanElement, vClass, myPlanElement->getParentJunctions().front(), lastLane);
230 }
232 // declare first lane
233 GNELane* firstLane = nullptr;
235 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().back();
237 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
239 firstLane = myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
240 }
241 // calculate path
242 if (firstLane) {
243 pathManager->calculatePath(myPlanElement, vClass, firstLane, myPlanElement->getParentJunctions().back());
244 }
245 } else {
246 // declare first edge
247 GNELane* firstLane = nullptr;
249 firstLane = myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
251 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().back();
253 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
254 }
255 // declare last lane
256 GNELane* lastLane = nullptr;
258 lastLane = myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
260 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().back();
262 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front();
263 }
264 if (firstLane && lastLane) {
265 pathManager->calculatePath(myPlanElement, vClass, firstLane, lastLane);
266 } else if (firstLane) {
267 pathManager->calculateConsecutivePathLanes(myPlanElement, {firstLane});
268 } else if (lastLane) {
269 pathManager->calculateConsecutivePathLanes(myPlanElement, {lastLane});
270 }
271 }
272 // update geometry
274}
275
276
277void
279 // get tag property
280 const auto tagProperty = myPlanElement->getTagProperty();
281 // check if plan start or end in a TAZ (becase in this case has to be inserted in RTREE
282 if (tagProperty->planFromTAZ() || tagProperty->planToTAZ()) {
283 // declare first and last positions
284 Position firstPos = Position::INVALID;
285 Position lastPos = Position::INVALID;
286 // set first position
287 if (tagProperty->planFromEdge()) {
288 // from junction
289 firstPos = myPlanElement->getFirstPathLane()->getLaneShape().back();
290 } else if (tagProperty->planFromJunction()) {
291 // from junction
292 firstPos = myPlanElement->getParentJunctions().front()->getPositionInView();
293 } else if (tagProperty->planFromStoppingPlace()) {
294 // end of stoppingPlace lane shape
295 firstPos = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLaneShape().back();
296 } else if (tagProperty->planFromTAZ()) {
297 // from TAZ
298 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
299 firstPos = myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
300 } else {
301 firstPos = myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
302 }
303 }
304 // set last position
305 if (tagProperty->planToEdge()) {
306 // from junction
307 lastPos = myPlanElement->getLastPathLane()->getLaneShape().back();
308 } else if (tagProperty->planToJunction()) {
309 // from junction
310 lastPos = myPlanElement->getParentJunctions().back()->getPositionInView();
311 } else if (tagProperty->planToStoppingPlace()) {
312 // end of stoppingPlace lane shape
313 lastPos = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLaneShape().front();
314 } else if (tagProperty->planToTAZ()) {
315 // from TAZ
316 if (myPlanElement->getParentTAZs().back()->getAttribute(SUMO_ATTR_CENTER).empty()) {
317 lastPos = myPlanElement->getParentTAZs().back()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
318 } else {
319 lastPos = myPlanElement->getParentTAZs().back()->getAttributePosition(SUMO_ATTR_CENTER);
320 }
321 }
322 // use both position to calculate a line
323 if ((firstPos != Position::INVALID) && (lastPos != Position::INVALID)) {
325 } else {
327 }
328 }
329 // update centering boundary
331 // update child demand elements
332 for (const auto& demandElement : myPlanElement->getChildDemandElements()) {
333 demandElement->updateGeometry();
334 }
335}
336
337
342
343
344void
346 // remove additional from grid
347 if (myPlanBoundary.isInitialised() && updateGrid) {
349 }
351 // if this element is over route, add their boundary
352 if (myPlanElement->getParentDemandElements().size() > 1) {
353 myPlanBoundary.add(myPlanElement->getParentDemandElements().at(1)->getCenteringBoundary());
354 }
355 // add the combination of all parent edges's boundaries
356 for (const auto& edge : myPlanElement->getParentEdges()) {
357 myPlanBoundary.add(edge->getCenteringBoundary());
358 }
359 // add the combination of all parent edges's boundaries
360 for (const auto& junction : myPlanElement->getParentJunctions()) {
361 myPlanBoundary.add(junction->getCenteringBoundary());
362 }
363 // add the combination of all parent additional's boundaries (stoppingPlaces and TAZs)
364 for (const auto& additional : myPlanElement->getParentAdditionals()) {
365 if (additional->getTagProperty()->getTag() == SUMO_TAG_TAZ) {
366 if (additional->getAttribute(SUMO_ATTR_CENTER).empty()) {
367 myPlanBoundary.add(additional->getAttributePosition(GNE_ATTR_TAZ_CENTROID));
368 } else {
369 myPlanBoundary.add(additional->getAttributePosition(SUMO_ATTR_CENTER));
370 }
371 } else {
372 myPlanBoundary.add(additional->getCenteringBoundary());
373 }
374 }
375 // check if is valid
378 }
379 // add additional into RTREE again
380 if (myPlanBoundary.isInitialised() && updateGrid) {
382 }
383}
384
385
388 // get tag property
389 const auto tagProperty = myPlanElement->getTagProperty();
390 // continue depending of parents
391 if (tagProperty->planRoute()) {
392 // route
393 return myPlanElement->getParentDemandElements().at(1)->getPositionInView();
394 } else if (tagProperty->isPlanStop()) {
396 } else if (tagProperty->planFromEdge() || tagProperty->planConsecutiveEdges() || tagProperty->planEdge()) {
397 // first edge
398 return myPlanElement->getParentEdges().front()->getPositionInView();
399 } else if (tagProperty->planFromJunction()) {
400 // first junction
401 return myPlanElement->getParentJunctions().front()->getPositionInView();
402 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace()) {
403 // first additional
404 return myPlanElement->getParentStoppingPlaces().front()->getPositionInView();
405 } else if (tagProperty->planFromTAZ()) {
406 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
407 return myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
408 } else {
409 return myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
410 }
411 } else {
412 // return parent position
413 return Position(0, 0);
414 }
415}
416
417
418std::string
420 // continue depending of key
421 switch (key) {
422 // Common plan attributes
423 case SUMO_ATTR_ID:
424 case GNE_ATTR_PARENT:
425 return myPlanElement->getParentDemandElements().at(0)->getID();
427 if (myDepartPosition < 0) {
428 return "";
429 } else {
431 }
432 case SUMO_ATTR_ENDPOS:
434 if (myArrivalPosition < 0) {
435 return "";
436 } else {
438 }
439 // route
440 case SUMO_ATTR_ROUTE:
441 return myPlanElement->getParentDemandElements().at(1)->getID();
442 // edges
443 case SUMO_ATTR_EDGE:
444 case SUMO_ATTR_EDGES:
446 // stoppingPlaces (single and back)
452 return myPlanElement->getParentStoppingPlaces().back()->getID();
453 // from elements
454 case SUMO_ATTR_FROM:
455 return myPlanElement->getParentEdges().front()->getID();
457 return myPlanElement->getParentJunctions().front()->getID();
459 return myPlanElement->getParentTAZs().front()->getID();
465 return myPlanElement->getParentStoppingPlaces().front()->getID();
466 // to elements
467 case SUMO_ATTR_TO:
468 return myPlanElement->getParentEdges().back()->getID();
470 return myPlanElement->getParentJunctions().back()->getID();
471 case SUMO_ATTR_TO_TAZ:
472 return myPlanElement->getParentTAZs().back()->getID();
473 default:
475 }
476}
477
478
479double
481 // get tag property
482 const auto tagProperty = myPlanElement->getTagProperty();
483 // declare plan parent
484 const auto planParent = myPlanElement->getParentDemandElements().at(0);
485 // continue depending of key
486 switch (key) {
488 if (tagProperty->planStoppingPlace()) {
489 // use startpos of stoppingPlace parent (stops)
490 const auto factor = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLengthGeometryFactor();
491 return myPlanElement->getParentStoppingPlaces().front()->getAttributeDouble(SUMO_ATTR_STARTPOS) * factor;
492 } else if (tagProperty->planFromStoppingPlace()) {
493 // use end position of stoppingPlace parent (for plans that starts in stoppingPlaces)
494 const auto factor = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLengthGeometryFactor();
495 return myPlanElement->getParentStoppingPlaces().front()->getAttributeDouble(SUMO_ATTR_ENDPOS) * factor;
496 } else if (tagProperty->planFromTAZ()) {
497 return 0;
498 } else if (tagProperty->planFromJunction()) {
499 return -1;
500 } else {
501 // get previous plan element
502 const auto previousPlan = planParent->getPreviousChildDemandElement(myPlanElement);
503 // continue depending of previous plan
504 if (previousPlan) {
505 // use previous plan end position (normally the arrival position)
506 const auto posOverLane = previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
507 // if posOverLane is -1, means that previousPlan ends in the end of lane.
508 if (posOverLane == -1) {
509 // INVALID_DOUBLE will put the startPositio at the end of line
510 return INVALID_DOUBLE;
511 } else {
512 return previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
513 }
514 } else {
515 // use depart position defined in parent (person or container)
516 return planParent->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
517 }
518 }
519 }
521 // continue depending of parents
522 if (tagProperty->planStoppingPlace()) {
523 // use end position of the stoppingPlace (stops)
524 const auto factor = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLengthGeometryFactor();
525 return myPlanElement->getParentStoppingPlaces().back()->getAttributeDouble(SUMO_ATTR_ENDPOS) * factor;
526 } else if (tagProperty->planToStoppingPlace()) {
527 // use start position of the stoppingPlace (for elements that ends in stoppingPlaces)
528 const auto factor = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLengthGeometryFactor();
529 return myPlanElement->getParentStoppingPlaces().back()->getAttributeDouble(SUMO_ATTR_STARTPOS) * factor;
530 } else if (tagProperty->planToJunction() || tagProperty->planToTAZ()) {
531 // junctions and TAZs return always -1
532 return -1;
533 } else if ((tagProperty->isPlanStopPerson() || tagProperty->isPlanStopContainer()) && tagProperty->planEdge()) {
534 // elements that ends in stop always uses the end (arrival) position of the stops over edges
535 return myArrivalPosition;
536 } else {
537 // check if next plan is a stop over edge
538 const auto nextPlan = planParent->getNextChildDemandElement(myPlanElement);
539 if (nextPlan && (nextPlan->getTagProperty()->isPlanStopPerson() ||
540 nextPlan->getTagProperty()->isPlanStopContainer()) &&
541 nextPlan->getTagProperty()->planEdge()) {
542 // if next plan is an stop over stoppingPlaces, use ends of stoppingPlace
543 return nextPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
544 } else {
545 // use arrival position
546 return myArrivalPosition;
547 }
548 }
550 return myDepartPosition;
551 case SUMO_ATTR_ENDPOS:
553 return myArrivalPosition;
554 default:
555 throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have a doubleattribute of type '" + toString(key) + "'");
556 }
557}
558
559
562 // get tag property
563 const auto tagProperty = myPlanElement->getTagProperty();
564 // declare plan parent
565 const auto planParent = myPlanElement->getParentDemandElements().at(0);
566 // continue depending of key
567 switch (key) {
569 // get previous plan
570 const auto previousPlan = planParent->getPreviousChildDemandElement(myPlanElement);
571 if (previousPlan && previousPlan->getTagProperty()->isPlanStop() && previousPlan->getTagProperty()->planStoppingPlace()) {
572 return previousPlan->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().back();
573 }
574 // continue depending of from element
575 if (tagProperty->planStoppingPlace()) {
576 return myPlanElement->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().front();
577 } else if (tagProperty->planFromStoppingPlace()) {
578 return myPlanElement->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().back();
579 } else if (tagProperty->planFromJunction()) {
580 // junction view position
581 return myPlanElement->getParentJunctions().front()->getPositionInView();
582 } else if (tagProperty->planFromTAZ()) {
583 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
584 return myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
585 } else {
586 return myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
587 }
588 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planRoute() || tagProperty->planFromEdge()) {
589 // get first path lane
590 const auto firstLane = myPlanElement->getFirstPathLane();
591 // check if first lane exists
592 if (firstLane == nullptr) {
593 return Position::INVALID;
594 }
595 // declare lane position
596 double lanePosition = 0;
597 // continue depending of conditions
598 if (previousPlan) {
599 // use previous geometry end position
600 lanePosition = previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
601 } else {
602 // use departPos defined in planParent
603 lanePosition = planParent->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
604 }
605 // get lane shape
606 const auto& laneShape = firstLane->getLaneShape();
607 // continue depending of lane position
608 if (lanePosition <= 0) {
609 return laneShape.front();
610 } else if (lanePosition >= laneShape.length2D()) {
611 return laneShape.back();
612 } else {
613 return laneShape.positionAtOffset2D(lanePosition);
614 }
615 } else {
616 return Position::INVALID;
617 }
618 }
620 // check parents
621 if (tagProperty->planToJunction()) {
622 // junctions
623 return myPlanElement->getParentJunctions().back()->getPositionInView();
624 } else if (tagProperty->planStoppingPlace()) {
625 // get additional back shape (stops)
626 return myPlanElement->getParentStoppingPlaces().back()->getAdditionalGeometry().getShape().back();
627 } else if (tagProperty->planToStoppingPlace()) {
628 // get additional front shape
629 return myPlanElement->getParentStoppingPlaces().back()->getAdditionalGeometry().getShape().front();
630 } else if (tagProperty->planToTAZ()) {
631 // taz
632 if (myPlanElement->getParentTAZs().back()->getAttribute(SUMO_ATTR_CENTER).empty()) {
633 return myPlanElement->getParentTAZs().back()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
634 } else {
635 return myPlanElement->getParentTAZs().back()->getAttributePosition(SUMO_ATTR_CENTER);
636 }
637 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planRoute() || tagProperty->planFromEdge()) {
638 // get next plan
639 const auto nextPlan = planParent->getNextChildDemandElement(myPlanElement);
640 // if next plan exist, then use their first lane (needed to maintain connectivity with rides)
641 const auto lastLane = nextPlan ? nextPlan->getFirstPathLane() : myPlanElement->getLastPathLane();
642 // check if last lane exists
643 if (lastLane == nullptr) {
644 return Position::INVALID;
645 }
646 // get lane shape
647 const auto& laneShape = lastLane->getLaneShape();
648 // continue depending of arrival position
649 if (nextPlan && nextPlan->getTagProperty()->isPlanStop()) {
650 return nextPlan->getAttributePosition(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
651 } else if (myArrivalPosition == 0) {
652 return laneShape.front();
653 } else if ((myArrivalPosition == -1) || (myArrivalPosition >= laneShape.length2D())) {
654 return laneShape.back();
655 } else {
656 return laneShape.positionAtOffset2D(myArrivalPosition);
657 }
658 } else {
659 return Position::INVALID;
660 }
661 }
662 default:
663 throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have a position attribute of type '" + toString(key) + "'");
664 }
665}
666
667
668void
669GNEDemandElementPlan::setPlanAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
670 // continue depending of key
671 switch (key) {
672 // common attributes
675 case SUMO_ATTR_ENDPOS:
676 case GNE_ATTR_PARENT:
678 break;
679 default:
680 myPlanElement->setCommonAttribute(key, value, undoList);
681 break;
682 }
683}
684
685
686bool
687GNEDemandElementPlan::isPlanValid(SumoXMLAttr key, const std::string& value) {
688 // continue depending of key
689 switch (key) {
690 // common attributes
691 case GNE_ATTR_PARENT:
692 return false;
695 if (value.empty()) {
696 return true;
697 } else if (GNEAttributeCarrier::canParse<double>(value)) {
698 return GNEAttributeCarrier::parse<double>(value) >= 0;
699 } else {
700 return false;
701 }
702 case SUMO_ATTR_ENDPOS:
703 return GNEAttributeCarrier::canParse<double>(value);
704 default:
705 return myPlanElement->isCommonAttributeValid(key, value);
706 }
707}
708
709
710bool
712 switch (key) {
713 // edges
714 case SUMO_ATTR_EDGES:
715 // edge
716 case SUMO_ATTR_EDGE:
717 // route
718 case SUMO_ATTR_ROUTE:
719 // from
720 case SUMO_ATTR_FROM:
728 // to
729 case SUMO_ATTR_TO:
731 case SUMO_ATTR_TO_TAZ:
737 // depart pos (temporal, probably will be removed)
739 return false;
740 default:
741 return true;
742 }
743}
744
745
746void
748 bool recompute = false;
749 switch (key) {
750 // from-to attributes (needed if we're replacing junction by geometry points and similar operations)
751 case SUMO_ATTR_FROM:
753 recompute = true;
754 break;
755 case SUMO_ATTR_TO:
757 recompute = true;
758 break;
759 // Common plan attributes
760 case GNE_ATTR_PARENT:
761 replacePlanParent(value);
762 break;
764 if (value.empty()) {
765 myDepartPosition = -1;
766 } else {
767 myDepartPosition = GNEAttributeCarrier::parse<double>(value);
768 }
769 recompute = true;
770 break;
771 case SUMO_ATTR_ENDPOS:
773 if (value.empty()) {
775 } else {
776 myArrivalPosition = GNEAttributeCarrier::parse<double>(value);
777 }
778 recompute = true;
779 break;
780 default:
782 break;
783 }
784 // check if compute geometry and path
785 if (recompute && !myPlanElement->isTemplate()) {
788 }
789}
790
791
792std::string
794 // get tag property
795 const auto tagProperty = myPlanElement->getTagProperty();
796 // declare result
797 std::string result;
798 // clear result
799 int index = 0;
800 while (tagProperty->getTagStr().at(index) != ':') {
801 result.push_back(tagProperty->getTagStr().at(index));
802 index++;
803 }
804 result += ": ";
805 // continue depending of attributes
806 if (tagProperty->planConsecutiveEdges()) {
807 // edges
808 return result + myPlanElement->getParentEdges().front()->getID() + " ... " + myPlanElement->getParentEdges().back()->getID();
809 } else if (tagProperty->planRoute()) {
810 // route
811 return result + myPlanElement->getParentDemandElements().at(1)->getID();
812 } else if (tagProperty->planEdge()) {
813 // edge
814 return result + myPlanElement->getParentEdges().front()->getID();
815 } else if (tagProperty->planStoppingPlace()) {
816 // stoppingPlace
817 return myPlanElement->getParentStoppingPlaces().front()->getID();
818 } else {
819 // stoppingPlace
820 if (tagProperty->planFromStoppingPlace()) {
821 result += myPlanElement->getParentStoppingPlaces().front()->getID();
822 }
823 // TAZ
824 if (tagProperty->planFromTAZ()) {
825 result += myPlanElement->getParentTAZs().front()->getID();
826 }
827 // junction
828 if (tagProperty->planFromJunction()) {
829 result += myPlanElement->getParentJunctions().front()->getID();
830 }
831 // edge
832 if (tagProperty->planFromEdge()) {
833 result += myPlanElement->getParentEdges().front()->getID();
834 }
835 // arrow
836 result += " -> ";
837 // stoppingPlace
838 if (tagProperty->planToStoppingPlace()) {
839 result += myPlanElement->getParentStoppingPlaces().back()->getID();
840 }
841 // TAZ
842 if (tagProperty->planToTAZ()) {
843 result += myPlanElement->getParentTAZs().back()->getID();
844 }
845 // junction
846 if (tagProperty->planToJunction()) {
847 result += myPlanElement->getParentJunctions().back()->getID();
848 }
849 // edge
850 if (tagProperty->planToEdge()) {
851 result += myPlanElement->getParentEdges().back()->getID();
852 }
853 return result;
854 }
855}
856
857
858bool
860 const auto viewNet = myPlanElement->getNet()->getViewNet();
861 const auto& inspectedElements = viewNet->getInspectedElements();
862 // check conditions
863 if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
864 viewNet->getNetworkViewOptions().showDemandElements() &&
865 viewNet->getDemandViewOptions().showAllPersonPlans()) {
866 // show all person plans in network mode
867 return true;
868 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
869 viewNet->getDemandViewOptions().showAllPersonPlans()) {
870 // show all person plans
871 return true;
872 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() && myPlanElement->isAttributeCarrierSelected()) {
873 // show selected
874 return true;
875 } else if (inspectedElements.isACInspected(myPlanElement->getParentDemandElements().front())) {
876 // person parent is inspected
877 return true;
878 } else if (viewNet->getDemandViewOptions().getLockedPerson() == myPlanElement->getParentDemandElements().front()) {
879 // person parent is locked
880 return true;
881 } else {
882 // check if parent
883 if (inspectedElements.getFirstAC() && inspectedElements.getFirstAC()->getTagProperty()->isPlanPerson() &&
884 (inspectedElements.getFirstAC()->getAttribute(GNE_ATTR_PARENT) == myPlanElement->getAttribute(GNE_ATTR_PARENT))) {
885 // common person parent
886 return true;
887 } else {
888 // all conditions are false
889 return false;
890 }
891 }
892}
893
894
895bool
897 const auto viewNet = myPlanElement->getNet()->getViewNet();
898 const auto& inspectedElements = viewNet->getInspectedElements();
899 // check conditions
900 if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
901 viewNet->getNetworkViewOptions().showDemandElements() &&
902 viewNet->getDemandViewOptions().showAllContainerPlans()) {
903 // show all container plans in network mode
904 return true;
905 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
906 viewNet->getDemandViewOptions().showAllContainerPlans()) {
907 // show all container plans
908 return true;
909 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() && myPlanElement->isAttributeCarrierSelected()) {
910 // show selected
911 return true;
912 } else if (inspectedElements.isACInspected(myPlanElement->getParentDemandElements().front())) {
913 // container parent is inspected
914 return true;
915 } else if (viewNet->getDemandViewOptions().getLockedContainer() == myPlanElement->getParentDemandElements().front()) {
916 // container parent is locked
917 return true;
918 } else {
919 // check if parent is inspected
920 if (inspectedElements.getFirstAC() && inspectedElements.getFirstAC()->getTagProperty()->isPlanContainer() &&
921 (inspectedElements.getFirstAC()->getAttribute(GNE_ATTR_PARENT) == myPlanElement->getAttribute(GNE_ATTR_PARENT))) {
922 // common container parent
923 return true;
924 } else {
925 // all conditions are false
926 return false;
927 }
928 }
929}
930
931
932void
933GNEDemandElementPlan::drawPlanGL(const bool drawPlan, const GUIVisualizationSettings& s, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
934 const auto viewNet = myPlanElement->getNet()->getViewNet();
935 const auto& inspectedElements = viewNet->getInspectedElements();
936 // get plan parent
937 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
938 // get tag property
939 const auto tagProperty = myPlanElement->getTagProperty();
940 // get plan geometry
941 auto& planGeometry = myPlanElement->myDemandElementGeometry;
942 // draw relations between TAZs
943 if (drawPlan && (planGeometry.getShape().size() > 0)) {
944 // draw boundary
945 if (s.drawBoundaries) {
947 }
948 // get detail level
949 const auto d = s.getDetailLevel(1);
950 // check if draw with double width
951 const bool drawHalfWidth = ((inspectedElements.getFirstAC() != myPlanElement) && (inspectedElements.getFirstAC() != planParent) && !gViewObjectsHandler.isObjectSelected(myPlanElement));
952 // calculate path width
953 double pathWidth = s.widthSettings.walkWidth;
954 if (tagProperty->isPlanRide()) {
955 pathWidth = s.widthSettings.rideWidth;
956 } else if (tagProperty->isPlanPersonTrip()) {
957 pathWidth = s.widthSettings.personTripWidth;
958 }
959 // draw geometry only if we'rent in drawForObjectUnderCursor mode
960 if ((tagProperty->isPlanPerson() && s.checkDrawPerson(d, myPlanElement->isAttributeCarrierSelected())) ||
961 (tagProperty->isPlanContainer() && s.checkDrawContainer(d, myPlanElement->isAttributeCarrierSelected()))) {
962 // push matrix
964 // translate to front
966 // set color
967 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
968 // draw line
969 GUIGeometry::drawGeometry(d, planGeometry, pathWidth * (drawHalfWidth ? 1 : 2));
970 if (drawHalfWidth) {
971 GLHelper::drawTriangleAtEnd(planGeometry.getShape().front(), planGeometry.getShape().back(), 0.5, 0.5, 0.5);
972 } else {
973 GLHelper::drawTriangleAtEnd(planGeometry.getShape().front(), planGeometry.getShape().back(), 1, 1, 1);
974 }
975 // pop matrix
977 // draw dotted contour
979 }
980 // calculate contour and draw dotted geometry
981 myPlanContour.calculateContourExtrudedShape(s, d, myPlanElement, planGeometry.getShape(), myPlanElement->getType(), pathWidth * 2,
982 1, true, true, 0, nullptr, nullptr);
983 // calculate contour for end
984 myPlanContourEnd.calculateContourCircleShape(s, d, myPlanElement, planGeometry.getShape().back(), 1, myPlanElement->getType(), 1, nullptr);
985 }
986 // check if draw plan parent
987 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
988 planParent->drawGL(s);
989 }
990}
991
992
993void
995 const double offsetFront, const double planWidth, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
996 const auto viewNet = myPlanElement->getNet()->getViewNet();
997 const auto& inspectedElements = viewNet->getInspectedElements();
998 // get tag property
999 const auto tagProperty = myPlanElement->getTagProperty();
1000 // get plan parent
1001 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1002 // check if draw plan element can be drawn
1003 if (drawPlan && segment->getLane() && myPlanElement->getNet()->getDemandPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment->getLane(), tagProperty->getTag(), true)) {
1004 // draw boundary
1005 if (tagProperty->isPlacedInRTree() && s.drawBoundaries) {
1007 }
1008 // get detail level
1009 const auto d = s.getDetailLevel(1);
1010 // declare path geometry
1011 GUIGeometry planGeometry;
1012 // update pathGeometry depending of first and last segment
1013 if (segment->isFirstSegment() && segment->isLastSegment()) {
1014 if (tagProperty->planFromTAZ()) {
1015 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1020 } else if (tagProperty->planToTAZ()) {
1021 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1026 } else {
1027 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1032 }
1033 } else if (segment->isFirstSegment()) {
1034 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1037 -1,
1039 } else if (segment->isLastSegment()) {
1040 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1041 -1,
1045 } else {
1046 planGeometry = segment->getLane()->getLaneGeometry();
1047 }
1048 // calculate path width double
1049 const double drawingWidth = s.addSize.getExaggeration(s, segment->getLane()) * planWidth * 2;
1050 // check if draw with double width
1051 const bool drawHalfWidth = ((inspectedElements.getFirstAC() != myPlanElement) && (inspectedElements.getFirstAC() != planParent) && !gViewObjectsHandler.isObjectSelected(myPlanElement));
1052 // get end pos radius
1053 const double endPosRadius = getEndPosRadius(s, segment, drawHalfWidth);
1054 // draw geometry only if we'rent in drawForObjectUnderCursor mode
1055 if ((tagProperty->isPlanPerson() && s.checkDrawPerson(d, myPlanElement->isAttributeCarrierSelected())) ||
1056 (tagProperty->isPlanContainer() && s.checkDrawContainer(d, myPlanElement->isAttributeCarrierSelected()))) {
1057 // Add a draw matrix
1059 // Start with the drawing of the area traslating matrix to origin
1061 // Set color
1062 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1063 // draw geometry depending of drawWithDoubleWidth
1064 GUIGeometry::drawGeometry(d, planGeometry, drawingWidth * (drawHalfWidth ? 0.5 : 1));
1065 // draw red arrows
1066 drawFromArrow(s, segment->getLane(), segment);
1067 drawToArrow(s, segment->getLane(), segment);
1068 // Pop last matrix
1070 // Draw name if isn't being drawn for selecting
1072 // draw dotted contour
1074 // draw TAZ Center dotted contour
1076 }
1077 // declare trim geometry to draw
1078 const auto& shape = (segment->isFirstSegment() || segment->isLastSegment()) ? planGeometry.getShape() : segment->getLane()->getLaneShape();
1079 // calculate contour and draw dotted geometry (always with double width)
1080 if (segment->isFirstSegment()) {
1081 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, true, false,
1082 0, segment, segment->getLane()->getParentEdge());
1083 } else if (segment->isLastSegment()) {
1084 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, false, false,
1085 0, segment, segment->getLane()->getParentEdge());
1086 // calculate contour for end
1088 myPlanElement->getType(), 1, segment->getLane());
1089 } else {
1090 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, false, false, 0,
1091 segment, segment->getLane()->getParentEdge());
1092 }
1093 // check if add this path element to redraw buffer
1096 }
1097 }
1098 // check if draw plan parent
1099 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1100 planParent->drawGL(s);
1101 }
1102}
1103
1104
1105void
1107 const double offsetFront, const double planWidth, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
1108 const auto viewNet = myPlanElement->getNet()->getViewNet();
1109 const auto& inspectedElements = viewNet->getInspectedElements();
1110 // get tag property
1111 const auto tagProperty = myPlanElement->getTagProperty();
1112 // get plan parent
1113 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1114 // check if draw plan elements can be drawn
1115 if (drawPlan && myPlanElement->getNet()->getDemandPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment, tagProperty->getTag(), false)) {
1116 // draw boundary
1117 if (tagProperty->isPlacedInRTree() && s.drawBoundaries) {
1119 }
1120 // get detail level
1121 const auto d = s.getDetailLevel(1);
1122 // calculate path width double
1123 const double pathWidthDouble = s.addSize.getExaggeration(s, segment->getLane()) * planWidth * 2;
1124 // check if draw with double width
1125 const bool drawWithDoubleWidth = ((inspectedElements.getFirstAC() == myPlanElement) || (inspectedElements.getFirstAC() == planParent) || gViewObjectsHandler.isObjectSelected(myPlanElement));
1126 // draw geometry only if we'rent in drawForObjectUnderCursor mode
1128 // push a draw matrix
1130 // Start with the drawing of the area traslating matrix to origin
1132 // Set plan color
1133 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1134 // check if draw lane2lane connection or a red line
1135 if (segment->getPreviousLane() && segment->getNextLane()) {
1136 if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
1137 // obtain lane2lane geometry
1138 const GUIGeometry& lane2laneGeometry = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane());
1139 // draw lane2lane
1140 GUIGeometry::drawGeometry(d, lane2laneGeometry, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1141 } else {
1142 // Set invalid plan color
1144 // draw line between end of first shape and first position of second shape
1145 GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), segment->getNextLane()->getLaneShape().front()}, (0.5 * pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5)));
1146 }
1147 } else if (segment->getPreviousLane()) {
1148 // draw line between center of junction and last lane shape
1149 GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), myPlanElement->getParentJunctions().back()->getPositionInView()}, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1150 } else if (segment->getNextLane()) {
1151 // draw line between center of junction and first lane shape
1152 GLHelper::drawBoxLines({myPlanElement->getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()}, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1153 }
1154 // Pop last matrix
1156 // draw lock icon
1158 // draw dotted contour
1160 }
1161 // check if shape dotted contour has to be drawn
1162 if (segment->getPreviousLane() && segment->getNextLane()) {
1163 if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
1164 // get shape
1165 const auto& shape = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()).getShape();
1166 // calculate contour and draw dotted geometry (always with double width)
1167 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), pathWidthDouble, 1, false, false, 0, segment, segment->getJunction());
1168 }
1169 } else if (segment->getPreviousLane()) {
1170 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, {segment->getPreviousLane()->getLaneShape().back(), myPlanElement->getParentJunctions().back()->getPositionInView()},
1171 myPlanElement->getType(), pathWidthDouble, 1, false, true, 0, segment, segment->getJunction());
1172 } else if (segment->getNextLane()) {
1173 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, {myPlanElement->getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()},
1174 myPlanElement->getType(), pathWidthDouble, 1, true, false, 0, segment, segment->getJunction());
1175 }
1176 // check if add this path element to redraw buffer
1179 }
1180 }
1181 // check if draw plan parent
1182 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1183 planParent->drawGL(s);
1184 }
1185}
1186
1187
1190 // get previous plan
1191 const auto previousPlan = myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement);
1192 if (previousPlan) {
1193 // get previous lane
1194 const auto previousLastLane = previousPlan->getLastPathLane();
1195 // get first lane
1196 const auto firstLane = myPlanElement->getFirstPathLane();
1197 // compare edges
1198 if (previousLastLane && firstLane && (previousLastLane->getParentEdge() != firstLane->getParentEdge())) {
1200 }
1201 // in the future, check more elements
1202 }
1203 // get next child
1204 const auto nextPlan = myPlanElement->getParentDemandElements().at(0)->getNextChildDemandElement(myPlanElement);
1205 if (nextPlan) {
1206 // get previous lane
1207 const auto nextFirstLane = nextPlan->getFirstPathLane();
1208 // get first lane
1209 const auto lastLane = myPlanElement->getLastPathLane();
1210 // compare edges
1211 if (nextFirstLane && lastLane && (nextFirstLane->getParentEdge() != lastLane->getParentEdge())) {
1213 }
1214 // in the future, check more elements
1215 }
1216 // all ok, then return true
1218}
1219
1220
1221std::string
1223 // get previous plan
1224 const auto previousPlan = myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement);
1225 if (previousPlan) {
1226 // get previous lane
1227 const auto previousLastLane = previousPlan->getLastPathLane();
1228 // get first lane
1229 const auto firstLane = myPlanElement->getLastPathLane();
1230 // compare edges
1231 if (previousLastLane && firstLane && (previousLastLane->getParentEdge() != firstLane->getParentEdge())) {
1232 return TLF("Edge '%' is not consecutive with edge '%'", previousLastLane->getParentEdge()->getID(), firstLane->getParentEdge()->getID());
1233 }
1234 // in the future, check more elements
1235 }
1236 // get next child
1237 const auto nextPlan = myPlanElement->getParentDemandElements().at(0)->getNextChildDemandElement(myPlanElement);
1238 if (nextPlan) {
1239 // get previous lane
1240 const auto nextFirstLane = nextPlan->getFirstPathLane();
1241 // get first lane
1242 const auto lastLane = myPlanElement->getLastPathLane();
1243 // compare edges
1244 if (nextFirstLane && lastLane && (nextFirstLane->getParentEdge() != lastLane->getParentEdge())) {
1245 return TLF("Edge '%' is not consecutive with edge '%'", nextFirstLane->getParentEdge()->getID(), lastLane->getParentEdge()->getID());
1246 }
1247 // in the future, check more elements
1248 }
1249 // undefined problem
1250 return "undefined problem";
1251}
1252
1253
1254double
1255GNEDemandElementPlan::getEndPosRadius(const GUIVisualizationSettings& s, const GNESegment* segment, const bool drawHalfWidth) const {
1256 // check if myPlanElement is the last segment
1257 if (segment->isLastSegment()) {
1258 // calculate circle width
1259 const double circleRadius = (drawHalfWidth ? myArrivalPositionDiameter * 0.5 : myArrivalPositionDiameter);
1260 return circleRadius * MIN2((double)0.5, s.laneWidthExaggeration);
1261 } else {
1262 return -1;
1263 }
1264}
1265
1266
1267void
1269 // draw ifcurrent amd next segment is placed over lanes
1270 if (segment->getNextLane()) {
1271 // get firstPosition (last position of current lane shape)
1272 const Position from = lane->getLaneShape().back();
1273 // get lastPosition (first position of next lane shape)
1274 const Position to = segment->getNextLane()->getLaneShape().front();
1275 // push draw matrix
1277 // move front
1278 glTranslated(0, 0, 4);
1279 // draw child line
1281 // pop draw matrix
1283 }
1284}
1285
1286
1287void
1289 // draw the line if previos segment and current segment is placed over lanes
1290 if (segment->getPreviousLane()) {
1291 // get firstPosition (last position of current lane shape)
1292 const Position from = lane->getLaneShape().front();
1293 // get lastPosition (first position of next lane shape)
1294 const Position to = segment->getPreviousLane()->getLaneShape().back();
1295 // push draw matrix
1297 // move front
1298 glTranslated(0, 0, 4);
1299 // draw child line
1301 // pop draw matrix
1303 }
1304}
1305
1306
1307void
1309 // check if myPlanElement is the last segment
1310 if (endPosRadius > 0) {
1312 // push draw matrix
1314 // translate to pos and move to
1315 glTranslated(geometryEndPos.x(), geometryEndPos.y(), 4);
1316 // resolution of drawn circle depending of the zoom (To improve smothness)
1317 GLHelper::drawFilledCircleDetailed(d, endPosRadius);
1318 // pop draw matrix
1320 }
1321}
1322
1323
1324void
1332
1333/****************************************************************************/
@ GLO_TAZ
Traffic Assignment Zones (TAZs)
GUIViewObjectsHandler gViewObjectsHandler
#define TLF(string,...)
Definition MsgHandler.h:306
@ SUMO_TAG_TAZ
a traffic assignment zone
@ SUMO_TAG_STOP
stop for vehicles
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:49
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 drawFilledCircleDetailed(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
GUIGeometry myDemandElementGeometry
demand element geometry (also called "stacked geometry")
void replaceLastParentEdge(const std::string &value)
replace the last parent edge
void replaceDemandElementParent(const std::vector< SumoXMLTag > tags, const std::string &value, const int parentIndex)
replace demand element parent
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
void replacePlanParent(const std::string &newParentID)
replace plan parent
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
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:234
const GNELane2laneConnection & getLane2laneConnections() const
get Lane2laneConnection struct
Definition GNELane.cpp:678
const GUIGeometry & getLaneGeometry() const
get lane geometry
Definition GNELane.cpp:228
GNEEdge * getParentEdge() const
get parent edge
Definition GNELane.cpp:216
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1449
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition GNENet.cpp:1459
GNEPathManager * getDemandPathManager()
get demand path manager
Definition GNENet.cpp:198
GNEViewNet * getViewNet() const
get view net (used for simplify code)
Definition GNENet.cpp:144
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
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
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.
virtual void drawGL(const GUIVisualizationSettings &s) const =0
Draws the object.
void buildPopUpMenuCommonOptions(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, GUISUMOAbstractView *parent, const SumoXMLTag tag, const bool selected, const bool allowDelete, const bool addSeparator)
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 const std::vector< SumoXMLTag > persons
persons namespace
static const std::vector< SumoXMLTag > containers
containers namespace
Static storage of an output device and its base (abstract) implementation.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute
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:198
bool isCurrentSupermodeDemand() const
@check if current supermode is Demand
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