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  myMovingGeometryBoundary() {
69 }
70 
71 
72 GNEAdditional::GNEAdditional(GNEAdditional* singleAdditionalParent, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement) :
73  GUIGlObject(type, singleAdditionalParent->generateAdditionalChildID(tag)),
75  Parameterised(),
76  myViewNet(viewNet),
77  myAdditionalName(additionalName),
78  myBlockMovement(blockMovement),
79  myFirstAdditionalParent(singleAdditionalParent),
80  mySecondAdditionalParent(nullptr),
82  // check that additional parent is of expected type
83  assert(singleAdditionalParent->getTag() == getTagProperties(getTag()).getParentTag());
84 }
85 
86 
87 GNEAdditional::GNEAdditional(GNEAdditional* firstAdditionalParent, GNEAdditional* secondAdditionalParent, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement) :
88  GUIGlObject(type, firstAdditionalParent->generateAdditionalChildID(tag)),
90  Parameterised(),
91  myViewNet(viewNet),
92  myAdditionalName(additionalName),
93  myBlockMovement(blockMovement),
94  myFirstAdditionalParent(firstAdditionalParent),
95  mySecondAdditionalParent(secondAdditionalParent),
97  // check that additional parent is of expected type
98  assert(firstAdditionalParent->getTag() == getTagProperties(getTag()).getParentTag());
99 }
100 
101 
102 GNEAdditional::GNEAdditional(const std::string& id, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement, std::vector<GNEEdge*> edgeChilds) :
103  GUIGlObject(type, id),
104  GNEAttributeCarrier(tag),
105  Parameterised(),
106  myViewNet(viewNet),
107  myAdditionalName(additionalName),
108  myBlockMovement(blockMovement),
109  myFirstAdditionalParent(nullptr),
110  mySecondAdditionalParent(nullptr),
111  myEdgeChilds(edgeChilds),
112  myBlockIconRotation(0.) {
113 }
114 
115 
116 GNEAdditional::GNEAdditional(const std::string& id, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement, std::vector<GNELane*> laneChilds) :
117  GUIGlObject(type, id),
118  GNEAttributeCarrier(tag),
119  Parameterised(),
120  myViewNet(viewNet),
121  myAdditionalName(additionalName),
122  myBlockMovement(blockMovement),
123  myFirstAdditionalParent(nullptr),
124  mySecondAdditionalParent(nullptr),
125  myLaneChilds(laneChilds),
126  myBlockIconRotation(0.) {
127 }
128 
129 
131 
132 
133 void
135  // obtain tag properties
136  const TagValues& tagProperties = getTagProperties(getTag());
137  // first check if minimum number of childs is correct
138  if ((tagProperties.hasMinimumNumberOfChilds() || tagProperties.hasMinimumNumberOfChilds()) && !checkAdditionalChildRestriction()) {
139  WRITE_WARNING(toString(getTag()) + " with ID='" + getID() + "' cannot be written");
140  } else {
141  // Open Tag or synonim Tag
142  if (tagProperties.hasTagSynonym()) {
143  device.openTag(tagProperties.getTagSynonym());
144  } else {
145  device.openTag(getTag());
146  }
147  // iterate over attributes and write it
148  for (auto i : tagProperties) {
149  // obtain attribute
150  std::string attribute = getAttribute(i.first);
151  if (i.second.isOptional() && i.second.hasDefaultValue() && !i.second.isCombinable()) {
152  // Only write attributes with default value if is different of original
153  if (i.second.getDefaultValue() != attribute) {
154  // check if attribute must be written using a synonim
155  if (i.second.hasAttrSynonym()) {
156  device.writeAttr(i.second.getAttrSynonym(), attribute);
157  } else {
158  // SVC permissions uses their own writting function
159  if (i.second.isSVCPermission()) {
160  // disallow attribute musn't be written
161  if (i.first != SUMO_ATTR_DISALLOW) {
162  writePermissions(device, parseVehicleClasses(attribute));
163  }
164  } else {
165  device.writeAttr(i.first, attribute);
166  }
167  }
168  }
169  } else {
170  // Attributes without default values are always writted
171  if (i.second.hasAttrSynonym()) {
172  device.writeAttr(i.second.getAttrSynonym(), attribute);
173  } else {
174  // SVC permissions uses their own writting function
175  if (i.second.isSVCPermission()) {
176  // disallow attribute musn't be written
177  if (i.first != SUMO_ATTR_DISALLOW) {
178  writePermissions(device, parseVehicleClasses(attribute));
179  }
180  } else {
181  device.writeAttr(i.first, attribute);
182  }
183  }
184  }
185  }
186  // save generic parameters
187  writeParams(device);
188  // iterate over childs and write it in XML (or in a different file)
189  if (tagProperties.canWriteChildsSeparate() && tagProperties.hasAttribute(SUMO_ATTR_FILE) && !getAttribute(SUMO_ATTR_FILE).empty()) {
190  // we assume that rerouter values files is placed in the same folder as the additional file
192  deviceChilds.writeXMLHeader("rerouterValue", "additional_file.xsd");
193  // save childs in a different filename
194  for (auto i : myAdditionalChilds) {
195  // avoid to write two times additionals that haben two parents (Only write as child of first parent)
196  if (i->getSecondAdditionalParent() == nullptr) {
197  i->writeAdditional(deviceChilds);
198  } else if (getTag() == getTagProperties(i->getTag()).getParentTag()) {
199  i->writeAdditional(deviceChilds);
200  }
201  }
202  deviceChilds.close();
203  } else {
204  for (auto i : myAdditionalChilds) {
205  // avoid to write two times additionals that haben two parents (Only write as child of first parent)
206  if (i->getSecondAdditionalParent() == nullptr) {
207  i->writeAdditional(device);
208  } else if (getTag() == getTagProperties(i->getTag()).getParentTag()) {
209  i->writeAdditional(device);
210  }
211  }
212  }
213  // Close tag
214  device.closeTag();
215  }
216 }
217 
218 
219 void
221  throw InvalidArgument(toString(getTag()) + " doesn't have an additional dialog");
222 }
223 
224 
225 void
227  // save current centering boundary
229 }
230 
231 
232 void
234  // check that endGeometryMoving was called only once
236  // Remove object from net
238  // reset myMovingGeometryBoundary
240  // update geometry without updating grid
241  updateGeometry(false);
242  // add object into grid again (using the new centering boundary)
244  }
245 }
246 
247 
248 GNEViewNet*
250  return myViewNet;
251 }
252 
253 
256  return myShape;
257 }
258 
259 
260 bool
262  return myBlockMovement;
263 }
264 
265 
269 }
270 
271 
275 }
276 
277 
278 std::string
280  int counter = 0;
281  while (myViewNet->getNet()->retrieveAdditional(childTag, getID() + toString(childTag) + toString(counter), false) != nullptr) {
282  counter++;
283  }
284  return (getID() + toString(childTag) + toString(counter));
285 }
286 
287 
288 void
290  // First check that additional wasn't already inserted
291  if (std::find(myAdditionalChilds.begin(), myAdditionalChilds.end(), additional) != myAdditionalChilds.end()) {
292  throw ProcessError(toString(additional->getTag()) + " with ID='" + additional->getID() + "' was already inserted in " + toString(getTag()) + " with ID='" + getID() + "'");
293  } else {
294  myAdditionalChilds.push_back(additional);
295  // Check if childs has to be sorted automatically
296  if (getTagProperties(getTag()).canAutomaticSortChilds()) {
298  }
299  // update geometry (for set geometry of lines between Parents and Childs)
300  updateGeometry(true);
301  }
302 }
303 
304 
305 void
307  // First check that additional was already inserted
308  auto it = std::find(myAdditionalChilds.begin(), myAdditionalChilds.end(), additional);
309  if (it == myAdditionalChilds.end()) {
310  throw ProcessError(toString(additional->getTag()) + " with ID='" + additional->getID() + "' doesn't exist in " + toString(getTag()) + " with ID='" + getID() + "'");
311  } else {
312  myAdditionalChilds.erase(it);
313  // Check if childs has to be sorted automatically
314  if (getTagProperties(getTag()).canAutomaticSortChilds()) {
316  }
317  // update geometry (for remove geometry of lines between Parents and Childs)
318  updateGeometry(true);
319  }
320 }
321 
322 
323 const std::vector<GNEAdditional*>&
325  return myAdditionalChilds;
326 }
327 
328 
329 void
331  if (getTag() == SUMO_TAG_E3DETECTOR) {
332  // we need to sort Entry/Exits due additional.xds model
333  std::vector<GNEAdditional*> sortedEntryExits;
334  // obtain all entrys
335  for (auto i : myAdditionalChilds) {
336  if (i->getTag() == SUMO_TAG_DET_ENTRY) {
337  sortedEntryExits.push_back(i);
338  }
339  }
340  // obtain all exits
341  for (auto i : myAdditionalChilds) {
342  if (i->getTag() == SUMO_TAG_DET_EXIT) {
343  sortedEntryExits.push_back(i);
344  }
345  }
346  // change myAdditionalChilds for sortedEntryExits
347  if (sortedEntryExits.size() == myAdditionalChilds.size()) {
348  myAdditionalChilds = sortedEntryExits;
349  } else {
350  throw ProcessError("Some additional childs were lost during sorting");
351  }
352  } else {
353  // declare a vector to keep sorted childs
354  std::vector<std::pair<std::pair<double, double>, GNEAdditional*> > sortedChilds;
355  // iterate over additional childs
356  for (auto i : myAdditionalChilds) {
357  sortedChilds.push_back(std::make_pair(std::make_pair(0., 0.), i));
358  // set begin/start attribute
359  if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_TIME) && canParse<double>(i->getAttribute(SUMO_ATTR_TIME))) {
360  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_TIME));
361  } else if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_BEGIN) && canParse<double>(i->getAttribute(SUMO_ATTR_BEGIN))) {
362  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_BEGIN));
363  }
364  // set end attribute
365  if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_END) && canParse<double>(i->getAttribute(SUMO_ATTR_END))) {
366  sortedChilds.back().first.second = parse<double>(i->getAttribute(SUMO_ATTR_END));
367  } else {
368  sortedChilds.back().first.second = sortedChilds.back().first.first;
369  }
370  }
371  // sort childs
372  std::sort(sortedChilds.begin(), sortedChilds.end());
373  // make sure that number of sorted childs is the same as the additional childs
374  if (sortedChilds.size() == myAdditionalChilds.size()) {
375  myAdditionalChilds.clear();
376  for (auto i : sortedChilds) {
377  myAdditionalChilds.push_back(i.second);
378  }
379  } else {
380  throw ProcessError("Some additional childs were lost during sorting");
381  }
382  }
383 }
384 
385 
386 bool
388  // declare a vector to keep sorted childs
389  std::vector<std::pair<std::pair<double, double>, GNEAdditional*> > sortedChilds;
390  // iterate over additional childs
391  for (auto i : myAdditionalChilds) {
392  sortedChilds.push_back(std::make_pair(std::make_pair(0., 0.), i));
393  // set begin/start attribute
394  if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_TIME) && canParse<double>(i->getAttribute(SUMO_ATTR_TIME))) {
395  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_TIME));
396  } else if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_BEGIN) && canParse<double>(i->getAttribute(SUMO_ATTR_BEGIN))) {
397  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_BEGIN));
398  }
399  // set end attribute
400  if (getTagProperties(i->getTag()).hasAttribute(SUMO_ATTR_END) && canParse<double>(i->getAttribute(SUMO_ATTR_END))) {
401  sortedChilds.back().first.second = parse<double>(i->getAttribute(SUMO_ATTR_END));
402  } else {
403  sortedChilds.back().first.second = sortedChilds.back().first.first;
404  }
405  }
406  // sort childs
407  std::sort(sortedChilds.begin(), sortedChilds.end());
408  // make sure that number of sorted childs is the same as the additional childs
409  if (sortedChilds.size() == myAdditionalChilds.size()) {
410  if (sortedChilds.size() <= 1) {
411  return true;
412  } else {
413  // check overlapping
414  for (int i = 0; i < (int)sortedChilds.size() - 1; i++) {
415  if (sortedChilds.at(i).first.second > sortedChilds.at(i + 1).first.first) {
416  return false;
417  }
418  }
419  }
420  return true;
421  } else {
422  throw ProcessError("Some additional childs were lost during sorting");
423  }
424 }
425 
426 
427 void
429  // Check that edge is valid and doesn't exist previously
430  if (edge == nullptr) {
431  throw InvalidArgument("Trying to add an empty " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
432  } else if (std::find(myEdgeChilds.begin(), myEdgeChilds.end(), edge) != myEdgeChilds.end()) {
433  throw InvalidArgument("Trying to add a duplicate " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
434  } else {
435  myEdgeChilds.push_back(edge);
436  }
437 }
438 
439 
440 void
442  // Check that edge is valid and exist previously
443  if (edge == nullptr) {
444  throw InvalidArgument("Trying to remove an empty " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
445  } else if (std::find(myEdgeChilds.begin(), myEdgeChilds.end(), edge) == myEdgeChilds.end()) {
446  throw InvalidArgument("Trying to remove a non previously inserted " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
447  } else {
448  myEdgeChilds.erase(std::find(myEdgeChilds.begin(), myEdgeChilds.end(), edge));
449  }
450 }
451 
452 
453 const std::vector<GNEEdge*>&
455  return myEdgeChilds;
456 }
457 
458 
459 void
461  // Check that lane is valid and doesn't exist previously
462  if (lane == nullptr) {
463  throw InvalidArgument("Trying to add an empty " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
464  } else if (std::find(myLaneChilds.begin(), myLaneChilds.end(), lane) != myLaneChilds.end()) {
465  throw InvalidArgument("Trying to add a duplicate " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
466  } else {
467  myLaneChilds.push_back(lane);
468  }
469 }
470 
471 
472 void
474  // Check that lane is valid and exist previously
475  if (lane == nullptr) {
476  throw InvalidArgument("Trying to remove an empty " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
477  } else if (std::find(myLaneChilds.begin(), myLaneChilds.end(), lane) == myLaneChilds.end()) {
478  throw InvalidArgument("Trying to remove a non previously inserted " + toString(SUMO_TAG_EDGE) + " child in " + toString(getTag()) + " with ID='" + getID() + "'");
479  } else {
480  myLaneChilds.erase(std::find(myLaneChilds.begin(), myLaneChilds.end(), lane));
481  }
482 }
483 
484 
485 const std::vector<GNELane*>&
487  return myLaneChilds;
488 }
489 
490 
493  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
494  // obtain tag properties
495  const auto& tagProperties = getTagProperties(getTag());
496  // build header
497  buildPopupHeader(ret, app);
498  // build menu command for center button and copy cursor position to clipboard
500  buildPositionCopyEntry(ret, false);
501  // buld menu commands for names
502  new FXMenuCommand(ret, ("Copy " + toString(getTag()) + " name to clipboard").c_str(), 0, ret, MID_COPY_NAME);
503  new FXMenuCommand(ret, ("Copy " + toString(getTag()) + " typed name to clipboard").c_str(), 0, ret, MID_COPY_TYPED_NAME);
504  new FXMenuSeparator(ret);
505  // build selection and show parameters menu
508  // show option to open additional dialog
509  if (getTagProperties(getTag()).hasDialog()) {
510  new FXMenuCommand(ret, ("Open " + toString(getTag()) + " Dialog").c_str(), getIcon(), &parent, MID_OPEN_ADDITIONAL_DIALOG);
511  new FXMenuSeparator(ret);
512  }
513  // Show position parameters
514  if (tagProperties.hasAttribute(SUMO_ATTR_LANE)) {
516  // Show menu command inner position
517  const double innerPos = myShape.nearest_offset_to_point2D(parent.getPositionInformation());
518  new FXMenuCommand(ret, ("Cursor position inner additional: " + toString(innerPos)).c_str(), 0, 0, 0);
519  // If shape isn't empty, show menu command lane position
520  if (myShape.size() > 0) {
521  const double lanePos = lane->getShape().nearest_offset_to_point2D(myShape[0]);
522  new FXMenuCommand(ret, ("Cursor position over " + toString(SUMO_TAG_LANE) + ": " + toString(innerPos + lanePos)).c_str(), 0, 0, 0);
523  }
524  } else if (tagProperties.hasAttribute(SUMO_ATTR_EDGE)) {
526  // Show menu command inner position
527  const double innerPos = myShape.nearest_offset_to_point2D(parent.getPositionInformation());
528  new FXMenuCommand(ret, ("Cursor position inner additional: " + toString(innerPos)).c_str(), 0, 0, 0);
529  // If shape isn't empty, show menu command edge position
530  if (myShape.size() > 0) {
531  const double edgePos = edge->getLanes().at(0)->getShape().nearest_offset_to_point2D(myShape[0]);
532  new FXMenuCommand(ret, ("Mouse position over " + toString(SUMO_TAG_EDGE) + ": " + toString(innerPos + edgePos)).c_str(), 0, 0, 0);
533  }
534  } else {
535  new FXMenuCommand(ret, ("Cursor position in view: " + toString(getPositionInView().x()) + "," + toString(getPositionInView().y())).c_str(), 0, 0, 0);
536  }
537  return ret;
538 }
539 
540 
543  // Create table
544  GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this, getTagProperties(getTag()).getNumberOfAttributes());
545  // Iterate over attributes
546  for (auto i : getTagProperties(getTag())) {
547  // Add attribute and set it dynamic if aren't unique
548  if (i.second.isUnique()) {
549  ret->mkItem(toString(i.first).c_str(), false, getAttribute(i.first));
550  } else {
551  ret->mkItem(toString(i.first).c_str(), true, getAttribute(i.first));
552  }
553  }
554  // close building
555  ret->closeBuilding();
556  return ret;
557 }
558 
559 
560 Boundary
562  // Return Boundary depending if myMovingGeometryBoundary is initialised (important for move geometry)
565  } else if (myShape.size() > 0) {
567  b.grow(20);
568  return b;
569  } else if (myFirstAdditionalParent) {
571  } else {
572  return Boundary(-0.1, 0.1, 0, 1, 0, 1);
573  }
574 }
575 
576 
577 bool
578 GNEAdditional::isRouteValid(const std::vector<GNEEdge*>& edges, bool report) {
579  if (edges.size() == 0) {
580  // routes cannot be empty
581  return false;
582  } else if (edges.size() == 1) {
583  // routes with a single edge are valid
584  return true;
585  } else {
586  // iterate over edges to check that compounds a chain
587  auto it = edges.begin();
588  while (it != edges.end() - 1) {
589  GNEEdge* currentEdge = *it;
590  GNEEdge* nextEdge = *(it + 1);
591  // consecutive edges aren't allowed
592  if (currentEdge->getID() == nextEdge->getID()) {
593  return false;
594  }
595  // make sure that edges are consecutives
596  if (std::find(currentEdge->getGNEJunctionDestiny()->getGNEOutgoingEdges().begin(),
597  currentEdge->getGNEJunctionDestiny()->getGNEOutgoingEdges().end(),
598  nextEdge) == currentEdge->getGNEJunctionDestiny()->getGNEOutgoingEdges().end()) {
599  if (report) {
600  WRITE_WARNING("Parameter 'Route' invalid. " + toString(currentEdge->getTag()) + " '" + currentEdge->getID() +
601  "' ins't consecutive to " + toString(nextEdge->getTag()) + " '" + nextEdge->getID() + "'");
602  }
603  return false;
604  }
605  it++;
606  }
607  }
608  return true;
609 }
610 
611 
612 void
614  // iterate over attributes and set default value
615  for (auto i : getTagProperties(getTag())) {
616  if (i.second.hasDefaultValue()) {
617  setAttribute(i.first, i.second.getDefaultValue());
618  }
619  }
620 }
621 
622 
623 void
625  if (myShape.size() > 0 && myShape.length() != 0) {
626  // If length of the shape is distint to 0, Obtain rotation of center of shape
628  } else if (additionalLane) {
629  // If additional is over a lane, set rotation in the position over lane
630  double posOverLane = additionalLane->getShape().nearest_offset_to_point2D(getPositionInView());
631  myBlockIconRotation = additionalLane->getShape().rotationDegreeAtOffset(posOverLane) - 90;
632  } else {
633  // In other case, rotation is 0
635  }
636 }
637 
638 
639 void
640 GNEAdditional::drawLockIcon(double size) const {
641  if (myViewNet->showLockIcon()) {
642  // Start pushing matrix
643  glPushMatrix();
644  // Traslate to middle of shape
645  glTranslated(myBlockIconPosition.x(), myBlockIconPosition.y(), getType() + 0.1);
646  // Set draw color
647  glColor3d(1, 1, 1);
648  // Rotate depending of myBlockIconRotation
649  glRotated(myBlockIconRotation, 0, 0, -1);
650  // Rotate 180 degrees
651  glRotated(180, 0, 0, 1);
652  // Traslate depending of the offset
653  glTranslated(myBlockIconOffset.x(), myBlockIconOffset.y(), 0);
654  // Draw icon depending of the state of additional
655  if (mySelected) {
657  // Draw not movable texture if additional isn't movable and is selected
659  } else if (myBlockMovement) {
660  // Draw lock texture if additional is movable, is blocked and is selected
662  } else {
663  // Draw empty texture if additional is movable, isn't blocked and is selected
665  }
666  } else {
667  if (!getTagProperties(getTag()).canBlockMovement()) {
668  // Draw not movable texture if additional isn't movable
670  } else if (myBlockMovement) {
671  // Draw lock texture if additional is movable and is blocked
673  } else {
674  // Draw empty texture if additional is movable and isn't blocked
676  }
677  }
678  // Pop matrix
679  glPopMatrix();
680  }
681 }
682 
683 
684 void
686  // first clear connection positions
689 
690  // calculate position and rotation of every simbol for every edge
691  for (auto i : myEdgeChilds) {
692  for (auto j : i->getLanes()) {
693  std::pair<Position, double> posRot;
694  // set position and lenght depending of shape's lengt
695  if (j->getShape().length() - 6 > 0) {
696  posRot.first = j->getShape().positionAtOffset(j->getShape().length() - 6);
697  posRot.second = j->getShape().rotationDegreeAtOffset(j->getShape().length() - 6);
698  } else {
699  posRot.first = j->getShape().positionAtOffset(j->getShape().length());
700  posRot.second = j->getShape().rotationDegreeAtOffset(j->getShape().length());
701  }
702  mySymbolsPositionAndRotation.push_back(posRot);
703  }
704  }
705 
706  // calculate position and rotation of every symbol for every lane
707  for (auto i : myLaneChilds) {
708  std::pair<Position, double> posRot;
709  // set position and lenght depending of shape's lengt
710  if (i->getShape().length() - 6 > 0) {
711  posRot.first = i->getShape().positionAtOffset(i->getShape().length() - 6);
712  posRot.second = i->getShape().rotationDegreeAtOffset(i->getShape().length() - 6);
713  } else {
714  posRot.first = i->getShape().positionAtOffset(i->getShape().length());
715  posRot.second = i->getShape().rotationDegreeAtOffset(i->getShape().length());
716  }
717  mySymbolsPositionAndRotation.push_back(posRot);
718  }
719 
720  // calculate position for every additional child
721  for (auto i : myAdditionalChilds) {
722  // check that position is different of position
723  if (i->getPositionInView() != getPositionInView()) {
724  std::vector<Position> posConnection;
725  double A = std::abs(i->getPositionInView().x() - getPositionInView().x());
726  double B = std::abs(i->getPositionInView().y() - getPositionInView().y());
727  // Set positions of connection's vertex. Connection is build from Entry to E3
728  posConnection.push_back(i->getPositionInView());
729  if (getPositionInView().x() > i->getPositionInView().x()) {
730  if (getPositionInView().y() > i->getPositionInView().y()) {
731  posConnection.push_back(Position(i->getPositionInView().x() + A, i->getPositionInView().y()));
732  } else {
733  posConnection.push_back(Position(i->getPositionInView().x(), i->getPositionInView().y() - B));
734  }
735  } else {
736  if (getPositionInView().y() > i->getPositionInView().y()) {
737  posConnection.push_back(Position(i->getPositionInView().x(), i->getPositionInView().y() + B));
738  } else {
739  posConnection.push_back(Position(i->getPositionInView().x() - A, i->getPositionInView().y()));
740  }
741  }
742  posConnection.push_back(getPositionInView());
743  myChildConnectionPositions.push_back(posConnection);
744  }
745  }
746 
747  // calculate geometry for connections between parent and childs
748  for (auto i : mySymbolsPositionAndRotation) {
749  std::vector<Position> posConnection;
750  double A = std::abs(i.first.x() - getPositionInView().x());
751  double B = std::abs(i.first.y() - getPositionInView().y());
752  // Set positions of connection's vertex. Connection is build from Entry to E3
753  posConnection.push_back(i.first);
754  if (getPositionInView().x() > i.first.x()) {
755  if (getPositionInView().y() > i.first.y()) {
756  posConnection.push_back(Position(i.first.x() + A, i.first.y()));
757  } else {
758  posConnection.push_back(Position(i.first.x(), i.first.y() - B));
759  }
760  } else {
761  if (getPositionInView().y() > i.first.y()) {
762  posConnection.push_back(Position(i.first.x(), i.first.y() + B));
763  } else {
764  posConnection.push_back(Position(i.first.x() - A, i.first.y()));
765  }
766  }
767  posConnection.push_back(getPositionInView());
768  myChildConnectionPositions.push_back(posConnection);
769  }
770 }
771 
772 
773 void
775  // Iterate over myConnectionPositions
776  for (auto i : myChildConnectionPositions) {
777  // Add a draw matrix
778  glPushMatrix();
779  // traslate in the Z axis
780  glTranslated(0, 0, getType() - 0.01);
781  // Set color of the base
782  GLHelper::setColor(RGBColor(255, 235, 0));
783  for (auto j = i.begin(); (j + 1) != i.end(); j++) {
784  // Draw Lines
785  GLHelper::drawLine((*j), (*(j + 1)));
786  }
787  // Pop draw matrix
788  glPopMatrix();
789  }
790 }
791 
792 
793 const std::string&
795  return getMicrosimID();
796 }
797 
798 
799 bool
800 GNEAdditional::isValidAdditionalID(const std::string& newID) const {
801  if (SUMOXMLDefinitions::isValidNetID(newID) && (myViewNet->getNet()->retrieveAdditional(getTag(), newID, false) == nullptr)) {
802  return true;
803  } else {
804  return false;
805  }
806 }
807 
808 
809 void
810 GNEAdditional::changeAdditionalID(const std::string& newID) {
811  if (myViewNet->getNet()->retrieveAdditional(getTag(), newID, false) != nullptr) {
812  throw InvalidArgument("An Additional with tag " + toString(getTag()) + " and ID = " + newID + " already exists");
813  } else if (!SUMOXMLDefinitions::isValidNetID(newID)) {
814  throw InvalidArgument("Additional ID " + newID + " contains invalid characters");
815  } else {
816  // Save old ID
817  std::string oldID = getMicrosimID();
818  // set New ID
819  setMicrosimID(newID);
820  // update additional ID in the container of net
821  myViewNet->getNet()->updateAdditionalID(oldID, this);
822  }
823 }
824 
825 
826 GNEEdge*
827 GNEAdditional::changeEdge(GNEEdge* oldEdge, const std::string& newEdgeID) {
828  if (oldEdge == nullptr) {
829  throw InvalidArgument(toString(getTag()) + " with ID '" + getMicrosimID() + "' doesn't belong to an " + toString(SUMO_TAG_EDGE));
830  } else {
831  oldEdge->removeAdditionalChild(this);
832  GNEEdge* newEdge = myViewNet->getNet()->retrieveEdge(newEdgeID);
833  newEdge->addAdditionalChild(this);
834  updateGeometry(true);
835  return newEdge;
836  }
837 }
838 
839 
840 GNELane*
841 GNEAdditional::changeLane(GNELane* oldLane, const std::string& newLaneID) {
842  if (oldLane == nullptr) {
843  throw InvalidArgument(toString(getTag()) + " with ID '" + getMicrosimID() + "' doesn't belong to a " + toString(SUMO_TAG_LANE));
844  } else {
845  oldLane->removeAdditionalChild(this);
846  GNELane* newLane = myViewNet->getNet()->retrieveLane(newLaneID);
847  newLane->addAdditionalChild(this);
848  updateGeometry(true);
849  return newLane;
850  }
851 }
852 
853 
854 void
855 GNEAdditional::changeFirstAdditionalParent(const std::string& newAdditionalParentID) {
856  if (myFirstAdditionalParent == nullptr) {
857  throw InvalidArgument(toString(getTag()) + " with ID '" + getMicrosimID() + "' doesn't have an additional parent");
858  } else {
859  // remove this additional of the childs of parent additional
861  // set new additional parent
863  // add this additional int the childs of parent additional
865  updateGeometry(true);
866  }
867 }
868 
869 
870 void
871 GNEAdditional::changeSecondAdditionalParent(const std::string& newAdditionalParentID) {
872  if (mySecondAdditionalParent == nullptr) {
873  throw InvalidArgument(toString(getTag()) + " with ID '" + getMicrosimID() + "' doesn't have an additional parent");
874  } else {
875  // remove this additional of the childs of parent additional
877  // set new additional parent
879  // add this additional int the childs of parent additional
881  updateGeometry(true);
882  }
883 }
884 
885 
886 void
888  if (!myViewNet) {
889  throw ProcessError("ViewNet cannot be nullptr");
890  } else {
891  gSelected.select(dynamic_cast<GUIGlObject*>(this)->getGlID());
892  if (changeFlag) {
893  mySelected = true;
894  }
895  }
896 }
897 
898 
899 void
901  if (!myViewNet) {
902  throw ProcessError("ViewNet cannot be nullptr");
903  } else {
904  gSelected.deselect(dynamic_cast<GUIGlObject*>(this)->getGlID());
905  if (changeFlag) {
906  mySelected = false;
907  }
908  }
909 }
910 
911 
912 bool
914  return mySelected;
915 }
916 
917 
918 bool
920  // throw exception because this function mus be implemented in child (see GNEE3Detector)
921  throw ProcessError("Calling non-implemented function checkAdditionalChildRestriction during saving of " + toString(getTag()) + ". It muss be reimplemented in child class");
922 }
923 
924 
925 bool
926 GNEAdditional::addGenericParameter(const std::string& key, const std::string& value) {
927  if (!knowsParameter(key)) {
928  setParameter(key, value);
929  return true;
930  } else {
931  return false;
932  }
933 }
934 
935 
936 bool
937 GNEAdditional::removeGenericParameter(const std::string& key) {
938  if (knowsParameter(key)) {
939  unsetParameter(key);
940  return true;
941  } else {
942  return false;
943  }
944 }
945 
946 
947 bool
948 GNEAdditional::updateGenericParameter(const std::string& oldKey, const std::string& newKey) {
949  if (knowsParameter(oldKey) && !knowsParameter(newKey)) {
950  std::string value = getParameter(oldKey);
951  unsetParameter(oldKey);
952  setParameter(newKey, value);
953  return true;
954  } else {
955  return false;
956  }
957 }
958 
959 
960 bool
961 GNEAdditional::updateGenericParameterValue(const std::string& key, const std::string& newValue) {
962  if (knowsParameter(key)) {
963  setParameter(key, newValue);
964  return true;
965  } else {
966  return false;
967  }
968 }
969 
970 
971 std::string
973  std::string result;
974  // Generate an string using the following structure: "key1=value1|key2=value2|...
975  for (auto i : getParametersMap()) {
976  result += i.first + "=" + i.second + "|";
977  }
978  // remove the last "|"
979  if (!result.empty()) {
980  result.pop_back();
981  }
982  return result;
983 }
984 
985 
986 std::vector<std::pair<std::string, std::string> >
988  std::vector<std::pair<std::string, std::string> > result;
989  // iterate over parameters map and fill result
990  for (auto i : getParametersMap()) {
991  result.push_back(std::make_pair(i.first, i.second));
992  }
993  return result;
994 }
995 
996 
997 void
998 GNEAdditional::setGenericParametersStr(const std::string& value) {
999  // clear parameters
1000  clearParameter();
1001  // separate value in a vector of string using | as separator
1002  std::vector<std::string> parsedValues;
1003  StringTokenizer stValues(value, "|", true);
1004  while (stValues.hasNext()) {
1005  parsedValues.push_back(stValues.next());
1006  }
1007  // check that parsed values (A=B)can be parsed in generic parameters
1008  for (auto i : parsedValues) {
1009  std::vector<std::string> parsedParameters;
1010  StringTokenizer stParam(i, "=", true);
1011  while (stParam.hasNext()) {
1012  parsedParameters.push_back(stParam.next());
1013  }
1014  // Check that parsed parameters are exactly two and contains valid chracters
1015  if (parsedParameters.size() == 2 && SUMOXMLDefinitions::isValidGenericParameterKey(parsedParameters.front()) && SUMOXMLDefinitions::isValidGenericParameterValue(parsedParameters.back())) {
1016  setParameter(parsedParameters.front(), parsedParameters.back());
1017  }
1018  }
1019 }
1020 
1021 
1022 void
1024 }
1025 
1026 
1027 /****************************************************************************/
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:907
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:1787
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:1832
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:1167
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:613
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
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
void buildSelectionPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to (de)select the object.
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:1160
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:1066
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.