Eclipse SUMO - Simulation of Urban MObility
GNEDemandElement.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 // A abstract class for demand elements
19 /****************************************************************************/
20 
21 #include <netedit/GNENet.h>
22 #include <netedit/GNEViewNet.h>
23 #include <netedit/GNEViewParent.h>
30 #include <utils/gui/div/GLHelper.h>
35 
36 #include "GNEDemandElement.h"
37 #include "GNERouteHandler.h"
38 
39 // ===========================================================================
40 // member method definitions
41 // ===========================================================================
42 
43 GNEDemandElement::GNEDemandElement(const std::string& id, GNENet* net, GUIGlObjectType type, SumoXMLTag tag, FXIcon* icon, const int options,
44  const std::vector<GNEJunction*>& junctionParents,
45  const std::vector<GNEEdge*>& edgeParents,
46  const std::vector<GNELane*>& laneParents,
47  const std::vector<GNEAdditional*>& additionalParents,
48  const std::vector<GNEDemandElement*>& demandElementParents,
49  const std::vector<GNEGenericData*>& genericDataParents) :
50  GNEPathManager::PathElement(type, id, icon, options),
51  GNEHierarchicalElement(net, tag, junctionParents, edgeParents, laneParents, additionalParents, demandElementParents, genericDataParents),
53  myStackedLabelNumber(0) {
54  // check if is template
55  myIsTemplate = id.empty();
56 }
57 
58 
59 GNEDemandElement::GNEDemandElement(GNEDemandElement* demandElementParent, GNENet* net, GUIGlObjectType type, SumoXMLTag tag, FXIcon* icon, const int options,
60  const std::vector<GNEJunction*>& junctionParents,
61  const std::vector<GNEEdge*>& edgeParents,
62  const std::vector<GNELane*>& laneParents,
63  const std::vector<GNEAdditional*>& additionalParents,
64  const std::vector<GNEDemandElement*>& demandElementParents,
65  const std::vector<GNEGenericData*>& genericDataParents) :
66  GNEPathManager::PathElement(type, demandElementParent->getID(), icon, options),
67  GNEHierarchicalElement(net, tag, junctionParents, edgeParents, laneParents, additionalParents, demandElementParents, genericDataParents),
69  myStackedLabelNumber(0) {
70 }
71 
72 
74 
75 
76 void
77 GNEDemandElement::removeGeometryPoint(const Position /*clickedPosition*/, GNEUndoList* /*undoList*/) {
78  // currently there isn't demand elements with removable geometry points
79 }
80 
81 
84  return this;
85 }
86 
87 
88 const GUIGlObject*
90  return this;
91 }
92 
93 
94 const GUIGeometry&
97 }
98 
99 
102  // first check if there are demand elements
103  if (getChildDemandElements().empty()) {
104  return nullptr;
105  } else {
106  // find child demand element
107  auto it = std::find(getChildDemandElements().begin(), getChildDemandElements().end(), demandElement);
108  // return element or null depending of iterator
109  if (it == getChildDemandElements().end()) {
110  // in this case, we assume that the last child is the previos child
111  return getChildDemandElements().back();
112  } else if (it == getChildDemandElements().begin()) {
113  return nullptr;
114  } else {
115  return *(it - 1);
116  }
117  }
118 }
119 
120 
123  // find child demand element
124  auto it = std::find(getChildDemandElements().begin(), getChildDemandElements().end(), demandElement);
125  // return element or null depending of iterator
126  if (it == getChildDemandElements().end()) {
127  return nullptr;
128  } else if (it == (getChildDemandElements().end() - 1)) {
129  return nullptr;
130  } else {
131  return *(it + 1);
132  }
133 }
134 
135 
136 void
137 GNEDemandElement::updateDemandElementGeometry(const GNELane* lane, const double posOverLane) {
139 }
140 
141 
142 void
144  myStackedLabelNumber = stack;
145 }
146 
147 
148 void
149 GNEDemandElement::updateDemandElementSpreadGeometry(const GNELane* lane, const double posOverLane) {
151 }
152 
153 
154 const GUIGeometry&
157 }
158 
159 
160 bool
162  return false;
163 }
164 
165 
166 bool
168  return false;
169 }
170 
171 
172 bool
174  return false;
175 }
176 
177 
178 bool
180  // get modes
181  const auto& modes = myNet->getViewNet()->getEditModes();
182  // get frames
183  const auto& personFramePlanSelector = myNet->getViewNet()->getViewParent()->getPersonFrame()->getPlanSelector();
184  const auto& personPlanFramePlanSelector = myNet->getViewNet()->getViewParent()->getPersonPlanFrame()->getPlanSelector();
185  const auto& containerFramePlanSelector = myNet->getViewNet()->getViewParent()->getContainerFrame()->getPlanSelector();
186  const auto& containerPlanFramePlanSelector = myNet->getViewNet()->getViewParent()->getContainerPlanFrame()->getPlanSelector();
187  // special case for Route
189  // get vehicle frame
190  const auto& vehicleFrame = myNet->getViewNet()->getViewParent()->getVehicleFrame();
191  // check if we're in vehicle mode
192  if (vehicleFrame->shown()) {
193  // get current vehicle template
194  const auto& vehicleTemplate = vehicleFrame->getVehicleTagSelector()->getCurrentTemplateAC();
195  // check if vehicle can be placed over route
196  if (vehicleTemplate && vehicleTemplate->getTagProperty().vehicleRoute()) {
198  }
199  } else if (modes.isCurrentSupermodeDemand()) {
200  // check if we're in person or personPlan modes
201  if (((modes.demandEditMode == DemandEditMode::DEMAND_PERSON) && personFramePlanSelector->markRoutes()) ||
202  ((modes.demandEditMode == DemandEditMode::DEMAND_PERSONPLAN) && personPlanFramePlanSelector->markRoutes()) ||
203  ((modes.demandEditMode == DemandEditMode::DEMAND_CONTAINER) && containerFramePlanSelector->markRoutes()) ||
204  ((modes.demandEditMode == DemandEditMode::DEMAND_CONTAINERPLAN) && containerPlanFramePlanSelector->markRoutes())) {
206  }
207  }
208  }
209  return false;
210 }
211 
212 
213 bool
215  // get edit modes
216  const auto& editModes = myNet->getViewNet()->getEditModes();
217  // check if we're in delete mode
218  if (editModes.isCurrentSupermodeDemand() && (editModes.demandEditMode == DemandEditMode::DEMAND_DELETE)) {
220  } else {
221  return false;
222  }
223 }
224 
225 
226 bool
228  // get edit modes
229  const auto& editModes = myNet->getViewNet()->getEditModes();
230  // check if we're in select mode
231  if (editModes.isCurrentSupermodeDemand() && (editModes.demandEditMode == DemandEditMode::DEMAND_SELECT)) {
233  } else {
234  return false;
235  }
236 }
237 
238 
239 bool
241  // get edit modes
242  const auto& editModes = myNet->getViewNet()->getEditModes();
243  // check first set of conditions
244  if (!myNet->getViewNet()->isCurrentlyMovingElements() && // another elements are not currently moved
245  editModes.isCurrentSupermodeDemand() && // supermode demand
246  (editModes.demandEditMode == DemandEditMode::DEMAND_MOVE) && // move mode
247  myNet->getViewNet()->checkOverLockedElement(this, mySelected) && // no locked
248  myNet->getViewNet()->getViewObjectsSelector().getGUIGlObjectFront() == this) { // first element
249  // continue depending of subtype
250  if (myTagProperty.isVehicle()) {
251  // only vehicles over edges can be moved
253  return true;
254  } else {
255  return false;
256  }
257  } else if ((myTagProperty.isPerson() || myTagProperty.isContainer()) && (getChildDemandElements().size() > 0)) {
258  // only persons/containers with their first plan over edge can be moved
259  return getChildDemandElements().front()->getTagProperty().planFromEdge();
260  } else {
261  return false;
262  }
263  } else {
264  return false;
265  }
266 }
267 
268 
269 void
271  throw InvalidArgument(getTagStr() + " doesn't have a demand element dialog");
272 }
273 
274 
277  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
278  // build header
279  buildPopupHeader(ret, app);
280  // build menu command for center button and copy cursor position to clipboard
282  buildPositionCopyEntry(ret, app);
283  // build menu commands for names
284  GUIDesigns::buildFXMenuCommand(ret, "Copy " + getTagStr() + " name to clipboard", nullptr, ret, MID_COPY_NAME);
285  GUIDesigns::buildFXMenuCommand(ret, "Copy " + getTagStr() + " typed name to clipboard", nullptr, ret, MID_COPY_TYPED_NAME);
286  new FXMenuSeparator(ret);
287  // build selection and show parameters menu
290  // show option to open demand element dialog
291  if (myTagProperty.hasDialog()) {
292  GUIDesigns::buildFXMenuCommand(ret, ("Open " + getTagStr() + " Dialog").c_str(), getACIcon(), &parent, MID_OPEN_ADDITIONAL_DIALOG);
293  new FXMenuSeparator(ret);
294  }
295  GUIDesigns::buildFXMenuCommand(ret, "Cursor position in view: " + toString(getPositionInView().x()) + "," + toString(getPositionInView().y()), nullptr, nullptr, 0);
296  return ret;
297 }
298 
299 
302  // Create table
303  GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
304  // Iterate over attributes
305  for (const auto& i : myTagProperty) {
306  // Add attribute and set it dynamic if aren't unique
307  if (i.isUnique()) {
308  ret->mkItem(i.getAttrStr().c_str(), false, getAttribute(i.getAttr()));
309  } else {
310  ret->mkItem(i.getAttrStr().c_str(), true, getAttribute(i.getAttr()));
311  }
312  }
313  // close building
314  ret->closeBuilding();
315  return ret;
316 }
317 
318 
319 bool
323  } else {
324  return true;
325  }
326 }
327 
328 
329 void
332 }
333 
334 
335 void
337  // we need an special checks due hierarchies
338  if (myTagProperty.isPlan()) {
339  // get person/container plarent
340  GNEDemandElement* planParent = getParentDemandElements().front();
341  // if this is the last person/container plan element, remove parent instead plan
342  if (planParent->getChildDemandElements().size() == 1) {
343  planParent->deleteGLObject();
344  } else {
346  }
347  } else if (myTagProperty.getTag() == GNE_TAG_ROUTE_EMBEDDED) {
348  // remove parent demand element
349  getParentDemandElements().front()->deleteGLObject();
350  } else {
352  }
353 }
354 
355 
356 void
360  } else {
362  }
363  // update information label
365 }
366 
367 
368 void
370  updateGeometry();
371 }
372 
373 
374 bool
376  return mySelected;
377 }
378 
379 // ---------------------------------------------------------------------------
380 // GNEDemandElement - protected methods
381 // ---------------------------------------------------------------------------
382 
383 bool
384 GNEDemandElement::isValidDemandElementID(const std::string& value) const {
385  if (value == getID()) {
386  return true;
387  } else if (SUMOXMLDefinitions::isValidVehicleID(value)) {
388  return (myNet->getAttributeCarriers()->retrieveDemandElement(myTagProperty.getTag(), value, false) == nullptr);
389  } else {
390  return false;
391  }
392 }
393 
394 
395 bool
396 GNEDemandElement::isValidDemandElementID(const std::vector<SumoXMLTag>& tags, const std::string& value) const {
397  if (value == getID()) {
398  return true;
399  } else if (SUMOXMLDefinitions::isValidVehicleID(value)) {
400  return (myNet->getAttributeCarriers()->retrieveDemandElements(tags, value, false) == nullptr);
401  } else {
402  return false;
403  }
404 }
405 
406 
407 void
408 GNEDemandElement::setDemandElementID(const std::string& newID) {
409  // update ID
411  setMicrosimID(newID);
412  } else {
414  }
415  // check if update ids of child elements
417  // Change IDs of all person plans children (stops, embedded routes...)
418  for (const auto& childDemandElement : getChildDemandElements()) {
419  childDemandElement->setDemandElementID(getID());
420  }
421  }
422 }
423 
424 
427  if (getParentDemandElements().size() < 1) {
428  throw InvalidArgument("This demand element doesn't have a type parent");
429  } else if (!getParentDemandElements().at(0)->getTagProperty().isType()
430  && !getParentDemandElements().at(0)->getTagProperty().isTypeDist()) {
431  throw InvalidArgument("The first parent isn't a type");
432  } else if (getParentDemandElements().at(0)->getTagProperty().getTag() == SUMO_TAG_VTYPE) {
433  return getParentDemandElements().at(0);
434  } else {
435  // get typeDistribution ID
436  const auto typeDistributionID = getParentDemandElements().at(0)->getID();
437  // obtain all types with the given typeDistribution sorted by ID
438  std::map<std::string, GNEDemandElement*> sortedTypes;
439  for (const auto& type : myNet->getAttributeCarriers()->getDemandElements().at(SUMO_TAG_VTYPE)) {
440  if (type.second->getAttribute(GNE_ATTR_VTYPE_DISTRIBUTION) == typeDistributionID) {
441  sortedTypes[type.second->getID()] = type.second;
442  }
443  }
444  // return first type, or default vType
445  if (sortedTypes.size() > 0) {
446  return sortedTypes.begin()->second;
447  } else if (myNet->getAttributeCarriers()->getDemandElements().size() > 0) {
448  return myNet->getAttributeCarriers()->getDemandElements().at(SUMO_TAG_VTYPE).begin()->second;
449  } else {
450  throw InvalidArgument("no vTypes");
451  }
452  }
453 }
454 
455 
458  if (getParentDemandElements().size() < 2) {
459  throw InvalidArgument("This demand element doesn't have two parent");
460  } else if (getParentDemandElements().at(1)->getTagProperty().getTag() != SUMO_TAG_ROUTE) {
461  throw InvalidArgument("This demand element doesn't have a route parent");
462  } else {
463  return getParentDemandElements().at(1);
464  }
465 }
466 
467 
468 std::vector<GNEDemandElement*>
471  // get stops
472  std::vector<GNEDemandElement*> invalidStops;
473  // get edge stop index
474  const auto edgeStopIndex = getEdgeStopIndex();
475  // take all stops/waypoints with index = -1
476  for (const auto& edgeStop : edgeStopIndex) {
477  if (edgeStop.stopIndex == -1) {
478  for (const auto& stop : edgeStop.stops) {
479  invalidStops.push_back(stop);
480  }
481  }
482  }
483  return invalidStops;
484  } else {
485  return {};
486  }
487 }
488 
489 
490 void
492  // get two points
493  const Position posA = element->getParentJunctions().front()->getPositionInView();
494  const Position posB = element->getParentJunctions().back()->getPositionInView();
495  const double rot = ((double)atan2((posB.x() - posA.x()), (posA.y() - posB.y())) * (double) 180.0 / (double)M_PI);
496  const double len = posA.distanceTo2D(posB);
497  // push draw matrix
499  // Start with the drawing of the area traslating matrix to origin
500  myNet->getViewNet()->drawTranslateFrontAttributeCarrier(this, element->getType() + 0.1);
501  // set trip color
503  // draw line
504  GLHelper::drawBoxLine(posA, rot, len, 0.25);
505  // pop draw matrix
507 }
508 
509 
510 void
511 GNEDemandElement::drawStackLabel(const int number, const std::string& element, const Position& position, const double rotation, const double width, const double length, const double exaggeration) const {
512  // declare contour width
513  const double contourWidth = (0.05 * exaggeration);
514  // Push matrix
516  // Traslate to top
517  glTranslated(position.x(), position.y(), GLO_ROUTE + getType() + 0.1 + GLO_PERSONFLOW);
518  glRotated(rotation, 0, 0, -1);
519  glTranslated((width * exaggeration * 0.5) + (0.35 * exaggeration), 0, 0);
520  // draw external box
522  GLHelper::drawBoxLine(Position(), 0, (length * exaggeration), 0.3 * exaggeration);
523  // draw internal box
524  glTranslated(0, 0, 0.1);
525  GLHelper::setColor(RGBColor(0, 128, 0));
526  GLHelper::drawBoxLine(Position(0, -contourWidth), Position(0, -contourWidth), 0, (length * exaggeration) - (contourWidth * 2), (0.3 * exaggeration) - contourWidth);
527  // draw stack label
528  GLHelper::drawText(element + "s stacked: " + toString(number), Position(0, length * exaggeration * -0.5), (.1 * exaggeration), (0.6 * exaggeration), RGBColor::WHITE, 90, 0, -1);
529  // pop draw matrix
531 }
532 
533 
534 void
536  replaceParentElements(this, parse<std::vector<GNEEdge*> >(getNet(), value));
537 }
538 
539 
540 void
542  replaceParentElements(this, parse<std::vector<GNELane*> >(getNet(), value));
543 }
544 
545 
546 void
548  std::vector<GNEJunction*> parentJunctions = getParentJunctions();
549  parentJunctions[0] = myNet->getAttributeCarriers()->retrieveJunction(value);
550  // replace parent junctions
551  replaceParentElements(this, parentJunctions);
552 }
553 
554 
555 void
557  std::vector<GNEJunction*> parentJunctions = getParentJunctions();
558  parentJunctions[(int)parentJunctions.size() - 1] = myNet->getAttributeCarriers()->retrieveJunction(value);
559  // replace parent junctions
560  replaceParentElements(this, parentJunctions);
561 }
562 
563 
564 void
565 GNEDemandElement::replaceFirstParentEdge(const std::string& value) {
566  std::vector<GNEEdge*> parentEdges = getParentEdges();
567  parentEdges[0] = myNet->getAttributeCarriers()->retrieveEdge(value);
568  // replace parent edges
569  replaceParentElements(this, parentEdges);
570 }
571 
572 
573 void
574 GNEDemandElement::replaceLastParentEdge(const std::string& value) {
575  std::vector<GNEEdge*> parentEdges = getParentEdges();
576  parentEdges[(int)parentEdges.size() - 1] = myNet->getAttributeCarriers()->retrieveEdge(value);
577  // replace parent edges
578  replaceParentElements(this, parentEdges);
579 }
580 
581 
582 void
584  std::vector<GNEAdditional*> parentAdditionals = getParentAdditionals();
585  parentAdditionals[0] = myNet->getAttributeCarriers()->retrieveAdditional(tag, value);
586  // replace parent additionals
587  replaceParentElements(this, parentAdditionals);
588 }
589 
590 
591 void
593  std::vector<GNEAdditional*> parentAdditionals = getParentAdditionals();
594  parentAdditionals[(int)parentAdditionals.size() - 1] = myNet->getAttributeCarriers()->retrieveAdditional(tag, value);
595  // replace parent additionals
596  replaceParentElements(this, parentAdditionals);
597 }
598 
599 
600 void
601 GNEDemandElement::replaceDemandElementParent(SumoXMLTag tag, const std::string& value, const int parentIndex) {
602  std::vector<GNEDemandElement*> parentDemandElements = getParentDemandElements();
603  parentDemandElements[parentIndex] = myNet->getAttributeCarriers()->retrieveDemandElement(tag, value);
604  // replace parent demand elements
605  replaceParentElements(this, parentDemandElements);
606 }
607 
608 
609 void
611  std::vector<GNEDemandElement*> parents;
612  if (value.size() > 0) {
614  }
615  replaceParentElements(this, parents);
616 }
617 
618 
619 bool
621  // throw exception because this function mus be implemented in child (see GNEE3Detector)
622  throw ProcessError(StringUtils::format("Calling non-implemented function checkChildDemandElementRestriction during saving of %. It muss be reimplemented in child class", getTagStr()));
623 }
624 
625 
626 std::vector<GNEDemandElement::EdgeStopIndex>
628  std::vector<GNEDemandElement::EdgeStopIndex> edgeStopIndex;
629  // first check that this stop has parent
630  if (getParentDemandElements().size() > 0) {
631  // get path edges depending of parent
632  std::vector<GNEEdge*> pathEdges;
633  // get parent demand element
634  const auto parent = getParentDemandElements().front();
635  // continue depending of parent
636  if (parent->getTagProperty().hasAttribute(SUMO_ATTR_EDGES)) {
637  pathEdges = parent->getParentEdges();
638  } else if (parent->getTagProperty().vehicleRoute()) {
639  // get route edges
640  if (parent->getParentDemandElements().size() > 1) {
641  pathEdges = parent->getParentDemandElements().at(1)->getParentEdges();
642  }
643  } else if (parent->getTagProperty().vehicleRouteEmbedded()) {
644  // get embedded route edges
645  pathEdges = parent->getChildDemandElements().front()->getParentEdges();
646  } else {
647  // get last parent edge
648  const auto lastEdge = parent->getParentEdges().back();
649  bool stop = false;
650  const auto& pathElementSegments = myNet->getPathManager()->getPathElementSegments(parent);
651  // extract all edges from pathElement parent
652  for (auto it = pathElementSegments.begin(); (it != pathElementSegments.end()) && !stop; it++) {
653  if ((*it)->getLane()) {
654  pathEdges.push_back((*it)->getLane()->getParentEdge());
655  // stop if path correspond to last edge
656  if (pathEdges.back() == lastEdge) {
657  stop = true;
658  }
659  }
660  }
661  }
662  // get all parent's stops and waypoints sorted by position
663  for (const auto& demandElement : parent->getChildDemandElements()) {
664  if (demandElement->getTagProperty().isVehicleStop()) {
665  // get stop/waypoint edge
666  GNEEdge* edge = nullptr;
667  if (demandElement->getParentAdditionals().size() > 0) {
668  edge = demandElement->getParentAdditionals().front()->getParentLanes().front()->getParentEdge();
669  } else {
670  edge = demandElement->getParentLanes().front()->getParentEdge();
671  }
672  // check if add a new edgeStopIndex or update last
673  if ((edgeStopIndex.size() > 0) && (edgeStopIndex.back().edge == edge)) {
674  edgeStopIndex.back().stops.push_back(demandElement);
675  } else {
676  edgeStopIndex.push_back(EdgeStopIndex(edge, demandElement));
677  }
678  }
679  }
680  // declare index for current stop
681  int currentEdgeStopIndex = 0;
682  for (int i = 0; (i < (int)pathEdges.size()) && (currentEdgeStopIndex < (int)edgeStopIndex.size()); i++) {
683  // check if current edge stop index is in the path
684  if (edgeStopIndex[currentEdgeStopIndex].edge == pathEdges.at(i)) {
685  edgeStopIndex[currentEdgeStopIndex].stopIndex = i;
686  currentEdgeStopIndex++;
687  } else {
688  // check if edge exist in the rest of the path
689  bool next = false;
690  for (int j = (i + 1); j < (int)pathEdges.size(); j++) {
691  if (edgeStopIndex[currentEdgeStopIndex].edge == pathEdges.at(j)) {
692  next = true;
693  }
694  }
695  if (!next) {
696  // ignore current stops (because is out of path)
697  currentEdgeStopIndex++;
698  }
699  }
700  }
701  }
702  // sort stops by position
703  for (auto& edgeStop : edgeStopIndex) {
704  if (edgeStop.stops.size() > 1) {
705  // copy all stops to a map to sort it by endPos
706  std::map<double, std::vector<GNEDemandElement*> > sortedStops;
707  for (const auto& stop : edgeStop.stops) {
708  if (sortedStops.count(stop->getAttributeDouble(SUMO_ATTR_ENDPOS)) == 0) {
709  sortedStops[stop->getAttributeDouble(SUMO_ATTR_ENDPOS)] = {stop};
710  } else {
711  sortedStops[stop->getAttributeDouble(SUMO_ATTR_ENDPOS)].push_back(stop);
712  }
713  }
714  // update stops with sorted stops
715  edgeStop.stops.clear();
716  for (const auto& sortedStop : sortedStops) {
717  edgeStop.stops.insert(edgeStop.stops.end(), sortedStop.second.begin(), sortedStop.second.end());
718  }
719  }
720  }
721  return edgeStopIndex;
722 }
723 
724 
725 RGBColor
727  // set color depending of color active
728  switch (c.getActive()) {
729  case 0: {
730  // test for emergency vehicle
731  if (getTypeParent()->getAttribute(SUMO_ATTR_GUISHAPE) == "emergency") {
732  return RGBColor::WHITE;
733  }
734  // test for firebrigade
735  if (getTypeParent()->getAttribute(SUMO_ATTR_GUISHAPE) == "firebrigade") {
736  return RGBColor::RED;
737  }
738  // test for police car
739  if (getTypeParent()->getAttribute(SUMO_ATTR_GUISHAPE) == "police") {
740  return RGBColor::BLUE;
741  }
742  if (getTypeParent()->getAttribute(SUMO_ATTR_GUISHAPE) == "scooter") {
743  return RGBColor::WHITE;
744  }
745  // check if color was set
746  if (parameters->wasSet(VEHPARS_COLOR_SET)) {
747  return parameters->color;
748  } else {
749  // take their parent's color)
750  return getTypeParent()->getColor();
751  }
752  }
753  case 2: {
754  if (parameters->wasSet(VEHPARS_COLOR_SET)) {
755  return parameters->color;
756  } else {
757  return c.getScheme().getColor(0);
758  }
759  }
760  case 3: {
762  return getTypeParent()->getColor();
763  } else {
764  return c.getScheme().getColor(0);
765  }
766  break;
767  }
768  case 4: {
770  return getRouteParent()->getColor();
771  } else {
772  return c.getScheme().getColor(0);
773  }
774  }
775  case 5: {
776  Position p = getRouteParent()->getParentEdges().at(0)->getLanes().at(0)->getLaneShape()[0];
777  const Boundary& b = myNet->getBoundary();
778  Position center = b.getCenter();
779  double hue = 180. + atan2(center.x() - p.x(), center.y() - p.y()) * 180. / M_PI;
780  double sat = p.distanceTo(center) / center.distanceTo(Position(b.xmin(), b.ymin()));
781  return RGBColor::fromHSV(hue, sat, 1.);
782  }
783  case 6: {
784  Position p = getRouteParent()->getParentEdges().back()->getLanes().at(0)->getLaneShape()[-1];
785  const Boundary& b = myNet->getBoundary();
786  Position center = b.getCenter();
787  double hue = 180. + atan2(center.x() - p.x(), center.y() - p.y()) * 180. / M_PI;
788  double sat = p.distanceTo(center) / center.distanceTo(Position(b.xmin(), b.ymin()));
789  return RGBColor::fromHSV(hue, sat, 1.);
790  }
791  case 7: {
792  Position pb = getRouteParent()->getParentEdges().at(0)->getLanes().at(0)->getLaneShape()[0];
793  Position pe = getRouteParent()->getParentEdges().back()->getLanes().at(0)->getLaneShape()[-1];
794  const Boundary& b = myNet->getBoundary();
795  double hue = 180. + atan2(pb.x() - pe.x(), pb.y() - pe.y()) * 180. / M_PI;
796  Position minp(b.xmin(), b.ymin());
797  Position maxp(b.xmax(), b.ymax());
798  double sat = pb.distanceTo(pe) / minp.distanceTo(maxp);
799  return RGBColor::fromHSV(hue, sat, 1.);
800  }
801  case 35: { // color randomly (by pointer hash)
802  std::hash<const GNEDemandElement*> ptr_hash;
803  const double hue = (double)(ptr_hash(this) % 360); // [0-360]
804  const double sat = (double)((ptr_hash(this) / 360) % 67) / 100. + 0.33; // [0.33-1]
805  return RGBColor::fromHSV(hue, sat, 1.);
806  }
807  default: {
808  return c.getScheme().getColor(0);
809  }
810  }
811 }
812 
813 
814 std::string
816  SumoXMLTag tagDistribution = SUMO_TAG_NOTHING;
818  tagDistribution = SUMO_TAG_VTYPE_DISTRIBUTION;
819  } else if (myTagProperty.getTag() == SUMO_TAG_ROUTE) {
820  tagDistribution = SUMO_TAG_ROUTE_DISTRIBUTION;
821  } else {
822  return "";
823  }
824  // check if the current element is in the distributions
825  std::vector<std::string> distributionParents;
826  for (const auto& distribution : myNet->getAttributeCarriers()->getDemandElements().at(tagDistribution)) {
827  if (distribution.second->keyExists(this)) {
828  distributionParents.push_back(distribution.second->getID());
829  }
830  }
831  return toString(distributionParents);
832 }
833 
834 
835 void
837  std::vector<GNEEdge*> edges;
838  if (myTagProperty.isRoute()) {
839  edges = getParentEdges();
840  } else if (myTagProperty.vehicleRoute()) {
841  edges = getParentDemandElements().at(1)->getParentEdges();
842  } else if (myTagProperty.vehicleRouteEmbedded()) {
843  edges = getChildDemandElements().front()->getParentEdges();
844  } else if (myTagProperty.vehicleEdges()) {
845  edges = getParentEdges();
846  }
847  // calculate path
848  const auto path = myNet->getPathManager()->getPathCalculator()->calculateDijkstraPath(getVClass(), edges);
849  // check path size
850  if (path.size() > 0) {
851  double length = 0;
852  for (const auto& edge : path) {
853  length += edge->getNBEdge()->getFinalLength();
854  }
855  for (int i = 0; i < ((int)path.size() - 1); i++) {
856  length += path.at(i)->getLanes().front()->getLane2laneConnections().getLane2laneGeometry(path.at(i + 1)->getLanes().front()).getShape().length();
857  }
858  GUIDesigns::buildFXMenuCommand(ret, TL("Route length: ") + toString(length), nullptr, ret, MID_COPY_NAME);
859  }
860 }
861 
862 
863 void
865  // create menu pane for transform operations
866  FXMenuPane* transformOperation = new FXMenuPane(ret);
867  ret->insertMenuPaneChild(transformOperation);
868  auto reverseMenuCascade = new FXMenuCascade(ret, TL("reverse"), nullptr, transformOperation);
869  // build menu commands
870  GUIDesigns::buildFXMenuCommand(transformOperation, TLF("reverse current %", myTagProperty.getTagStr()), nullptr, myNet->getViewNet(), MID_GNE_REVERSE);
871  GUIDesigns::buildFXMenuCommand(transformOperation, TLF("Add reverse %", myTagProperty.getTagStr()), nullptr, myNet->getViewNet(), MID_GNE_ADDREVERSE);
872  // check if reverse can be added
873  if (GNERouteHandler::canReverse(this)) {
874  reverseMenuCascade->enable();
875  } else {
876  reverseMenuCascade->disable();
877  }
878 }
879 
880 /****************************************************************************/
@ DEMAND_PERSONPLAN
Mode for editing person plan.
@ DEMAND_CONTAINER
Mode for editing container.
@ DEMAND_DELETE
mode for deleting demand elements
@ DEMAND_PERSON
Mode for editing person.
@ DEMAND_SELECT
mode for selecting demand elements
@ DEMAND_MOVE
mode for moving demand elements
@ DEMAND_CONTAINERPLAN
Mode for editing container plan.
@ MID_GNE_ADDREVERSE
add reverse element
Definition: GUIAppEnum.h:1412
@ MID_COPY_TYPED_NAME
Copy typed object name - popup entry.
Definition: GUIAppEnum.h:455
@ MID_GNE_REVERSE
reverse current element
Definition: GUIAppEnum.h:1410
@ MID_OPEN_ADDITIONAL_DIALOG
open additional dialog (used in netedit)
Definition: GUIAppEnum.h:469
@ MID_COPY_NAME
Copy object name - popup entry.
Definition: GUIAppEnum.h:453
GUIGlObjectType
@ GLO_ROUTE
a route
@ GLO_PERSONFLOW
a person flow
#define TL(string)
Definition: MsgHandler.h:315
#define TLF(string,...)
Definition: MsgHandler.h:317
const int VEHPARS_COLOR_SET
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_VTYPE
description of a vehicle/person/container type
@ SUMO_TAG_NOTHING
invalid tag, must be the last one
@ SUMO_TAG_ROUTE_DISTRIBUTION
distribution of a route
@ SUMO_TAG_ROUTE
begin/end of the description of a route
@ SUMO_TAG_VTYPE_DISTRIBUTION
distribution of a vehicle type
@ GNE_TAG_ROUTE_EMBEDDED
embedded route
@ SUMO_ATTR_ENDPOS
@ GNE_ATTR_VTYPE_DISTRIBUTION
vehicle type distribution
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_GUISHAPE
@ SUMO_ATTR_COLOR
A color information.
@ SUMO_ATTR_ID
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
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:130
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:118
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:136
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:124
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:654
static void popMatrix()
pop matrix
Definition: GLHelper.cpp:130
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition: GLHelper.cpp:295
static void pushMatrix()
push matrix
Definition: GLHelper.cpp:117
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition: GLHelper.cpp:756
const std::string getID() const
get ID (all Attribute Carriers have one)
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
FXIcon * getACIcon() const
get FXIcon associated to this AC
bool mySelected
boolean to check if this AC is selected (instead of GUIGlObjectStorage)
bool myIsTemplate
whether the current object is a template object (not drawn in the view)
static T parse(const std::string &string)
parses a value of type T from string (used for basic types: int, double, bool, etc....
virtual bool isAttributeEnabled(SumoXMLAttr key) const
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
GNENet * myNet
pointer to net
GNENet * getNet() const
get pointer to net
void selectAttributeCarrier(const bool changeFlag=true)
select attribute carrier using GUIGlobalSelection
const GNETagProperties & myTagProperty
reference to tagProperty associated with this attribute carrier
GNEPlanSelector * getPlanSelector() const
get containerPlan selector
GNEPlanSelector * getPlanSelector() const
get containerPlan selector
void buildMenuCommandRouteLength(GUIGLObjectPopupMenu *ret) const
build menu command route length
void replaceDemandParentEdges(const std::string &value)
replace demand parent edges
virtual void updateGeometry()=0
update pre-computed geometry information
std::vector< GNEDemandElement * > getInvalidStops() const
get invalid stops
virtual SUMOVehicleClass getVClass() const =0
obtain VClass related with this demand element
void updateDemandElementGeometry(const GNELane *lane, const double posOverLane)
update element stacked geometry (stacked)
void replaceDemandElementParent(SumoXMLTag tag, const std::string &value, const int parentIndex)
replace demand element parent
void drawStackLabel(const int number, const std::string &element, const Position &position, const double rotation, const double width, const double length, const double exaggeration) const
draw stack label
bool checkDrawOverContour() const
check if draw over contour (orange)
std::string getDistributionParents() const
get distribution in which the given element is part
GUIGeometry myDemandElementGeometry
demand element geometry (also called "stacked geometry")
bool isValidDemandElementID(const std::string &value) const
check if a new demand element ID is valid
GNEDemandElement * getNextChildDemandElement(const GNEDemandElement *demandElement) const
get next child demand element to the given demand element
void updateDemandElementStackLabel(const int stack)
update stack label
void replaceLastParentEdge(const std::string &value)
replace the last parent edge
void drawJunctionLine(const GNEDemandElement *element) const
draw line between junctions
virtual std::string getAttribute(SumoXMLAttr key) const =0
GUIGlObject * getGUIGlObject()
get GUIGlObject associated with this AttributeCarrier
bool isPathElementSelected() const
check if path element is selected
bool checkDrawToContour() const
check if draw from contour (magenta)
void replaceFirstParentAdditional(SumoXMLTag tag, const std::string &value)
replace the first parent additional
GNEDemandElement * getRouteParent() const
get route parent (always the second parent demand element)
void selectGLObject()
select element
bool checkDrawMoveContour() const
check if draw move contour (red)
bool checkDrawDeleteContour() const
check if draw delete contour (pink/white)
void setDemandElementID(const std::string &newID)
set demand element id
GUIGeometry mySpreadGeometry
demand element spread geometry (Only used by vehicles and pedestrians)
void buildMenuAddReverse(GUIGLObjectPopupMenu *ret) const
build menu command route length
void replaceFirstParentJunction(const std::string &value)
replace the first parent junction
std::vector< EdgeStopIndex > getEdgeStopIndex() const
get edgeStopIndex
bool checkDrawRelatedContour() const
check if draw related contour (cyan)
void setVTypeDistributionParent(const std::string &value)
set VTypeDistribution parent
void updateGLObject()
update GLObject (geometry, ID, etc.)
GNEDemandElement * getTypeParent() const
get type parent (needed because first parent can be either type or typeDistribution)
bool checkDrawSelectContour() const
check if draw select contour (blue)
void replaceDemandParentLanes(const std::string &value)
replace demand parent lanes
void replaceFirstParentEdge(const std::string &value)
replace the first parent edge
int myStackedLabelNumber
stacked label number
virtual const RGBColor & getColor() const =0
get color
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
void updateDemandElementSpreadGeometry(const GNELane *lane, const double posOverLane)
update element spread geometry
virtual Position getPositionInView() const =0
Returns position of demand element in view.
RGBColor getColorByScheme(const GUIColorer &c, const SUMOVehicleParameter *parameters) const
get color by scheme (used by vehicles, persons and containers)
const GUIGeometry & getDemandElementGeometry()
get demand element geometry (stacked)
virtual GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
virtual bool checkChildDemandElementRestriction() const
check restriction with the number of children
void removeGeometryPoint(const Position clickedPosition, GNEUndoList *undoList)
remove geometry point in the clicked position (Currently unused in shapes)
GNEDemandElement * getPreviousChildDemandElement(const GNEDemandElement *demandElement) const
get previous child demand element to the given demand element
bool isGLObjectLocked() const
check if element is locked
void markAsFrontElement()
mark element as front element
void replaceLastParentAdditional(SumoXMLTag tag, const std::string &value)
replace the last parent additional
virtual ~GNEDemandElement()
Destructor.
virtual void openDemandElementDialog()
open DemandElement Dialog
void deleteGLObject()
delete element
void replaceLastParentJunction(const std::string &value)
replace the last parent junction
bool checkDrawFromContour() const
check if draw from contour (green)
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
const std::vector< GNELane * > & getParentLanes() const
get parent lanes
void replaceParentElements(T *elementChild, const U &newParents)
replace parent elements
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
double myMoveElementLateralOffset
move element lateral offset (used by elements placed over lanes
GNEAdditional * retrieveAdditional(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named additional.
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
GNEDemandElement * retrieveDemandElements(const std::vector< SumoXMLTag > types, const std::string &id, bool hardFail=true) const
Returns the named demand element.
void updateDemandElementID(GNEDemandElement *demandElement, const std::string &newID)
update demand element ID in container
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
GNEDemandElement * retrieveDemandElement(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named demand element.
const std::map< SumoXMLTag, std::map< const GUIGlObject *, GNEDemandElement * > > & getDemandElements() const
get demand elements
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:42
void deleteDemandElement(GNEDemandElement *demandElement, GNEUndoList *undoList)
remove demand element
Definition: GNENet.cpp:675
const Boundary & getBoundary() const
returns the bounder of the network
Definition: GNENet.cpp:141
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:2136
std::vector< GNEEdge * > calculateDijkstraPath(const SUMOVehicleClass vClass, const std::vector< GNEEdge * > &edges) const
calculate Dijkstra path between a list of edges (for example, from-via-to edges)
PathCalculator * getPathCalculator()
obtain instance of PathCalculator
const std::vector< Segment * > & getPathElementSegments(PathElement *pathElement) const
get path segments
GNEPlanSelector * getPlanSelector() const
get personPlan selector
GNEPlanSelector * getPlanSelector() const
get personPlan selector
static bool canReverse(const GNEDemandElement *element)
reverse functions
void updateInformationLabel()
update information label
SelectionInformation * getSelectionInformation() const
get modul for selection information
bool isContainer() const
return true if tag correspond to a container element
bool isPlan() const
plans
const std::string & getTagStr() const
get Tag vinculated with this attribute Property in String Format (used to avoid multiple calls to toS...
bool isRoute() const
return true if tag correspond to a route element
bool isVehicle() const
return true if tag correspond to a vehicle element
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
bool vehicleRouteEmbedded() const
return true if tag correspond to a vehicle placed over an embedded route
bool hasDialog() const
return true if tag correspond to an element that can be edited using a dialog
bool vehicleEdges() const
return true if tag correspond to a vehicle placed over from-to edges
bool hasAttribute(SumoXMLAttr attr) const
check if current TagProperties owns the attribute "attr"
bool isVehicleStop() const
return true if tag correspond to a vehicle stop element
bool isPerson() const
return true if tag correspond to a person element
bool vehicleRoute() const
plan parents
GNEAttributeCarrier * getCurrentTemplateAC() const
get current templateAC
GNETagSelector * getVehicleTagSelector() const
get vehicle tag selector (needed for transform vehicles)
bool isObjectLocked(GUIGlObjectType objectType, const bool selected) const
check if given GLObject is locked for inspect, select, delete and move
const GUIGlObject * getGUIGlObjectFront() const
get front attribute carrier or a pointer to nullptr
bool isCurrentlyMovingElements() const
check if an element is being moved
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:723
void setFrontAttributeCarrier(GNEAttributeCarrier *AC)
set front attributeCarrier
void drawTranslateFrontAttributeCarrier(const GNEAttributeCarrier *AC, double typeOrLayer, const double extraOffset=0)
draw front attributeCarrier
GNEViewParent * getViewParent() const
get the net object
bool checkOverLockedElement(const GUIGlObject *GLObject, const bool isSelected) const
check if given element is locked (used for drawing select and delete contour)
GNEUndoList * getUndoList() const
get the undoList object
const GNEViewNetHelper::ViewObjectsSelector & getViewObjectsSelector() const
get objects under cursor
Definition: GNEViewNet.cpp:477
GNEViewNetHelper::LockManager & getLockManager()
get lock manager
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:553
GNEPersonPlanFrame * getPersonPlanFrame() const
get frame for DEMAND_PERSONFRAME
GNESelectorFrame * getSelectorFrame() const
get frame for select elements
GNEContainerPlanFrame * getContainerPlanFrame() const
get frame for DEMAND_CONTAINERFRAME
GNEVehicleFrame * getVehicleFrame() const
get frame for DEMAND_VEHICLE
GNEContainerFrame * getContainerFrame() const
get frame for DEMAND_CONTAINER
GNEPersonFrame * getPersonFrame() const
get frame for DEMAND_PERSON
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.
void insertMenuPaneChild(FXMenuPane *child)
Insert a sub-menu pane in this GUIGLObjectPopupMenu.
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 void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
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,...
A window containing a gl-object's parameter.
void mkItem(const char *name, bool dynamic, ValueSource< T > *src)
Adds a row which obtains its value from a ValueSource.
void closeBuilding(const Parameterised *p=0)
Closes the building of the table.
T getColor(const double value) const
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:276
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimensions
Definition: Position.h:266
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 WHITE
Definition: RGBColor.h:192
static const RGBColor BLUE
Definition: RGBColor.h:187
static const RGBColor GREY
Definition: RGBColor.h:194
static RGBColor fromHSV(double h, double s, double v)
Converts the given hsv-triplet to rgb, inspired by http://alvyray.com/Papers/CG/hsv2rgb....
Definition: RGBColor.cpp:371
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition: RGBColor.h:199
static const RGBColor RED
named colors
Definition: RGBColor.h:185
Structure representing possible vehicle parameter.
RGBColor color
The vehicle's color, TraCI may change this.
bool wasSet(int what) const
Returns whether the given parameter was set.
static bool isValidVehicleID(const std::string &value)
whether the given string is a valid id for a vehicle or flow
static const std::string format(const std::string &format, T value, Targs... Fargs)
adds a new formatted message
Definition: StringUtils.h:185
#define M_PI
Definition: odrSpiral.cpp:45
auxiliar struct used for calculate pathStopIndex
bool isCurrentSupermodeDemand() const
@check if current supermode is Demand