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 <netedit/GNENet.h>
24 #include <netedit/GNEViewParent.h>
30 #include <utils/gui/div/GLHelper.h>
37 
38 #include "GNEAdditional.h"
39 
40 // ===========================================================================
41 // member method definitions
42 // ===========================================================================
43 
44 GNEAdditional::GNEAdditional(const std::string& id, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement) :
45  GUIGlObject(type, id),
47  Parameterised(),
48  myViewNet(viewNet),
49  myAdditionalName(additionalName),
50  myBlockMovement(blockMovement),
51  myFirstAdditionalParent(nullptr),
52  mySecondAdditionalParent(nullptr),
53  myBlockIcon(this),
54  myChildConnections(this) {
55 }
56 
57 
58 GNEAdditional::GNEAdditional(GNEAdditional* singleAdditionalParent, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement) :
59  GUIGlObject(type, singleAdditionalParent->generateAdditionalChildID(tag)),
61  Parameterised(),
62  myViewNet(viewNet),
63  myAdditionalName(additionalName),
64  myBlockMovement(blockMovement),
65  myFirstAdditionalParent(singleAdditionalParent),
66  mySecondAdditionalParent(nullptr),
67  myBlockIcon(this),
68  myChildConnections(this) {
69  // check that additional parent is of expected type
70  assert(singleAdditionalParent->getTagProperty().getTag() == myTagProperty.getParentTag());
71 }
72 
73 
74 GNEAdditional::GNEAdditional(GNEAdditional* firstAdditionalParent, GNEAdditional* secondAdditionalParent, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement) :
75  GUIGlObject(type, firstAdditionalParent->generateAdditionalChildID(tag)),
77  Parameterised(),
78  myViewNet(viewNet),
79  myAdditionalName(additionalName),
80  myBlockMovement(blockMovement),
81  myFirstAdditionalParent(firstAdditionalParent),
82  mySecondAdditionalParent(secondAdditionalParent),
83  myBlockIcon(this),
84  myChildConnections(this) {
85  // check that additional parent is of expected type
86  assert(firstAdditionalParent->getTagProperty().getTag() == myTagProperty.getParentTag());
87 }
88 
89 
90 GNEAdditional::GNEAdditional(const std::string& id, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement, std::vector<GNEEdge*> edgeChilds) :
91  GUIGlObject(type, id),
93  Parameterised(),
94  myViewNet(viewNet),
95  myAdditionalName(additionalName),
96  myBlockMovement(blockMovement),
97  myFirstAdditionalParent(nullptr),
98  mySecondAdditionalParent(nullptr),
99  myEdgeChilds(edgeChilds),
100  myBlockIcon(this),
101  myChildConnections(this) {
102 }
103 
104 
105 GNEAdditional::GNEAdditional(const std::string& id, GNEViewNet* viewNet, GUIGlObjectType type, SumoXMLTag tag, std::string additionalName, bool blockMovement, std::vector<GNELane*> laneChilds) :
106  GUIGlObject(type, id),
107  GNEAttributeCarrier(tag),
108  Parameterised(),
109  myViewNet(viewNet),
110  myAdditionalName(additionalName),
111  myBlockMovement(blockMovement),
112  myFirstAdditionalParent(nullptr),
113  mySecondAdditionalParent(nullptr),
114  myLaneChilds(laneChilds),
115  myBlockIcon(this),
116  myChildConnections(this) {
117 }
118 
119 
121 
122 
123 void
125  // obtain tag properties
126  const TagProperties& tagProperties = myTagProperty;
127  // first check if minimum number of childs is correct
128  if ((tagProperties.hasMinimumNumberOfChilds() || tagProperties.hasMinimumNumberOfChilds()) && !checkAdditionalChildRestriction()) {
129  WRITE_WARNING(getTagStr() + " with ID='" + getID() + "' cannot be written");
130  } else {
131  // Open Tag or synonym Tag
132  if (tagProperties.hasTagSynonym()) {
133  device.openTag(tagProperties.getTagSynonym());
134  } else {
135  device.openTag(myTagProperty.getTag());
136  }
137  // iterate over attributes and write it
138  for (auto i : tagProperties) {
139  // obtain attribute
140  std::string attribute = getAttribute(i.first);
141  if (i.second.isOptional() && i.second.hasDefaultValue() && !i.second.isCombinable()) {
142  // Only write attributes with default value if is different from original
143  if (i.second.getDefaultValue() != attribute) {
144  // check if attribute must be written using a synonim
145  if (i.second.hasAttrSynonym()) {
146  device.writeAttr(i.second.getAttrSynonym(), attribute);
147  } else {
148  // SVC permissions uses their own writting function
149  if (i.second.isSVCPermission()) {
150  // disallow attribute musn't be written
151  if (i.first != SUMO_ATTR_DISALLOW) {
152  writePermissions(device, parseVehicleClasses(attribute));
153  }
154  } else if(tagProperties.canMaskXYZPositions() && (i.first == SUMO_ATTR_POSITION)) {
155  // get position attribute and write it separate
156  Position pos = parse<Position>(getAttribute(SUMO_ATTR_POSITION));
157  device.writeAttr(SUMO_ATTR_X, toString(pos.x()));
158  device.writeAttr(SUMO_ATTR_Y, toString(pos.y()));
159  // write 0 only if is different from 0 (the default value)
160  if(pos.z() != 0) {
161  device.writeAttr(SUMO_ATTR_Z, toString(pos.z()));
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 if(tagProperties.canMaskXYZPositions() && (i.first == SUMO_ATTR_POSITION)) {
180  // get position attribute and write it separate
181  Position pos = parse<Position>(getAttribute(SUMO_ATTR_POSITION));
182  device.writeAttr(SUMO_ATTR_X, toString(pos.x()));
183  device.writeAttr(SUMO_ATTR_Y, toString(pos.y()));
184  // write 0 only if is different from 0 (the default value)
185  if(pos.z() != 0) {
186  device.writeAttr(SUMO_ATTR_Z, toString(pos.z()));
187  }
188  } else {
189  device.writeAttr(i.first, attribute);
190  }
191  }
192  }
193  }
194  // iterate over childs and write it in XML (or in a different file)
195  if (tagProperties.canWriteChildsSeparate() && tagProperties.hasAttribute(SUMO_ATTR_FILE) && !getAttribute(SUMO_ATTR_FILE).empty()) {
196  // we assume that rerouter values files is placed in the same folder as the additional file
198  deviceChilds.writeXMLHeader("rerouterValue", "additional_file.xsd");
199  // save childs in a different filename
200  for (auto i : myAdditionalChilds) {
201  // avoid to write two times additionals that haben two parents (Only write as child of first parent)
202  if (i->getSecondAdditionalParent() == nullptr) {
203  i->writeAdditional(deviceChilds);
204  } else if (myTagProperty.getTag() == i->getTagProperty().getParentTag()) {
205  i->writeAdditional(deviceChilds);
206  }
207  }
208  deviceChilds.close();
209  } else {
210  for (auto i : myAdditionalChilds) {
211  // avoid to write two times additionals that haben two parents (Only write as child of first parent)
212  if (i->getSecondAdditionalParent() == nullptr) {
213  i->writeAdditional(device);
214  } else if (myTagProperty.getTag() == i->getTagProperty().getParentTag()) {
215  i->writeAdditional(device);
216  }
217  }
218  }
219  // save generic parameters (Always after childs to avoid problems with additionals.xsd)
220  writeParams(device);
221  // Close tag
222  device.closeTag();
223  }
224 }
225 
226 
227 bool
229  return true;
230 }
231 
232 
233 std::string
235  return "";
236 }
237 
238 
239 void
241  throw InvalidArgument(getTagStr() + " cannot fix any problem");
242 }
243 
244 
245 void
247  throw InvalidArgument(getTagStr() + " doesn't have an additional dialog");
248 }
249 
250 
251 void
253  // always save original position over view
255  // obtain tag properties (to improve code legibility)
256  const TagProperties& tagProperties = myTagProperty;
257  // check if position over lane or lanes has to be saved
258  if (tagProperties.canBePlacedOverLane()) {
259  if(tagProperties.canMaskStartEndPos()) {
260  // obtain start and end position
263  } else {
264  // obtain position attribute
266  }
267  } else if (tagProperties.canBePlacedOverLanes()) {
268  // obtain start and end position
271  }
272  // save current centering boundary
274 }
275 
276 
277 void
279  // check that endGeometryMoving was called only once
281  // Remove object from net
283  // reset myMovingGeometryBoundary
285  // update geometry without updating grid
286  updateGeometry(false);
287  // add object into grid again (using the new centering boundary)
289  }
290 }
291 
292 
293 GNEViewNet*
295  return myViewNet;
296 }
297 
298 
301  return myGeometry.shape;
302 }
303 
304 
305 bool
307  return myBlockMovement;
308 }
309 
310 
314 }
315 
316 
320 }
321 
322 
323 std::string
325  int counter = 0;
326  while (myViewNet->getNet()->retrieveAdditional(childTag, getID() + toString(childTag) + toString(counter), false) != nullptr) {
327  counter++;
328  }
329  return (getID() + toString(childTag) + toString(counter));
330 }
331 
332 
333 void
335  // First check that additional wasn't already inserted
336  if (std::find(myAdditionalChilds.begin(), myAdditionalChilds.end(), additional) != myAdditionalChilds.end()) {
337  throw ProcessError(additional->getTagStr() + " with ID='" + additional->getID() + "' was already inserted in " + getTagStr() + " with ID='" + getID() + "'");
338  } else {
339  myAdditionalChilds.push_back(additional);
340  // Check if childs has to be sorted automatically
343  }
344  // update additional parent after add additional (note: by default non-implemented)
346  // update geometry (for set geometry of lines between Parents and Childs)
347  updateGeometry(true);
348  }
349 }
350 
351 
352 void
354  // First check that additional was already inserted
355  auto it = std::find(myAdditionalChilds.begin(), myAdditionalChilds.end(), additional);
356  if (it == myAdditionalChilds.end()) {
357  throw ProcessError(additional->getTagStr() + " with ID='" + additional->getID() + "' doesn't exist in " + getTagStr() + " with ID='" + getID() + "'");
358  } else {
359  myAdditionalChilds.erase(it);
360  // Check if childs has to be sorted automatically
363  }
364  // update additional parent after add additional (note: by default non-implemented)
366  // update geometry (for remove geometry of lines between Parents and Childs)
367  updateGeometry(true);
368  }
369 }
370 
371 
372 const std::vector<GNEAdditional*>&
374  return myAdditionalChilds;
375 }
376 
377 
378 void
381  // we need to sort Entry/Exits due additional.xds model
382  std::vector<GNEAdditional*> sortedEntryExits;
383  // obtain all entrys
384  for (auto i : myAdditionalChilds) {
385  if (i->getTagProperty().getTag() == SUMO_TAG_DET_ENTRY) {
386  sortedEntryExits.push_back(i);
387  }
388  }
389  // obtain all exits
390  for (auto i : myAdditionalChilds) {
391  if (i->getTagProperty().getTag() == SUMO_TAG_DET_EXIT) {
392  sortedEntryExits.push_back(i);
393  }
394  }
395  // change myAdditionalChilds for sortedEntryExits
396  if (sortedEntryExits.size() == myAdditionalChilds.size()) {
397  myAdditionalChilds = sortedEntryExits;
398  } else {
399  throw ProcessError("Some additional childs were lost during sorting");
400  }
401  } else if (myTagProperty.getTag() == SUMO_TAG_TAZ) {
402  // we need to sort Entry/Exits due additional.xds model
403  std::vector<GNEAdditional*> sortedTAZSourceSink;
404  // obtain all TAZSources
405  for (auto i : myAdditionalChilds) {
406  if (i->getTagProperty().getTag() == SUMO_TAG_TAZSOURCE) {
407  sortedTAZSourceSink.push_back(i);
408  }
409  }
410  // obtain all TAZSinks
411  for (auto i : myAdditionalChilds) {
412  if (i->getTagProperty().getTag() == SUMO_TAG_TAZSINK) {
413  sortedTAZSourceSink.push_back(i);
414  }
415  }
416  // change myAdditionalChilds for sortedEntryExits
417  if (sortedTAZSourceSink.size() == myAdditionalChilds.size()) {
418  myAdditionalChilds = sortedTAZSourceSink;
419  } else {
420  throw ProcessError("Some additional childs were lost during sorting");
421  }
422  } else {
423  // declare a vector to keep sorted childs
424  std::vector<std::pair<std::pair<double, double>, GNEAdditional*> > sortedChilds;
425  // iterate over additional childs
426  for (auto i : myAdditionalChilds) {
427  sortedChilds.push_back(std::make_pair(std::make_pair(0., 0.), i));
428  // set begin/start attribute
429  if (i->getTagProperty().hasAttribute(SUMO_ATTR_TIME) && canParse<double>(i->getAttribute(SUMO_ATTR_TIME))) {
430  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_TIME));
431  } else if (i->getTagProperty().hasAttribute(SUMO_ATTR_BEGIN) && canParse<double>(i->getAttribute(SUMO_ATTR_BEGIN))) {
432  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_BEGIN));
433  }
434  // set end attribute
435  if (i->getTagProperty().hasAttribute(SUMO_ATTR_END) && canParse<double>(i->getAttribute(SUMO_ATTR_END))) {
436  sortedChilds.back().first.second = parse<double>(i->getAttribute(SUMO_ATTR_END));
437  } else {
438  sortedChilds.back().first.second = sortedChilds.back().first.first;
439  }
440  }
441  // sort childs
442  std::sort(sortedChilds.begin(), sortedChilds.end());
443  // make sure that number of sorted childs is the same as the additional childs
444  if (sortedChilds.size() == myAdditionalChilds.size()) {
445  myAdditionalChilds.clear();
446  for (auto i : sortedChilds) {
447  myAdditionalChilds.push_back(i.second);
448  }
449  } else {
450  throw ProcessError("Some additional childs were lost during sorting");
451  }
452  }
453 }
454 
455 
456 bool
458  // declare a vector to keep sorted childs
459  std::vector<std::pair<std::pair<double, double>, GNEAdditional*> > sortedChilds;
460  // iterate over additional childs
461  for (auto i : myAdditionalChilds) {
462  sortedChilds.push_back(std::make_pair(std::make_pair(0., 0.), i));
463  // set begin/start attribute
464  if (i->getTagProperty().hasAttribute(SUMO_ATTR_TIME) && canParse<double>(i->getAttribute(SUMO_ATTR_TIME))) {
465  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_TIME));
466  } else if (i->getTagProperty().hasAttribute(SUMO_ATTR_BEGIN) && canParse<double>(i->getAttribute(SUMO_ATTR_BEGIN))) {
467  sortedChilds.back().first.first = parse<double>(i->getAttribute(SUMO_ATTR_BEGIN));
468  }
469  // set end attribute
470  if (i->getTagProperty().hasAttribute(SUMO_ATTR_END) && canParse<double>(i->getAttribute(SUMO_ATTR_END))) {
471  sortedChilds.back().first.second = parse<double>(i->getAttribute(SUMO_ATTR_END));
472  } else {
473  sortedChilds.back().first.second = sortedChilds.back().first.first;
474  }
475  }
476  // sort childs
477  std::sort(sortedChilds.begin(), sortedChilds.end());
478  // make sure that number of sorted childs is the same as the additional childs
479  if (sortedChilds.size() == myAdditionalChilds.size()) {
480  if (sortedChilds.size() <= 1) {
481  return true;
482  } else {
483  // check overlapping
484  for (int i = 0; i < (int)sortedChilds.size() - 1; i++) {
485  if (sortedChilds.at(i).first.second > sortedChilds.at(i + 1).first.first) {
486  return false;
487  }
488  }
489  }
490  return true;
491  } else {
492  throw ProcessError("Some additional childs were lost during sorting");
493  }
494 }
495 
496 
497 void
499  // Check that edge is valid and doesn't exist previously
500  if (edge == nullptr) {
501  throw InvalidArgument("Trying to add an empty " + toString(SUMO_TAG_EDGE) + " child in " + getTagStr() + " with ID='" + getID() + "'");
502  } else if (std::find(myEdgeChilds.begin(), myEdgeChilds.end(), edge) != myEdgeChilds.end()) {
503  throw InvalidArgument("Trying to add a duplicate " + toString(SUMO_TAG_EDGE) + " child in " + getTagStr() + " with ID='" + getID() + "'");
504  } else {
505  myEdgeChilds.push_back(edge);
506  }
507 }
508 
509 
510 void
512  // Check that edge is valid and exist previously
513  if (edge == nullptr) {
514  throw InvalidArgument("Trying to remove an empty " + toString(SUMO_TAG_EDGE) + " child in " + getTagStr() + " with ID='" + getID() + "'");
515  } else if (std::find(myEdgeChilds.begin(), myEdgeChilds.end(), edge) == myEdgeChilds.end()) {
516  throw InvalidArgument("Trying to remove a non previously inserted " + toString(SUMO_TAG_EDGE) + " child in " + getTagStr() + " with ID='" + getID() + "'");
517  } else {
518  myEdgeChilds.erase(std::find(myEdgeChilds.begin(), myEdgeChilds.end(), edge));
519  }
520 }
521 
522 
523 const std::vector<GNEEdge*>&
525  return myEdgeChilds;
526 }
527 
528 
529 void
531  // Check that lane is valid and doesn't exist previously
532  if (lane == nullptr) {
533  throw InvalidArgument("Trying to add an empty " + toString(SUMO_TAG_EDGE) + " child in " + getTagStr() + " with ID='" + getID() + "'");
534  } else if (std::find(myLaneChilds.begin(), myLaneChilds.end(), lane) != myLaneChilds.end()) {
535  throw InvalidArgument("Trying to add a duplicate " + toString(SUMO_TAG_EDGE) + " child in " + getTagStr() + " with ID='" + getID() + "'");
536  } else {
537  myLaneChilds.push_back(lane);
538  }
539 }
540 
541 
542 void
544  // Check that lane is valid and exist previously
545  if (lane == nullptr) {
546  throw InvalidArgument("Trying to remove an empty " + toString(SUMO_TAG_EDGE) + " child in " + getTagStr() + " with ID='" + getID() + "'");
547  } else if (std::find(myLaneChilds.begin(), myLaneChilds.end(), lane) == myLaneChilds.end()) {
548  throw InvalidArgument("Trying to remove a non previously inserted " + toString(SUMO_TAG_EDGE) + " child in " + getTagStr() + " with ID='" + getID() + "'");
549  } else {
550  myLaneChilds.erase(std::find(myLaneChilds.begin(), myLaneChilds.end(), lane));
551  }
552 }
553 
554 
555 const std::vector<GNELane*>&
557  return myLaneChilds;
558 }
559 
560 
563  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
564  // build header
565  buildPopupHeader(ret, app);
566  // build menu command for center button and copy cursor position to clipboard
568  buildPositionCopyEntry(ret, false);
569  // buld menu commands for names
570  new FXMenuCommand(ret, ("Copy " + getTagStr() + " name to clipboard").c_str(), nullptr, ret, MID_COPY_NAME);
571  new FXMenuCommand(ret, ("Copy " + getTagStr() + " typed name to clipboard").c_str(), nullptr, ret, MID_COPY_TYPED_NAME);
572  new FXMenuSeparator(ret);
573  // build selection and show parameters menu
576  // show option to open additional dialog
577  if (myTagProperty.hasDialog()) {
578  new FXMenuCommand(ret, ("Open " + getTagStr() + " Dialog").c_str(), getIcon(), &parent, MID_OPEN_ADDITIONAL_DIALOG);
579  new FXMenuSeparator(ret);
580  }
581  // Show position parameters
584  // Show menu command inner position
585  const double innerPos = myGeometry.shape.nearest_offset_to_point2D(parent.getPositionInformation());
586  new FXMenuCommand(ret, ("Cursor position inner additional: " + toString(innerPos)).c_str(), nullptr, nullptr, 0);
587  // If shape isn't empty, show menu command lane position
588  if (myGeometry.shape.size() > 0) {
589  const double lanePos = lane->getShape().nearest_offset_to_point2D(myGeometry.shape[0]);
590  new FXMenuCommand(ret, ("Cursor position over " + toString(SUMO_TAG_LANE) + ": " + toString(innerPos + lanePos)).c_str(), nullptr, nullptr, 0);
591  }
594  // Show menu command inner position
595  const double innerPos = myGeometry.shape.nearest_offset_to_point2D(parent.getPositionInformation());
596  new FXMenuCommand(ret, ("Cursor position inner additional: " + toString(innerPos)).c_str(), nullptr, nullptr, 0);
597  // If shape isn't empty, show menu command edge position
598  if (myGeometry.shape.size() > 0) {
599  const double edgePos = edge->getLanes().at(0)->getShape().nearest_offset_to_point2D(myGeometry.shape[0]);
600  new FXMenuCommand(ret, ("Mouse position over " + toString(SUMO_TAG_EDGE) + ": " + toString(innerPos + edgePos)).c_str(), nullptr, nullptr, 0);
601  }
602  } else {
603  new FXMenuCommand(ret, ("Cursor position in view: " + toString(getPositionInView().x()) + "," + toString(getPositionInView().y())).c_str(), nullptr, nullptr, 0);
604  }
605  return ret;
606 }
607 
608 
611  // Create table
613  // Iterate over attributes
614  for (const auto &i : myTagProperty) {
615  // Add attribute and set it dynamic if aren't unique
616  if (i.second.isUnique()) {
617  ret->mkItem(toString(i.first).c_str(), false, getAttribute(i.first));
618  } else {
619  ret->mkItem(toString(i.first).c_str(), true, getAttribute(i.first));
620  }
621  }
622  // close building
623  ret->closeBuilding();
624  return ret;
625 }
626 
627 
628 Boundary
630  // Return Boundary depending if myMovingGeometryBoundary is initialised (important for move geometry)
633  } else if (myGeometry.shape.size() > 0) {
635  b.grow(20);
636  return b;
637  } else if (myGeometry.multiShape.size() > 0) {
638  // obtain boundary of multishape fixed
640  b.grow(20);
641  return b;
642  } else if (myFirstAdditionalParent) {
644  } else {
645  return Boundary(-0.1, -0.1, 0.1, 0.1);
646  }
647 }
648 
649 
650 bool
651 GNEAdditional::isRouteValid(const std::vector<GNEEdge*>& edges, bool report) {
652  if (edges.size() == 0) {
653  // routes cannot be empty
654  return false;
655  } else if (edges.size() == 1) {
656  // routes with a single edge are valid
657  return true;
658  } else {
659  // iterate over edges to check that compounds a chain
660  auto it = edges.begin();
661  while (it != edges.end() - 1) {
662  GNEEdge* currentEdge = *it;
663  GNEEdge* nextEdge = *(it + 1);
664  // consecutive edges aren't allowed
665  if (currentEdge->getID() == nextEdge->getID()) {
666  return false;
667  }
668  // make sure that edges are consecutives
669  if (std::find(currentEdge->getGNEJunctionDestiny()->getGNEOutgoingEdges().begin(),
670  currentEdge->getGNEJunctionDestiny()->getGNEOutgoingEdges().end(),
671  nextEdge) == currentEdge->getGNEJunctionDestiny()->getGNEOutgoingEdges().end()) {
672  if (report) {
673  WRITE_WARNING("Parameter 'Route' invalid. " + currentEdge->getTagStr() + " '" + currentEdge->getID() +
674  "' ins't consecutive to " + nextEdge->getTagStr() + " '" + nextEdge->getID() + "'");
675  }
676  return false;
677  }
678  it++;
679  }
680  }
681  return true;
682 }
683 
684 
685 void
687  // by default nothing to do
688 }
689 
690 
692 
693 
694 void
696  shape.clear();
697  multiShape.clear();
698  shapeRotations.clear();
699  shapeLengths.clear();
700  multiShapeRotations.clear();
701  multiShapeLengths.clear();
702  multiShapeUnified.clear();
703 }
704 
705 
706 void
708  // merge all multishape parts in a single shape
709  for (auto i : multiShape) {
710  multiShapeUnified.append(i);
711  }
712 }
713 
714 
715 void
717  // Get number of parts of the shape
718  int numberOfSegments = (int)shape.size() - 1;
719  // If number of segments is more than 0
720  if (numberOfSegments >= 0) {
721  // Reserve memory (To improve efficiency)
722  shapeRotations.reserve(numberOfSegments);
723  shapeLengths.reserve(numberOfSegments);
724  // For every part of the shape
725  for (int i = 0; i < numberOfSegments; ++i) {
726  // Obtain first position
727  const Position& f = shape[i];
728  // Obtain next position
729  const Position& s = shape[i + 1];
730  // Save distance between position into myShapeLengths
731  shapeLengths.push_back(f.distanceTo(s));
732  // Save rotation (angle) of the vector constructed by points f and s
733  shapeRotations.push_back((double)atan2((s.x() - f.x()), (f.y() - s.y())) * (double) 180.0 / (double)M_PI);
734  }
735  }
736 }
737 
738 
739 void
741  // Get number of parts of the shape for every part shape
742  std::vector<int> numberOfSegments;
743  for (auto i : multiShape) {
744  // numseg cannot be 0
745  int numSeg = (int)i.size() - 1;
746  numberOfSegments.push_back((numSeg>=0)? numSeg : 0);
747  multiShapeRotations.push_back(std::vector<double>());
748  multiShapeLengths.push_back(std::vector<double>());
749  }
750  // If number of segments is more than 0
751  for (int i = 0; i < (int)multiShape.size(); i++) {
752  // Reserve size for every part
753  multiShapeRotations.back().reserve(numberOfSegments.at(i));
754  multiShapeLengths.back().reserve(numberOfSegments.at(i));
755  // iterate over each segment
756  for (int j = 0; j < numberOfSegments.at(i); j++) {
757  // Obtain first position
758  const Position& f = multiShape[i][j];
759  // Obtain next position
760  const Position& s = multiShape[i][j + 1];
761  // Save distance between position into myShapeLengths
762  multiShapeLengths.at(i).push_back(f.distanceTo(s));
763  // Save rotation (angle) of the vector constructed by points f and s
764  multiShapeRotations.at(i).push_back((double)atan2((s.x() - f.x()), (f.y() - s.y())) * (double) 180.0 / (double)M_PI);
765  }
766  }
767 }
768 
769 
771  myAdditional(additional),
772  rotation(0.) {}
773 
774 
775 void
777  if (myAdditional->myGeometry.shape.size() > 0 && myAdditional->myGeometry.shape.length() != 0) {
778  // If length of the shape is distint to 0, Obtain rotation of center of shape
780  } else if (additionalLane) {
781  // If additional is over a lane, set rotation in the position over lane
782  double posOverLane = additionalLane->getShape().nearest_offset_to_point2D(myAdditional->getPositionInView());
783  rotation = additionalLane->getShape().rotationDegreeAtOffset(posOverLane) - 90;
784  } else {
785  // In other case, rotation is 0
786  rotation = 0;
787  }
788 }
789 
790 
791 void
792 GNEAdditional::BlockIcon::draw(double size) const {
794  // Start pushing matrix
795  glPushMatrix();
796  // Traslate to middle of shape
797  glTranslated(position.x(), position.y(), myAdditional->getType() + 0.1);
798  // Set draw color
799  glColor3d(1, 1, 1);
800  // Rotate depending of rotation
801  glRotated(rotation, 0, 0, -1);
802  // Rotate 180 degrees
803  glRotated(180, 0, 0, 1);
804  // Traslate depending of the offset
805  glTranslated(offset.x(), offset.y(), 0);
806  // Draw icon depending of the state of additional
807  if (myAdditional->mySelected) {
809  // Draw not movable texture if additional isn't movable and is selected
811  } else if (myAdditional->myBlockMovement) {
812  // Draw lock texture if additional is movable, is blocked and is selected
814  } else {
815  // Draw empty texture if additional is movable, isn't blocked and is selected
817  }
818  } else {
820  // Draw not movable texture if additional isn't movable
822  } else if (myAdditional->myBlockMovement) {
823  // Draw lock texture if additional is movable and is blocked
825  } else {
826  // Draw empty texture if additional is movable and isn't blocked
828  }
829  }
830  // Pop matrix
831  glPopMatrix();
832  }
833 }
834 
835 
837  myAdditional(additional) {}
838 
839 
840 void
842  // first clear connection positions
843  connectionPositions.clear();
845 
846  // calculate position and rotation of every simbol for every edge
847  for (auto i : myAdditional->myEdgeChilds) {
848  for (auto j : i->getLanes()) {
849  std::pair<Position, double> posRot;
850  // set position and lenght depending of shape's lengt
851  if (j->getShape().length() - 6 > 0) {
852  posRot.first = j->getShape().positionAtOffset(j->getShape().length() - 6);
853  posRot.second = j->getShape().rotationDegreeAtOffset(j->getShape().length() - 6);
854  } else {
855  posRot.first = j->getShape().positionAtOffset(j->getShape().length());
856  posRot.second = j->getShape().rotationDegreeAtOffset(j->getShape().length());
857  }
858  symbolsPositionAndRotation.push_back(posRot);
859  }
860  }
861 
862  // calculate position and rotation of every symbol for every lane
863  for (auto i : myAdditional->myLaneChilds) {
864  std::pair<Position, double> posRot;
865  // set position and lenght depending of shape's lengt
866  if (i->getShape().length() - 6 > 0) {
867  posRot.first = i->getShape().positionAtOffset(i->getShape().length() - 6);
868  posRot.second = i->getShape().rotationDegreeAtOffset(i->getShape().length() - 6);
869  } else {
870  posRot.first = i->getShape().positionAtOffset(i->getShape().length());
871  posRot.second = i->getShape().rotationDegreeAtOffset(i->getShape().length());
872  }
873  symbolsPositionAndRotation.push_back(posRot);
874  }
875 
876  // calculate position for every additional child
877  for (auto i : myAdditional->myAdditionalChilds) {
878  // check that position is different of position
879  if (i->getPositionInView() != myAdditional->getPositionInView()) {
880  std::vector<Position> posConnection;
881  double A = std::abs(i->getPositionInView().x() - myAdditional->getPositionInView().x());
882  double B = std::abs(i->getPositionInView().y() - myAdditional->getPositionInView().y());
883  // Set positions of connection's vertex. Connection is build from Entry to E3
884  posConnection.push_back(i->getPositionInView());
885  if (myAdditional->getPositionInView().x() > i->getPositionInView().x()) {
886  if (myAdditional->getPositionInView().y() > i->getPositionInView().y()) {
887  posConnection.push_back(Position(i->getPositionInView().x() + A, i->getPositionInView().y()));
888  } else {
889  posConnection.push_back(Position(i->getPositionInView().x(), i->getPositionInView().y() - B));
890  }
891  } else {
892  if (myAdditional->getPositionInView().y() > i->getPositionInView().y()) {
893  posConnection.push_back(Position(i->getPositionInView().x(), i->getPositionInView().y() + B));
894  } else {
895  posConnection.push_back(Position(i->getPositionInView().x() - A, i->getPositionInView().y()));
896  }
897  }
898  posConnection.push_back(myAdditional->getPositionInView());
899  connectionPositions.push_back(posConnection);
900  }
901  }
902 
903  // calculate geometry for connections between parent and childs
904  for (auto i : symbolsPositionAndRotation) {
905  std::vector<Position> posConnection;
906  double A = std::abs(i.first.x() - myAdditional->getPositionInView().x());
907  double B = std::abs(i.first.y() - myAdditional->getPositionInView().y());
908  // Set positions of connection's vertex. Connection is build from Entry to E3
909  posConnection.push_back(i.first);
910  if (myAdditional->getPositionInView().x() > i.first.x()) {
911  if (myAdditional->getPositionInView().y() > i.first.y()) {
912  posConnection.push_back(Position(i.first.x() + A, i.first.y()));
913  } else {
914  posConnection.push_back(Position(i.first.x(), i.first.y() - B));
915  }
916  } else {
917  if (myAdditional->getPositionInView().y() > i.first.y()) {
918  posConnection.push_back(Position(i.first.x(), i.first.y() + B));
919  } else {
920  posConnection.push_back(Position(i.first.x() - A, i.first.y()));
921  }
922  }
923  posConnection.push_back(myAdditional->getPositionInView());
924  connectionPositions.push_back(posConnection);
925  }
926 }
927 
928 
929 void
931  // Iterate over myConnectionPositions
932  for (auto i : connectionPositions) {
933  // Add a draw matrix
934  glPushMatrix();
935  // traslate in the Z axis
936  glTranslated(0, 0, myAdditional->getType() - 0.01);
937  // Set color of the base
938  GLHelper::setColor(RGBColor(255, 235, 0));
939  for (auto j = i.begin(); (j + 1) != i.end(); j++) {
940  // Draw Lines
941  GLHelper::drawLine((*j), (*(j + 1)));
942  }
943  // Pop draw matrix
944  glPopMatrix();
945  }
946 }
947 
948 
949 void
951  // iterate over attributes and set default value
952  for (const auto &i : myTagProperty) {
953  if (i.second.hasDefaultValue()) {
954  setAttribute(i.first, i.second.getDefaultValue());
955  }
956  }
957 }
958 
959 
960 const std::string&
962  return getMicrosimID();
963 }
964 
965 
966 bool
967 GNEAdditional::isValidAdditionalID(const std::string& newID) const {
968  if (SUMOXMLDefinitions::isValidNetID(newID) && (myViewNet->getNet()->retrieveAdditional(myTagProperty.getTag(), newID, false) == nullptr)) {
969  return true;
970  } else {
971  return false;
972  }
973 }
974 
975 
976 bool
977 GNEAdditional::isValidDetectorID(const std::string& newID) const {
978  if (SUMOXMLDefinitions::isValidDetectorID(newID) && (myViewNet->getNet()->retrieveAdditional(myTagProperty.getTag(), newID, false) == nullptr)) {
979  return true;
980  } else {
981  return false;
982  }
983 }
984 
985 
986 void
987 GNEAdditional::changeAdditionalID(const std::string& newID) {
988  if (myViewNet->getNet()->retrieveAdditional(myTagProperty.getTag(), newID, false) != nullptr) {
989  throw InvalidArgument("An Additional with tag " + getTagStr() + " and ID = " + newID + " already exists");
990  } else {
991  // Save old ID
992  std::string oldID = getMicrosimID();
993  // set New ID
994  setMicrosimID(newID);
995  // update additional ID in the container of net
996  myViewNet->getNet()->updateAdditionalID(oldID, this);
997  }
998 }
999 
1000 
1001 GNEEdge*
1002 GNEAdditional::changeEdge(GNEEdge* oldEdge, const std::string& newEdgeID) {
1003  if (oldEdge == nullptr) {
1004  throw InvalidArgument(getTagStr() + " with ID '" + getMicrosimID() + "' doesn't belong to an " + toString(SUMO_TAG_EDGE));
1005  } else {
1006  oldEdge->removeAdditionalChild(this);
1007  GNEEdge* newEdge = myViewNet->getNet()->retrieveEdge(newEdgeID);
1008  newEdge->addAdditionalChild(this);
1009  updateGeometry(true);
1010  return newEdge;
1011  }
1012 }
1013 
1014 
1015 GNELane*
1016 GNEAdditional::changeLane(GNELane* oldLane, const std::string& newLaneID) {
1017  if (oldLane == nullptr) {
1018  throw InvalidArgument(getTagStr() + " with ID '" + getMicrosimID() + "' doesn't belong to a " + toString(SUMO_TAG_LANE));
1019  } else {
1020  oldLane->removeAdditionalChild(this);
1021  GNELane* newLane = myViewNet->getNet()->retrieveLane(newLaneID);
1022  newLane->addAdditionalChild(this);
1023  updateGeometry(true);
1024  return newLane;
1025  }
1026 }
1027 
1028 
1029 void
1030 GNEAdditional::changeFirstAdditionalParent(const std::string& newAdditionalParentID) {
1031  if (myFirstAdditionalParent == nullptr) {
1032  throw InvalidArgument(getTagStr() + " with ID '" + getMicrosimID() + "' doesn't have an additional parent");
1033  } else {
1034  // remove this additional of the childs of parent additional
1036  // set new additional parent
1038  // add this additional int the childs of parent additional
1040  updateGeometry(true);
1041  }
1042 }
1043 
1044 
1045 void
1046 GNEAdditional::changeSecondAdditionalParent(const std::string& newAdditionalParentID) {
1047  if (mySecondAdditionalParent == nullptr) {
1048  throw InvalidArgument(getTagStr() + " with ID '" + getMicrosimID() + "' doesn't have an additional parent");
1049  } else {
1050  // remove this additional of the childs of parent additional
1052  // set new additional parent
1054  // add this additional int the childs of parent additional
1056  updateGeometry(true);
1057  }
1058 }
1059 
1060 
1061 void
1063  if (!myViewNet) {
1064  throw ProcessError("ViewNet cannot be nullptr");
1065  } else {
1066  gSelected.select(dynamic_cast<GUIGlObject*>(this)->getGlID());
1067  // add object of list into selected objects
1069  if (changeFlag) {
1070  mySelected = true;
1071  }
1072  }
1073 }
1074 
1075 
1076 void
1078  if (!myViewNet) {
1079  throw ProcessError("ViewNet cannot be nullptr");
1080  } else {
1081  gSelected.deselect(dynamic_cast<GUIGlObject*>(this)->getGlID());
1082  // remove object of list of selected objects
1084  if (changeFlag) {
1085  mySelected = false;
1086 
1087  }
1088  }
1089 }
1090 
1091 
1092 bool
1094  return mySelected;
1095 }
1096 
1097 
1098 bool
1100  // throw exception because this function mus be implemented in child (see GNEE3Detector)
1101  throw ProcessError("Calling non-implemented function checkAdditionalChildRestriction during saving of " + getTagStr() + ". It muss be reimplemented in child class");
1102 }
1103 
1104 
1105 std::string
1107  std::string result;
1108  // Generate an string using the following structure: "key1=value1|key2=value2|...
1109  for (auto i : getParametersMap()) {
1110  result += i.first + "=" + i.second + "|";
1111  }
1112  // remove the last "|"
1113  if (!result.empty()) {
1114  result.pop_back();
1115  }
1116  return result;
1117 }
1118 
1119 
1120 std::vector<std::pair<std::string, std::string> >
1122  std::vector<std::pair<std::string, std::string> > result;
1123  // iterate over parameters map and fill result
1124  for (auto i : getParametersMap()) {
1125  result.push_back(std::make_pair(i.first, i.second));
1126  }
1127  return result;
1128 }
1129 
1130 
1131 void
1132 GNEAdditional::setGenericParametersStr(const std::string& value) {
1133  // clear parameters
1134  clearParameter();
1135  // separate value in a vector of string using | as separator
1136  std::vector<std::string> parsedValues;
1137  StringTokenizer stValues(value, "|", true);
1138  while (stValues.hasNext()) {
1139  parsedValues.push_back(stValues.next());
1140  }
1141  // check that parsed values (A=B)can be parsed in generic parameters
1142  for (auto i : parsedValues) {
1143  std::vector<std::string> parsedParameters;
1144  StringTokenizer stParam(i, "=", true);
1145  while (stParam.hasNext()) {
1146  parsedParameters.push_back(stParam.next());
1147  }
1148  // Check that parsed parameters are exactly two and contains valid chracters
1149  if (parsedParameters.size() == 2 && SUMOXMLDefinitions::isValidGenericParameterKey(parsedParameters.front()) && SUMOXMLDefinitions::isValidGenericParameterValue(parsedParameters.back())) {
1150  setParameter(parsedParameters.front(), parsedParameters.back());
1151  }
1152  }
1153 }
1154 
1155 
1156 void
1158 }
1159 
1160 
1161 /****************************************************************************/
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
const TagProperties & myTagProperty
the xml tag to which this attribute carrier corresponds
void addEdgeChild(GNEEdge *edge)
add edge child
bool hasTagSynonym() const
return true if tag correspond to an element that will be written in XML with another tag ...
virtual void fixAdditionalProblem()
fix additional problem (by default throw an exception, has to be reimplemented in childs) ...
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:900
bool isAdditionalBlocked() const
Check if additional item is currently blocked (i.e. cannot be moved with mouse)
SumoXMLTag getTagSynonym() const
get tag synonym
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.
void addedLockedObject(const GUIGlObjectType type)
set object selected
PositionVector multiShapeUnified
multi shape unified
const std::vector< GNEEdge * > & getGNEOutgoingEdges() const
Returns incoming GNEEdges.
a source within a district (connection road)
void calculateMultiShapeRotationsAndLengths()
calculate multi shape rotations and lenghts
std::string next()
double z() const
Returns the z-position.
Definition: Position.h:67
GUIGlObjectType
begin/end of the description of a single lane
const std::vector< GNEEdge * > & getEdgeChilds() const
get edge chidls
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
std::string secondOriginalPosition
value for saving second original position over lane before moving
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
a traffic assignment zone
GNEAdditional * myAdditional
pointer to additional parent
bool canBePlacedOverLane() const
return true if tag correspond to an element that can be placed over a lane
Stores the information about how to visualize structures.
bool hasMinimumNumberOfChilds() const
return true if tag correspond to an element that only have a limited number of childs ...
void select(GUIGlID id, bool update=true)
Adds the object with the given id.
GNEViewParent * getViewParent() const
get the net object
Position offset
The offSet of the block icon.
double y() const
Returns the y-position.
Definition: Position.h:62
struct with the attribute Properties
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:57
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
bool canMaskStartEndPos() const
return true if tag correspond to an element that can mask the attributes "start" and "end" position a...
void unselectAttributeCarrier(bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
FXIcon * getIcon() const
get FXIcon associated to this AC
Position position
position of the block icon
BlockIcon myBlockIcon
variable BlockIcon
void clearGeometry()
reset geometry
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:47
Position originalViewPosition
value for saving first original position over lane before moving
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
BlockIcon(GNEAdditional *additional)
constructor
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
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
virtual bool isAdditionalValid() const
check if current additional is valid to be writed into XML (by default true, can be reimplemented in ...
void changeAdditionalID(const std::string &newID)
change ID of additional
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
virtual std::string getAttribute(SumoXMLAttr key) const =0
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
std::vector< std::pair< Position, double > > symbolsPositionAndRotation
position and rotation of every symbol over lane
an e3 entry point
double rotation
The rotation of the block icon.
bool isValidDetectorID(const std::string &newID) const
check if a new detector ID is valid
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
virtual std::string getAdditionalProblem() const
return a string with the current additional problem (by default empty, can be reimplemented in childs...
GNEViewNet * myViewNet
The GNEViewNet this additional element belongs.
AdditionalMove myMove
variable AdditionalMove
GNEAdditional * retrieveAdditional(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named additional.
Definition: GNENet.cpp:1785
ChildConnections(GNEAdditional *additional)
constructor
bool canBlockMovement() const
return true if tag correspond to an element that can block their movement
bool showLockIcon() const
check if lock icon should be visible
LockGLObjectTypes * getLockGLObjectTypes() const
get selected items
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:1830
void draw() const
draw connections between Parent and childrens
GUIGlObjectType getType() const
Returns the type of the object as coded in GUIGlObjectType.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
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
int getNumberOfAttributes() const
get number of attributes
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
PositionVector shape
The shape of the additional element.
bool canAutomaticSortChilds() const
return true if tag correspond to an element that can sort their childs automatic
an e3 exit point
A list of positions.
std::string myAdditionalName
name of additional
std::vector< PositionVector > connectionPositions
Matrix with the Vertex&#39;s positions of connections between parents an their childs.
void removeLockedObject(const GUIGlObjectType type)
set object unselected
void removeGLObjectFromGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1160
static bool isValidDetectorID(const std::string &value)
whether the given string is a valid id for an detector
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:464
void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
ChildConnections myChildConnections
variable ChildConnections
GNESelectorFrame * getSelectorFrame() const
get frame for GNE_MODE_SELECT
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
~GNEAdditional()
Destructor.
std::vector< PositionVector > multiShape
The multi-shape of the additional element (used by certain additionals)
An upper class for objects with additional parameters.
Definition: Parameterised.h:44
virtual void updateGeometry(bool updateGrid)=0
update pre-computed geometry information
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 calculateShapeRotationsAndLengths()
calculate shape rotations and lenghts
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
reserved GLO type to pack all additionals
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:669
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:873
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:617
double length() const
Returns the length.
virtual void updateAdditionalParent()
update parent after add or remove a child (can be reimplemented, for example used for stadistics) ...
GNEEdge * changeEdge(GNEEdge *oldEdge, const std::string &newEdgeID)
change edge of additional
a sink within a district (connection road)
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
#define M_PI
Definition: odrSpiral.cpp:40
An Element which don&#39;t belongs to GNENet but has influency in the simulation.
Definition: GNEAdditional.h:48
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
AdditionalGeometry myGeometry
geometry to be precomputed in updateGeometry(...)
const std::string & getTagStr() const
get tag assigned to this object in string format
weights: time range end
Boundary movingGeometryBoundary
boundary used during moving of elements (to avoid insertion in RTREE
bool isInitialised() const
check if Boundary is Initialised
Definition: Boundary.cpp:217
The popup menu of a globject.
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.
SumoXMLTag getParentTag() const
if Tag owns a parent, return parent tag
void update()
update Connection&#39;s geometry
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
Definition: Position.h:234
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
bool hasAttribute(SumoXMLAttr attr) const
check if current TagProperties owns the attribute attr
const TagProperties & getTagProperty() const
get Tag Property assigned to this object
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
std::string firstOriginalLanePosition
value for saving first original position over lane before moving
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)
bool hasDialog() const
return true if tag correspond to an element that can be edited using a dialog
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:1153
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:1059
void startGeometryMoving()
Copy typed object name - popup entry.
Definition: GUIAppEnum.h:232
A window containing a gl-object&#39;s parameter.
GNEAdditional * myAdditional
pointer to additional parent
bool canBePlacedOverLanes() const
return true if tag correspond
GNEAdditional * myFirstAdditionalParent
pointer to first Additional parent
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
GNELane * changeLane(GNELane *oldLane, const std::string &newLaneID)
change lane of additional
void setRotation(GNELane *additionalLane=nullptr)
set Rotation of block Icon (must be called in updateGeometry(bool updateGrid) function) ...
void addLaneChild(GNELane *lane)
add lane child
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
std::vector< GNELane * > myLaneChilds
vector with the lane childs of this additional
void draw(double size=0.5) const
draw lock icon
void calculateMultiShapeUnified()
calculate multi shape unified
void clearParameter()
Clears the parameter map.
GNEAdditional * mySecondAdditionalParent
pointer to second Additional parent
std::vector< GNEEdge * > myEdgeChilds
vector with the edge childs of this additional
virtual Position getPositionInView() const =0
Returns position of additional in view.