SUMO - Simulation of Urban MObility
GNEAdditional.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
15 // A abstract class for representation of additional elements
16 /****************************************************************************/
17 
18 // ===========================================================================
19 // included modules
20 // ===========================================================================
21 #include <config.h>
22 
23 #include <string>
24 #include <iostream>
25 #include <utility>
30 #include <utils/common/ToString.h>
31 #include <utils/geom/GeomHelper.h>
39 #include <utils/gui/div/GLHelper.h>
46 #include <netedit/GNENet.h>
47 #include <netedit/GNEUndoList.h>
48 #include <netedit/GNEViewNet.h>
49 #include <netedit/GNEViewParent.h>
50 
51 #include "GNEAdditional.h"
52 
53 
54 // ===========================================================================
55 // member method definitions
56 // ===========================================================================
57 
58 GNEAdditional::GNEAdditional(const std::string& id, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement) :
59  GUIGlObject(type, id),
61  Parameterised(),
62  myViewNet(viewNet),
63  myAdditionalName(additionalName),
64  myBlockMovement(blockMovement),
65  myFirstAdditionalParent(nullptr),
66  mySecondAdditionalParent(nullptr),
67  myBlockIconRotation(0.) {
68 }
69 
70 
71 GNEAdditional::GNEAdditional(GNEAdditional* singleAdditionalParent, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement) :
72  GUIGlObject(type, singleAdditionalParent->generateAdditionalChildID(tag)),
74  Parameterised(),
75  myViewNet(viewNet),
76  myAdditionalName(additionalName),
77  myBlockMovement(blockMovement),
78  myFirstAdditionalParent(singleAdditionalParent),
79  mySecondAdditionalParent(nullptr),
81  // check that additional parent is of expected type
82  assert(singleAdditionalParent->getTag() == getTagProperties(getTag()).getParentTag());
83 }
84 
85 
86 GNEAdditional::GNEAdditional(GNEAdditional* firstAdditionalParent, GNEAdditional* secondAdditionalParent, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement) :
87  GUIGlObject(type, firstAdditionalParent->generateAdditionalChildID(tag)),
89  Parameterised(),
90  myViewNet(viewNet),
91  myAdditionalName(additionalName),
92  myBlockMovement(blockMovement),
93  myFirstAdditionalParent(firstAdditionalParent),
94  mySecondAdditionalParent(secondAdditionalParent),
96  // check that additional parent is of expected type
97  assert(firstAdditionalParent->getTag() == getTagProperties(getTag()).getParentTag());
98 }
99 
100 
101 GNEAdditional::GNEAdditional(const std::string& id, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement, std::vector<GNEEdge*> edgeChilds) :
102  GUIGlObject(type, id),
103  GNEAttributeCarrier(tag),
104  Parameterised(),
105  myViewNet(viewNet),
106  myAdditionalName(additionalName),
107  myBlockMovement(blockMovement),
108  myFirstAdditionalParent(nullptr),
109  mySecondAdditionalParent(nullptr),
110  myEdgeChilds(edgeChilds),
111  myBlockIconRotation(0.) {
112 }
113 
114 
115 GNEAdditional::GNEAdditional(const std::string& id, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement, std::vector<GNELane*> laneChilds) :
116  GUIGlObject(type, id),
117  GNEAttributeCarrier(tag),
118  Parameterised(),
119  myViewNet(viewNet),
120  myAdditionalName(additionalName),
121  myBlockMovement(blockMovement),
122  myFirstAdditionalParent(nullptr),
123  mySecondAdditionalParent(nullptr),
124  myLaneChilds(laneChilds),
125  myBlockIconRotation(0.) {
126 }
127 
128 
130 
131 
132 void
134  // obtain tag properties
135  const TagValues& tagProperties = getTagProperties(getTag());
136  // first check if minimum number of childs is correct
137  if ((tagProperties.hasMinimumNumberOfChilds() || tagProperties.hasMinimumNumberOfChilds()) && !checkAdditionalChildRestriction()) {
138  WRITE_WARNING(toString(getTag()) + " with ID='" + getID() + "' cannot be written");
139  } else {
140  // Open Tag or synonim Tag
141  if (tagProperties.hasTagSynonym()) {
142  device.openTag(tagProperties.getTagSynonym());
143  } else {
144  device.openTag(getTag());
145  }
146  // iterate over attributes and write it
147  for (auto i : tagProperties) {
148  // obtain attribute
149  std::string attribute = getAttribute(i.first);
150  if (i.second.isOptional() && i.second.hasDefaultValue() && !i.second.isCombinable()) {
151  // Only write attributes with default value if is different of original
152  if (i.second.getDefaultValue() != attribute) {
153  // check if attribute must be written using a synonim
154  if (i.second.hasAttrSynonym()) {
155  device.writeAttr(i.second.getAttrSynonym(), attribute);
156  } else {
157  // SVC permissions uses their own writting function
158  if (i.second.isSVCPermission()) {
159  // disallow attribute musn't be written
160  if (i.first != SUMO_ATTR_DISALLOW) {
161  writePermissions(device, parseVehicleClasses(attribute));
162  }
163  } else {
164  device.writeAttr(i.first, attribute);
165  }
166  }
167  }
168  } else {
169  // Attributes without default values are always writted
170  if (i.second.hasAttrSynonym()) {
171  device.writeAttr(i.second.getAttrSynonym(), attribute);
172  } else {
173  // SVC permissions uses their own writting function
174  if (i.second.isSVCPermission()) {
175  // disallow attribute musn't be written
176  if (i.first != SUMO_ATTR_DISALLOW) {
177  writePermissions(device, parseVehicleClasses(attribute));
178  }
179  } else {
180  device.writeAttr(i.first, attribute);
181  }
182  }
183  }
184  }
185  // save generic parameters
186  writeParams(device);
187  // iterate over childs and write it in XML (or in a different file)
188  if (tagProperties.canWriteChildsSeparate() && tagProperties.hasAttribute(SUMO_ATTR_FILE) && !getAttribute(SUMO_ATTR_FILE).empty()) {
189  // we assume that rerouter values files is placed in the same folder as the additional file
191  deviceChilds.writeXMLHeader("rerouterValue", "additional_file.xsd");
192  // save childs in a different filename
193  for (auto i : myAdditionalChilds) {
194  // avoid to write two times additionals that haben two parents (Only write as child of first parent)
195  if (i->getSecondAdditionalParent() == nullptr) {
196  i->writeAdditional(deviceChilds);
197  } else if (getTag() == getTagProperties(i->getTag()).getParentTag()) {
198  i->writeAdditional(deviceChilds);
199  }
200  }
201  deviceChilds.close();
202  } else {
203  for (auto i : myAdditionalChilds) {
204  // avoid to write two times additionals that haben two parents (Only write as child of first parent)
205  if (i->getSecondAdditionalParent() == nullptr) {
206  i->writeAdditional(device);
207  } else if (getTag() == getTagProperties(i->getTag()).getParentTag()) {
208  i->writeAdditional(device);
209  }
210  }
211  }
212  // Close tag
213  device.closeTag();
214  }
215 }
216 
217 
218 void
220  throw InvalidArgument(toString(getTag()) + " doesn't have an additional dialog");
221 }
222 
223 
224 void
226  // save current centering boundary
228 }
229 
230 
231 void
233  // check that endGeometryMoving was called only once
235  // Remove object from net
237  // reset myMovingGeometryBoundary
239  // update geometry without updating grid
240  updateGeometry(false);
241  // add object into grid again (using the new centering boundary)
243  }
244 }
245 
246 
247 GNEViewNet*
249  return myViewNet;
250 }
251 
252 
255  return myShape;
256 }
257 
258 
259 bool
261  return myBlockMovement;
262 }
263 
264 
268 }
269 
270 
274 }
275 
276 
277 std::string
279  int counter = 0;
280  while (myViewNet->getNet()->retrieveAdditional(childTag, getID() + toString(childTag) + toString(counter), false) != nullptr) {
281  counter++;
282  }
283  return (getID() + toString(childTag) + toString(counter));
284 }
285 
286 
287 void
289  // First check that additional wasn't already inserted
290  if (std::find(myAdditionalChilds.begin(), myAdditionalChilds.end(), additional) != myAdditionalChilds.end()) {
291  throw ProcessError(toString(additional->getTag()) + " with ID='" + additional->getID() + "' was already inserted in " + toString(getTag()) + " with ID='" + getID() + "'");
292  } else {
293  myAdditionalChilds.push_back(additional);
294  // Check if childs has to be sorted automatically
295  if (getTagProperties(getTag()).canAutomaticSortChilds()) {
297  }
298  // update geometry (for set geometry of lines between Parents and Childs)
299  updateGeometry(true);
300  }
301 }
302 
303 
304 void
306  // First check that additional was already inserted
307  auto it = std::find(myAdditionalChilds.begin(), myAdditionalChilds.end(), additional);
308  if (it == myAdditionalChilds.end()) {
309  throw ProcessError(toString(additional->getTag()) + " with ID='" + additional->getID() + "' doesn't exist in " + toString(getTag()) + " with ID='" + getID() + "'");
310  } else {
311  myAdditionalChilds.erase(it);
312  // Check if childs has to be sorted automatically
313  if (getTagProperties(getTag()).canAutomaticSortChilds()) {
315  }
316  // update geometry (for remove geometry of lines between Parents and Childs)
317  updateGeometry(true);
318  }
319 }
320 
321 
322 const std::vector<GNEAdditional*>&
324  return myAdditionalChilds;
325 }
326 
327 
328 void
330  if (getTag() == SUMO_TAG_E3DETECTOR) {
331  // we need to sort Entry/Exits due additional.xds model
332  std::vector<GNEAdditional*> sortedEntryExits;
333  // obtain all entrys
334  for (auto i : myAdditionalChilds) {
335  if (i->getTag() == SUMO_TAG_DET_ENTRY) {
336  sortedEntryExits.push_back(i);
337  }
338  }
339  // obtain all exits
340  for (auto i : myAdditionalChilds) {
341  if (i->getTag() == SUMO_TAG_DET_EXIT) {
342  sortedEntryExits.push_back(i);
343  }
344  }
345  // change myAdditionalChilds for sortedEntryExits
346  if (sortedEntryExits.size() == myAdditionalChilds.size()) {
347  myAdditionalChilds = sortedEntryExits;
348  } else {
349  throw ProcessError("Some additional childs were lost during sorting");
350  }
351  } else {
352  // declare a vector to keep sorted childs
353  std::vector<std::pair<std::pair<double, double>, GNEAdditional*> > sortedChilds;
354  // iterate over additional childs
355  for (auto i : myAdditionalChilds) {
356  sortedChilds.push_back(std::make_pair(std::make_pair(0., 0.), i));
357  // set begin/start attribute
358  if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_TIME) && canParse<double>(i->getAttribute(SUMO_ATTR_TIME))) {
359  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_TIME));
360  } else if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_BEGIN) && canParse<double>(i->getAttribute(SUMO_ATTR_BEGIN))) {
361  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_BEGIN));
362  }
363  // set end attribute
364  if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_END) && canParse<double>(i->getAttribute(SUMO_ATTR_END))) {
365  sortedChilds.back().first.second = parse<double>(i->getAttribute(SUMO_ATTR_END));
366  } else {
367  sortedChilds.back().first.second = sortedChilds.back().first.first;
368  }
369  }
370  // sort childs
371  std::sort(sortedChilds.begin(), sortedChilds.end());
372  // make sure that number of sorted childs is the same as the additional childs
373  if (sortedChilds.size() == myAdditionalChilds.size()) {
374  myAdditionalChilds.clear();
375  for (auto i : sortedChilds) {
376  myAdditionalChilds.push_back(i.second);
377  }
378  } else {
379  throw ProcessError("Some additional childs were lost during sorting");
380  }
381  }
382 }
383 
384 
385 bool
387  // declare a vector to keep sorted childs
388  std::vector<std::pair<std::pair<double, double>, GNEAdditional*> > sortedChilds;
389  // iterate over additional childs
390  for (auto i : myAdditionalChilds) {
391  sortedChilds.push_back(std::make_pair(std::make_pair(0., 0.), i));
392  // set begin/start attribute
393  if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_TIME) && canParse<double>(i->getAttribute(SUMO_ATTR_TIME))) {
394  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_TIME));
395  } else if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_BEGIN) && canParse<double>(i->getAttribute(SUMO_ATTR_BEGIN))) {
396  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_BEGIN));
397  }
398  // set end attribute
399  if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_END) && canParse<double>(i->getAttribute(SUMO_ATTR_END))) {
400  sortedChilds.back().first.second = parse<double>(i->getAttribute(SUMO_ATTR_END));
401  } else {
402  sortedChilds.back().first.second = sortedChilds.back().first.first;
403  }
404  }
405  // sort childs
406  std::sort(sortedChilds.begin(), sortedChilds.end());
407  // make sure that number of sorted childs is the same as the additional childs
408  if (sortedChilds.size() == myAdditionalChilds.size()) {
409  if (sortedChilds.size() <= 1) {
410  return true;
411  } else {
412  // check overlapping
413  for (int i = 0; i < (int)sortedChilds.size() - 1; i++) {
414  if (sortedChilds.at(i).first.second > sortedChilds.at(i + 1).first.first) {
415  return false;
416  }
417  }
418  }
419  return true;
420  } else {
421  throw ProcessError("Some additional childs were lost during sorting");
422  }
423 }
424 
425 
426 void
428  // Check that edge is valid and doesn't exist previously
429  if (edge == nullptr) {
430  throw InvalidArgument("Trying to add an empty " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
431  } else if (std::find(myEdgeChilds.begin(), myEdgeChilds.end(), edge) != myEdgeChilds.end()) {
432  throw InvalidArgument("Trying to add a duplicate " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
433  } else {
434  myEdgeChilds.push_back(edge);
435  }
436 }
437 
438 
439 void
441  // Check that edge is valid and exist previously
442  if (edge == nullptr) {
443  throw InvalidArgument("Trying to remove an empty " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
444  } else if (std::find(myEdgeChilds.begin(), myEdgeChilds.end(), edge) == myEdgeChilds.end()) {
445  throw InvalidArgument("Trying to remove a non previously inserted " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
446  } else {
447  myEdgeChilds.erase(std::find(myEdgeChilds.begin(), myEdgeChilds.end(), edge));
448  }
449 }
450 
451 
452 const std::vector<GNEEdge*>&
454  return myEdgeChilds;
455 }
456 
457 
458 void
460  // Check that lane is valid and doesn't exist previously
461  if (lane == nullptr) {
462  throw InvalidArgument("Trying to add an empty " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
463  } else if (std::find(myLaneChilds.begin(), myLaneChilds.end(), lane) != myLaneChilds.end()) {
464  throw InvalidArgument("Trying to add a duplicate " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
465  } else {
466  myLaneChilds.push_back(lane);
467  }
468 }
469 
470 
471 void
473  // Check that lane is valid and exist previously
474  if (lane == nullptr) {
475  throw InvalidArgument("Trying to remove an empty " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
476  } else if (std::find(myLaneChilds.begin(), myLaneChilds.end(), lane) == myLaneChilds.end()) {
477  throw InvalidArgument("Trying to remove a non previously inserted " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
478  } else {
479  myLaneChilds.erase(std::find(myLaneChilds.begin(), myLaneChilds.end(), lane));
480  }
481 }
482 
483 
484 const std::vector<GNELane*>&
486  return myLaneChilds;
487 }
488 
489 
492  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
493  // obtain tag properties
494  const auto& tagProperties = getTagProperties(getTag());
495  // build header
496  buildPopupHeader(ret, app);
497  // build menu command for center button and copy cursor position to clipboard
499  buildPositionCopyEntry(ret, false);
500  // buld menu commands for names
501  new FXMenuCommand(ret, ("Copy " + toString(getTag()) + " name to clipboard").c_str(), 0, ret, MID_COPY_NAME);
502  new FXMenuCommand(ret, ("Copy " + toString(getTag()) + " typed name to clipboard").c_str(), 0, ret, MID_COPY_TYPED_NAME);
503  new FXMenuSeparator(ret);
504  // build selection and show parameters menu
507  // show option to open additional dialog
508  if (getTagProperties(getTag()).hasDialog()) {
509  new FXMenuCommand(ret, ("Open " + toString(getTag()) + " Dialog").c_str(), getIcon(), &parent, MID_OPEN_ADDITIONAL_DIALOG);
510  new FXMenuSeparator(ret);
511  }
512  // Show position parameters
513  if (tagProperties.hasAttribute(SUMO_ATTR_LANE)) {
515  // Show menu command inner position
516  const double innerPos = myShape.nearest_offset_to_point2D(parent.getPositionInformation());
517  new FXMenuCommand(ret, ("Cursor position inner additional: " + toString(innerPos)).c_str(), 0, 0, 0);
518  // If shape isn't empty, show menu command lane position
519  if (myShape.size() > 0) {
520  const double lanePos = lane->getShape().nearest_offset_to_point2D(myShape[0]);
521  new FXMenuCommand(ret, ("Cursor position over " + toString(SUMO_TAG_LANE) + ": " + toString(innerPos + lanePos)).c_str(), 0, 0, 0);
522  }
523  } else if (tagProperties.hasAttribute(SUMO_ATTR_EDGE)) {
525  // Show menu command inner position
526  const double innerPos = myShape.nearest_offset_to_point2D(parent.getPositionInformation());
527  new FXMenuCommand(ret, ("Cursor position inner additional: " + toString(innerPos)).c_str(), 0, 0, 0);
528  // If shape isn't empty, show menu command edge position
529  if (myShape.size() > 0) {
530  const double edgePos = edge->getLanes().at(0)->getShape().nearest_offset_to_point2D(myShape[0]);
531  new FXMenuCommand(ret, ("Mouse position over " + toString(SUMO_TAG_EDGE) + ": " + toString(innerPos + edgePos)).c_str(), 0, 0, 0);
532  }
533  } else {
534  new FXMenuCommand(ret, ("Cursor position in view: " + toString(getPositionInView().x()) + "," + toString(getPositionInView().y())).c_str(), 0, 0, 0);
535  }
536  return ret;
537 }
538 
539 
542  // Create table
543  GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this, getTagProperties(getTag()).getNumberOfAttributes());
544  // Iterate over attributes
545  for (auto i : getTagProperties(getTag())) {
546  // Add attribute and set it dynamic if aren't unique
547  if (i.second.isUnique()) {
548  ret->mkItem(toString(i.first).c_str(), false, getAttribute(i.first));
549  } else {
550  ret->mkItem(toString(i.first).c_str(), true, getAttribute(i.first));
551  }
552  }
553  // close building
554  ret->closeBuilding();
555  return ret;
556 }
557 
558 
559 Boundary
561  // Return Boundary depending if myMovingGeometryBoundary is initialised (important for move geometry)
564  } else if (myShape.size() > 0) {
566  b.grow(20);
567  return b;
568  } else if (myFirstAdditionalParent) {
570  } else {
571  return Boundary(-0.1, 0.1, 0, 1, 0, 1);
572  }
573 }
574 
575 
576 bool
577 GNEAdditional::isRouteValid(const std::vector<GNEEdge*>& edges, bool report) {
578  if (edges.size() == 0) {
579  // routes cannot be empty
580  return false;
581  } else if (edges.size() == 1) {
582  // routes with a single edge are valid
583  return true;
584  } else {
585  // iterate over edges to check that compounds a chain
586  auto it = edges.begin();
587  while (it != edges.end() - 1) {
588  GNEEdge* currentEdge = *it;
589  GNEEdge* nextEdge = *(it + 1);
590  // consecutive edges aren't allowed
591  if (currentEdge->getID() == nextEdge->getID()) {
592  return false;
593  }
594  // make sure that edges are consecutives
595  if (std::find(currentEdge->getGNEJunctionDestiny()->getGNEOutgoingEdges().begin(),
596  currentEdge->getGNEJunctionDestiny()->getGNEOutgoingEdges().end(),
597  nextEdge) == currentEdge->getGNEJunctionDestiny()->getGNEOutgoingEdges().end()) {
598  if (report) {
599  WRITE_WARNING("Parameter 'Route' invalid. " + toString(currentEdge->getTag()) + " '" + currentEdge->getID() +
600  "' ins't consecutive to " + toString(nextEdge->getTag()) + " '" + nextEdge->getID() + "'");
601  }
602  return false;
603  }
604  it++;
605  }
606  }
607  return true;
608 }
609 
610 
611 void
613  // iterate over attributes and set default value
614  for (auto i : getTagProperties(getTag())) {
615  if (i.second.hasDefaultValue()) {
616  setAttribute(i.first, i.second.getDefaultValue());
617  }
618  }
619 }
620 
621 
622 void
624  if (myShape.size() > 0 && myShape.length() != 0) {
625  // If length of the shape is distint to 0, Obtain rotation of center of shape
627  } else if (additionalLane) {
628  // If additional is over a lane, set rotation in the position over lane
629  double posOverLane = additionalLane->getShape().nearest_offset_to_point2D(getPositionInView());
630  myBlockIconRotation = additionalLane->getShape().rotationDegreeAtOffset(posOverLane) - 90;
631  } else {
632  // In other case, rotation is 0
634  }
635 }
636 
637 
638 void
639 GNEAdditional::drawLockIcon(double size) const {
640  if (myViewNet->showLockIcon()) {
641  // Start pushing matrix
642  glPushMatrix();
643  // Traslate to middle of shape
644  glTranslated(myBlockIconPosition.x(), myBlockIconPosition.y(), getType() + 0.1);
645  // Set draw color
646  glColor3d(1, 1, 1);
647  // Rotate depending of myBlockIconRotation
648  glRotated(myBlockIconRotation, 0, 0, -1);
649  // Rotate 180 degrees
650  glRotated(180, 0, 0, 1);
651  // Traslate depending of the offset
652  glTranslated(myBlockIconOffset.x(), myBlockIconOffset.y(), 0);
653  // Draw icon depending of the state of additional
654  if (mySelected) {
656  // Draw not movable texture if additional isn't movable and is selected
658  } else if (myBlockMovement) {
659  // Draw lock texture if additional is movable, is blocked and is selected
661  } else {
662  // Draw empty texture if additional is movable, isn't blocked and is selected
664  }
665  } else {
666  if (!getTagProperties(getTag()).canBlockMovement()) {
667  // Draw not movable texture if additional isn't movable
669  } else if (myBlockMovement) {
670  // Draw lock texture if additional is movable and is blocked
672  } else {
673  // Draw empty texture if additional is movable and isn't blocked
675  }
676  }
677  // Pop matrix
678  glPopMatrix();
679  }
680 }
681 
682 
683 void
685  // first clear connection positions
688 
689  // calculate position and rotation of every simbol for every edge
690  for (auto i : myEdgeChilds) {
691  for (auto j : i->getLanes()) {
692  std::pair<Position, double> posRot;
693  // set position and lenght depending of shape's lengt
694  if (j->getShape().length() - 6 > 0) {
695  posRot.first = j->getShape().positionAtOffset(j->getShape().length() - 6);
696  posRot.second = j->getShape().rotationDegreeAtOffset(j->getShape().length() - 6);
697  } else {
698  posRot.first = j->getShape().positionAtOffset(j->getShape().length());
699  posRot.second = j->getShape().rotationDegreeAtOffset(j->getShape().length());
700  }
701  mySymbolsPositionAndRotation.push_back(posRot);
702  }
703  }
704 
705  // calculate position and rotation of every symbol for every lane
706  for (auto i : myLaneChilds) {
707  std::pair<Position, double> posRot;
708  // set position and lenght depending of shape's lengt
709  if (i->getShape().length() - 6 > 0) {
710  posRot.first = i->getShape().positionAtOffset(i->getShape().length() - 6);
711  posRot.second = i->getShape().rotationDegreeAtOffset(i->getShape().length() - 6);
712  } else {
713  posRot.first = i->getShape().positionAtOffset(i->getShape().length());
714  posRot.second = i->getShape().rotationDegreeAtOffset(i->getShape().length());
715  }
716  mySymbolsPositionAndRotation.push_back(posRot);
717  }
718 
719  // calculate position for every additional child
720  for (auto i : myAdditionalChilds) {
721  // check that position is different of position
722  if (i->getPositionInView() != getPositionInView()) {
723  std::vector<Position> posConnection;
724  double A = std::abs(i->getPositionInView().x() - getPositionInView().x());
725  double B = std::abs(i->getPositionInView().y() - getPositionInView().y());
726  // Set positions of connection's vertex. Connection is build from Entry to E3
727  posConnection.push_back(i->getPositionInView());
728  if (getPositionInView().x() > i->getPositionInView().x()) {
729  if (getPositionInView().y() > i->getPositionInView().y()) {
730  posConnection.push_back(Position(i->getPositionInView().x() + A, i->getPositionInView().y()));
731  } else {
732  posConnection.push_back(Position(i->getPositionInView().x(), i->getPositionInView().y() - B));
733  }
734  } else {
735  if (getPositionInView().y() > i->getPositionInView().y()) {
736  posConnection.push_back(Position(i->getPositionInView().x(), i->getPositionInView().y() + B));
737  } else {
738  posConnection.push_back(Position(i->getPositionInView().x() - A, i->getPositionInView().y()));
739  }
740  }
741  posConnection.push_back(getPositionInView());
742  myChildConnectionPositions.push_back(posConnection);
743  }
744  }
745 
746  // calculate geometry for connections between parent and childs
747  for (auto i : mySymbolsPositionAndRotation) {
748  std::vector<Position> posConnection;
749  double A = std::abs(i.first.x() - getPositionInView().x());
750  double B = std::abs(i.first.y() - getPositionInView().y());
751  // Set positions of connection's vertex. Connection is build from Entry to E3
752  posConnection.push_back(i.first);
753  if (getPositionInView().x() > i.first.x()) {
754  if (getPositionInView().y() > i.first.y()) {
755  posConnection.push_back(Position(i.first.x() + A, i.first.y()));
756  } else {
757  posConnection.push_back(Position(i.first.x(), i.first.y() - B));
758  }
759  } else {
760  if (getPositionInView().y() > i.first.y()) {
761  posConnection.push_back(Position(i.first.x(), i.first.y() + B));
762  } else {
763  posConnection.push_back(Position(i.first.x() - A, i.first.y()));
764  }
765  }
766  posConnection.push_back(getPositionInView());
767  myChildConnectionPositions.push_back(posConnection);
768  }
769 }
770 
771 
772 void
774  // Iterate over myConnectionPositions
775  for (auto i : myChildConnectionPositions) {
776  // Add a draw matrix
777  glPushMatrix();
778  // traslate in the Z axis
779  glTranslated(0, 0, getType() - 0.01);
780  // Set color of the base
781  GLHelper::setColor(RGBColor(255, 235, 0));
782  for (auto j = i.begin(); (j + 1) != i.end(); j++) {
783  // Draw Lines
784  GLHelper::drawLine((*j), (*(j + 1)));
785  }
786  // Pop draw matrix
787  glPopMatrix();
788  }
789 }
790 
791 
792 const std::string&
794  return getMicrosimID();
795 }
796 
797 
798 bool
799 GNEAdditional::isValidAdditionalID(const std::string& newID) const {
800  if (SUMOXMLDefinitions::isValidNetID(newID) && (myViewNet->getNet()->retrieveAdditional(getTag(), newID, false) == nullptr)) {
801  return true;
802  } else {
803  return false;
804  }
805 }
806 
807 
808 void
809 GNEAdditional::changeAdditionalID(const std::string& newID) {
810  if (myViewNet->getNet()->retrieveAdditional(getTag(), newID, false) != nullptr) {
811  throw InvalidArgument("An Additional with tag " + toString(getTag()) + " and ID = " + newID + " already exists");
812  } else if (!SUMOXMLDefinitions::isValidNetID(newID)) {
813  throw InvalidArgument("Additional ID " + newID + " contains invalid characters");
814  } else {
815  // Save old ID
816  std::string oldID = getMicrosimID();
817  // set New ID
818  setMicrosimID(newID);
819  // update additional ID in the container of net
820  myViewNet->getNet()->updateAdditionalID(oldID, this);
821  }
822 }
823 
824 
825 GNEEdge*
826 GNEAdditional::changeEdge(GNEEdge* oldEdge, const std::string& newEdgeID) {
827  if (oldEdge == nullptr) {
828  throw InvalidArgument(toString(getTag()) + " with ID '" + getMicrosimID() + "' doesn't belong to an " + toString(SUMO_TAG_EDGE));
829  } else {
830  oldEdge->removeAdditionalChild(this);
831  GNEEdge* newEdge = myViewNet->getNet()->retrieveEdge(newEdgeID);
832  newEdge->addAdditionalChild(this);
833  updateGeometry(true);
834  return newEdge;
835  }
836 }
837 
838 
839 GNELane*
840 GNEAdditional::changeLane(GNELane* oldLane, const std::string& newLaneID) {
841  if (oldLane == nullptr) {
842  throw InvalidArgument(toString(getTag()) + " with ID '" + getMicrosimID() + "' doesn't belong to a " + toString(SUMO_TAG_LANE));
843  } else {
844  oldLane->removeAdditionalChild(this);
845  GNELane* newLane = myViewNet->getNet()->retrieveLane(newLaneID);
846  newLane->addAdditionalChild(this);
847  updateGeometry(true);
848  return newLane;
849  }
850 }
851 
852 
853 void
854 GNEAdditional::changeFirstAdditionalParent(const std::string& newAdditionalParentID) {
855  if (myFirstAdditionalParent == nullptr) {
856  throw InvalidArgument(toString(getTag()) + " with ID '" + getMicrosimID() + "' doesn't have an additional parent");
857  } else {
858  // remove this additional of the childs of parent additional
860  // set new additional parent
862  // add this additional int the childs of parent additional
864  updateGeometry(true);
865  }
866 }
867 
868 
869 void
870 GNEAdditional::changeSecondAdditionalParent(const std::string& newAdditionalParentID) {
871  if (mySecondAdditionalParent == nullptr) {
872  throw InvalidArgument(toString(getTag()) + " with ID '" + getMicrosimID() + "' doesn't have an additional parent");
873  } else {
874  // remove this additional of the childs of parent additional
876  // set new additional parent
878  // add this additional int the childs of parent additional
880  updateGeometry(true);
881  }
882 }
883 
884 
885 void
887  if (!myViewNet) {
888  throw ProcessError("ViewNet cannot be nullptr");
889  } else {
890  gSelected.select(dynamic_cast<GUIGlObject*>(this)->getGlID());
891  if (changeFlag) {
892  mySelected = true;
893  }
894  }
895 }
896 
897 
898 void
900  if (!myViewNet) {
901  throw ProcessError("ViewNet cannot be nullptr");
902  } else {
903  gSelected.deselect(dynamic_cast<GUIGlObject*>(this)->getGlID());
904  if (changeFlag) {
905  mySelected = false;
906  }
907  }
908 }
909 
910 
911 bool
913  return mySelected;
914 }
915 
916 
917 bool
919  // throw exception because this function mus be implemented in child (see GNEE3Detector)
920  throw ProcessError("Calling non-implemented function checkAdditionalChildRestriction during saving of " + toString(getTag()) + ". It muss be reimplemented in child class");
921 }
922 
923 
924 bool
925 GNEAdditional::addGenericParameter(const std::string& key, const std::string& value) {
926  if (!knowsParameter(key)) {
927  setParameter(key, value);
928  return true;
929  } else {
930  return false;
931  }
932 }
933 
934 
935 bool
936 GNEAdditional::removeGenericParameter(const std::string& key) {
937  if (knowsParameter(key)) {
938  unsetParameter(key);
939  return true;
940  } else {
941  return false;
942  }
943 }
944 
945 
946 bool
947 GNEAdditional::updateGenericParameter(const std::string& oldKey, const std::string& newKey) {
948  if (knowsParameter(oldKey) && !knowsParameter(newKey)) {
949  std::string value = getParameter(oldKey);
950  unsetParameter(oldKey);
951  setParameter(newKey, value);
952  return true;
953  } else {
954  return false;
955  }
956 }
957 
958 
959 bool
960 GNEAdditional::updateGenericParameterValue(const std::string& key, const std::string& newValue) {
961  if (knowsParameter(key)) {
962  setParameter(key, newValue);
963  return true;
964  } else {
965  return false;
966  }
967 }
968 
969 
970 std::string
972  std::string result;
973  // Generate an string using the following structure: "key1=value1|key2=value2|...
974  for (auto i : getParametersMap()) {
975  result += i.first + "=" + i.second + "|";
976  }
977  // remove the last "|"
978  if (!result.empty()) {
979  result.pop_back();
980  }
981  return result;
982 }
983 
984 
985 std::vector<std::pair<std::string, std::string> >
987  std::vector<std::pair<std::string, std::string> > result;
988  // iterate over parameters map and fill result
989  for (auto i : getParametersMap()) {
990  result.push_back(std::make_pair(i.first, i.second));
991  }
992  return result;
993 }
994 
995 
996 void
997 GNEAdditional::setGenericParametersStr(const std::string& value) {
998  // clear parameters
999  clearParameter();
1000  // separate value in a vector of string using | as separator
1001  std::vector<std::string> parsedValues;
1002  StringTokenizer stValues(value, "|", true);
1003  while (stValues.hasNext()) {
1004  parsedValues.push_back(stValues.next());
1005  }
1006  // check that parsed values (A=B)can be parsed in generic parameters
1007  for (auto i : parsedValues) {
1008  std::vector<std::string> parsedParameters;
1009  StringTokenizer stParam(i, "=", true);
1010  while (stParam.hasNext()) {
1011  parsedParameters.push_back(stParam.next());
1012  }
1013  // Check that parsed parameters are exactly two and contains valid chracters
1014  if (parsedParameters.size() == 2 && SUMOXMLDefinitions::isValidGenericParameterKey(parsedParameters.front()) && SUMOXMLDefinitions::isValidGenericParameterValue(parsedParameters.back())) {
1015  setParameter(parsedParameters.front(), parsedParameters.back());
1016  }
1017  }
1018 }
1019 
1020 
1021 void
1023 }
1024 
1025 
1026 /****************************************************************************/
bool mySelected
boolean to check if this AC is selected (instead of GUIGlObjectStorage)
void removeEdgeChild(GNEEdge *edge)
remove edge child
static void drawTexturedBox(int which, double size)
Draws a named texture as a box with the given size.
virtual void openAdditionalDialog()
open Additional Dialog
bool updateGenericParameter(const std::string &oldKey, const std::string &newKey)
update generic parameter
void addEdgeChild(GNEEdge *edge)
add edge child
Copy object name - popup entry.
Definition: GUIAppEnum.h:230
void writePermissions(OutputDevice &into, SVCPermissions permissions)
writes allowed disallowed attributes if needed;
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
double rotationDegreeAtOffset(double pos) const
Returns the rotation at the given length.
void close()
Closes the device and removes it from the dictionary.
SumoXMLTag
Numbers representing SUMO-XML - element names.
GNEEdge * retrieveEdge(const std::string &id, bool failHard=true)
get edge by id
Definition: GNENet.cpp:915
bool isAdditionalBlocked() const
Check if additional item is currently blocked (i.e. cannot be moved with mouse)
void setBlockIconRotation(GNELane *additionalLane=nullptr)
void writeAdditional(OutputDevice &device) const
writte additional element into a xml file
void removeAdditionalChild(GNEAdditional *additional)
remove additional child from this additional
void closeBuilding(const Parameterised *p=0)
Closes the building of the table.
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
std::string next()
bool hasMinimumNumberOfChilds() const
return true if tag correspond to an element that only have a limited number of childs ...
GUIGlObjectType
begin/end of the description of a single lane
const std::vector< GNEEdge * > & getEdgeChilds() const
get edge chidls
bool canBlockMovement() const
return true if tag correspond to an element that can block their movement
void setGenericParametersStr(const std::string &value)
set generic parameters in string format
const std::string & getAdditionalID() const
returns Additional ID
const std::vector< GNELane * > & getLaneChilds() const
get lanes of VSS
void changeFirstAdditionalParent(const std::string &newAdditionalParentID)
change first additional parent of additional
GNEAdditional(const std::string &id, GNEViewNet *viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement)
Constructor.
static GUIGlID getTexture(GUITexture which)
returns a texture previously defined in the enum GUITexture
Boundary myMovingGeometryBoundary
boundary used during moving of elements
Stores the information about how to visualize structures.
void select(GUIGlID id, bool update=true)
Adds the object with the given id.
double y() const
Returns the y-position.
Definition: Position.h:61
void unsetParameter(const std::string &key)
Removes a parameter.
std::vector< std::pair< std::string, std::string > > getGenericParameters() const
return generic parameters as vector of pairs format
PositionVector getShape() const
Returns additional element&#39;s shape.
void mkItem(const char *name, bool dynamic, ValueSource< T > *src)
Adds a row which obtains its value from a ValueSource.
double x() const
Returns the x-position.
Definition: Position.h:56
virtual void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)=0
method for setting the attribute and letting the object perform additional changes ...
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
weights: time range begin
void unselectAttributeCarrier(bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
FXIcon * getIcon() const
get FXIcon associated to this AC
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:47
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
void setDefaultValues()
change all attributes of additional with their default values (note: this cannot be undo) ...
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
virtual bool checkAdditionalChildRestriction() const
check restriction with the number of childs
bool removeGenericParameter(const std::string &key)
remove generic parameter
static bool isValidGenericParameterKey(const std::string &value)
whether the given string is a valid key for a generic parameter
void buildPositionCopyEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to copy the cursor position if geo projection is used, also builds an entry for copying the geo-position.
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
void changeAdditionalID(const std::string &newID)
change ID of additional
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
std::vector< PositionVector > myChildConnectionPositions
Matrix with the Vertex&#39;s positions of connections between parents an their childs.
virtual std::string getAttribute(SumoXMLAttr key) const =0
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:242
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
an e3 entry point
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
GNEViewNet * myViewNet
The GNEViewNet this additional element belongs.
GNEAdditional * retrieveAdditional(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named additional.
Definition: GNENet.cpp:1795
SumoXMLTag getTagSynonym() const
get tag synonym
bool showLockIcon() const
check if lock icon should be visible
void drawChildConnections() const
draw connections between Parent and childrens
static bool isValidGenericParameterValue(const std::string &value)
whether the given string is a valid value for a generic parameter
void updateAdditionalID(const std::string &oldID, GNEAdditional *additional)
update additional ID in container
Definition: GNENet.cpp:1840
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
void drawLockIcon(double size=0.5) const
draw lock icon
bool knowsParameter(const std::string &key) const
Returns whether the parameter is known.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:573
void addAdditionalChild(GNEAdditional *additional)
add additional child to this edge
PositionVector myShape
The shape of the additional element.
GNEAdditional * getSecondAdditionalParent() const
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
an e3 exit point
A list of positions.
std::string myAdditionalName
name of additional
void removeGLObjectFromGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1175
bool updateGenericParameterValue(const std::string &key, const std::string &newValue)
update value generic parameter
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
void selectAttributeCarrier(bool changeFlag=true)
GNEJunction * getGNEJunctionDestiny() const
returns the destination-junction
Definition: GNEEdge.cpp:453
void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
void updateChildConnections()
update Connection&#39;s geometry
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:301
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
const std::string getID() const
function to support debugging
void removeAdditionalChild(GNEAdditional *additional)
remove additional child from this edge
void sortAdditionalChilds()
sort childs (used by Rerouters and VSS)
static void drawLine(const Position &beg, double rot, double visLength)
Draws a thin line.
Definition: GLHelper.cpp:270
bool hasTagSynonym() const
return true if tag correspond to an element that will be written in XML with another tag ...
~GNEAdditional()
Destructor.
An upper class for objects with additional parameters.
Definition: Parameterised.h:44
virtual void updateGeometry(bool updateGrid)=0
update pre-computed geometry information
Position myBlockIconOffset
The offSet of the block icon.
bool myBlockMovement
boolean to check if additional element is blocked (i.e. cannot be moved with mouse) ...
std::vector< GNEAdditional * > myAdditionalChilds
vector with the Additional childs
void writeParams(OutputDevice &device) const
write Params in the given outputdevice
begin/end of the description of an edge
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
GNEAdditional * getFirstAdditionalParent() const
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:50
void reset()
Resets the boundary.
Definition: Boundary.cpp:67
void changeSecondAdditionalParent(const std::string &newAdditionalParentID)
change second additional parent of additional
trigger: the time of the step
GNEViewNet * getViewNet() const
Returns a pointer to GNEViewNet in which additional element is located.
const PositionVector & getShape() const
returns the shape of the lane
Definition: GNELane.cpp:679
void deselect(GUIGlID id)
Deselects the object with the given id.
const std::vector< GNELane * > & getLanes()
returns a reference to the lane vector
Definition: GNEEdge.cpp:832
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:263
double length() const
Returns the length.
GNEEdge * changeEdge(GNEEdge *oldEdge, const std::string &newEdgeID)
change edge of additional
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
An Element which don&#39;t belongs to GNENet but has influency in the simulation.
Definition: GNEAdditional.h:53
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
weights: time range end
std::vector< std::pair< Position, double > > mySymbolsPositionAndRotation
position and rotation of every simbol over lane
bool isInitialised() const
check if Boundary is Initialised
Definition: Boundary.cpp:217
The popup menu of a globject.
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
std::string getGenericParametersStr() const
return generic parameters in string format
open additional dialog (used in netedit)
Definition: GUIAppEnum.h:240
GNENet * getNet() const
get the net object
std::string generateAdditionalChildID(SumoXMLTag childTag)
gererate a new ID for an additional child
const std::map< std::string, std::string > & getParametersMap() const
Returns the inner key/value map.
GUIGlID getGlID() const
Returns the numerical id of the object.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static bool isRouteValid(const std::vector< GNEEdge *> &edges, bool report)
check if a route is valid
Position getPositionInformation() const
Returns the cursor&#39;s x/y position within the network.
bool isValidAdditionalID(const std::string &newID) const
check if a new additional ID is valid
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
static std::string getFilePath(const std::string &path)
Removes the file information from the given path.
Definition: FileHelpers.cpp:65
void mouseOverObject(const GUIVisualizationSettings &s) const
method for check if mouse is over objects
static const TagValues & getTagProperties(SumoXMLTag tag)
get Tag Properties
void addAdditionalChild(GNEAdditional *additional)
add additional child to this additional
void removeLaneChild(GNELane *lane)
remove lane child
void endGeometryMoving()
begin movement (used when user click over additional to start a movement, to avoid problems with prob...
bool checkAdditionalChildsOverlapping() const
check if childs are overlapped (Used by Rerouters)
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
const std::vector< GNEAdditional * > & getAdditionalChilds() const
return vector of additionals that have as Parent this edge (For example, Calibrators) ...
void addGLObjectIntoGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1168
GUISelectedStorage gSelected
A global holder of selected objects.
GNELane * retrieveLane(const std::string &id, bool failHard=true, bool checkVolatileChange=false)
get lane by id
Definition: GNENet.cpp:1074
void startGeometryMoving()
Copy typed object name - popup entry.
Definition: GUIAppEnum.h:232
A window containing a gl-object&#39;s parameter.
double myBlockIconRotation
The rotation of the block icon.
GNEAdditional * myFirstAdditionalParent
pointer to first Addititional parent
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
struct with the attribute Properties
GNELane * changeLane(GNELane *oldLane, const std::string &newLaneID)
change lane of additional
void addLaneChild(GNELane *lane)
add lane child
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
Position myBlockIconPosition
position of the block icon
std::vector< GNELane * > myLaneChilds
vector with the lane childs of this additional
bool addGenericParameter(const std::string &key, const std::string &value)
add generic parameter
void clearParameter()
Clears the parameter map.
GNEAdditional * mySecondAdditionalParent
pointer to second Addititional parent
std::vector< GNEEdge * > myEdgeChilds
vector with the edge childs of this additional
SumoXMLTag getTag() const
get XML Tag assigned to this object
SumoXMLTag getParentTag() const
if Tag owns a parent, return parent tag
virtual Position getPositionInView() const =0
Returns position of additional in view.