SUMO - Simulation of Urban MObility
GNEEdge.cpp
Go to the documentation of this file.
1 /****************************************************************************/
7 // A road/street connecting two junctions (netedit-version, adapted from GUIEdge)
8 // Basically a container for an NBEdge with drawing and editing capabilities
9 /****************************************************************************/
10 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
11 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
12 /****************************************************************************/
13 //
14 // This file is part of SUMO.
15 // SUMO is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #ifdef _MSC_VER
27 #include <windows_config.h>
28 #else
29 #include <config.h>
30 #endif
31 
32 #include <vector>
33 #include <cmath>
34 #include <string>
35 #include <algorithm>
39 #include <utils/geom/GeomHelper.h>
42 #include <utils/gui/div/GLHelper.h>
43 #include "GNEEdge.h"
44 #include "GNENet.h"
45 #include "GNEUndoList.h"
46 #include "GNEChange_Attribute.h"
47 #include "GNEChange_Lane.h"
48 #include "GNEJunction.h"
49 #include "GNELane.h"
50 #include "GNEAdditional.h"
51 #include "GNEAdditionalSet.h"
52 
53 
54 #ifdef CHECK_MEMORY_LEAKS
55 #include <foreign/nvwa/debug_new.h>
56 #endif // CHECK_MEMORY_LEAKS
57 
58 
59 
60 // ===========================================================================
61 // static
62 // ===========================================================================
64 
65 // ===========================================================================
66 // members methods
67 // ===========================================================================
68 GNEEdge::GNEEdge(NBEdge& nbe, GNENet* net, bool wasSplit, bool loaded):
69  GNENetElement(net, nbe.getID(), GLO_EDGE, SUMO_TAG_EDGE),
70  myNBEdge(nbe) ,
71  myOrigShape(nbe.getInnerGeometry()),
72  myLanes(0),
73  myAmResponsible(false),
74  myWasSplit(wasSplit),
75  myConnectionStatus(loaded ? LOADED : GUESSED) {
76  // Create lanes
77  int numLanes = myNBEdge.getNumLanes();
78  myLanes.reserve(numLanes);
79  for (int i = 0; i < numLanes; i++) {
80  myLanes.push_back(new GNELane(*this, i));
81  myLanes.back()->incRef("GNEEdge::GNEEdge");
82  }
83 }
84 
85 
87  for (LaneVector::iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
88  (*i)->decRef("GNEEdge::~GNEEdge");
89  if ((*i)->unreferenced()) {
90  delete *i;
91  }
92  }
93  if (myAmResponsible) {
94  delete &myNBEdge;
95  }
96  // Remove all references to this edge in their additionals
97  for (AdditionalVector::iterator i = myAdditionals.begin(); i != myAdditionals.end(); i++) {
98  (*i)->removeEdgeReference();
99  }
100 }
101 
102 
103 void
105 
106 
107 Boundary
109  Boundary ret;
110  for (LaneVector::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
111  ret.add((*i)->getBoundary());
112  }
113  ret.grow(10); // !!! magic value
114  return ret;
115 }
116 
117 
118 Boundary
120  Boundary b = getBoundary();
121  b.grow(20);
122  return b;
123 }
124 
125 
128  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
129  buildPopupHeader(ret, app);
133  buildPositionCopyEntry(ret, false);
134  return ret;
135 }
136 
137 
141 }
142 
143 
147 }
148 
149 void
151  /* do something different for connectors?
152  if (myNBEdge.isMacroscopicConnector()) {
153  }
154  */
155 
156  // draw the lanes
157  for (LaneVector::const_iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
158  (*i)->drawGL(s);
159  }
160 
161  // draw geometry hints
162  if (s.scale * SNAP_RADIUS > 1.) { // check whether it is not too small
163  GLHelper::setColor(s.junctionColorer.getSchemes()[0].getColor(2));
164  glPushName(getGlID());
166  for (int i = 1; i < (int)geom.size() - 1; i++) {
167  Position pos = geom[i];
168  glPushMatrix();
169  glTranslated(pos.x(), pos.y(), GLO_JUNCTION - 0.01);
171  glPopMatrix();
172  }
173  glPopName();
174  }
175 
176  // (optionally) draw the name and/or the street name
177  const bool drawStreetName = s.streetName.show && myNBEdge.getStreetName() != "";
178  if (s.edgeName.show || drawStreetName) {
179  glPushName(getGlID());
180  GNELane* lane1 = myLanes[0];
181  GNELane* lane2 = myLanes[myLanes.size() - 1];
182  Position p = lane1->getShape().positionAtOffset(lane1->getShape().length() / (SUMOReal) 2.);
183  p.add(lane2->getShape().positionAtOffset(lane2->getShape().length() / (SUMOReal) 2.));
184  p.mul(.5);
185  SUMOReal angle = lane1->getShape().rotationDegreeAtOffset(lane1->getShape().length() / (SUMOReal) 2.);
186  angle += 90;
187  if (angle > 90 && angle < 270) {
188  angle -= 180;
189  }
190  if (s.edgeName.show) {
191  drawName(p, s.scale, s.edgeName, angle);
192  }
193  if (drawStreetName) {
195  s.streetName.size / s.scale, s.streetName.color, angle);
196  }
197  glPopName();
198  }
199 }
200 
201 
205  GUIParameterTableWindow* ret = 0;
206  UNUSED_PARAMETER(&app);
207  return ret;
208 }
209 
210 
211 void
213  Position delta = junction->getNBNode()->getPosition() - origPos;
215  // geometry endpoint need not equal junction position hence we modify it with delta
216  if (junction == getSource()) {
217  geom[0].add(delta);
218  } else {
219  geom[-1].add(delta);
220  }
221  setGeometry(geom, false);
222 }
223 
224 NBEdge*
226  return &myNBEdge;
227 }
228 
229 
230 Position
231 GNEEdge::getSplitPos(const Position& clickPos) {
232  const PositionVector& geom = myNBEdge.getGeometry();
233  int index = geom.indexOfClosest(clickPos);
234  if (geom[index].distanceTo(clickPos) < SNAP_RADIUS) {
235  // split at existing geometry point
236  return geom[index];
237  } else {
238  // split straight between the next two points
239  return geom.positionAtOffset(geom.nearest_offset_to_point2D(clickPos));
240  }
241 }
242 
243 
244 Position
245 GNEEdge::moveGeometry(const Position& oldPos, const Position& newPos, bool relative) {
247  bool changed = changeGeometry(geom, getMicrosimID(), oldPos, newPos, relative);
248  if (changed) {
249  setGeometry(geom, false);
250  return newPos;
251  } else {
252  return oldPos;
253  }
254 }
255 
256 
257 bool
258 GNEEdge::changeGeometry(PositionVector& geom, const std::string& id, const Position& oldPos, const Position& newPos, bool relative, bool moveEndPoints) {
259  if (geom.size() < 2) {
260  throw ProcessError("Invalid geometry size in edge " + id);
261  } else {
262  int index = geom.indexOfClosest(oldPos);
263  const SUMOReal nearestOffset = geom.nearest_offset_to_point2D(oldPos, true);
264  if (nearestOffset != GeomHelper::INVALID_OFFSET
265  && (moveEndPoints || (nearestOffset >= SNAP_RADIUS
266  && nearestOffset <= geom.length2D() - SNAP_RADIUS))) {
267  const Position nearest = geom.positionAtOffset2D(nearestOffset);
268  const SUMOReal distance = geom[index].distanceTo2D(nearest);
269  if (distance < SNAP_RADIUS) { //move existing
270  if (moveEndPoints || (index != 0 && index != (int)geom.size() - 1)) {
271  const bool closed = geom.isClosed();
272  if (relative) {
273  geom[index] = geom[index] + newPos;
274  } else {
275  geom[index] = newPos;
276  }
277  if (closed && moveEndPoints && (index == 0 || index == (int)geom.size() - 1)) {
278  const int otherIndex = (int)geom.size() - 1 - index;
279  geom[otherIndex] = geom[index];
280  }
281  return true;
282  }
283  } else {
284  if (relative) {
285  int index = geom.insertAtClosest(nearest);
286  geom[index] = geom[index] + newPos;
287  return true;
288  } else {
289  geom.insertAtClosest(newPos); // insert new
290  return true;
291  }
292  }
293  }
294  return false;
295  }
296 }
297 
298 
299 void
302  if (geom.size() == 0) {
303  return;
304  }
305  geom.add(delta.x(), delta.y(), delta.z());
306  setGeometry(geom, true);
307 }
308 
309 
310 bool
313  if (geom.size() == 0) {
314  return false;
315  }
316  int index = geom.indexOfClosest(pos);
317  if (geom[index].distanceTo(pos) < SNAP_RADIUS) {
318  geom.erase(geom.begin() + index);
319  setAttribute(SUMO_ATTR_SHAPE, toString(geom), undoList);
320  return true;
321  } else {
322  return false;
323  }
324 }
325 
326 
327 void
329  undoList->p_begin("set endpoint");
331  int index = geom.indexOfClosest(pos);
332  if (geom[index].distanceTo(pos) < SNAP_RADIUS) { // snap to existing geometry
333  pos = geom[index];
334  }
335  Position destPos = getDest()->getNBNode()->getPosition();
336  Position sourcePos = getSource()->getNBNode()->getPosition();
337  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
338  setAttribute(GNE_ATTR_SHAPE_END, toString(pos), undoList);
340  } else {
341  setAttribute(GNE_ATTR_SHAPE_START, toString(pos), undoList);
343  }
344  // possibly existing inner point is no longer needed
345  deleteGeometry(pos, undoList);
346  undoList->p_end();
347 }
348 
349 
350 void
352  Position destPos = getDest()->getNBNode()->getPosition();
353  Position sourcePos = getSource()->getNBNode()->getPosition();
354  if (pos.distanceTo2D(destPos) < pos.distanceTo2D(sourcePos)) {
355  setAttribute(GNE_ATTR_SHAPE_END, toString(destPos), undoList);
357  } else {
358  setAttribute(GNE_ATTR_SHAPE_START, toString(sourcePos), undoList);
360  }
361 }
362 
363 
364 void
366  myNBEdge.setGeometry(geom, inner);
370  myNet->refreshElement(this);
371 }
372 
373 
374 void
376  // Update geometry of lanes
377  for (LaneVector::iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
378  (*i)->updateGeometry();
379  }
380  // Update geometry of additionals vinculated to this edge
381  for (AdditionalVector::iterator i = myAdditionals.begin(); i != myAdditionals.end(); ++i) {
382  (*i)->updateGeometry();
383  }
384  // Update geometry of additionalSets vinculated to this edge
385  for (AdditionalSetVector::iterator i = myAdditionalSets.begin(); i != myAdditionalSets.end(); ++i) {
386  (*i)->updateGeometry();
387  }
388 }
389 
390 
391 void
393  undoList->p_begin("copy template");
401  // copy lane attributes as well
402  for (int i = 0; i < (int)myLanes.size(); i++) {
403  myLanes[i]->setAttribute(SUMO_ATTR_ALLOW, tpl->myLanes[i]->getAttribute(SUMO_ATTR_ALLOW), undoList);
404  myLanes[i]->setAttribute(SUMO_ATTR_DISALLOW, tpl->myLanes[i]->getAttribute(SUMO_ATTR_DISALLOW), undoList);
405  myLanes[i]->setAttribute(SUMO_ATTR_SPEED, tpl->myLanes[i]->getAttribute(SUMO_ATTR_SPEED), undoList);
406  myLanes[i]->setAttribute(SUMO_ATTR_WIDTH, tpl->myLanes[i]->getAttribute(SUMO_ATTR_WIDTH), undoList);
407  myLanes[i]->setAttribute(SUMO_ATTR_ENDOFFSET, tpl->myLanes[i]->getAttribute(SUMO_ATTR_ENDOFFSET), undoList);
408  }
409  undoList->p_end();
410 }
411 
412 
413 std::set<GUIGlID>
415  std::set<GUIGlID> result;
416  for (size_t i = 0; i < myLanes.size(); i++) {
417  result.insert(myLanes[i]->getGlID());
418  }
419  return result;
420 }
421 
422 
423 const std::vector<GNELane*>&
425  return myLanes;
426 }
427 
428 
429 bool
431  return myWasSplit;
432 }
433 
434 
435 std::string
437  switch (key) {
438  case SUMO_ATTR_ID:
439  return getMicrosimID();
440  case SUMO_ATTR_FROM:
441  return getSource()->getMicrosimID();
442  case SUMO_ATTR_TO:
443  return getDest()->getMicrosimID();
444  case SUMO_ATTR_NUMLANES:
445  return toString(myNBEdge.getNumLanes());
446  case SUMO_ATTR_PRIORITY:
447  return toString(myNBEdge.getPriority());
448  case SUMO_ATTR_LENGTH:
449  return toString(myNBEdge.getFinalLength());
450  case SUMO_ATTR_TYPE:
451  return myNBEdge.getTypeID();
452  case SUMO_ATTR_SHAPE:
456  case SUMO_ATTR_NAME:
457  return myNBEdge.getStreetName();
458  case SUMO_ATTR_ALLOW:
459  // return all allowed classes (may differ from the written attributes)
461  (myNBEdge.hasLaneSpecificPermissions() ? " (combined!)" : ""));
462  case SUMO_ATTR_DISALLOW: {
463  // return classes disallowed on at least one lane (may differ from the written attributes)
464  SVCPermissions combinedDissallowed = 0;
465  for (int i = 0; i < (int)myNBEdge.getNumLanes(); ++i) {
466  combinedDissallowed |= ~myNBEdge.getPermissions(i);
467  }
468  return (getVehicleClassNames(combinedDissallowed) +
469  (myNBEdge.hasLaneSpecificPermissions() ? " (combined!)" : ""));
470  }
471  case SUMO_ATTR_SPEED:
473  return "lane specific";
474  } else {
475  return toString(myNBEdge.getSpeed());
476  }
477  case SUMO_ATTR_WIDTH:
479  return "lane specific";
480  } else {
481  return toString(myNBEdge.getLaneWidth());
482  }
483  case SUMO_ATTR_ENDOFFSET:
485  return "lane specific";
486  } else {
487  return toString(myNBEdge.getEndOffset());
488  }
490  return myConnectionStatus;
492  return toString(myNBEdge.getGeometry()[0]);
493  case GNE_ATTR_SHAPE_END:
494  return toString(myNBEdge.getGeometry()[-1]);
495  default:
496  throw InvalidArgument("edge attribute '" + toString(key) + "' not allowed");
497  }
498 }
499 
500 
501 void
502 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
503  switch (key) {
504  case SUMO_ATTR_WIDTH:
505  case SUMO_ATTR_ENDOFFSET:
506  case SUMO_ATTR_SPEED:
507  case SUMO_ATTR_ALLOW:
508  case SUMO_ATTR_DISALLOW: {
509  undoList->p_begin("change edge attribute");
510  const std::string origValue = getAttribute(key); // will have intermediate value of "lane specific"
511  // lane specific attributes need to be changed via lanes to allow undo
512  for (LaneVector::iterator it = myLanes.begin(); it != myLanes.end(); it++) {
513  (*it)->setAttribute(key, value, undoList);
514  }
515  // ensure that the edge value is also changed. Actually this sets the lane attributes again but it does not matter
516  undoList->p_add(new GNEChange_Attribute(this, key, value, true, origValue));
517  undoList->p_end();
518  break;
519  }
520  case SUMO_ATTR_FROM: {
521  undoList->p_begin("change edge attribute");
522  undoList->p_add(new GNEChange_Attribute(this, key, value));
523  getSource()->setLogicValid(false, undoList);
524  myNet->retrieveJunction(value)->setLogicValid(false, undoList);
525  setAttribute(GNE_ATTR_SHAPE_START, toString(getSource()->getNBNode()->getPosition()), undoList);
527  undoList->p_end();
528  break;
529  }
530  case SUMO_ATTR_TO: {
531  undoList->p_begin("change edge attribute");
532  undoList->p_add(new GNEChange_Attribute(this, key, value));
533  getDest()->setLogicValid(false, undoList);
534  myNet->retrieveJunction(value)->setLogicValid(false, undoList);
535  setAttribute(GNE_ATTR_SHAPE_END, toString(getDest()->getNBNode()->getPosition()), undoList);
537  undoList->p_end();
538  break;
539  }
540  case SUMO_ATTR_ID:
541  case SUMO_ATTR_PRIORITY:
542  case SUMO_ATTR_LENGTH:
543  case SUMO_ATTR_TYPE:
547  case GNE_ATTR_SHAPE_END:
548  undoList->p_add(new GNEChange_Attribute(this, key, value));
549  break;
550  case SUMO_ATTR_NAME:
551  // user cares about street names. Make sure they appear in the output
553  OptionsCont::getOptions().set("output.street-names", "true");
554  undoList->p_add(new GNEChange_Attribute(this, key, value));
555  break;
556  case SUMO_ATTR_NUMLANES:
557  if (value != getAttribute(key)) {
558  setNumLanes(parse<int>(value), undoList);
559  }
560  break;
561  case SUMO_ATTR_SHAPE:
562  // @note: assumes value of inner geometry!
563  // actually the geometry is already updated (incrementally
564  // during mouse movement). We set the restore point to the end
565  // of the last change-set
567  undoList->p_add(new GNEChange_Attribute(this, key, value));
568  break;
569  default:
570  throw InvalidArgument("edge attribute '" + toString(key) + "' not allowed");
571  }
572 }
573 
574 
575 bool
576 GNEEdge::isValid(SumoXMLAttr key, const std::string& value) {
577  switch (key) {
578  case SUMO_ATTR_ID:
579  return isValidID(value) && myNet->retrieveEdge(value, false) == 0;
580  break;
581  case SUMO_ATTR_FROM:
582  return isValidID(value) && myNet->retrieveJunction(value, false) != 0 && value != getDest()->getMicrosimID();
583  break;
584  case SUMO_ATTR_TO:
585  return isValidID(value) && myNet->retrieveJunction(value, false) != 0 && value != getSource()->getMicrosimID();
586  break;
587  case SUMO_ATTR_SPEED:
588  return isPositive<SUMOReal>(value);
589  break;
590  case SUMO_ATTR_NUMLANES:
591  return isPositive<int>(value);
592  break;
593  case SUMO_ATTR_PRIORITY:
594  return canParse<int>(value);
595  break;
596  case SUMO_ATTR_LENGTH:
597  return canParse<SUMOReal>(value) && (isPositive<SUMOReal>(value) || parse<SUMOReal>(value) == NBEdge::UNSPECIFIED_LOADED_LENGTH);
598  break;
599  case SUMO_ATTR_ALLOW:
600  case SUMO_ATTR_DISALLOW:
601  return canParseVehicleClasses(value);
602  break;
603  case SUMO_ATTR_TYPE:
604  return true;
605  break;
606  case SUMO_ATTR_SHAPE: {
607  bool ok = true;
609  value, "user-supplied position", 0, ok, true);
610  return ok;
611  break;
612  }
615  break;
616  case SUMO_ATTR_NAME:
617  return true;
618  break;
619  case SUMO_ATTR_WIDTH:
620  return canParse<SUMOReal>(value) && (isPositive<SUMOReal>(value) || parse<SUMOReal>(value) == NBEdge::UNSPECIFIED_WIDTH);
621  break;
622  case SUMO_ATTR_ENDOFFSET:
623  return canParse<SUMOReal>(value);
624  break;
625  default:
626  throw InvalidArgument("edge attribute '" + toString(key) + "' not allowed");
627  }
628 }
629 
630 
631 void
633  myAmResponsible = newVal;
634 }
635 
636 // ===========================================================================
637 // private
638 // ===========================================================================
639 void
640 GNEEdge::setAttribute(SumoXMLAttr key, const std::string& value) {
641  switch (key) {
642  case SUMO_ATTR_ID:
643  myNet->renameEdge(this, value);
644  break;
645  case SUMO_ATTR_FROM:
646  myNet->changeEdgeEndpoints(this, value, getDest()->getMicrosimID());
647  break;
648  case SUMO_ATTR_TO:
649  myNet->changeEdgeEndpoints(this, getSource()->getMicrosimID(), value);
650  break;
651  case SUMO_ATTR_NUMLANES:
652  throw InvalidArgument("GNEEdge::setAttribute (private) called for attr SUMO_ATTR_NUMLANES. This should never happen");
653  break;
654  case SUMO_ATTR_PRIORITY:
655  myNBEdge.myPriority = parse<int>(value);
656  break;
657  case SUMO_ATTR_LENGTH:
658  myNBEdge.setLoadedLength(parse<SUMOReal>(value));
659  break;
660  case SUMO_ATTR_TYPE:
661  myNBEdge.myType = value;
662  break;
663  case SUMO_ATTR_SHAPE:
664  bool ok;
665  myOrigShape = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, true);
666  setGeometry(myOrigShape, true);
667  break;
670  break;
671  case SUMO_ATTR_NAME:
672  myNBEdge.setStreetName(value);
673  break;
674  case SUMO_ATTR_SPEED:
675  myNBEdge.setSpeed(-1, parse<SUMOReal>(value));
676  break;
677  case SUMO_ATTR_WIDTH:
678  myNBEdge.setLaneWidth(-1, parse<SUMOReal>(value));
679  break;
680  case SUMO_ATTR_ENDOFFSET:
681  myNBEdge.setEndOffset(-1, parse<SUMOReal>(value));
682  break;
683  case SUMO_ATTR_ALLOW:
684  break; // no edge value
685  case SUMO_ATTR_DISALLOW:
686  break; // no edge value
688  myConnectionStatus = value;
689  if (value == GUESSED) {
691  } else if (value == MODIFIED) {
693  }
694  break;
695  case GNE_ATTR_SHAPE_START: {
697  geom[0] = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, false)[0];
698  setGeometry(geom, false);
699  break;
700  }
701  case GNE_ATTR_SHAPE_END: {
703  geom[-1] = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, false)[0];
704  setGeometry(geom, false);
705  break;
706  }
707  default:
708  throw InvalidArgument("edge attribute '" + toString(key) + "' not allowed");
709  }
710 }
711 
712 
713 void
714 GNEEdge::setNumLanes(int numLanes, GNEUndoList* undoList) {
715  undoList->p_begin("change number of lanes");
716  getSource()->setLogicValid(false, undoList);
717  getDest()->setLogicValid(false, undoList);
718 
719  const int oldNumLanes = (int)myLanes.size();
720  for (int i = oldNumLanes; i < numLanes; i++) {
721  // since the GNELane does not exist yet, it cannot have yet been referenced so we only pass a zero-pointer
722  undoList->add(new GNEChange_Lane(this, 0,
723  myNBEdge.getLaneStruct(oldNumLanes - 1), true), true);
724  }
725  for (int i = oldNumLanes - 1; i > numLanes - 1; i--) {
726  // delete leftmost lane
727  undoList->add(new GNEChange_Lane(this, myLanes[i], myNBEdge.getLaneStruct(i), false), true);
728  }
729  undoList->p_end();
730 }
731 
732 
733 void
734 GNEEdge::addLane(GNELane* lane, const NBEdge::Lane& laneAttrs) {
735  const int index = lane ? lane->getIndex() : myNBEdge.getNumLanes();
736  // the laneStruct must be created first to ensure we have some geometry
737  myNBEdge.addLane(index);
738  if (lane) {
739  // restore a previously deleted lane
740  myLanes.insert(myLanes.begin() + index, lane);
741 
742  } else {
743  // create a new lane by copying leftmost lane
744  lane = new GNELane(*this, index);
745  myLanes.push_back(lane);
746  }
747  lane->incRef("GNEEdge::addLane");
748  // we copy all attributes except shape since this is recomputed from edge shape
749  myNBEdge.setSpeed(lane->getIndex(), laneAttrs.speed);
750  myNBEdge.setPermissions(laneAttrs.permissions, lane->getIndex());
752  myNBEdge.setEndOffset(lane->getIndex(), laneAttrs.endOffset);
753  myNBEdge.setLaneWidth(lane->getIndex(), laneAttrs.width);
754  // udate indices
755  for (int i = 0; i < (int)myLanes.size(); ++i) {
756  myLanes[i]->setIndex(i);
757  }
758  /* while technically correct, this looks ugly
759  getSource()->invalidateShape();
760  getDest()->invalidateShape();
761  */
762  myNet->refreshElement(this);
763 }
764 
765 
766 void
768  if (myLanes.size() == 0) {
769  throw ProcessError("Should not remove the last lane from an edge\n");
770  }
771  if (lane == 0) {
772  lane = myLanes.back();
773  }
774  myNBEdge.deleteLane(lane->getIndex());
775  lane->decRef("GNEEdge::removeLane");
776  myLanes.erase(myLanes.begin() + lane->getIndex());
777  if (lane->unreferenced()) {
778  delete lane;
779  }
780  // udate indices
781  for (int i = 0; i < (int)myLanes.size(); ++i) {
782  myLanes[i]->setIndex(i);
783  }
784  /* while technically correct, this looks ugly
785  getSource()->invalidateShape();
786  getDest()->invalidateShape();
787  */
788 
789  myNet->refreshElement(this);
790 }
791 
792 void
793 GNEEdge::addConnection(int fromLane, const std::string& toEdgeID, int toLane, bool mayPass) {
794  GNEEdge* destEdge = myNet->retrieveEdge(toEdgeID);
795  myNBEdge.setConnection(fromLane, destEdge->getNBEdge(), toLane, NBEdge::L2L_USER, true, mayPass);
796  myNet->refreshElement(this); // actually we only do this to force a redraw
797 }
798 
799 
800 void
801 GNEEdge::removeConnection(int fromLane, const std::string& toEdgeID, int toLane) {
802  NBEdge* destEdge = myNet->retrieveEdge(toEdgeID)->getNBEdge();
803  if (destEdge == myNBEdge.getTurnDestination()) {
805  }
806  myNBEdge.removeFromConnections(destEdge, fromLane, toLane);
807  myNet->refreshElement(this); // actually we only do this to force a redraw
808 }
809 
810 
811 void
812 GNEEdge::setMicrosimID(const std::string& newID) {
814  for (LaneVector::iterator i = myLanes.begin(); i != myLanes.end(); ++i) {
815  (*i)->setMicrosimID(getNBEdge()->getLaneID((*i)->getIndex()));
816  }
817 }
818 
819 
820 bool
822  // Check if additional already exists before insertion
823  for (AdditionalVector::iterator i = myAdditionals.begin(); i != myAdditionals.end(); i++) {
824  if ((*i) == additional) {
825  return false;
826  }
827  }
828  // Insert it and retur true
829  myAdditionals.push_back(additional);
830  return true;
831 }
832 
833 
834 bool
836  // search additional and remove it
837  for (AdditionalVector::iterator i = myAdditionals.begin(); i != myAdditionals.end(); i++) {
838  if ((*i) == additional) {
839  myAdditionals.erase(i);
840  return true;
841  }
842  }
843  // If additional wasn't found, return false
844  return false;
845 }
846 
847 
848 const std::vector<GNEAdditional*>&
850  return myAdditionals;
851 }
852 
853 
854 bool
856  // Check if additionalSet already exists before insertion
857  for (AdditionalSetVector::iterator i = myAdditionalSets.begin(); i != myAdditionalSets.end(); i++) {
858  if ((*i) == additionalSet) {
859  return false;
860  }
861  }
862  // Insert it and retur true
863  myAdditionalSets.push_back(additionalSet);
864  return true;
865 }
866 
867 
868 bool
870  // search additionalSet and remove it
871  for (AdditionalSetVector::iterator i = myAdditionalSets.begin(); i != myAdditionalSets.end(); i++) {
872  if ((*i) == additionalSet) {
873  myAdditionalSets.erase(i);
874  return true;
875  }
876  }
877  // If additionalSet wasn't found, return false
878  return false;
879 }
880 
881 
882 const std::vector<GNEAdditionalSet*>&
884  return myAdditionalSets;
885 }
886 
887 /****************************************************************************/
void addLane(GNELane *lane, const NBEdge::Lane &laneAttrs)
increase number of lanes by one use the given attributes and restore the GNELane
Definition: GNEEdge.cpp:734
void copyTemplate(GNEEdge *tpl, GNEUndoList *undolist)
copy edge attributes from tpl
Definition: GNEEdge.cpp:392
void invalidateConnections(bool reallowSetting=false)
Definition: NBEdge.cpp:962
The information about how to spread the lanes from the given position.
const std::string & getTypeID() const
Definition: NBEdge.h:930
SUMOReal endOffset
This lane&#39;s offset to the intersection begin.
Definition: NBEdge.h:136
void setNumLanes(int numLanes, GNEUndoList *undoList)
changes the number of lanes. When reducing the number of lanes, higher-numbered lanes are removed fir...
Definition: GNEEdge.cpp:714
GNEEdge * retrieveEdge(const std::string &id, bool failHard=true)
get edge by id
Definition: GNENet.cpp:616
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:203
GUIVisualizationTextSettings streetName
void resetWritable()
Resets all options to be writeable.
GNENet * myNet
the net to inform about updates
bool myAmResponsible
whether we are responsible for deleting myNBNode
Definition: GNEEdge.h:250
SUMOReal nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
void invalidateShape()
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
void addConnection(int fromLane, const std::string &toEdgeID, int toLane, bool mayPass)
adds a connection
Definition: GNEEdge.cpp:793
std::string myConnectionStatus
modification status of the connections
Definition: GNEEdge.h:256
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:119
void refreshElement(GUIGlObject *o)
refreshes boundary information for o and update
Definition: GNENet.cpp:690
bool hasString(const std::string &str) const
PositionVector myOrigShape
restore point for undo
Definition: GNEEdge.h:244
void setMicrosimID(const std::string &newID)
override to also set lane ids
Definition: GNEEdge.cpp:812
static StringBijection< LaneSpreadFunction > LaneSpreadFunctions
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:737
bool hasLaneSpecificEndOffset() const
whether lanes differ in offset
Definition: NBEdge.cpp:1491
void setLaneWidth(int lane, SUMOReal width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2476
std::set< GUIGlID > getLaneGlIDs()
returns GLIDs of all lanes
Definition: GNEEdge.cpp:414
void setSpeed(int lane, SUMOReal speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2531
void setLogicValid(bool valid, GNEUndoList *undoList=0, const std::string &status=GUESSED)
Stores the information about how to visualize structures.
int SVCPermissions
The representation of a single edge during network building.
Definition: NBEdge.h:70
void declareConnectionsAsLoaded()
Definition: NBEdge.h:1101
Position moveGeometry(const Position &oldPos, const Position &newPos, bool relative=false)
change the edge geometry It is up to the Edge to decide whether an new geometry node should be genera...
Definition: GNEEdge.cpp:245
const std::vector< T > & getSchemes() const
NBNode * getNBNode() const
Return net build node.
void setStreetName(const std::string &name)
sets the street name of this edge
Definition: NBEdge.h:491
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEEdge.cpp:436
SUMOReal getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:469
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:86
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given ...
Definition: NBEdge.cpp:2547
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:54
void p_begin(const std::string &description)
Begin undo command sub-group. This begins a new group of commands that are treated as a single comman...
Definition: GNEUndoList.cpp:86
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
static void drawText(const std::string &text, const Position &pos, const SUMOReal layer, const SUMOReal size, const RGBColor &col=RGBColor::BLACK, const SUMOReal angle=0)
draw Text with given parameters
Definition: GLHelper.cpp:460
bool addAdditional(GNEAdditional *additional)
add additional to this edge
Definition: GNEEdge.cpp:821
const std::vector< GNEAdditional * > & getAdditionals() const
return list of additionals associated with this edge
Definition: GNEEdge.cpp:849
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1090
An Element wich group additionalSet elements.
bool isClosed() const
check if PositionVector is closed
bool myWasSplit
whether this edge was created from a split
Definition: GNEEdge.h:253
~GNEEdge()
Destructor.
Definition: GNEEdge.cpp:86
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
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.
Position positionAtOffset2D(SUMOReal pos, SUMOReal lateralOffset=0) const
Returns the position at the given length.
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge&#39;s geometry
Definition: NBEdge.cpp:449
int getIndex() const
returns the index of the lane
Definition: GNELane.cpp:500
GUIGlID getGlID() const
Returns the numerical id of the object.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:48
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
SUMOReal scale
information about a lane&#39;s width (temporary, used for a single view)
bool removeAdditional(GNEAdditional *additional)
remove additional from this edge
Definition: GNEEdge.cpp:835
const std::vector< GNEAdditionalSet * > & getAdditionalSets()
return list of additionalSets associated with this edge
Definition: GNEEdge.cpp:883
virtual GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
Definition: GNEEdge.cpp:203
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEEdge.cpp:150
SUMOReal speed
The speed allowed on this lane.
Definition: NBEdge.h:130
virtual const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
void p_add(GNEChange_Attribute *cmd)
special method, avoid empty changes, always execute
GUIVisualizationTextSettings edgeName
static void drawFilledCircle(SUMOReal width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:344
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:122
const std::string & getID() const
Returns the id.
Definition: Named.h:66
SUMOReal length2D() const
Returns the length.
static bool isValidID(const std::string &value)
true if value is a valid sumo ID
SVCPermissions permissions
List of vehicle types that are allowed on this lane.
Definition: NBEdge.h:132
void addLane(int index, bool recompute=true)
Definition: NBEdge.cpp:2368
static const std::string MODIFIED
feature has been manually modified (implies approval)
const PositionVector getInnerGeometry() const
Returns the geometry of the edge without the endpoints.
Definition: NBEdge.cpp:430
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:228
bool hasLaneSpecificSpeed() const
whether lanes differ in speed
Definition: NBEdge.cpp:1469
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:355
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:443
SVCPermissions preferred
List of vehicle types that are preferred on this lane.
Definition: NBEdge.h:134
void p_end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise, the sub-group will be added as a new command into parent group. A matching begin() must have been called previously.
Definition: GNEUndoList.cpp:93
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
void deleteLane(int index, bool recompute=true)
Definition: NBEdge.cpp:2403
GNEJunction * retrieveJunction(const std::string &id, bool failHard=true)
get junction by id
Definition: GNENet.cpp:603
A list of positions.
void add(SUMOReal xoff, SUMOReal yoff, SUMOReal zoff)
int indexOfClosest(const Position &p) const
index of the closest position to p
bool hasLaneSpecificPermissions() const
whether lanes differ in allowed vehicle classes
Definition: NBEdge.cpp:1455
friend class GNEChange_Attribute
declare friend class
AdditionalVector myAdditionals
vector with the additonals vinculated with this edge
Definition: GNEEdge.h:259
Boundary getBoundary() const
Returns the street&#39;s geometry.
Definition: GNEEdge.cpp:108
SUMOReal z() const
Returns the z-position.
Definition: Position.h:73
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:347
Position positionAtOffset(SUMOReal pos, SUMOReal lateralOffset=0) const
Returns the position at the given length.
int myPriority
The priority of the edge.
Definition: NBEdge.h:1303
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GNEEdge.cpp:119
GUIColorer junctionColorer
The junction colorer.
int insertAtClosest(const Position &p)
inserts p between the two closest positions and returns the insertion index
void drawName(const Position &pos, const SUMOReal scale, const GUIVisualizationTextSettings &settings, const SUMOReal angle=0) const
draw name of item
void setLoadedLength(SUMOReal val)
Definition: NBEdge.cpp:2590
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
void incRef(const std::string &debugMsg="")
The connection was given by the user.
Definition: NBEdge.h:113
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:935
std::string getVehicleClassNames(SVCPermissions permissions)
Returns the ids of the given classes, divided using a &#39; &#39;.
void removeLane(GNELane *lane)
the number of lanes by one. argument is only used to increase robustness (assertions) ...
Definition: GNEEdge.cpp:767
SUMOReal getEndOffset() const
Returns the offset to the destination node.
Definition: NBEdge.h:498
virtual GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNEEdge.cpp:127
void decRef(const std::string &debugMsg="")
void setGeometry(PositionVector geom, bool inner)
update edge geometry and inform the lanes
Definition: GNEEdge.cpp:365
GNEEdge(NBEdge &nbe, GNENet *net, bool wasSplit=false, bool loaded=false)
Constructor.
Definition: GNEEdge.cpp:68
bool canParseVehicleClasses(const std::string &classes)
Checks whether the given string contains only known vehicle classes.
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:54
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:2575
SUMOReal length() const
Returns the length.
SUMOReal rotationDegreeAtOffset(SUMOReal pos) const
Returns the rotation at the given length.
void add(SUMOReal x, SUMOReal y)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:76
void setResponsible(bool newVal)
set responsibility for deleting internal strctures
Definition: GNEEdge.cpp:632
Boundary & grow(SUMOReal by)
extends the boundary by the given amount
Definition: Boundary.cpp:201
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:371
const PositionVector & getShape() const
returns the shape of the lane
Definition: GNELane.cpp:456
const std::vector< GNELane * > & getLanes()
returns a reference to the lane vector
Definition: GNEEdge.cpp:424
bool set(const std::string &name, const std::string &value)
Sets the given value for the named option.
bool deleteGeometry(const Position &pos, GNEUndoList *undoList)
deletes the closest geometry node within SNAP_RADIUS.
Definition: GNEEdge.cpp:311
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
static const SUMOReal UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:212
An Element which don&#39;t belongs to GNENet but has influency in the simulation.
Definition: GNEAdditional.h:63
void setPreferredVehicleClass(SVCPermissions permissions, int lane=-1)
Definition: NBEdge.cpp:2561
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:546
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
void updateJunctionPosition(GNEJunction *junction, const Position &origPos)
update edge geometry after junction move
Definition: GNEEdge.cpp:212
void updateGeometry()
update pre-computed geometry information
Definition: GNEEdge.cpp:104
The popup menu of a globject.
an edge
static const SUMOReal SNAP_RADIUS
Definition: GNEEdge.h:237
void mul(SUMOReal val)
Multiplies both positions with the given value.
Definition: Position.h:99
void buildSelectionPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to (de)select the object.
std::string myType
The type of the edge.
Definition: NBEdge.h:1289
GNEJunction * getDest() const
returns the destination-junction
Definition: GNEEdge.cpp:145
void renameEdge(GNEEdge *edge, const std::string &newID)
updates the map and reserves new id
Definition: GNENet.cpp:940
bool isValid(SumoXMLAttr key, const std::string &value)
Definition: GNEEdge.cpp:576
void updateLaneGeometries()
update edge geometry and inform the lanes let the lanes recompute their precomputed geometry informat...
Definition: GNEEdge.cpp:375
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge&#39;s lanes&#39; lateral offset is computed.
Definition: NBEdge.h:626
void removeExplicitTurnaround(std::string id)
remove edge id from the list of explicit turnarounds
Definition: GNENet.cpp:980
LaneVector myLanes
List of this edges lanes.
Definition: GNEEdge.h:247
SUMOReal distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:232
bool removeAdditionalSet(GNEAdditionalSet *additionalSet)
remove GNEAdditionalSet from this edge
Definition: GNEEdge.cpp:869
bool hasLaneSpecificWidth() const
whether lanes differ in width
Definition: NBEdge.cpp:1480
void setEndOffset(int lane, SUMOReal offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2515
#define SUMOReal
Definition: config.h:213
static const std::string GUESSED
feature has been reguessed (may still be unchanged be we can&#39;t tell (yet)
bool addAdditionalSet(GNEAdditionalSet *additionalSet)
add GNEAdditionalSet to this edge
Definition: GNEEdge.cpp:855
void setEndpoint(Position pos, GNEUndoList *undoList)
makes pos the new geometry endpoint at the appropriate end
Definition: GNEEdge.cpp:328
void removeConnection(int fromLane, const std::string &toEdgeID, int toLane)
removes a connection
Definition: GNEEdge.cpp:801
empty max
AdditionalSetVector myAdditionalSets
vector with the additonalSets vinculated with this edge
Definition: GNEEdge.h:262
NBEdge & myNBEdge
the underlying NBEdge
Definition: GNEEdge.h:241
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:451
SUMOReal getFinalLength() const
length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:2755
NBEdge * getNBEdge()
returns the internal NBEdge
Definition: GNEEdge.cpp:225
const SUMOReal SUMO_const_halfLaneWidth
Definition: StdDefs.h:50
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:560
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
Definition: GNEEdge.cpp:502
const std::string & getStreetName() const
Returns the street name of this edge.
Definition: NBEdge.h:485
void resetEndpoint(const Position &pos, GNEUndoList *undoList)
restores the endpoint to the junction position at the appropriate end
Definition: GNEEdge.cpp:351
A window containing a gl-object&#39;s parameter.
void changeEdgeEndpoints(GNEEdge *edge, const std::string &newSourceID, const std::string &newDestID)
modifies endpoins of the given edge
Definition: GNENet.cpp:949
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2339
bool wasSplit()
whether this edge was created from a split
Definition: GNEEdge.cpp:430
GNEJunction * getSource() const
returns the source-junction
Definition: GNEEdge.cpp:139
Position getSplitPos(const Position &clickPos)
Definition: GNEEdge.cpp:231
friend class GNEChange_Lane
Friend class.
Definition: GNEEdge.h:57
static PositionVector parseShapeReporting(const std::string &shpdef, const std::string &objecttype, const char *objectid, bool &ok, bool allowEmpty, bool report=true)
Builds a PositionVector from a string representation, reporting occured errors.
static bool changeGeometry(PositionVector &geom, const std::string &id, const Position &oldPos, const Position &newPos, bool relative=false, bool moveEndPoints=false)
Definition: GNEEdge.cpp:258
SUMOReal width
This lane&#39;s width.
Definition: NBEdge.h:138
static const SUMOReal INVALID_OFFSET
a value to signify offsets outside the range of [0, Line.length()]
Definition: GeomHelper.h:59
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
a junction
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:363