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
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
147 GUIDesigns::buildFXMenuCommand(ret, ("Cursor position in view: " + toString(getPlanPositionInView().x()) + "," + toString(getPlanPositionInView().y())).c_str(), nullptr, nullptr, 0);
148 return ret;
149}
150
151
152GNELane*
154 // get tag property
155 const auto tagProperty = myPlanElement->getTagProperty();
156 // get vclass
157 auto vClass = myPlanElement->getVClass();
158 // continue depending of parents
159 if (tagProperty->planRoute()) {
160 // route
161 return myPlanElement->getParentDemandElements().at(1)->getParentEdges().front()->getLaneByAllowedVClass(vClass);
162 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planFromEdge() || tagProperty->planEdge()) {
163 // edges
164 return myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
165 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace() || tagProperty->planToStoppingPlace()) {
166 // additional
167 return myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
168 } else {
169 // in other cases (TAZ, junctions, etc.) return null
170 return nullptr;
171 }
172}
173
174
175GNELane*
177 // get tag property
178 const auto tagProperty = myPlanElement->getTagProperty();
179 // get vclass
180 auto vClass = myPlanElement->getVClass();
181 // check parents
182 if (tagProperty->planRoute()) {
183 // route
184 return myPlanElement->getParentDemandElements().at(1)->getParentEdges().back()->getLaneByAllowedVClass(vClass);
185 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planToEdge() || tagProperty->planEdge()) {
186 // edges
187 return myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
188 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace() || tagProperty->planToStoppingPlace()) {
189 // additional
190 return myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getParentEdge()->getLaneByAllowedVClass(vClass);
191 } else {
192 // in other cases (TAZ, junctions, etc.) return null
193 return nullptr;
194 }
195}
196
197
198void
200 // get tag property
201 const auto tagProperty = myPlanElement->getTagProperty();
202 // get vClass
203 auto vClass = myPlanElement->getVClass();
204 // get path manager
205 auto pathManager = myPlanElement->getNet()->getDemandPathManager();
206 // continue depending of parents
207 if (tagProperty->planRoute()) {
208 // calculate consecutive path using route edges
209 pathManager->calculateConsecutivePathEdges(myPlanElement, vClass, myPlanElement->getParentDemandElements().at(1)->getParentEdges());
210 } else if (tagProperty->planConsecutiveEdges()) {
211 // calculate consecutive path using edges
212 pathManager->calculateConsecutivePathEdges(myPlanElement, vClass, myPlanElement->getParentEdges());
214 // calculate path using junctions
215 pathManager->calculatePath(myPlanElement, vClass, myPlanElement->getParentJunctions().front(), myPlanElement->getParentJunctions().back());
217 // declare last lane
218 GNELane* lastLane = nullptr;
220 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().back();
222 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front();
223 } else if (myPlanElement->myTagProperty->planToEdge()) {
224 lastLane = myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
225 }
226 // calculate path
227 if (lastLane) {
228 pathManager->calculatePath(myPlanElement, vClass, myPlanElement->getParentJunctions().front(), lastLane);
229 }
231 // declare first lane
232 GNELane* firstLane = nullptr;
234 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().back();
236 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
238 firstLane = myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
239 }
240 // calculate path
241 if (firstLane) {
242 pathManager->calculatePath(myPlanElement, vClass, firstLane, myPlanElement->getParentJunctions().back());
243 }
244 } else {
245 // declare first edge
246 GNELane* firstLane = nullptr;
248 firstLane = myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
250 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().back();
252 firstLane = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front();
253 }
254 // declare last lane
255 GNELane* lastLane = nullptr;
257 lastLane = myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
259 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().back();
261 lastLane = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front();
262 }
263 if (firstLane && lastLane) {
264 pathManager->calculatePath(myPlanElement, vClass, firstLane, lastLane);
265 } else if (firstLane) {
266 pathManager->calculateConsecutivePathLanes(myPlanElement, {firstLane});
267 } else if (lastLane) {
268 pathManager->calculateConsecutivePathLanes(myPlanElement, {lastLane});
269 }
270 }
271 // update geometry
273}
274
275
276void
278 // get tag property
279 const auto tagProperty = myPlanElement->getTagProperty();
280 // check if plan start or end in a TAZ (becase in this case has to be inserted in RTREE
281 if (tagProperty->planFromTAZ() || tagProperty->planToTAZ()) {
282 // declare first and last positions
283 Position firstPos = Position::INVALID;
284 Position lastPos = Position::INVALID;
285 // set first position
286 if (tagProperty->planFromEdge()) {
287 // from junction
288 firstPos = myPlanElement->getFirstPathLane()->getLaneShape().back();
289 } else if (tagProperty->planFromJunction()) {
290 // from junction
291 firstPos = myPlanElement->getParentJunctions().front()->getPositionInView();
292 } else if (tagProperty->planFromStoppingPlace()) {
293 // end of stoppingPlace lane shape
294 firstPos = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLaneShape().back();
295 } else if (tagProperty->planFromTAZ()) {
296 // from TAZ
297 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
298 firstPos = myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
299 } else {
300 firstPos = myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
301 }
302 }
303 // set last position
304 if (tagProperty->planToEdge()) {
305 // from junction
306 lastPos = myPlanElement->getLastPathLane()->getLaneShape().back();
307 } else if (tagProperty->planToJunction()) {
308 // from junction
309 lastPos = myPlanElement->getParentJunctions().back()->getPositionInView();
310 } else if (tagProperty->planToStoppingPlace()) {
311 // end of stoppingPlace lane shape
312 lastPos = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLaneShape().front();
313 } else if (tagProperty->planToTAZ()) {
314 // from TAZ
315 if (myPlanElement->getParentTAZs().back()->getAttribute(SUMO_ATTR_CENTER).empty()) {
316 lastPos = myPlanElement->getParentTAZs().back()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
317 } else {
318 lastPos = myPlanElement->getParentTAZs().back()->getAttributePosition(SUMO_ATTR_CENTER);
319 }
320 }
321 // use both position to calculate a line
322 if ((firstPos != Position::INVALID) && (lastPos != Position::INVALID)) {
324 } else {
326 }
327 }
328 // update centering boundary
330 // update child demand elements
331 for (const auto& demandElement : myPlanElement->getChildDemandElements()) {
332 demandElement->updateGeometry();
333 }
334}
335
336
341
342
343void
345 // remove additional from grid
346 if (myPlanBoundary.isInitialised() && updateGrid) {
348 }
350 // if this element is over route, add their boundary
351 if (myPlanElement->getParentDemandElements().size() > 1) {
352 myPlanBoundary.add(myPlanElement->getParentDemandElements().at(1)->getCenteringBoundary());
353 }
354 // add the combination of all parent edges's boundaries
355 for (const auto& edge : myPlanElement->getParentEdges()) {
356 myPlanBoundary.add(edge->getCenteringBoundary());
357 }
358 // add the combination of all parent edges's boundaries
359 for (const auto& junction : myPlanElement->getParentJunctions()) {
360 myPlanBoundary.add(junction->getCenteringBoundary());
361 }
362 // add the combination of all parent additional's boundaries (stoppingPlaces and TAZs)
363 for (const auto& additional : myPlanElement->getParentAdditionals()) {
364 if (additional->getTagProperty()->getTag() == SUMO_TAG_TAZ) {
365 if (additional->getAttribute(SUMO_ATTR_CENTER).empty()) {
366 myPlanBoundary.add(additional->getAttributePosition(GNE_ATTR_TAZ_CENTROID));
367 } else {
368 myPlanBoundary.add(additional->getAttributePosition(SUMO_ATTR_CENTER));
369 }
370 } else {
371 myPlanBoundary.add(additional->getCenteringBoundary());
372 }
373 }
374 // check if is valid
377 }
378 // add additional into RTREE again
379 if (myPlanBoundary.isInitialised() && updateGrid) {
381 }
382}
383
384
387 // get tag property
388 const auto tagProperty = myPlanElement->getTagProperty();
389 // continue depending of parents
390 if (tagProperty->planRoute()) {
391 // route
392 return myPlanElement->getParentDemandElements().at(1)->getPositionInView();
393 } else if (tagProperty->isPlanStop()) {
395 } else if (tagProperty->planFromEdge() || tagProperty->planConsecutiveEdges() || tagProperty->planEdge()) {
396 // first edge
397 return myPlanElement->getParentEdges().front()->getPositionInView();
398 } else if (tagProperty->planFromJunction()) {
399 // first junction
400 return myPlanElement->getParentJunctions().front()->getPositionInView();
401 } else if (tagProperty->planStoppingPlace() || tagProperty->planFromStoppingPlace()) {
402 // first additional
403 return myPlanElement->getParentStoppingPlaces().front()->getPositionInView();
404 } else if (tagProperty->planFromTAZ()) {
405 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
406 return myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
407 } else {
408 return myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
409 }
410 } else {
411 // return parent position
412 return Position(0, 0);
413 }
414}
415
416
417std::string
419 // continue depending of key
420 switch (key) {
421 // Common plan attributes
422 case SUMO_ATTR_ID:
423 case GNE_ATTR_PARENT:
424 return myPlanElement->getParentDemandElements().at(0)->getID();
426 if (myDepartPosition < 0) {
427 return "";
428 } else {
430 }
431 case SUMO_ATTR_ENDPOS:
433 if (myArrivalPosition < 0) {
434 return "";
435 } else {
437 }
438 // route
439 case SUMO_ATTR_ROUTE:
440 return myPlanElement->getParentDemandElements().at(1)->getID();
441 // edges
442 case SUMO_ATTR_EDGE:
443 case SUMO_ATTR_EDGES:
445 // stoppingPlaces (single and back)
451 return myPlanElement->getParentStoppingPlaces().back()->getID();
452 // from elements
453 case SUMO_ATTR_FROM:
454 return myPlanElement->getParentEdges().front()->getID();
456 return myPlanElement->getParentJunctions().front()->getID();
458 return myPlanElement->getParentTAZs().front()->getID();
464 return myPlanElement->getParentStoppingPlaces().front()->getID();
465 // to elements
466 case SUMO_ATTR_TO:
467 return myPlanElement->getParentEdges().back()->getID();
469 return myPlanElement->getParentJunctions().back()->getID();
470 case SUMO_ATTR_TO_TAZ:
471 return myPlanElement->getParentTAZs().back()->getID();
472 default:
474 }
475}
476
477
478double
480 // get tag property
481 const auto tagProperty = myPlanElement->getTagProperty();
482 // declare plan parent
483 const auto planParent = myPlanElement->getParentDemandElements().at(0);
484 // continue depending of key
485 switch (key) {
487 if (tagProperty->planStoppingPlace()) {
488 // use startpos of stoppingPlace parent (stops)
489 const auto factor = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLengthGeometryFactor();
490 return myPlanElement->getParentStoppingPlaces().front()->getAttributeDouble(SUMO_ATTR_STARTPOS) * factor;
491 } else if (tagProperty->planFromStoppingPlace()) {
492 // use end position of stoppingPlace parent (for plans that starts in stoppingPlaces)
493 const auto factor = myPlanElement->getParentStoppingPlaces().front()->getParentLanes().front()->getLengthGeometryFactor();
494 return myPlanElement->getParentStoppingPlaces().front()->getAttributeDouble(SUMO_ATTR_ENDPOS) * factor;
495 } else if (tagProperty->planFromTAZ()) {
496 return 0;
497 } else if (tagProperty->planFromJunction()) {
498 return -1;
499 } else {
500 // get previous plan element
501 const auto previousPlan = planParent->getPreviousChildDemandElement(myPlanElement);
502 // continue depending of previous plan
503 if (previousPlan) {
504 // use previous plan end position (normally the arrival position)
505 const auto posOverLane = previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
506 // if posOverLane is -1, means that previousPlan ends in the end of lane.
507 if (posOverLane == -1) {
508 // INVALID_DOUBLE will put the startPositio at the end of line
509 return INVALID_DOUBLE;
510 } else {
511 return previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
512 }
513 } else {
514 // use depart position defined in parent (person or container)
515 return planParent->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
516 }
517 }
518 }
520 // continue depending of parents
521 if (tagProperty->planStoppingPlace()) {
522 // use end position of the stoppingPlace (stops)
523 const auto factor = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLengthGeometryFactor();
524 return myPlanElement->getParentStoppingPlaces().back()->getAttributeDouble(SUMO_ATTR_ENDPOS) * factor;
525 } else if (tagProperty->planToStoppingPlace()) {
526 // use start position of the stoppingPlace (for elements that ends in stoppingPlaces)
527 const auto factor = myPlanElement->getParentStoppingPlaces().back()->getParentLanes().front()->getLengthGeometryFactor();
528 return myPlanElement->getParentStoppingPlaces().back()->getAttributeDouble(SUMO_ATTR_STARTPOS) * factor;
529 } else if (tagProperty->planToJunction() || tagProperty->planToTAZ()) {
530 // junctions and TAZs return always -1
531 return -1;
532 } else if ((tagProperty->isPlanStopPerson() || tagProperty->isPlanStopContainer()) && tagProperty->planEdge()) {
533 // elements that ends in stop always uses the end (arrival) position of the stops over edges
534 return myArrivalPosition;
535 } else {
536 // check if next plan is a stop over edge
537 const auto nextPlan = planParent->getNextChildDemandElement(myPlanElement);
538 if (nextPlan && (nextPlan->getTagProperty()->isPlanStopPerson() ||
539 nextPlan->getTagProperty()->isPlanStopContainer()) &&
540 nextPlan->getTagProperty()->planEdge()) {
541 // if next plan is an stop over stoppingPlaces, use ends of stoppingPlace
542 return nextPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
543 } else {
544 // use arrival position
545 return myArrivalPosition;
546 }
547 }
549 return myDepartPosition;
550 case SUMO_ATTR_ENDPOS:
552 return myArrivalPosition;
553 default:
554 throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have a doubleattribute of type '" + toString(key) + "'");
555 }
556}
557
558
561 // get tag property
562 const auto tagProperty = myPlanElement->getTagProperty();
563 // declare plan parent
564 const auto planParent = myPlanElement->getParentDemandElements().at(0);
565 // continue depending of key
566 switch (key) {
568 // get previous plan
569 const auto previousPlan = planParent->getPreviousChildDemandElement(myPlanElement);
570 if (previousPlan && previousPlan->getTagProperty()->isPlanStop() && previousPlan->getTagProperty()->planStoppingPlace()) {
571 return previousPlan->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().back();
572 }
573 // continue depending of from element
574 if (tagProperty->planStoppingPlace()) {
575 return myPlanElement->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().front();
576 } else if (tagProperty->planFromStoppingPlace()) {
577 return myPlanElement->getParentStoppingPlaces().front()->getAdditionalGeometry().getShape().back();
578 } else if (tagProperty->planFromJunction()) {
579 // junction view position
580 return myPlanElement->getParentJunctions().front()->getPositionInView();
581 } else if (tagProperty->planFromTAZ()) {
582 if (myPlanElement->getParentTAZs().front()->getAttribute(SUMO_ATTR_CENTER).empty()) {
583 return myPlanElement->getParentTAZs().front()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
584 } else {
585 return myPlanElement->getParentTAZs().front()->getAttributePosition(SUMO_ATTR_CENTER);
586 }
587 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planRoute() || tagProperty->planFromEdge()) {
588 // get first path lane
589 const auto firstLane = myPlanElement->getFirstPathLane();
590 // check if first lane exists
591 if (firstLane == nullptr) {
592 return Position::INVALID;
593 }
594 // declare lane position
595 double lanePosition = 0;
596 // continue depending of conditions
597 if (previousPlan) {
598 // use previous geometry end position
599 lanePosition = previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
600 } else {
601 // use departPos defined in planParent
602 lanePosition = planParent->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
603 }
604 // get lane shape
605 const auto& laneShape = firstLane->getLaneShape();
606 // continue depending of lane position
607 if (lanePosition <= 0) {
608 return laneShape.front();
609 } else if (lanePosition >= laneShape.length2D()) {
610 return laneShape.back();
611 } else {
612 return laneShape.positionAtOffset2D(lanePosition);
613 }
614 } else {
615 return Position::INVALID;
616 }
617 }
619 // check parents
620 if (tagProperty->planToJunction()) {
621 // junctions
622 return myPlanElement->getParentJunctions().back()->getPositionInView();
623 } else if (tagProperty->planStoppingPlace()) {
624 // get additional back shape (stops)
625 return myPlanElement->getParentStoppingPlaces().back()->getAdditionalGeometry().getShape().back();
626 } else if (tagProperty->planToStoppingPlace()) {
627 // get additional front shape
628 return myPlanElement->getParentStoppingPlaces().back()->getAdditionalGeometry().getShape().front();
629 } else if (tagProperty->planToTAZ()) {
630 // taz
631 if (myPlanElement->getParentTAZs().back()->getAttribute(SUMO_ATTR_CENTER).empty()) {
632 return myPlanElement->getParentTAZs().back()->getAttributePosition(GNE_ATTR_TAZ_CENTROID);
633 } else {
634 return myPlanElement->getParentTAZs().back()->getAttributePosition(SUMO_ATTR_CENTER);
635 }
636 } else if (tagProperty->planConsecutiveEdges() || tagProperty->planRoute() || tagProperty->planFromEdge()) {
637 // get next plan
638 const auto nextPlan = planParent->getNextChildDemandElement(myPlanElement);
639 // if next plan exist, then use their first lane (needed to maintain connectivity with rides)
640 const auto lastLane = nextPlan ? nextPlan->getFirstPathLane() : myPlanElement->getLastPathLane();
641 // check if last lane exists
642 if (lastLane == nullptr) {
643 return Position::INVALID;
644 }
645 // get lane shape
646 const auto& laneShape = lastLane->getLaneShape();
647 // continue depending of arrival position
648 if (nextPlan && nextPlan->getTagProperty()->isPlanStop()) {
649 return nextPlan->getAttributePosition(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
650 } else if (myArrivalPosition == 0) {
651 return laneShape.front();
652 } else if ((myArrivalPosition == -1) || (myArrivalPosition >= laneShape.length2D())) {
653 return laneShape.back();
654 } else {
655 return laneShape.positionAtOffset2D(myArrivalPosition);
656 }
657 } else {
658 return Position::INVALID;
659 }
660 }
661 default:
662 throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have a position attribute of type '" + toString(key) + "'");
663 }
664}
665
666
667void
668GNEDemandElementPlan::setPlanAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
669 // continue depending of key
670 switch (key) {
671 // common attributes
674 case SUMO_ATTR_ENDPOS:
675 case GNE_ATTR_PARENT:
677 break;
678 default:
679 myPlanElement->setCommonAttribute(key, value, undoList);
680 break;
681 }
682}
683
684
685bool
686GNEDemandElementPlan::isPlanValid(SumoXMLAttr key, const std::string& value) {
687 // continue depending of key
688 switch (key) {
689 // common attributes
690 case GNE_ATTR_PARENT:
691 return false;
694 if (value.empty()) {
695 return true;
696 } else if (GNEAttributeCarrier::canParse<double>(value)) {
697 return GNEAttributeCarrier::parse<double>(value) >= 0;
698 } else {
699 return false;
700 }
701 case SUMO_ATTR_ENDPOS:
702 return GNEAttributeCarrier::canParse<double>(value);
703 default:
704 return myPlanElement->isCommonAttributeValid(key, value);
705 }
706}
707
708
709bool
711 switch (key) {
712 // edges
713 case SUMO_ATTR_EDGES:
714 // edge
715 case SUMO_ATTR_EDGE:
716 // route
717 case SUMO_ATTR_ROUTE:
718 // from
719 case SUMO_ATTR_FROM:
727 // to
728 case SUMO_ATTR_TO:
730 case SUMO_ATTR_TO_TAZ:
736 // depart pos (temporal, probably will be removed)
738 return false;
739 default:
740 return true;
741 }
742}
743
744
745void
747 bool recompute = false;
748 switch (key) {
749 // from-to attributes (needed if we're replacing junction by geometry points and similar operations)
750 case SUMO_ATTR_FROM:
752 recompute = true;
753 break;
754 case SUMO_ATTR_TO:
756 recompute = true;
757 break;
758 // Common plan attributes
759 case GNE_ATTR_PARENT:
760 replacePlanParent(value);
761 break;
763 if (value.empty()) {
764 myDepartPosition = -1;
765 } else {
766 myDepartPosition = GNEAttributeCarrier::parse<double>(value);
767 }
768 recompute = true;
769 break;
770 case SUMO_ATTR_ENDPOS:
772 if (value.empty()) {
774 } else {
775 myArrivalPosition = GNEAttributeCarrier::parse<double>(value);
776 }
777 recompute = true;
778 break;
779 default:
781 break;
782 }
783 // check if compute geometry and path
784 if (recompute && !myPlanElement->isTemplate()) {
787 }
788}
789
790
791std::string
793 // get tag property
794 const auto tagProperty = myPlanElement->getTagProperty();
795 // declare result
796 std::string result;
797 // clear result
798 int index = 0;
799 while (tagProperty->getTagStr().at(index) != ':') {
800 result.push_back(tagProperty->getTagStr().at(index));
801 index++;
802 }
803 result += ": ";
804 // continue depending of attributes
805 if (tagProperty->planConsecutiveEdges()) {
806 // edges
807 return result + myPlanElement->getParentEdges().front()->getID() + " ... " + myPlanElement->getParentEdges().back()->getID();
808 } else if (tagProperty->planRoute()) {
809 // route
810 return result + myPlanElement->getParentDemandElements().at(1)->getID();
811 } else if (tagProperty->planEdge()) {
812 // edge
813 return result + myPlanElement->getParentEdges().front()->getID();
814 } else if (tagProperty->planStoppingPlace()) {
815 // stoppingPlace
816 return myPlanElement->getParentStoppingPlaces().front()->getID();
817 } else {
818 // stoppingPlace
819 if (tagProperty->planFromStoppingPlace()) {
820 result += myPlanElement->getParentStoppingPlaces().front()->getID();
821 }
822 // TAZ
823 if (tagProperty->planFromTAZ()) {
824 result += myPlanElement->getParentTAZs().front()->getID();
825 }
826 // junction
827 if (tagProperty->planFromJunction()) {
828 result += myPlanElement->getParentJunctions().front()->getID();
829 }
830 // edge
831 if (tagProperty->planFromEdge()) {
832 result += myPlanElement->getParentEdges().front()->getID();
833 }
834 // arrow
835 result += " -> ";
836 // stoppingPlace
837 if (tagProperty->planToStoppingPlace()) {
838 result += myPlanElement->getParentStoppingPlaces().back()->getID();
839 }
840 // TAZ
841 if (tagProperty->planToTAZ()) {
842 result += myPlanElement->getParentTAZs().back()->getID();
843 }
844 // junction
845 if (tagProperty->planToJunction()) {
846 result += myPlanElement->getParentJunctions().back()->getID();
847 }
848 // edge
849 if (tagProperty->planToEdge()) {
850 result += myPlanElement->getParentEdges().back()->getID();
851 }
852 return result;
853 }
854}
855
856
857bool
859 const auto viewNet = myPlanElement->getNet()->getViewNet();
860 const auto& inspectedElements = viewNet->getInspectedElements();
861 // check conditions
862 if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
863 viewNet->getNetworkViewOptions().showDemandElements() &&
864 viewNet->getDemandViewOptions().showAllPersonPlans()) {
865 // show all person plans in network mode
866 return true;
867 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
868 viewNet->getDemandViewOptions().showAllPersonPlans()) {
869 // show all person plans
870 return true;
871 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() && myPlanElement->isAttributeCarrierSelected()) {
872 // show selected
873 return true;
874 } else if (inspectedElements.isACInspected(myPlanElement->getParentDemandElements().front())) {
875 // person parent is inspected
876 return true;
877 } else if (viewNet->getDemandViewOptions().getLockedPerson() == myPlanElement->getParentDemandElements().front()) {
878 // person parent is locked
879 return true;
880 } else {
881 // check if parent
882 if (inspectedElements.getFirstAC() && inspectedElements.getFirstAC()->getTagProperty()->isPlanPerson() &&
883 (inspectedElements.getFirstAC()->getAttribute(GNE_ATTR_PARENT) == myPlanElement->getAttribute(GNE_ATTR_PARENT))) {
884 // common person parent
885 return true;
886 } else {
887 // all conditions are false
888 return false;
889 }
890 }
891}
892
893
894bool
896 const auto viewNet = myPlanElement->getNet()->getViewNet();
897 const auto& inspectedElements = viewNet->getInspectedElements();
898 // check conditions
899 if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
900 viewNet->getNetworkViewOptions().showDemandElements() &&
901 viewNet->getDemandViewOptions().showAllContainerPlans()) {
902 // show all container plans in network mode
903 return true;
904 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
905 viewNet->getDemandViewOptions().showAllContainerPlans()) {
906 // show all container plans
907 return true;
908 } else if (viewNet->getEditModes().isCurrentSupermodeDemand() && myPlanElement->isAttributeCarrierSelected()) {
909 // show selected
910 return true;
911 } else if (inspectedElements.isACInspected(myPlanElement->getParentDemandElements().front())) {
912 // container parent is inspected
913 return true;
914 } else if (viewNet->getDemandViewOptions().getLockedContainer() == myPlanElement->getParentDemandElements().front()) {
915 // container parent is locked
916 return true;
917 } else {
918 // check if parent is inspected
919 if (inspectedElements.getFirstAC() && inspectedElements.getFirstAC()->getTagProperty()->isPlanContainer() &&
920 (inspectedElements.getFirstAC()->getAttribute(GNE_ATTR_PARENT) == myPlanElement->getAttribute(GNE_ATTR_PARENT))) {
921 // common container parent
922 return true;
923 } else {
924 // all conditions are false
925 return false;
926 }
927 }
928}
929
930
931void
932GNEDemandElementPlan::drawPlanGL(const bool drawPlan, const GUIVisualizationSettings& s, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
933 const auto viewNet = myPlanElement->getNet()->getViewNet();
934 const auto& inspectedElements = viewNet->getInspectedElements();
935 // get plan parent
936 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
937 // get tag property
938 const auto tagProperty = myPlanElement->getTagProperty();
939 // get plan geometry
940 auto& planGeometry = myPlanElement->myDemandElementGeometry;
941 // draw relations between TAZs
942 if (drawPlan && (planGeometry.getShape().size() > 0)) {
943 // draw boundary
944 if (s.drawBoundaries) {
946 }
947 // get detail level
948 const auto d = s.getDetailLevel(1);
949 // check if draw with double width
950 const bool drawHalfWidth = ((inspectedElements.getFirstAC() != myPlanElement) && (inspectedElements.getFirstAC() != planParent) && !gViewObjectsHandler.isObjectSelected(myPlanElement));
951 // calculate path width
952 double pathWidth = s.widthSettings.walkWidth;
953 if (tagProperty->isPlanRide()) {
954 pathWidth = s.widthSettings.rideWidth;
955 } else if (tagProperty->isPlanPersonTrip()) {
956 pathWidth = s.widthSettings.personTripWidth;
957 }
958 // draw geometry only if we'rent in drawForObjectUnderCursor mode
959 if ((tagProperty->isPlanPerson() && s.checkDrawPerson(d, myPlanElement->isAttributeCarrierSelected())) ||
960 (tagProperty->isPlanContainer() && s.checkDrawContainer(d, myPlanElement->isAttributeCarrierSelected()))) {
961 // push matrix
963 // translate to front
965 // set color
966 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
967 // draw line
968 GUIGeometry::drawGeometry(d, planGeometry, pathWidth * (drawHalfWidth ? 1 : 2));
969 if (drawHalfWidth) {
970 GLHelper::drawTriangleAtEnd(planGeometry.getShape().front(), planGeometry.getShape().back(), 0.5, 0.5, 0.5);
971 } else {
972 GLHelper::drawTriangleAtEnd(planGeometry.getShape().front(), planGeometry.getShape().back(), 1, 1, 1);
973 }
974 // pop matrix
976 // draw dotted contour
978 }
979 // calculate contour and draw dotted geometry
980 myPlanContour.calculateContourExtrudedShape(s, d, myPlanElement, planGeometry.getShape(), myPlanElement->getType(), pathWidth * 2,
981 1, true, true, 0, nullptr, nullptr);
982 // calculate contour for end
983 myPlanContourEnd.calculateContourCircleShape(s, d, myPlanElement, planGeometry.getShape().back(), 1, myPlanElement->getType(), 1, nullptr);
984 }
985 // check if draw plan parent
986 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
987 planParent->drawGL(s);
988 }
989}
990
991
992void
994 const double offsetFront, const double planWidth, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
995 const auto viewNet = myPlanElement->getNet()->getViewNet();
996 const auto& inspectedElements = viewNet->getInspectedElements();
997 // get tag property
998 const auto tagProperty = myPlanElement->getTagProperty();
999 // get plan parent
1000 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1001 // check if draw plan element can be drawn
1002 if (drawPlan && segment->getLane() && myPlanElement->getNet()->getDemandPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment->getLane(), tagProperty->getTag(), true)) {
1003 // draw boundary
1004 if (tagProperty->isPlacedInRTree() && s.drawBoundaries) {
1006 }
1007 // get detail level
1008 const auto d = s.getDetailLevel(1);
1009 // declare path geometry
1010 GUIGeometry planGeometry;
1011 // update pathGeometry depending of first and last segment
1012 if (segment->isFirstSegment() && segment->isLastSegment()) {
1013 if (tagProperty->planFromTAZ()) {
1014 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1019 } else if (tagProperty->planToTAZ()) {
1020 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1025 } else {
1026 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1031 }
1032 } else if (segment->isFirstSegment()) {
1033 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1036 -1,
1038 } else if (segment->isLastSegment()) {
1039 planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1040 -1,
1044 } else {
1045 planGeometry = segment->getLane()->getLaneGeometry();
1046 }
1047 // calculate path width double
1048 const double drawingWidth = s.addSize.getExaggeration(s, segment->getLane()) * planWidth * 2;
1049 // check if draw with double width
1050 const bool drawHalfWidth = ((inspectedElements.getFirstAC() != myPlanElement) && (inspectedElements.getFirstAC() != planParent) && !gViewObjectsHandler.isObjectSelected(myPlanElement));
1051 // get end pos radius
1052 const double endPosRadius = getEndPosRadius(s, segment, drawHalfWidth);
1053 // draw geometry only if we'rent in drawForObjectUnderCursor mode
1054 if ((tagProperty->isPlanPerson() && s.checkDrawPerson(d, myPlanElement->isAttributeCarrierSelected())) ||
1055 (tagProperty->isPlanContainer() && s.checkDrawContainer(d, myPlanElement->isAttributeCarrierSelected()))) {
1056 // Add a draw matrix
1058 // Start with the drawing of the area traslating matrix to origin
1060 // Set color
1061 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1062 // draw geometry depending of drawWithDoubleWidth
1063 GUIGeometry::drawGeometry(d, planGeometry, drawingWidth * (drawHalfWidth ? 0.5 : 1));
1064 // draw red arrows
1065 drawFromArrow(s, segment->getLane(), segment);
1066 drawToArrow(s, segment->getLane(), segment);
1067 // Pop last matrix
1069 // Draw name if isn't being drawn for selecting
1071 // draw dotted contour
1073 // draw TAZ Center dotted contour
1075 }
1076 // declare trim geometry to draw
1077 const auto& shape = (segment->isFirstSegment() || segment->isLastSegment()) ? planGeometry.getShape() : segment->getLane()->getLaneShape();
1078 // calculate contour and draw dotted geometry (always with double width)
1079 if (segment->isFirstSegment()) {
1080 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, true, false,
1081 0, segment, segment->getLane()->getParentEdge());
1082 } else if (segment->isLastSegment()) {
1083 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, false, false,
1084 0, segment, segment->getLane()->getParentEdge());
1085 // calculate contour for end
1087 myPlanElement->getType(), 1, segment->getLane());
1088 } else {
1089 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), drawingWidth, 1, false, false, 0,
1090 segment, segment->getLane()->getParentEdge());
1091 }
1092 // check if add this path element to redraw buffer
1095 }
1096 }
1097 // check if draw plan parent
1098 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1099 planParent->drawGL(s);
1100 }
1101}
1102
1103
1104void
1106 const double offsetFront, const double planWidth, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
1107 const auto viewNet = myPlanElement->getNet()->getViewNet();
1108 const auto& inspectedElements = viewNet->getInspectedElements();
1109 // get tag property
1110 const auto tagProperty = myPlanElement->getTagProperty();
1111 // get plan parent
1112 const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1113 // check if draw plan elements can be drawn
1114 if (drawPlan && myPlanElement->getNet()->getDemandPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment, tagProperty->getTag(), false)) {
1115 // draw boundary
1116 if (tagProperty->isPlacedInRTree() && s.drawBoundaries) {
1118 }
1119 // get detail level
1120 const auto d = s.getDetailLevel(1);
1121 // calculate path width double
1122 const double pathWidthDouble = s.addSize.getExaggeration(s, segment->getLane()) * planWidth * 2;
1123 // check if draw with double width
1124 const bool drawWithDoubleWidth = ((inspectedElements.getFirstAC() == myPlanElement) || (inspectedElements.getFirstAC() == planParent) || gViewObjectsHandler.isObjectSelected(myPlanElement));
1125 // draw geometry only if we'rent in drawForObjectUnderCursor mode
1127 // push a draw matrix
1129 // Start with the drawing of the area traslating matrix to origin
1131 // Set plan color
1132 GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1133 // check if draw lane2lane connection or a red line
1134 if (segment->getPreviousLane() && segment->getNextLane()) {
1135 if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
1136 // obtain lane2lane geometry
1137 const GUIGeometry& lane2laneGeometry = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane());
1138 // draw lane2lane
1139 GUIGeometry::drawGeometry(d, lane2laneGeometry, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1140 } else {
1141 // Set invalid plan color
1143 // draw line between end of first shape and first position of second shape
1144 GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), segment->getNextLane()->getLaneShape().front()}, (0.5 * pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5)));
1145 }
1146 } else if (segment->getPreviousLane()) {
1147 // draw line between center of junction and last lane shape
1148 GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), myPlanElement->getParentJunctions().back()->getPositionInView()}, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1149 } else if (segment->getNextLane()) {
1150 // draw line between center of junction and first lane shape
1151 GLHelper::drawBoxLines({myPlanElement->getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()}, pathWidthDouble * (drawWithDoubleWidth ? 1 : 0.5));
1152 }
1153 // Pop last matrix
1155 // draw lock icon
1157 // draw dotted contour
1159 }
1160 // check if shape dotted contour has to be drawn
1161 if (segment->getPreviousLane() && segment->getNextLane()) {
1162 if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
1163 // get shape
1164 const auto& shape = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()).getShape();
1165 // calculate contour and draw dotted geometry (always with double width)
1166 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, myPlanElement->getType(), pathWidthDouble, 1, false, false, 0, segment, segment->getJunction());
1167 }
1168 } else if (segment->getPreviousLane()) {
1169 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, {segment->getPreviousLane()->getLaneShape().back(), myPlanElement->getParentJunctions().back()->getPositionInView()},
1170 myPlanElement->getType(), pathWidthDouble, 1, false, true, 0, segment, segment->getJunction());
1171 } else if (segment->getNextLane()) {
1172 segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, {myPlanElement->getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()},
1173 myPlanElement->getType(), pathWidthDouble, 1, true, false, 0, segment, segment->getJunction());
1174 }
1175 // check if add this path element to redraw buffer
1178 }
1179 }
1180 // check if draw plan parent
1181 if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1182 planParent->drawGL(s);
1183 }
1184}
1185
1186
1189 // get previous plan
1190 const auto previousPlan = myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement);
1191 if (previousPlan) {
1192 // get previous lane
1193 const auto previousLastLane = previousPlan->getLastPathLane();
1194 // get first lane
1195 const auto firstLane = myPlanElement->getFirstPathLane();
1196 // compare edges
1197 if (previousLastLane && firstLane && (previousLastLane->getParentEdge() != firstLane->getParentEdge())) {
1199 }
1200 // in the future, check more elements
1201 }
1202 // get next child
1203 const auto nextPlan = myPlanElement->getParentDemandElements().at(0)->getNextChildDemandElement(myPlanElement);
1204 if (nextPlan) {
1205 // get previous lane
1206 const auto nextFirstLane = nextPlan->getFirstPathLane();
1207 // get first lane
1208 const auto lastLane = myPlanElement->getLastPathLane();
1209 // compare edges
1210 if (nextFirstLane && lastLane && (nextFirstLane->getParentEdge() != lastLane->getParentEdge())) {
1212 }
1213 // in the future, check more elements
1214 }
1215 // all ok, then return true
1217}
1218
1219
1220std::string
1222 // get previous plan
1223 const auto previousPlan = myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement);
1224 if (previousPlan) {
1225 // get previous lane
1226 const auto previousLastLane = previousPlan->getLastPathLane();
1227 // get first lane
1228 const auto firstLane = myPlanElement->getLastPathLane();
1229 // compare edges
1230 if (previousLastLane && firstLane && (previousLastLane->getParentEdge() != firstLane->getParentEdge())) {
1231 return TLF("Edge '%' is not consecutive with edge '%'", previousLastLane->getParentEdge()->getID(), firstLane->getParentEdge()->getID());
1232 }
1233 // in the future, check more elements
1234 }
1235 // get next child
1236 const auto nextPlan = myPlanElement->getParentDemandElements().at(0)->getNextChildDemandElement(myPlanElement);
1237 if (nextPlan) {
1238 // get previous lane
1239 const auto nextFirstLane = nextPlan->getFirstPathLane();
1240 // get first lane
1241 const auto lastLane = myPlanElement->getLastPathLane();
1242 // compare edges
1243 if (nextFirstLane && lastLane && (nextFirstLane->getParentEdge() != lastLane->getParentEdge())) {
1244 return TLF("Edge '%' is not consecutive with edge '%'", nextFirstLane->getParentEdge()->getID(), lastLane->getParentEdge()->getID());
1245 }
1246 // in the future, check more elements
1247 }
1248 // undefined problem
1249 return "undefined problem";
1250}
1251
1252
1253double
1254GNEDemandElementPlan::getEndPosRadius(const GUIVisualizationSettings& s, const GNESegment* segment, const bool drawHalfWidth) const {
1255 // check if myPlanElement is the last segment
1256 if (segment->isLastSegment()) {
1257 // calculate circle width
1258 const double circleRadius = (drawHalfWidth ? myArrivalPositionDiameter * 0.5 : myArrivalPositionDiameter);
1259 return circleRadius * MIN2((double)0.5, s.laneWidthExaggeration);
1260 } else {
1261 return -1;
1262 }
1263}
1264
1265
1266void
1268 // draw ifcurrent amd next segment is placed over lanes
1269 if (segment->getNextLane()) {
1270 // get firstPosition (last position of current lane shape)
1271 const Position from = lane->getLaneShape().back();
1272 // get lastPosition (first position of next lane shape)
1273 const Position to = segment->getNextLane()->getLaneShape().front();
1274 // push draw matrix
1276 // move front
1277 glTranslated(0, 0, 4);
1278 // draw child line
1280 // pop draw matrix
1282 }
1283}
1284
1285
1286void
1288 // draw the line if previos segment and current segment is placed over lanes
1289 if (segment->getPreviousLane()) {
1290 // get firstPosition (last position of current lane shape)
1291 const Position from = lane->getLaneShape().front();
1292 // get lastPosition (first position of next lane shape)
1293 const Position to = segment->getPreviousLane()->getLaneShape().back();
1294 // push draw matrix
1296 // move front
1297 glTranslated(0, 0, 4);
1298 // draw child line
1300 // pop draw matrix
1302 }
1303}
1304
1305
1306void
1308 // check if myPlanElement is the last segment
1309 if (endPosRadius > 0) {
1311 // push draw matrix
1313 // translate to pos and move to
1314 glTranslated(geometryEndPos.x(), geometryEndPos.y(), 4);
1315 // resolution of drawn circle depending of the zoom (To improve smothness)
1316 GLHelper::drawFilledCircleDetailled(d, endPosRadius);
1317 // pop draw matrix
1319 }
1320}
1321
1322
1323void
1331
1332/****************************************************************************/
@ 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: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
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: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
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
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 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 & 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