Eclipse SUMO - Simulation of Urban MObility
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-2024 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 
23 #include <netedit/GNENet.h>
24 #include <netedit/GNEUndoList.h>
25 #include <netedit/GNEViewNet.h>
26 #include <utils/gui/div/GLHelper.h>
28 
29 #include "GNEDemandElementPlan.h"
30 #include "GNERoute.h"
31 
32 // ===========================================================================
33 // static definitions
34 // ===========================================================================
35 
37 
38 // ===========================================================================
39 // GNEDemandElement method definitions
40 // ===========================================================================
41 
42 std::pair<SumoXMLTag, GUIIcon>
43 GNEDemandElementPlan::getWalkTagIcon(const std::vector<GNEEdge*>& consecutiveEdges,
44  const GNEDemandElement* route, const GNEEdge* fromEdge, const GNEEdge* toEdge,
45  const GNEAdditional* fromTAZ, const GNEAdditional* toTAZ, const GNEJunction* fromJunction,
46  const GNEJunction* toJunction, const GNEAdditional* fromBusStop, const GNEAdditional* toBusStop,
47  const GNEAdditional* fromTrainStop, const GNEAdditional* toTrainStop) {
48  // special case for elements with from-to edge
49  if (fromEdge && !toEdge && !fromTAZ && !toTAZ && !fromJunction && !toJunction &&
50  !fromBusStop && !toBusStop && !fromTrainStop && !toTrainStop &&
51  consecutiveEdges.empty() && !route) {
52  return std::make_pair(GNE_TAG_WALK_EDGES, GUIIcon::WALK_EDGES);
53  } else if (consecutiveEdges.size() > 0) {
54  return std::make_pair(GNE_TAG_WALK_EDGES, GUIIcon::WALK_EDGES);
55  } else if (route) {
56  return std::make_pair(GNE_TAG_WALK_ROUTE, GUIIcon::WALK_ROUTE);
57  } else if (fromEdge && toEdge) {
58  return std::make_pair(GNE_TAG_WALK_EDGE_EDGE, GUIIcon::WALK_EDGE);
59  } else if (fromEdge && toTAZ) {
60  return std::make_pair(GNE_TAG_WALK_EDGE_TAZ, GUIIcon::WALK_TAZ);
61  } else if (fromEdge && toJunction) {
62  return std::make_pair(GNE_TAG_WALK_EDGE_JUNCTION, GUIIcon::WALK_JUNCTION);
63  } else if (fromEdge && toBusStop) {
64  return std::make_pair(GNE_TAG_WALK_EDGE_BUSSTOP, GUIIcon::WALK_BUSSTOP);
65  } else if (fromEdge && toTrainStop) {
67  } else if (fromTAZ && toEdge) {
68  return std::make_pair(GNE_TAG_WALK_TAZ_EDGE, GUIIcon::WALK_EDGE);
69  } else if (fromTAZ && toTAZ) {
70  return std::make_pair(GNE_TAG_WALK_TAZ_TAZ, GUIIcon::WALK_TAZ);
71  } else if (fromTAZ && toJunction) {
72  return std::make_pair(GNE_TAG_WALK_TAZ_JUNCTION, GUIIcon::WALK_JUNCTION);
73  } else if (fromTAZ && toBusStop) {
74  return std::make_pair(GNE_TAG_WALK_TAZ_BUSSTOP, GUIIcon::WALK_BUSSTOP);
75  } else if (fromTAZ && toTrainStop) {
77  } else if (fromJunction && toEdge) {
78  return std::make_pair(GNE_TAG_WALK_JUNCTION_EDGE, GUIIcon::WALK_EDGE);
79  } else if (fromJunction && toTAZ) {
80  return std::make_pair(GNE_TAG_WALK_JUNCTION_TAZ, GUIIcon::WALK_TAZ);
81  } else if (fromJunction && toJunction) {
83  } else if (fromJunction && toBusStop) {
85  } else if (fromJunction && toTrainStop) {
87  } else if (fromBusStop && toEdge) {
88  return std::make_pair(GNE_TAG_WALK_BUSSTOP_EDGE, GUIIcon::WALK_EDGE);
89  } else if (fromBusStop && toTAZ) {
90  return std::make_pair(GNE_TAG_WALK_BUSSTOP_TAZ, GUIIcon::WALK_TAZ);
91  } else if (fromBusStop && toJunction) {
93  } else if (fromBusStop && toBusStop) {
95  } else if (fromBusStop && toTrainStop) {
97  } else if (fromTrainStop && toEdge) {
98  return std::make_pair(GNE_TAG_WALK_TRAINSTOP_EDGE, GUIIcon::WALK_EDGE);
99  } else if (fromTrainStop && toTAZ) {
100  return std::make_pair(GNE_TAG_WALK_TRAINSTOP_TAZ, GUIIcon::WALK_TAZ);
101  } else if (fromTrainStop && toJunction) {
103  } else if (fromTrainStop && toBusStop) {
105  } else if (fromTrainStop && toTrainStop) {
107  } else {
108  return std::make_pair(SUMO_TAG_NOTHING, GUIIcon::EMPTY);
109  }
110 }
111 
112 
113 std::pair<SumoXMLTag, GUIIcon>
115  const GNEAdditional* fromTAZ, const GNEAdditional* toTAZ, const GNEJunction* fromJunction,
116  const GNEJunction* toJunction, const GNEAdditional* fromBusStop, const GNEAdditional* toBusStop,
117  const GNEAdditional* fromTrainStop, const GNEAdditional* toTrainStop) {
118  // special case for elements with from-to edge
119  if (fromEdge && !toEdge && !fromTAZ && !toTAZ && !fromJunction && !toJunction &&
120  !fromBusStop && !toBusStop && !fromTrainStop && !toTrainStop) {
122  } else if (fromEdge && toEdge) {
124  } else if (fromEdge && toTAZ) {
126  } else if (fromEdge && toJunction) {
128  } else if (fromEdge && toBusStop) {
130  } else if (fromEdge && toTrainStop) {
132  } else if (fromTAZ && toEdge) {
134  } else if (fromTAZ && toTAZ) {
135  return std::make_pair(GNE_TAG_PERSONTRIP_TAZ_TAZ, GUIIcon::PERSONTRIP_TAZ);
136  } else if (fromTAZ && toJunction) {
138  } else if (fromTAZ && toBusStop) {
140  } else if (fromTAZ && toTrainStop) {
142  } else if (fromJunction && toEdge) {
144  } else if (fromJunction && toTAZ) {
146  } else if (fromJunction && toJunction) {
148  } else if (fromJunction && toBusStop) {
150  } else if (fromJunction && toTrainStop) {
152  } else if (fromBusStop && toEdge) {
154  } else if (fromBusStop && toTAZ) {
156  } else if (fromBusStop && toJunction) {
158  } else if (fromBusStop && toBusStop) {
160  } else if (fromBusStop && toTrainStop) {
162  } else if (fromTrainStop && toEdge) {
164  } else if (fromTrainStop && toTAZ) {
166  } else if (fromTrainStop && toJunction) {
168  } else if (fromTrainStop && toBusStop) {
170  } else if (fromTrainStop && toTrainStop) {
172  } else {
173  return std::make_pair(SUMO_TAG_NOTHING, GUIIcon::EMPTY);
174  }
175 }
176 
177 
178 std::pair<SumoXMLTag, GUIIcon>
179 GNEDemandElementPlan::getRideTagIcon(const GNEEdge* fromEdge, const GNEEdge* toEdge,
180  const GNEAdditional* fromBusStop, const GNEAdditional* toBusStop,
181  const GNEAdditional* fromTrainStop, const GNEAdditional* toTrainStop) {
182  // special case for elements with from-to edge
183  if (fromEdge && !toEdge && fromBusStop && !toBusStop && !fromTrainStop && !toTrainStop) {
184  return std::make_pair(GNE_TAG_RIDE_EDGE_EDGE, GUIIcon::RIDE_EDGE);
185  } else if (fromEdge && toEdge) {
186  return std::make_pair(GNE_TAG_RIDE_EDGE_EDGE, GUIIcon::RIDE_EDGE);
187  } else if (fromEdge && toBusStop) {
188  return std::make_pair(GNE_TAG_RIDE_EDGE_BUSSTOP, GUIIcon::RIDE_BUSSTOP);
189  } else if (fromEdge && toTrainStop) {
191  } else if (fromBusStop && toEdge) {
192  return std::make_pair(GNE_TAG_RIDE_BUSSTOP_EDGE, GUIIcon::RIDE_EDGE);
193  } else if (fromBusStop && toBusStop) {
194  return std::make_pair(GNE_TAG_RIDE_BUSSTOP_BUSSTOP, GUIIcon::RIDE_BUSSTOP);
195  } else if (fromBusStop && toTrainStop) {
197  } else if (fromTrainStop && toEdge) {
198  return std::make_pair(GNE_TAG_RIDE_TRAINSTOP_EDGE, GUIIcon::RIDE_EDGE);
199  } else if (fromTrainStop && toBusStop) {
201  } else if (fromTrainStop && toTrainStop) {
203  } else {
204  return std::make_pair(SUMO_TAG_NOTHING, GUIIcon::EMPTY);
205  }
206 }
207 
208 
209 std::pair<SumoXMLTag, GUIIcon>
211  const GNEAdditional* fromContainerStop, const GNEAdditional* toContainerStop) {
212  // special case for elements with from-to edge
213  if (fromEdge && !toEdge && !fromContainerStop && !toContainerStop) {
215  } else if (fromEdge && toEdge) {
217  } else if (fromEdge && toContainerStop) {
219  } else if (fromContainerStop && toEdge) {
221  } else if (fromContainerStop && toContainerStop) {
223  } else {
224  return std::make_pair(SUMO_TAG_NOTHING, GUIIcon::EMPTY);
225  }
226 }
227 
228 
229 std::pair<SumoXMLTag, GUIIcon>
230 GNEDemandElementPlan::getTranshipTagIcon(const std::vector<GNEEdge*>& consecutiveEdges,
231  const GNEEdge* fromEdge, const GNEEdge* toEdge, const GNEAdditional* fromContainerStop,
232  const GNEAdditional* toContainerStop) {
233  // special case for elements with from-to edge
234  if (fromEdge && !toEdge && !fromContainerStop && !toContainerStop && consecutiveEdges.empty()) {
235  return std::make_pair(GNE_TAG_TRANSHIP_EDGES, GUIIcon::TRANSHIP_EDGES);
236  } else if (consecutiveEdges.size() > 0) {
237  return std::make_pair(GNE_TAG_TRANSHIP_EDGES, GUIIcon::TRANSHIP_EDGES);
238  } else if (fromEdge && toEdge) {
239  return std::make_pair(GNE_TAG_TRANSHIP_EDGE_EDGE, GUIIcon::TRANSHIP_EDGE);
240  } else if (fromEdge && toContainerStop) {
242  } else if (fromContainerStop && toEdge) {
244  } else if (fromContainerStop && toContainerStop) {
246  } else {
247  return std::make_pair(SUMO_TAG_NOTHING, GUIIcon::EMPTY);
248  }
249 }
250 
251 
252 std::pair<SumoXMLTag, GUIIcon>
253 GNEDemandElementPlan::getPersonStopTagIcon(const GNEEdge* edge, const GNEAdditional* busStop, const GNEAdditional* trainStop) {
254  if (edge) {
255  return std::make_pair(GNE_TAG_STOPPERSON_EDGE, GUIIcon::STOPELEMENT);
256  } else if (busStop) {
257  return std::make_pair(GNE_TAG_STOPPERSON_BUSSTOP, GUIIcon::STOPELEMENT);
258  } else if (trainStop) {
259  return std::make_pair(GNE_TAG_STOPPERSON_TRAINSTOP, GUIIcon::STOPELEMENT);
260  } else {
261  return std::make_pair(SUMO_TAG_NOTHING, GUIIcon::EMPTY);
262  }
263 }
264 
265 
266 std::pair<SumoXMLTag, GUIIcon>
268  if (edge) {
269  return std::make_pair(GNE_TAG_STOPCONTAINER_EDGE, GUIIcon::STOPELEMENT);
270  } else if (containerStop) {
272  } else {
273  return std::make_pair(SUMO_TAG_NOTHING, GUIIcon::EMPTY);
274  }
275 }
276 
277 
278 GNEDemandElementPlan::GNEDemandElementPlan(GNEDemandElement* planElement, const double departPosition, const double arrivalPosition) :
279  myDepartPosition(departPosition),
280  myArrivalPosition(arrivalPosition),
281  myPlanElement(planElement) {
282 }
283 
284 
287  // get tag property
288  const auto tagProperty = myPlanElement->getTagProperty();
289  // only move personTrips defined over edges
290  if (tagProperty.planToEdge() || tagProperty.planConsecutiveEdges() || tagProperty.planEdge()) {
291  // get geometry end pos
293  // calculate circle width squared
294  const double circleWidthSquared = myArrivalPositionDiameter * myArrivalPositionDiameter;
295  // check if we clicked over a geometry end pos
296  if (myPlanElement->myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(geometryEndPos) <= ((circleWidthSquared + 2))) {
297  // continue depending of parent edges
298  if (myPlanElement->getParentEdges().size() > 0) {
299  return new GNEMoveOperation(myPlanElement, myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(myPlanElement->getVClass()), myArrivalPosition, false);
300  } else {
301  return new GNEMoveOperation(myPlanElement, myPlanElement->getParentDemandElements().at(1)->getParentEdges().back()->getLaneByAllowedVClass(myPlanElement->getVClass()), myArrivalPosition, false);
302  }
303  }
304  }
305  return nullptr;
306 }
307 
308 
309 void
311  const auto tagProperty = myPlanElement->getTagProperty();
312  // write attributes depending of parent elements
313  if (tagProperty.planConsecutiveEdges()) {
315  } else if (tagProperty.planRoute()) {
317  } else if (tagProperty.planEdge()) {
318  device.writeAttr(SUMO_ATTR_EDGE, myPlanElement->getParentEdges().front()->getID());
319  } else if (tagProperty.planBusStop()) {
320  device.writeAttr(SUMO_ATTR_BUS_STOP, myPlanElement->getParentAdditionals().front()->getID());
321  } else if (tagProperty.planTrainStop()) {
323  } else if (tagProperty.planContainerStop()) {
325  } else {
326  // write from attribute (if this is the first element)
327  if (myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement) == 0) {
328  // check if write edge or junction
329  if (tagProperty.planFromEdge()) {
330  device.writeAttr(SUMO_ATTR_FROM, myPlanElement->getParentEdges().front()->getID());
331  } else if (tagProperty.planFromTAZ()) {
332  device.writeAttr(SUMO_ATTR_FROM_TAZ, myPlanElement->getParentAdditionals().front()->getID());
333  } else if (tagProperty.planFromJunction()) {
335  }
336  // origin stopping places are transformed into an intial stop stage (see writeOriginStop)
337  }
338  // continue writting to attribute
339  if (tagProperty.planToEdge()) {
340  device.writeAttr(SUMO_ATTR_TO, myPlanElement->getParentEdges().back()->getID());
341  } else if (tagProperty.planToJunction()) {
343  } else if (tagProperty.planToTAZ()) {
344  device.writeAttr(SUMO_ATTR_TO_TAZ, myPlanElement->getParentAdditionals().back()->getID());
345  } else if (tagProperty.planToBusStop()) {
347  } else if (tagProperty.planToTrainStop()) {
349  } else if (tagProperty.planToContainerStop()) {
351  }
352  }
353  // check if write depart position
354  if (tagProperty.hasAttribute(SUMO_ATTR_DEPARTPOS) && (myDepartPosition > 0)) {
356  }
357  // check if write arrival position
358  if (tagProperty.hasAttribute(SUMO_ATTR_ARRIVALPOS) && (myArrivalPosition > 0)) {
360  }
361  // check if write end position
362  if (tagProperty.hasAttribute(SUMO_ATTR_ENDPOS)) {
364  }
365 }
366 
367 
368 void
370  const auto tagProperty = myPlanElement->getTagProperty();
371  // write extra stop element for a stopping place (if this is the first element)
372  if (tagProperty.planFromStoppingPlace()
373  && myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement) == nullptr) {
374  device.openTag(SUMO_TAG_STOP);
375  const std::string stopID = myPlanElement->getParentAdditionals().front()->getID();
376  if (tagProperty.planFromBusStop()) {
377  device.writeAttr(SUMO_ATTR_BUS_STOP, stopID);
378  } else if (tagProperty.planFromTrainStop()) {
379  device.writeAttr(SUMO_ATTR_TRAIN_STOP, stopID);
380  } else if (tagProperty.planFromContainerStop()) {
381  device.writeAttr(SUMO_ATTR_CONTAINER_STOP, stopID);
382  }
383  device.writeAttr(SUMO_ATTR_DURATION, 0);
384  device.closeTag();
385  }
386 }
387 
388 
391  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *myPlanElement);
392  // build header
393  myPlanElement->buildPopupHeader(ret, app);
394  // build menu command for center button and copy cursor position to clipboard
397  // build menu commands for names
398  GUIDesigns::buildFXMenuCommand(ret, "Copy " + myPlanElement->getTagStr() + " name to clipboard", nullptr, ret, MID_COPY_NAME);
399  GUIDesigns::buildFXMenuCommand(ret, "Copy " + myPlanElement->getTagStr() + " typed name to clipboard", nullptr, ret, MID_COPY_TYPED_NAME);
400  new FXMenuSeparator(ret);
401  // build selection and show parameters menu
404  GUIDesigns::buildFXMenuCommand(ret, ("Cursor position in view: " + toString(getPlanPositionInView().x()) + "," + toString(getPlanPositionInView().y())).c_str(), nullptr, nullptr, 0);
405  return ret;
406 }
407 
408 
409 GNELane*
411  // get tag property
412  const auto tagProperty = myPlanElement->getTagProperty();
413  // get vclass
414  auto vClass = myPlanElement->getVClass();
415  // continue depending of parents
416  if (tagProperty.planRoute()) {
417  // route
418  return myPlanElement->getParentDemandElements().at(1)->getParentEdges().front()->getLaneByAllowedVClass(vClass);
419  } else if (tagProperty.planConsecutiveEdges() || tagProperty.planFromEdge() || tagProperty.planEdge()) {
420  // edges
421  return myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
422  } else if (tagProperty.planStoppingPlace() || tagProperty.planFromStoppingPlace() || tagProperty.planToStoppingPlace()) {
423  // additional
424  return myPlanElement->getParentAdditionals().front()->getParentLanes().front();
425  } else {
426  // in other cases (TAZ, junctions, etc.) return null
427  return nullptr;
428  }
429 }
430 
431 
432 GNELane*
434  // get tag property
435  const auto tagProperty = myPlanElement->getTagProperty();
436  // get vclass
437  auto vClass = myPlanElement->getVClass();
438  // check parents
439  if (tagProperty.planRoute()) {
440  // route
441  return myPlanElement->getParentDemandElements().at(1)->getParentEdges().back()->getLaneByAllowedVClass(vClass);
442  } else if (tagProperty.planConsecutiveEdges() || tagProperty.planToEdge() || tagProperty.planEdge()) {
443  // edges
444  return myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
445  } else if (tagProperty.planStoppingPlace() || tagProperty.planFromStoppingPlace() || tagProperty.planToStoppingPlace()) {
446  // additional
447  return myPlanElement->getParentAdditionals().back()->getParentLanes().front()->getParentEdge()->getLaneByAllowedVClass(vClass);
448  } else {
449  // in other cases (TAZ, junctions, etc.) return null
450  return nullptr;
451  }
452 }
453 
454 
455 void
457  // get tag property
458  const auto tagProperty = myPlanElement->getTagProperty();
459  // get vClass
460  auto vClass = myPlanElement->getVClass();
461  // get path manager
462  auto pathManager = myPlanElement->getNet()->getPathManager();
463  // continue depending of parents
464  if (tagProperty.planRoute()) {
465  // calculate consecutive path using route edges
466  pathManager->calculateConsecutivePathEdges(myPlanElement, vClass, myPlanElement->getParentDemandElements().at(1)->getParentEdges());
467  } else if (tagProperty.planConsecutiveEdges()) {
468  // calculate consecutive path using edges
469  pathManager->calculateConsecutivePathEdges(myPlanElement, vClass, myPlanElement->getParentEdges());
471  // calculate path using junctions
472  pathManager->calculatePath(myPlanElement, vClass, myPlanElement->getParentJunctions().front(), myPlanElement->getParentJunctions().back());
474  // declare last lane
475  GNELane* lastLane = nullptr;
477  lastLane = myPlanElement->getParentAdditionals().back()->getParentLanes().back();
479  lastLane = myPlanElement->getParentAdditionals().back()->getParentLanes().front();
480  } else if (myPlanElement->myTagProperty.planToEdge()) {
481  lastLane = myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
482  }
483  // calculate path
484  if (lastLane) {
485  pathManager->calculatePath(myPlanElement, vClass, myPlanElement->getParentJunctions().front(), lastLane);
486  }
488  // declare first lane
489  GNELane* firstLane = nullptr;
491  firstLane = myPlanElement->getParentAdditionals().front()->getParentLanes().back();
493  firstLane = myPlanElement->getParentAdditionals().front()->getParentLanes().front();
494  } else if (myPlanElement->myTagProperty.planFromEdge()) {
495  firstLane = myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
496  }
497  // calculate path
498  if (firstLane) {
499  pathManager->calculatePath(myPlanElement, vClass, firstLane, myPlanElement->getParentJunctions().back());
500  }
501  } else {
502  // declare first edge
503  GNELane* firstLane = nullptr;
505  firstLane = myPlanElement->getParentEdges().front()->getLaneByAllowedVClass(vClass);
507  firstLane = myPlanElement->getParentAdditionals().front()->getParentLanes().back();
509  firstLane = myPlanElement->getParentAdditionals().front()->getParentLanes().front();
510  }
511  // declare last lane
512  GNELane* lastLane = nullptr;
514  lastLane = myPlanElement->getParentEdges().back()->getLaneByAllowedVClass(vClass);
516  lastLane = myPlanElement->getParentAdditionals().back()->getParentLanes().back();
518  lastLane = myPlanElement->getParentAdditionals().back()->getParentLanes().front();
519  }
520  if (firstLane && lastLane) {
521  pathManager->calculatePath(myPlanElement, vClass, firstLane, lastLane);
522  } else if (firstLane) {
523  pathManager->calculateConsecutivePathLanes(myPlanElement, {firstLane});
524  } else if (lastLane) {
525  pathManager->calculateConsecutivePathLanes(myPlanElement, {lastLane});
526  }
527  }
528  // update geometry
530 }
531 
532 
533 void
535  // get tag property
536  const auto tagProperty = myPlanElement->getTagProperty();
537  // declare first and last positions
538  Position firstPos = Position::INVALID;
539  Position lastPos = Position::INVALID;
540  // set first position
541  if (tagProperty.planFromJunction() && tagProperty.planToTAZ()) {
542  firstPos = myPlanElement->getParentJunctions().front()->getPositionInView();
543  lastPos = myPlanElement->getParentAdditionals().back()->getPositionInView();
544  } else if (tagProperty.planFromTAZ() && tagProperty.planToJunction()) {
545  firstPos = myPlanElement->getParentAdditionals().front()->getPositionInView();
546  lastPos = myPlanElement->getParentJunctions().back()->getPositionInView();
547  } else if (tagProperty.planFromTAZ() && tagProperty.planToTAZ()) {
548  firstPos = myPlanElement->getParentAdditionals().front()->getPositionInView();
549  lastPos = myPlanElement->getParentAdditionals().back()->getPositionInView();
550  }
551  // use both position to calculate a line
552  if ((firstPos != Position::INVALID) && (lastPos != Position::INVALID)) {
553  // remove from grid
556  // add into grid again
558  }
559  // update child demand elements
560  for (const auto& demandElement : myPlanElement->getChildDemandElements()) {
561  demandElement->updateGeometry();
562  }
563 }
564 
565 
566 Boundary
568  Boundary planBoundary;
569  // if this element is over route, add their boundary
570  if (myPlanElement->getParentDemandElements().size() > 1) {
571  planBoundary.add(myPlanElement->getParentDemandElements().at(1)->getCenteringBoundary());
572  }
573  // add the combination of all parent edges's boundaries
574  for (const auto& edge : myPlanElement->getParentEdges()) {
575  planBoundary.add(edge->getCenteringBoundary());
576  }
577  // add the combination of all parent edges's boundaries
578  for (const auto& junction : myPlanElement->getParentJunctions()) {
579  planBoundary.add(junction->getCenteringBoundary());
580  }
581  // add the combination of all parent additional's boundaries (stoppingPlaces and TAZs)
582  for (const auto& additional : myPlanElement->getParentAdditionals()) {
583  planBoundary.add(additional->getCenteringBoundary());
584  }
585  // check if is valid
586  if (planBoundary.isInitialised()) {
587  return planBoundary;
588  } else {
589  return myPlanElement->getParentDemandElements().front()->getCenteringBoundary();
590  }
591 }
592 
593 
594 Position
596  // get tag property
597  const auto tagProperty = myPlanElement->getTagProperty();
598  // continue depending of parents
599  if (tagProperty.planRoute()) {
600  // route
601  return myPlanElement->getParentDemandElements().at(1)->getPositionInView();
602  } else if (tagProperty.isPlanStop()) {
603  return myPlanElement->getDemandElementGeometry().getShape().front();
604  } else if (tagProperty.planFromEdge() || tagProperty.planConsecutiveEdges() || tagProperty.planEdge()) {
605  // first edge
606  return myPlanElement->getParentEdges().front()->getPositionInView();
607  } else if (tagProperty.planFromJunction()) {
608  // first junction
609  return myPlanElement->getParentJunctions().front()->getPositionInView();
610  } else if (tagProperty.planStoppingPlace() || tagProperty.planFromStoppingPlace() || tagProperty.planFromTAZ()) {
611  // first additional
612  return myPlanElement->getParentAdditionals().front()->getPositionInView();
613  } else {
614  // return parent position
615  return Position(0, 0);
616  }
617 }
618 
619 
620 std::string
622  // continue depending of key
623  switch (key) {
624  // Common plan attributes
625  case SUMO_ATTR_ID:
626  case GNE_ATTR_PARENT:
627  return myPlanElement->getParentDemandElements().at(0)->getID();
628  case GNE_ATTR_SELECTED:
630  case SUMO_ATTR_DEPARTPOS:
631  if (myDepartPosition < 0) {
632  return "";
633  } else {
634  return toString(myDepartPosition);
635  }
636  case SUMO_ATTR_ENDPOS:
638  if (myArrivalPosition < 0) {
639  return "";
640  } else {
641  return toString(myArrivalPosition);
642  }
643  // route
644  case SUMO_ATTR_ROUTE:
645  return myPlanElement->getParentDemandElements().at(1)->getID();
646  // edges
647  case SUMO_ATTR_EDGE:
648  case SUMO_ATTR_EDGES:
650  // stoppingPlaces
651  case SUMO_ATTR_BUS_STOP:
654  return myPlanElement->getParentAdditionals().back()->getID();
655  // from elements
656  case SUMO_ATTR_FROM:
657  return myPlanElement->getParentEdges().front()->getID();
659  return myPlanElement->getParentJunctions().front()->getID();
660  case SUMO_ATTR_FROM_TAZ:
663  return myPlanElement->getParentAdditionals().front()->getID();
664  // to elements
665  case SUMO_ATTR_TO:
666  return myPlanElement->getParentEdges().back()->getID();
668  return myPlanElement->getParentJunctions().back()->getID();
669  case SUMO_ATTR_TO_TAZ:
670  return myPlanElement->getParentAdditionals().back()->getID();
671  default:
672  throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
673  }
674 }
675 
676 
677 double
679  // get tag property
680  const auto tagProperty = myPlanElement->getTagProperty();
681  // declare plan parent
682  const auto planParent = myPlanElement->getParentDemandElements().at(0);
683  // continue depending of key
684  switch (key) {
686  if (tagProperty.planStoppingPlace()) {
687  // use startpos of stoppingPlace parent (stops)
688  return myPlanElement->getParentAdditionals().front()->getAttributeDouble(SUMO_ATTR_STARTPOS);
689  } else if (tagProperty.planFromStoppingPlace()) {
690  // use end position of stoppingPlace parent (for plans that starts in stoppingPlaces)
691  return myPlanElement->getParentAdditionals().front()->getAttributeDouble(SUMO_ATTR_ENDPOS);
692  } else if (tagProperty.planFromJunction() && tagProperty.planFromTAZ()) {
693  // junctions and TAZs return always -1
694  return -1;
695  } else {
696  // get previous plan element
697  const auto previousPlan = planParent->getPreviousChildDemandElement(myPlanElement);
698  // continue depending of previous plan
699  if (previousPlan) {
700  // use previous plan end position (normally the arrival position)
701  const auto posOverLane = previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
702  // if posOverLane is -1, means that previousPlan ends in the end of lane.
703  if (posOverLane == -1) {
704  // INVALID_DOUBLE will put the startPositio at the end of line
705  return INVALID_DOUBLE;
706  } else {
707  return previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
708  }
709  } else {
710  // use depart position defined in parent (person or container)
711  return planParent->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
712  }
713  }
714  }
716  // continue depending of parents
717  if (tagProperty.planStoppingPlace()) {
718  // use end position of the stoppingPlace (stops)
719  return myPlanElement->getParentAdditionals().back()->getAttributeDouble(SUMO_ATTR_ENDPOS);
720  } else if (tagProperty.planToStoppingPlace()) {
721  // use start position of the stoppingPlace (for elements that ends in stoppingPlaces)
722  return myPlanElement->getParentAdditionals().back()->getAttributeDouble(SUMO_ATTR_STARTPOS);
723  } else if (tagProperty.planToJunction() || tagProperty.planToTAZ()) {
724  // junctions and TAZs return always -1
725  return -1;
726  } else if ((tagProperty.isPlanStopPerson() || tagProperty.isPlanStopContainer()) && tagProperty.planEdge()) {
727  // elements that ends in stop always uses the end (arrival) position of the stops over edges
728  return myArrivalPosition;
729  } else {
730  // check if next plan is a stop over edge
731  const auto nextPlan = planParent->getNextChildDemandElement(myPlanElement);
732  if (nextPlan && (nextPlan->getTagProperty().isPlanStopPerson() ||
733  nextPlan->getTagProperty().isPlanStopContainer()) &&
734  nextPlan->getTagProperty().planEdge()) {
735  // if next plan is an stop over stoppingPlaces, use ends of stoppingPlace
736  return nextPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
737  } else {
738  // use arrival position
739  return myArrivalPosition;
740  }
741  }
742  case SUMO_ATTR_DEPARTPOS:
743  return myDepartPosition;
744  case SUMO_ATTR_ENDPOS:
746  return myArrivalPosition;
747  default:
748  throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have a doubleattribute of type '" + toString(key) + "'");
749  }
750 }
751 
752 
753 Position
755  // get tag property
756  const auto tagProperty = myPlanElement->getTagProperty();
757  // declare plan parent
758  const auto planParent = myPlanElement->getParentDemandElements().at(0);
759  // continue depending of key
760  switch (key) {
762  // get previous plan
763  const auto previousPlan = planParent->getPreviousChildDemandElement(myPlanElement);
764  if (previousPlan && previousPlan->getTagProperty().isPlanStop() && previousPlan->getTagProperty().planStoppingPlace()) {
765  return previousPlan->getParentAdditionals().front()->getAdditionalGeometry().getShape().back();
766  }
767  // continue depending of from element
768  if (tagProperty.planStoppingPlace()) {
769  return myPlanElement->getParentAdditionals().front()->getAdditionalGeometry().getShape().front();
770  } else if (tagProperty.planFromStoppingPlace()) {
771  return myPlanElement->getParentAdditionals().front()->getAdditionalGeometry().getShape().back();
772  } else if (tagProperty.planFromJunction()) {
773  // junction view position
774  return myPlanElement->getParentJunctions().front()->getPositionInView();
775  } else if (tagProperty.planFromTAZ()) {
776  // TAZ view position
777  return myPlanElement->getParentAdditionals().front()->getPositionInView();
778  } else if (tagProperty.planConsecutiveEdges() || tagProperty.planRoute() || tagProperty.planFromEdge()) {
779  // get first path lane
780  const auto firstLane = myPlanElement->getFirstPathLane();
781  // check if first lane exists
782  if (firstLane == nullptr) {
783  return Position::INVALID;
784  }
785  // declare lane position
786  double lanePosition = 0;
787  // continue depending of conditions
788  if (previousPlan) {
789  // use previous geometry end position
790  lanePosition = previousPlan->getAttributeDouble(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
791  } else if (myDepartPosition < 0) {
792  // use departPos defined in planParent
793  lanePosition = planParent->getAttributeDouble(SUMO_ATTR_DEPARTPOS);
794  } else {
795  // use departPos (only for tranships)
796  lanePosition = myDepartPosition;
797  }
798  // get lane shape
799  const auto& laneShape = firstLane->getLaneShape();
800  // continue depending of lane position
801  if (lanePosition <= 0) {
802  return laneShape.front();
803  } else if (lanePosition >= laneShape.length2D()) {
804  return laneShape.back();
805  } else {
806  return laneShape.positionAtOffset2D(lanePosition);
807  }
808  } else {
809  return Position::INVALID;
810  }
811  }
813  // check parents
814  if (tagProperty.planToJunction()) {
815  // junctions
816  return myPlanElement->getParentJunctions().back()->getPositionInView();
817  } else if (tagProperty.planToTAZ()) {
818  // taz
819  return myPlanElement->getParentAdditionals().back()->getPositionInView();
820  } else if (tagProperty.planStoppingPlace()) {
821  // get additional back shape (stops)
822  return myPlanElement->getParentAdditionals().back()->getAdditionalGeometry().getShape().back();
823  } else if (tagProperty.planToStoppingPlace()) {
824  // get additional front shape
825  return myPlanElement->getParentAdditionals().back()->getAdditionalGeometry().getShape().front();
826  } else if (tagProperty.planConsecutiveEdges() || tagProperty.planRoute() || tagProperty.planFromEdge()) {
827  // get next plan
828  const auto nextPlan = planParent->getNextChildDemandElement(myPlanElement);
829  // if next plan exist, then use their first lane (needed to maintain connectivity with rides)
830  const auto lastLane = nextPlan ? nextPlan->getFirstPathLane() : myPlanElement->getLastPathLane();
831  // check if last lane exists
832  if (lastLane == nullptr) {
833  return Position::INVALID;
834  }
835  // get lane shape
836  const auto& laneShape = lastLane->getLaneShape();
837  // continue depending of arrival position
838  if (nextPlan && nextPlan->getTagProperty().isPlanStop()) {
839  return nextPlan->getAttributePosition(GNE_ATTR_PLAN_GEOMETRY_ENDPOS);
840  } else if (myArrivalPosition == 0) {
841  return laneShape.front();
842  } else if ((myArrivalPosition == -1) || (myArrivalPosition >= laneShape.length2D())) {
843  return laneShape.back();
844  } else {
845  return laneShape.positionAtOffset2D(myArrivalPosition);
846  }
847  } else {
848  return Position::INVALID;
849  }
850  }
851  default:
852  throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have a position attribute of type '" + toString(key) + "'");
853  }
854 }
855 
856 
857 void
858 GNEDemandElementPlan::setPlanAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
859  // continue depending of key
860  switch (key) {
861  // common attributes
862  case SUMO_ATTR_DEPARTPOS:
864  case SUMO_ATTR_ENDPOS:
865  case GNE_ATTR_PARENT:
866  case GNE_ATTR_SELECTED:
868  break;
869  default:
870  throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
871  }
872 }
873 
874 
875 bool
876 GNEDemandElementPlan::isPlanValid(SumoXMLAttr key, const std::string& value) {
877  // continue depending of key
878  switch (key) {
879  // common attributes
880  case GNE_ATTR_PARENT:
881  return false;
882  case SUMO_ATTR_DEPARTPOS:
884  if (value.empty()) {
885  return true;
886  } else if (GNEAttributeCarrier::canParse<double>(value)) {
887  return GNEAttributeCarrier::parse<double>(value) >= 0;
888  } else {
889  return false;
890  }
891  case SUMO_ATTR_ENDPOS:
892  return GNEAttributeCarrier::canParse<double>(value);
893  case GNE_ATTR_SELECTED:
894  return GNEAttributeCarrier::canParse<bool>(value);
895  default:
896  throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
897  }
898 }
899 
900 
901 bool
903  switch (key) {
904  // edges
905  case SUMO_ATTR_EDGES:
906  // edge
907  case SUMO_ATTR_EDGE:
908  // route
909  case SUMO_ATTR_ROUTE:
910  // from
911  case SUMO_ATTR_FROM:
913  case SUMO_ATTR_FROM_TAZ:
916  // to
917  case SUMO_ATTR_TO:
919  case SUMO_ATTR_TO_TAZ:
920  case SUMO_ATTR_BUS_STOP:
923  return false;
924  case SUMO_ATTR_DEPARTPOS:
925  // depart position only enabled for first plan element
926  if (myPlanElement->getParentDemandElements().size() > 0) {
927  return myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement) == 0;
928  } else {
929  return false;
930  }
931  default:
932  return true;
933  }
934 }
935 
936 
937 void
938 GNEDemandElementPlan::setPlanAttribute(SumoXMLAttr key, const std::string& value) {
939  switch (key) {
940  // Common plan attributes
941  case GNE_ATTR_PARENT:
942  replacePlanParent(value);
943  break;
944  case SUMO_ATTR_DEPARTPOS:
945  if (value.empty()) {
946  myDepartPosition = -1;
947  } else {
948  myDepartPosition = GNEAttributeCarrier::parse<double>(value);
949  }
950  break;
951  case SUMO_ATTR_ENDPOS:
953  if (value.empty()) {
954  myArrivalPosition = -1;
955  } else {
956  myArrivalPosition = GNEAttributeCarrier::parse<double>(value);
957  }
958  break;
959  case GNE_ATTR_SELECTED:
960  if (GNEAttributeCarrier::parse<bool>(value)) {
962  } else {
964  }
965  // check if compute geometry and path
966  if (!myPlanElement->isTemplate()) {
969  }
970  break;
971  default:
972  throw InvalidArgument(myPlanElement->getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
973  }
974 }
975 
976 
977 std::string
979  // get tag property
980  const auto tagProperty = myPlanElement->getTagProperty();
981  // declare result
982  std::string result;
983  // clear result
984  int index = 0;
985  while (tagProperty.getTagStr().at(index) != ':') {
986  result.push_back(tagProperty.getTagStr().at(index));
987  index++;
988  }
989  result += ": ";
990  // continue depending of attributes
991  if (tagProperty.planConsecutiveEdges()) {
992  // edges
993  return result + myPlanElement->getParentEdges().front()->getID() + " ... " + myPlanElement->getParentEdges().back()->getID();
994  } else if (tagProperty.planRoute()) {
995  // route
996  return result + myPlanElement->getParentDemandElements().at(1)->getID();
997  } else if (tagProperty.planEdge()) {
998  // edge
999  return result + myPlanElement->getParentEdges().front()->getID();
1000  } else if (tagProperty.planStoppingPlace()) {
1001  // stoppingPlace
1002  return myPlanElement->getParentAdditionals().front()->getID();
1003  } else {
1004  // additional
1005  if (tagProperty.planFromStoppingPlace() || tagProperty.planFromTAZ()) {
1006  result += myPlanElement->getParentAdditionals().front()->getID();
1007  }
1008  // junction
1009  if (tagProperty.planFromJunction()) {
1010  result += myPlanElement->getParentJunctions().front()->getID();
1011  }
1012  // edge
1013  if (tagProperty.planFromEdge()) {
1014  result += myPlanElement->getParentEdges().front()->getID();
1015  }
1016  // arrow
1017  result += " -> ";
1018  // additional
1019  if (tagProperty.planToStoppingPlace() || tagProperty.planToTAZ()) {
1020  result += myPlanElement->getParentAdditionals().back()->getID();
1021  }
1022  // junction
1023  if (tagProperty.planToJunction()) {
1024  result += myPlanElement->getParentJunctions().back()->getID();
1025  }
1026  // edge
1027  if (tagProperty.planToEdge()) {
1028  result += myPlanElement->getParentEdges().back()->getID();
1029  }
1030  return result;
1031  }
1032 }
1033 
1034 
1035 bool
1037  // get view net
1038  auto viewNet = myPlanElement->getNet()->getViewNet();
1039  // check conditions
1040  if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
1041  viewNet->getNetworkViewOptions().showDemandElements() &&
1042  viewNet->getDemandViewOptions().showAllPersonPlans()) {
1043  // show all person plans in network mode
1044  return true;
1045  } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
1046  viewNet->getDemandViewOptions().showAllPersonPlans()) {
1047  // show all person plans
1048  return true;
1049  } else if (viewNet->getEditModes().isCurrentSupermodeDemand() && myPlanElement->isAttributeCarrierSelected()) {
1050  // show selected
1051  return true;
1052  } else if (viewNet->isAttributeCarrierInspected(myPlanElement->getParentDemandElements().front())) {
1053  // person parent is inspected
1054  return true;
1055  } else if (viewNet->getDemandViewOptions().getLockedPerson() == myPlanElement->getParentDemandElements().front()) {
1056  // person parent is locked
1057  return true;
1058  } else if (viewNet->getInspectedAttributeCarriers().empty()) {
1059  // nothing is inspected
1060  return false;
1061  } else {
1062  // get inspected AC
1063  const GNEAttributeCarrier* AC = viewNet->getInspectedAttributeCarriers().front();
1064  // check condition
1066  // common person parent
1067  return true;
1068  } else {
1069  // all conditions are false
1070  return false;
1071  }
1072  }
1073 }
1074 
1075 
1076 bool
1078  // get view net
1079  auto viewNet = myPlanElement->getNet()->getViewNet();
1080  // check conditions
1081  if (viewNet->getEditModes().isCurrentSupermodeNetwork() &&
1082  viewNet->getNetworkViewOptions().showDemandElements() &&
1083  viewNet->getDemandViewOptions().showAllContainerPlans()) {
1084  // show all container plans in network mode
1085  return true;
1086  } else if (viewNet->getEditModes().isCurrentSupermodeDemand() &&
1087  viewNet->getDemandViewOptions().showAllContainerPlans()) {
1088  // show all container plans
1089  return true;
1090  } else if (viewNet->getEditModes().isCurrentSupermodeDemand() && myPlanElement->isAttributeCarrierSelected()) {
1091  // show selected
1092  return true;
1093  } else if (viewNet->isAttributeCarrierInspected(myPlanElement->getParentDemandElements().front())) {
1094  // container parent is inspected
1095  return true;
1096  } else if (viewNet->getDemandViewOptions().getLockedContainer() == myPlanElement->getParentDemandElements().front()) {
1097  // container parent is locked
1098  return true;
1099  } else if (viewNet->getInspectedAttributeCarriers().empty()) {
1100  // nothing is inspected
1101  return false;
1102  } else {
1103  // get inspected AC
1104  const GNEAttributeCarrier* AC = viewNet->getInspectedAttributeCarriers().front();
1105  // check condition
1107  // common container parent
1108  return true;
1109  } else {
1110  // all conditions are false
1111  return false;
1112  }
1113  }
1114 }
1115 
1116 
1117 void
1118 GNEDemandElementPlan::drawPlanGL(const bool drawPlan, const GUIVisualizationSettings& s, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
1119  // get plan parent
1120  const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1121  // get tag property
1122  const auto tagProperty = myPlanElement->getTagProperty();
1123  // get plan geometry
1124  auto& planGeometry = myPlanElement->myDemandElementGeometry;
1125  // draw relations between TAZs
1126  if (drawPlan && (planGeometry.getShape().size() > 0)) {
1127  // get detail level
1128  const auto d = s.getDetailLevel(1);
1129  // get viewNet
1130  auto viewNet = myPlanElement->getNet()->getViewNet();
1131  // get inspected attribute carriers
1132  const auto& inspectedACs = viewNet->getInspectedAttributeCarriers();
1133  // get inspected plan
1134  const GNEAttributeCarrier* planInspected = (inspectedACs.size() > 0) ? inspectedACs.front() : nullptr;
1135  // flag to check if width must be duplicated
1136  const bool duplicateWidth = (planInspected == myPlanElement) || (planInspected == planParent);
1137  // calculate path width
1138  const double pathWidth = 0.25 * (duplicateWidth ? 2 : 1);
1139  // draw geometry only if we'rent in drawForObjectUnderCursor mode
1140  if (!s.drawForViewObjectsHandler) {
1141  // push matrix
1143  // translate to front
1144  viewNet->drawTranslateFrontAttributeCarrier(myPlanElement, GLO_TAZ + 1);
1145  // set color
1146  GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1147  // draw line
1148  GUIGeometry::drawGeometry(d, planGeometry, pathWidth);
1150  *(planGeometry.getShape().end() - 2),
1151  *(planGeometry.getShape().end() - 1),
1152  0.5, 0.5, 0.5);
1153  // pop matrix
1155  // draw dotted contour
1157  }
1158  // calculate contour and draw dotted geometry
1159  myPlanContour.calculateContourExtrudedShape(s, d, myPlanElement, planGeometry.getShape(), pathWidth, 1, true, true, 0);
1160  }
1161  // check if draw plan parent
1162  if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1163  planParent->drawGL(s);
1164  }
1165 }
1166 
1167 
1168 void
1170  const double offsetFront, const double planWidth, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
1171  // get view net
1172  auto viewNet = myPlanElement->getNet()->getViewNet();
1173  // get plan parent
1174  const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1175  // check if draw plan element can be drawn
1176  if (drawPlan && segment->getLane() && myPlanElement->getNet()->getPathManager()->getPathDraw()->checkDrawPathGeometry(s, segment->getLane(), myPlanElement->getTagProperty().getTag())) {
1177  // get detail level
1178  const auto d = s.getDetailLevel(1);
1179  // get inspected attribute carriers
1180  const auto& inspectedACs = viewNet->getInspectedAttributeCarriers();
1181  // get inspected plan
1182  const GNEAttributeCarrier* planInspected = (inspectedACs.size() > 0) ? inspectedACs.front() : nullptr;
1183  // flag to check if width must be duplicated
1184  const bool duplicateWidth = (planInspected == myPlanElement) || (planInspected == planParent);
1185  // calculate path width
1186  const double pathWidth = s.addSize.getExaggeration(s, segment->getLane()) * planWidth * (duplicateWidth ? 2 : 1);
1187  // declare path geometry
1188  GUIGeometry planGeometry;
1189  // update pathGeometry depending of first and last segment
1190  if (segment->isFirstSegment() && segment->isLastSegment()) {
1191  planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1196  } else if (segment->isFirstSegment()) {
1197  planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1200  -1,
1202  } else if (segment->isLastSegment()) {
1203  planGeometry.updateGeometry(segment->getLane()->getLaneGeometry().getShape(),
1204  -1,
1208  } else {
1209  planGeometry = segment->getLane()->getLaneGeometry();
1210  }
1211  // draw geometry only if we'rent in drawForObjectUnderCursor mode
1212  if (!s.drawForViewObjectsHandler) {
1213  // Add a draw matrix
1215  // Start with the drawing of the area traslating matrix to origin
1216  viewNet->drawTranslateFrontAttributeCarrier(myPlanElement, myPlanElement->getType(), offsetFront);
1217  // Set color
1218  GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1219  // draw geometry
1220  GUIGeometry::drawGeometry(d, planGeometry, pathWidth);
1221  // draw red arrows
1222  drawFromArrow(s, segment->getLane(), segment);
1223  drawToArrow(s, segment->getLane(), segment);
1224  // draw end position
1225  drawEndPosition(s, d, segment, duplicateWidth);
1226  // Pop last matrix
1228  // Draw name if isn't being drawn for selecting
1230  // draw dotted contour
1232  }
1233  // declare trim geometry to draw
1234  const auto shape = (segment->isFirstSegment() || segment->isLastSegment()) ? planGeometry.getShape() : segment->getLane()->getLaneShape();
1235  // calculate contour and draw dotted geometry
1236  if (duplicateWidth) {
1237  segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, pathWidth, 1, true, true, 0);
1238  } else {
1239  segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, pathWidth, 1, true, true, 0);
1240  }
1241  }
1242  // check if draw plan parent
1243  if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1244  planParent->drawGL(s);
1245  }
1246 }
1247 
1248 
1249 void
1251  const double offsetFront, const double planWidth, const RGBColor& planColor, const RGBColor& planSelectedColor) const {
1252  // get view net
1253  auto viewNet = myPlanElement->getNet()->getViewNet();
1254  // get plan parent
1255  const GNEDemandElement* planParent = myPlanElement->getParentDemandElements().front();
1256  // check if draw plan elements can be drawn
1258  // get detail level
1259  const auto d = s.getDetailLevel(1);
1260  // get inspected attribute carriers
1261  const auto& inspectedACs = viewNet->getInspectedAttributeCarriers();
1262  // get inspected plan
1263  const GNEAttributeCarrier* planInspected = (inspectedACs.size() > 0) ? inspectedACs.front() : nullptr;
1264  // flag to check if width must be duplicated
1265  const bool duplicateWidth = (planInspected == myPlanElement) || (planInspected == planParent);
1266  // calculate path width
1267  const double pathWidth = s.addSize.getExaggeration(s, segment->getPreviousLane()) * planWidth * (duplicateWidth ? 2 : 1);
1268  // draw geometry only if we'rent in drawForObjectUnderCursor mode
1269  if (!s.drawForViewObjectsHandler) {
1270  // push a draw matrix
1272  // Start with the drawing of the area traslating matrix to origin
1273  viewNet->drawTranslateFrontAttributeCarrier(myPlanElement, myPlanElement->getType(), offsetFront);
1274  // Set plan color
1275  GLHelper::setColor(myPlanElement->drawUsingSelectColor() ? planSelectedColor : planColor);
1276  // check if draw lane2lane connection or a red line
1277  if (segment->getPreviousLane() && segment->getNextLane()) {
1278  if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
1279  // obtain lane2lane geometry
1280  const GUIGeometry& lane2laneGeometry = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane());
1281  // draw lane2lane
1282  GUIGeometry::drawGeometry(d, lane2laneGeometry, pathWidth);
1283  } else {
1284  // Set invalid plan color
1286  // draw line between end of first shape and first position of second shape
1287  GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), segment->getNextLane()->getLaneShape().front()}, (0.5 * pathWidth));
1288  }
1289  } else if (segment->getPreviousLane()) {
1290  // draw line between center of junction and last lane shape
1291  GLHelper::drawBoxLines({segment->getPreviousLane()->getLaneShape().back(), myPlanElement->getParentJunctions().back()->getPositionInView()}, pathWidth);
1292  } else if (segment->getNextLane()) {
1293  // draw line between center of junction and first lane shape
1294  GLHelper::drawBoxLines({myPlanElement->getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()}, pathWidth);
1295  }
1296  // Pop last matrix
1298  // draw lock icon
1300  // draw dotted contour
1301  if (duplicateWidth) {
1303  } else {
1305  }
1306  }
1307  // check if shape dotted contour has to be drawn
1308  if (segment->getPreviousLane() && segment->getNextLane()) {
1309  if (segment->getPreviousLane()->getLane2laneConnections().exist(segment->getNextLane())) {
1310  // get shape
1311  const auto& shape = segment->getPreviousLane()->getLane2laneConnections().getLane2laneGeometry(segment->getNextLane()).getShape();
1312  // calculate contour and draw dotted geometry
1313  if (duplicateWidth) {
1314  segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, pathWidth, 1, true, true, 0);
1315  } else {
1316  segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, shape, pathWidth, 1, true, true, 0);
1317  }
1318  }
1319  } else if (segment->getPreviousLane()) {
1320  segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, {segment->getPreviousLane()->getLaneShape().back(), myPlanElement->getParentJunctions().back()->getPositionInView()},
1321  pathWidth, 1, true, true, 0);
1322  } else if (segment->getNextLane()) {
1323  segment->getContour()->calculateContourExtrudedShape(s, d, myPlanElement, {myPlanElement->getParentJunctions().front()->getPositionInView(), segment->getNextLane()->getLaneShape().front()},
1324  pathWidth, 1, true, true, 0);
1325  }
1326  }
1327  // check if draw plan parent
1328  if (planParent->getPreviousChildDemandElement(myPlanElement) == nullptr) {
1329  planParent->drawGL(s);
1330  }
1331 }
1332 
1333 
1336  // get previous plan
1337  const auto previousPlan = myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement);
1338  if (previousPlan) {
1339  // get previous lane
1340  const auto previousLastLane = previousPlan->getLastPathLane();
1341  // get first lane
1342  const auto firstLane = myPlanElement->getFirstPathLane();
1343  // compare edges
1344  if (previousLastLane && firstLane && (previousLastLane->getParentEdge() != firstLane->getParentEdge())) {
1346  }
1347  // in the future, check more elements
1348  }
1349  // get next child
1350  const auto nextPlan = myPlanElement->getParentDemandElements().at(0)->getNextChildDemandElement(myPlanElement);
1351  if (nextPlan) {
1352  // get previous lane
1353  const auto nextFirstLane = nextPlan->getFirstPathLane();
1354  // get first lane
1355  const auto lastLane = myPlanElement->getLastPathLane();
1356  // compare edges
1357  if (nextFirstLane && lastLane && (nextFirstLane->getParentEdge() != lastLane->getParentEdge())) {
1359  }
1360  // in the future, check more elements
1361  }
1362  // all ok, then return true
1364 }
1365 
1366 
1367 std::string
1369  // get previous plan
1370  const auto previousPlan = myPlanElement->getParentDemandElements().at(0)->getPreviousChildDemandElement(myPlanElement);
1371  if (previousPlan) {
1372  // get previous lane
1373  const auto previousLastLane = previousPlan->getLastPathLane();
1374  // get first lane
1375  const auto firstLane = myPlanElement->getLastPathLane();
1376  // compare edges
1377  if (previousLastLane && firstLane && (previousLastLane->getParentEdge() != firstLane->getParentEdge())) {
1378  return TLF("Edge '%' is not consecutive with edge '%'", previousLastLane->getParentEdge()->getID(), firstLane->getParentEdge()->getID());
1379  }
1380  // in the future, check more elements
1381  }
1382  // get next child
1383  const auto nextPlan = myPlanElement->getParentDemandElements().at(0)->getNextChildDemandElement(myPlanElement);
1384  if (nextPlan) {
1385  // get previous lane
1386  const auto nextFirstLane = nextPlan->getFirstPathLane();
1387  // get first lane
1388  const auto lastLane = myPlanElement->getLastPathLane();
1389  // compare edges
1390  if (nextFirstLane && lastLane && (nextFirstLane->getParentEdge() != lastLane->getParentEdge())) {
1391  return TLF("Edge '%' is not consecutive with edge '%'", nextFirstLane->getParentEdge()->getID(), lastLane->getParentEdge()->getID());
1392  }
1393  // in the future, check more elements
1394  }
1395  // undefined problem
1396  return "undefined problem";
1397 }
1398 
1399 
1400 void
1402  // draw ifcurrent amd next segment is placed over lanes
1403  if (segment->getNextLane()) {
1404  // get firstPosition (last position of current lane shape)
1405  const Position from = lane->getLaneShape().back();
1406  // get lastPosition (first position of next lane shape)
1407  const Position to = segment->getNextLane()->getLaneShape().front();
1408  // push draw matrix
1410  // move front
1411  glTranslated(0, 0, 4);
1412  // draw child line
1414  // pop draw matrix
1416  }
1417 }
1418 
1419 
1420 void
1422  // draw the line if previos segment and current segment is placed over lanes
1423  if (segment->getPreviousLane()) {
1424  // get firstPosition (last position of current lane shape)
1425  const Position from = lane->getLaneShape().front();
1426  // get lastPosition (first position of next lane shape)
1427  const Position to = segment->getPreviousLane()->getLaneShape().back();
1428  // push draw matrix
1430  // move front
1431  glTranslated(0, 0, 4);
1432  // draw child line
1434  // pop draw matrix
1436  }
1437 }
1438 
1439 
1440 void
1442  // check if myPlanElement is the last segment
1443  if (segment->isLastSegment()) {
1444  // calculate circle width
1445  const double circleRadius = (duplicateWidth ? myArrivalPositionDiameter : (myArrivalPositionDiameter / 2.0));
1446  const double circleWidth = circleRadius * MIN2((double)0.5, s.laneWidthExaggeration);
1447  const double circleWidthSquared = circleWidth * circleWidth;
1448  // get geometryEndPos
1450  // check if endPos can be drawn
1451  if (!s.drawForRectangleSelection || (myPlanElement->getNet()->getViewNet()->getPositionInformation().distanceSquaredTo2D(geometryEndPos) <= (circleWidthSquared + 2))) {
1452  // push draw matrix
1454  // translate to pos and move to
1455  glTranslated(geometryEndPos.x(), geometryEndPos.y(), 4);
1456  // resolution of drawn circle depending of the zoom (To improve smothness)
1457  GLHelper::drawFilledCircleDetailled(d, circleWidth);
1458  // pop draw matrix
1460  }
1461  }
1462 }
1463 
1464 
1465 bool
1466 GNEDemandElementPlan::replacePlanParent(const std::string& newParentID) {
1467  std::vector<SumoXMLTag> tags;
1469  tags.push_back(SUMO_TAG_PERSON);
1470  tags.push_back(SUMO_TAG_PERSONFLOW);
1471  } else {
1472  tags.push_back(SUMO_TAG_CONTAINER);
1473  tags.push_back(SUMO_TAG_CONTAINERFLOW);
1474  }
1475  // search new parent and set it
1476  for (const auto& tag : tags) {
1477  if (myPlanElement->getNet()->getAttributeCarriers()->retrieveDemandElement(tag, newParentID, false) != nullptr) {
1478  myPlanElement->replaceDemandElementParent(tag, newParentID, 0);
1479  return true;
1480  }
1481  }
1482  throw ProcessError("Invalid new parent ID");
1483 }
1484 
1485 /****************************************************************************/
@ MID_COPY_TYPED_NAME
Copy typed object name - popup entry.
Definition: GUIAppEnum.h:455
@ MID_COPY_NAME
Copy object name - popup entry.
Definition: GUIAppEnum.h:453
@ GLO_TAZ
Traffic Assignment Zones (TAZs)
@ PERSONTRIP_JUNCTION
@ PERSONTRIP_TRAINSTOP
@ WALK_TRAINSTOP
@ PERSONTRIP_BUSSTOP
@ TRANSPORT_CONTAINERSTOP
@ TRANSHIP_EDGE
@ TRANSHIP_EDGES
@ WALK_BUSSTOP
@ TRANSHIP_CONTAINERSTOP
@ TRANSPORT_EDGE
@ RIDE_BUSSTOP
@ RIDE_TRAINSTOP
@ PERSONTRIP_TAZ
@ PERSONTRIP_EDGE
@ WALK_JUNCTION
#define TLF(string,...)
Definition: MsgHandler.h:317
@ GNE_TAG_WALK_BUSSTOP_BUSSTOP
@ GNE_TAG_PERSONTRIP_EDGE_EDGE
@ GNE_TAG_PERSONTRIP_TAZ_EDGE
@ GNE_TAG_WALK_EDGE_TAZ
@ GNE_TAG_RIDE_BUSSTOP_BUSSTOP
@ GNE_TAG_PERSONTRIP_EDGE_JUNCTION
@ GNE_TAG_WALK_TAZ_BUSSTOP
@ GNE_TAG_PERSONTRIP_TRAINSTOP_EDGE
@ GNE_TAG_PERSONTRIP_BUSSTOP_EDGE
@ GNE_TAG_WALK_BUSSTOP_TRAINSTOP
@ GNE_TAG_PERSONTRIP_TAZ_TRAINSTOP
@ GNE_TAG_TRANSPORT_CONTAINERSTOP_EDGE
@ SUMO_TAG_NOTHING
invalid tag, must be the last one
@ GNE_TAG_TRANSHIP_EDGE_EDGE
@ GNE_TAG_WALK_EDGES
@ SUMO_TAG_CONTAINERFLOW
@ GNE_TAG_WALK_BUSSTOP_JUNCTION
@ GNE_TAG_TRANSHIP_EDGE_CONTAINERSTOP
@ GNE_TAG_STOPCONTAINER_EDGE
@ GNE_TAG_WALK_TRAINSTOP_TAZ
@ GNE_TAG_STOPPERSON_BUSSTOP
@ SUMO_TAG_STOP
stop for vehicles
@ GNE_TAG_PERSONTRIP_BUSSTOP_TRAINSTOP
@ GNE_TAG_PERSONTRIP_JUNCTION_BUSSTOP
@ GNE_TAG_PERSONTRIP_TRAINSTOP_TAZ
@ GNE_TAG_PERSONTRIP_JUNCTION_TRAINSTOP
@ GNE_TAG_PERSONTRIP_TRAINSTOP_BUSSTOP
@ GNE_TAG_PERSONTRIP_BUSSTOP_JUNCTION
@ GNE_TAG_TRANSHIP_EDGES
@ GNE_TAG_STOPCONTAINER_CONTAINERSTOP
@ GNE_TAG_RIDE_BUSSTOP_TRAINSTOP
@ GNE_TAG_PERSONTRIP_EDGE_TRAINSTOP
@ GNE_TAG_RIDE_BUSSTOP_EDGE
@ GNE_TAG_RIDE_TRAINSTOP_BUSSTOP
@ GNE_TAG_WALK_TRAINSTOP_EDGE
@ GNE_TAG_RIDE_EDGE_EDGE
@ GNE_TAG_PERSONTRIP_TRAINSTOP_TRAINSTOP
@ GNE_TAG_TRANSPORT_EDGE_EDGE
@ GNE_TAG_WALK_EDGE_TRAINSTOP
@ GNE_TAG_TRANSPORT_EDGE_CONTAINERSTOP
@ GNE_TAG_WALK_JUNCTION_TAZ
@ GNE_TAG_PERSONTRIP_TAZ_BUSSTOP
@ GNE_TAG_WALK_JUNCTION_JUNCTION
@ SUMO_TAG_CONTAINER
@ GNE_TAG_WALK_EDGE_EDGE
@ GNE_TAG_PERSONTRIP_TAZ_TAZ
@ GNE_TAG_PERSONTRIP_EDGE_BUSSTOP
@ GNE_TAG_PERSONTRIP_BUSSTOP_TAZ
@ GNE_TAG_WALK_BUSSTOP_EDGE
@ GNE_TAG_WALK_JUNCTION_TRAINSTOP
@ GNE_TAG_RIDE_EDGE_BUSSTOP
@ GNE_TAG_WALK_TAZ_JUNCTION
@ GNE_TAG_WALK_BUSSTOP_TAZ
@ GNE_TAG_TRANSPORT_CONTAINERSTOP_CONTAINERSTOP
@ GNE_TAG_PERSONTRIP_BUSSTOP_BUSSTOP
@ GNE_TAG_PERSONTRIP_JUNCTION_JUNCTION
@ GNE_TAG_WALK_TAZ_TAZ
@ GNE_TAG_WALK_TRAINSTOP_BUSSTOP
@ GNE_TAG_WALK_TAZ_EDGE
@ GNE_TAG_PERSONTRIP_TAZ_JUNCTION
@ GNE_TAG_RIDE_EDGE_TRAINSTOP
@ SUMO_TAG_PERSON
@ GNE_TAG_WALK_JUNCTION_BUSSTOP
@ GNE_TAG_WALK_JUNCTION_EDGE
@ GNE_TAG_WALK_TRAINSTOP_JUNCTION
@ GNE_TAG_PERSONTRIP_JUNCTION_EDGE
@ GNE_TAG_STOPPERSON_TRAINSTOP
@ GNE_TAG_WALK_EDGE_JUNCTION
@ GNE_TAG_PERSONTRIP_JUNCTION_TAZ
@ GNE_TAG_WALK_TRAINSTOP_TRAINSTOP
@ GNE_TAG_WALK_EDGE_BUSSTOP
@ GNE_TAG_TRANSHIP_CONTAINERSTOP_CONTAINERSTOP
@ GNE_TAG_WALK_TAZ_TRAINSTOP
@ GNE_TAG_RIDE_TRAINSTOP_TRAINSTOP
@ GNE_TAG_PERSONTRIP_TRAINSTOP_JUNCTION
@ GNE_TAG_STOPPERSON_EDGE
@ GNE_TAG_WALK_ROUTE
@ GNE_TAG_PERSONTRIP_EDGE_TAZ
@ SUMO_TAG_PERSONFLOW
@ GNE_TAG_TRANSHIP_CONTAINERSTOP_EDGE
@ GNE_TAG_RIDE_TRAINSTOP_EDGE
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_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_SELECTED
element is selected
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_TO_TAZ
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_FROM_TAZ
@ GNE_ATTR_PLAN_GEOMETRY_ENDPOS
person/container geometry end position
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_ID
@ SUMO_ATTR_DURATION
const double INVALID_DOUBLE
invalid double
Definition: StdDefs.h:64
T MIN2(T a, T b)
Definition: StdDefs.h:76
const double SUMO_const_halfLaneWidth
Definition: StdDefs.h:49
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
Position getCenter() const
Returns the center of the boundary.
Definition: Boundary.cpp:112
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:78
bool isInitialised() const
check if Boundary is Initialised
Definition: Boundary.cpp:235
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:654
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:629
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:130
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:347
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:539
static void pushMatrix()
push matrix
Definition: GLHelper.cpp:117
An Element which don't belong to GNENet but has influence in the simulation.
Definition: GNEAdditional.h:49
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
const std::string & getTagStr() const
get tag assigned to this object in string format
const GNETagProperties & getTagProperty() const
get tagProperty associated with this Attribute Carrier
bool isTemplate() const
check if this AC is template
void unselectAttributeCarrier(const bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
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
void selectAttributeCarrier(const bool changeFlag=true)
select attribute carrier using GUIGlobalSelection
virtual std::string getAttribute(SumoXMLAttr key) const =0
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 extrusionWidth, const double scale, const bool closeFirstExtrem, const bool closeLastExtrem, const double offset) const
calculate contour extruded (used in elements formed by a central shape)
Definition: GNEContour.cpp:88
void drawDottedContours(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEAttributeCarrier *AC, const double lineWidth, const bool addOffset) const
drawing contour functions
Definition: GNEContour.cpp:265
virtual void updateGeometry()=0
update pre-computed geometry information
virtual SUMOVehicleClass getVClass() const =0
obtain VClass related with this demand element
void replaceDemandElementParent(SumoXMLTag tag, const std::string &value, const int parentIndex)
replace demand element parent
GUIGeometry myDemandElementGeometry
demand element geometry (also called "stacked geometry")
virtual GNELane * getLastPathLane() const =0
get last path lane
virtual std::string getAttribute(SumoXMLAttr key) const =0
virtual void computePathElement()=0
compute pathElement
virtual GNELane * getFirstPathLane() const =0
get first path lane
virtual Position getPositionInView() const =0
Returns position of demand element in view.
const GUIGeometry & getDemandElementGeometry()
get demand element geometry (stacked)
Problem
enum class for demandElement problems
GNEDemandElement * getPreviousChildDemandElement(const GNEDemandElement *demandElement) const
get previous child demand element to the given demand element
virtual void drawGL(const GUIVisualizationSettings &s) const =0
Draws the object.
bool isPlanValid(SumoXMLAttr key, const std::string &value)
check if plan attribute is valid
Boundary getPlanCenteringBoundary() const
get centering boundaryt
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
void drawPlanLanePartial(const bool drawPlan, const GUIVisualizationSettings &s, const GNEPathManager::Segment *segment, const double offsetFront, const double planWidth, const RGBColor &planColor, const RGBColor &planSelectedColor) const
draw plan partial lane
GUIGLObjectPopupMenu * getPlanPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
void drawPlanJunctionPartial(const bool drawPlan, const GUIVisualizationSettings &s, const GNEPathManager::Segment *segment, const double offsetFront, const double planWidth, const RGBColor &planColor, const RGBColor &planSelectedColor) const
draw plan partial junction
void drawEndPosition(const GUIVisualizationSettings &s, const GUIVisualizationSettings::Detail d, const GNEPathManager::Segment *segment, const bool duplicateWidth) const
draw to arrow
static std::pair< SumoXMLTag, GUIIcon > getPersonStopTagIcon(const GNEEdge *edge, const GNEAdditional *busStop, const GNEAdditional *trainStop)
get the person stop tag and icon for the combination
GNEDemandElementPlan(GNEDemandElement *planElement, const double departPosition, const double arrivalPosition)
constructor
void drawFromArrow(const GUIVisualizationSettings &s, const GNELane *lane, const GNEPathManager::Segment *segment) const
draw from arrow
std::string getPlanHierarchyName() const
get plan Hierarchy Name (Used in AC Hierarchy)
void writeLocationAttributes(OutputDevice &device) const
write plan element common attributes
static std::pair< SumoXMLTag, GUIIcon > getPersonTripTagIcon(const GNEEdge *fromEdge, const GNEEdge *toEdge, const GNEAdditional *fromTAZ, const GNEAdditional *toTAZ, const GNEJunction *fromJunction, const GNEJunction *toJunction, const GNEAdditional *fromBusStop, const GNEAdditional *toBusStop, const GNEAdditional *fromTrainStop, const GNEAdditional *toTrainStop)
get the personTrip tag and icon for the combination
bool checkDrawPersonPlan() const
check if person plan can be drawn
GNEContour myPlanContour
variable used for draw contours
GNEMoveOperation * getPlanMoveOperation()
get move operation
void drawToArrow(const GUIVisualizationSettings &s, const GNELane *lane, const GNEPathManager::Segment *segment) const
draw to arrow
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)
static std::pair< SumoXMLTag, GUIIcon > getRideTagIcon(const GNEEdge *fromEdge, const GNEEdge *toEdge, const GNEAdditional *fromBusStop, const GNEAdditional *toBusStop, const GNEAdditional *fromTrainStop, const GNEAdditional *toTrainStop)
get the ride tag and icon for the combination
double myDepartPosition
depart position (used in tranships)
static const double myArrivalPositionDiameter
arrival position diameter
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
static std::pair< SumoXMLTag, GUIIcon > getContainerStopTagIcon(const GNEEdge *edge, const GNEAdditional *containerStop)
get the container stop tag and icon for the combination
GNELane * getLastPlanPathLane() const
get last plan path lane
GNEDemandElement * myPlanElement
pointer to plan element
void drawPlanGL(const bool drawPlan, const GUIVisualizationSettings &s, const RGBColor &planColor, const RGBColor &planSelectedColor) const
draw plan
void updatePlanGeometry()
update pre-computed geometry information
static std::pair< SumoXMLTag, GUIIcon > getTransportTagIcon(const GNEEdge *fromEdge, const GNEEdge *toEdge, const GNEAdditional *fromContainerStop, const GNEAdditional *toContainerStop)
get the transport tag and icon for the combination
GNELane * getFirstPlanPathLane() const
get first plan path lane
static std::pair< SumoXMLTag, GUIIcon > getTranshipTagIcon(const std::vector< GNEEdge * > &consecutiveEdges, const GNEEdge *fromEdge, const GNEEdge *toEdge, const GNEAdditional *fromContainerStop, const GNEAdditional *toContainerStop)
get the tranship tag and icon for the combination
static std::pair< SumoXMLTag, GUIIcon > getWalkTagIcon(const std::vector< GNEEdge * > &consecutiveEdges, const GNEDemandElement *route, const GNEEdge *fromEdge, const GNEEdge *toEdge, const GNEAdditional *fromTAZ, const GNEAdditional *toTAZ, const GNEJunction *fromJunction, const GNEJunction *toJunction, const GNEAdditional *fromBusStop, const GNEAdditional *toBusStop, const GNEAdditional *fromTrainStop, const GNEAdditional *toTrainStop)
get the walk tag and icon for the combination
void writeOriginStop(OutputDevice &device) const
write initial stop stage if plan starts at a stopping place
bool replacePlanParent(const std::string &newParentID)
replace plan parent
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:53
const std::vector< GNEJunction * > & getParentJunctions() const
get parent junctions
const std::vector< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
const std::vector< GNEDemandElement * > & getParentDemandElements() const
get parent demand elements
const std::vector< GNEAdditional * > & getParentAdditionals() const
get parent additionals
const std::vector< GNEEdge * > & getParentEdges() const
get parent edges
bool exist(const GNELane *toLane) const
check if exist a lane2lane geometry for the given toLane
const GUIGeometry & getLane2laneGeometry(const GNELane *toLane) const
get lane2lane geometry
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:46
const PositionVector & getLaneShape() const
get elements shape
Definition: GNELane.cpp:214
const GNELane2laneConnection & getLane2laneConnections() const
get Lane2laneConnection struct
Definition: GNELane.cpp:684
const GUIGeometry & getLaneGeometry() const
get lane geometry
Definition: GNELane.cpp:208
move operation
GNEDemandElement * retrieveDemandElement(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named demand element.
void addGLObjectIntoGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1302
void removeGLObjectFromGrid(GNEAttributeCarrier *AC)
add GL Object into net
Definition: GNENet.cpp:1311
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:123
GNEPathManager * getPathManager()
get path manager
Definition: GNENet.cpp:135
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:2069
bool checkDrawPathGeometry(const GUIVisualizationSettings &s, const GNELane *lane, SumoXMLTag tag)
check if path element geometry must be drawn in the given lane
const GNELane * getPreviousLane() const
get previous lane
GNEContour * getContour() const
getcontour associated with segment
const GNELane * getNextLane() const
get next lane
const GNELane * getLane() const
get lane associated with this segment
bool isLastSegment() const
check if segment is the last path's segment
bool isFirstSegment() const
check if segment is the first path's segment
PathDraw * getPathDraw()
obtain instance of PathDraw
void calculateConsecutivePathEdges(PathElement *pathElement, SUMOVehicleClass vClass, const std::vector< GNEEdge * > edges)
calculate consecutive path edges
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 isPlanContainer() const
return true if tag correspond to a container plan
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 std::vector< GNEAttributeCarrier * > & getInspectedAttributeCarriers() const
get inspected attribute carriers
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:538
static FXMenuCommand * buildFXMenuCommand(FXComposite *p, const std::string &text, FXIcon *icon, FXObject *tgt, FXSelector sel, const bool disable=false)
build menu command
Definition: GUIDesigns.cpp:42
The popup menu of a globject.
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
Definition: GUIGeometry.cpp:59
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
virtual Boundary getCenteringBoundary() const =0
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
Definition: GUIGlObject.h:156
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, const GUIMainWindow &app) const
Builds an entry which allows to copy the cursor position if geo projection is used,...
void drawName(const Position &pos, const double scale, const GUIVisualizationTextSettings &settings, const double angle=0, bool forceShow=false) const
draw name of item
virtual Position getPositionInformation() const
Returns the cursor's x/y position within the network.
Stores the information about how to visualize structures.
GUIVisualizationTextSettings addName
bool drawForRectangleSelection
whether drawing is performed for the purpose of selecting objects using a rectangle
GUIVisualizationSizeSettings addSize
Detail getDetailLevel(const double exaggeration) const
return the detail level
double laneWidthExaggeration
The lane exaggeration (upscale thickness)
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
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
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
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions)
Definition: Position.h:276
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:317
double x() const
Returns the x-position.
Definition: Position.h:55
double y() const
Returns the y-position.
Definition: Position.h:60
static const RGBColor RED
named colors
Definition: RGBColor.h:185
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 segmentWidthSmall
width of small dotted contour segments
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