Eclipse SUMO - Simulation of Urban MObility
GNEPoly.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-2019 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 class for visualizing and editing POIS in netedit (adapted from
16 // GUIPolygon and NLHandler)
17 /****************************************************************************/
18 
19 
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <string>
27 #include <utils/gui/div/GLHelper.h>
29 #include <netedit/GNENet.h>
31 #include <netedit/GNEUndoList.h>
32 #include <netedit/GNEViewNet.h>
34 
35 #include "GNEPoly.h"
36 
37 
38 // ===========================================================================
39 // static members
40 // ===========================================================================
41 
42 const double GNEPoly::myHintSize = 0.8;
43 
44 // ===========================================================================
45 // method definitions
46 // ===========================================================================
47 GNEPoly::GNEPoly(GNENet* net, const std::string& id, const std::string& type, const PositionVector& shape, bool geo, bool fill, double lineWidth,
48  const RGBColor& color, double layer, double angle, const std::string& imgFile, bool relativePath, bool movementBlocked, bool shapeBlocked) :
49  GUIPolygon(id, type, color, shape, geo, fill, lineWidth, layer, angle, imgFile, relativePath),
50  GNEShape(net, SUMO_TAG_POLY, movementBlocked, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}),
51  myNetElementShapeEdited(nullptr),
52  myBlockShape(shapeBlocked),
53  myClosedShape(shape.front() == shape.back()),
54  mySimplifiedShape(false),
56  // check if imgFile is valid
57  if (!imgFile.empty() && GUITexturesHelper::getTextureID(imgFile) == -1) {
58  setShapeImgFile("");
59  }
60  // set GEO shape
62  for (int i = 0; i < (int) myGeoShape.size(); i++) {
64  }
65 }
66 
67 
69 
70 
71 std::string
73  int counter = myNet->getPolygons().size();
74  while (myNet->retrievePolygon(getID() + toString(childTag) + toString(counter), false) != nullptr) {
75  counter++;
76  }
77  return (getID() + toString(childTag) + toString(counter));
78 }
79 
80 
81 void
83  // save current centering boundary
85 }
86 
87 
88 void
90  // check that endGeometryMoving was called only once
92  // Remove object from net
94  // reset myMovingGeometryBoundary
96  // add object into grid again (using the new centering boundary)
98  }
99 }
100 
101 
102 int
103 GNEPoly::moveVertexShape(const int index, const Position& oldPos, const Position& offset) {
104  // only move shape if block movement block shape are disabled
105  if (!myBlockMovement && !myBlockShape && (index != -1)) {
106  // check that index is correct before change position
107  if (index < (int)myShape.size()) {
108  // save current moving Geometry Point
110  // if closed shape and cliked is first or last, move both giving more priority to first always
111  if (myClosedShape && (index == 0 || index == (int)myShape.size() - 1)) {
112  // Change position of first shape Geometry Point and filtern position using snap to active grid
113  myShape.front() = oldPos;
114  myShape.front().add(offset);
115  myShape.front() = myNet->getViewNet()->snapToActiveGrid(myShape[index]);
116  // Change position of last shape Geometry Point and filtern position using snap to active grid
117  myShape.back() = oldPos;
118  myShape.back().add(offset);
119  myShape.back() = myNet->getViewNet()->snapToActiveGrid(myShape[index]);
120  } else {
121  // change position of Geometry Point and filtern position using snap to active grid
122  myShape[index] = oldPos;
123  myShape[index].add(offset);
124  myShape[index] = myNet->getViewNet()->snapToActiveGrid(myShape[index]);
125  }
126  // return index of moved Geometry Point
127  return index;
128  } else {
129  throw InvalidArgument("Index greater than shape size");
130  }
131  } else {
132  return index;
133  }
134 }
135 
136 
137 void
138 GNEPoly::moveEntireShape(const PositionVector& oldShape, const Position& offset) {
139  // only move shape if block movement is disabled and block shape is enabled
140  if (!myBlockMovement && myBlockShape) {
141  // restore original shape
142  myShape = oldShape;
143  // change all points of the shape shape using offset
144  for (auto& i : myShape) {
145  i.add(offset);
146  }
147  // update Geometry after moving
148  updateGeometry();
149  }
150 }
151 
152 
153 void
155  if (!myBlockMovement) {
156  // disable current moving vertex
158  // restore original shape into shapeToCommit
159  PositionVector shapeToCommit = myShape;
160  // restore old shape in polygon (to avoid problems with RTree)
161  myShape = oldShape;
162  // first check if double points has to be removed
163  shapeToCommit.removeDoublePoints(myHintSize);
164  if (shapeToCommit.size() != myShape.size() && !myNet->getViewNet()->getEditShapes().editingNetElementShapes) {
165  WRITE_WARNING("Merged shape's point")
166  }
167 
168  // check if polygon has to be closed
169  if (shapeToCommit.size() > 1 && shapeToCommit.front().distanceTo2D(shapeToCommit.back()) < (2 * myHintSize)) {
170  shapeToCommit.pop_back();
171  shapeToCommit.push_back(shapeToCommit.front());
172  }
173  // only use GNEChange_Attribute if we aren't editing a junction's shape
174  if (myNetElementShapeEdited == nullptr) {
175  // commit new shape
176  undoList->p_begin("moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
177  undoList->p_add(new GNEChange_Attribute(this, myNet, SUMO_ATTR_SHAPE, toString(shapeToCommit)));
178  undoList->p_end();
179  } else {
180  // set new shape calling private setAttribute function
181  setAttribute(SUMO_ATTR_SHAPE, toString(shapeToCommit));
182  }
183  }
184 }
185 
186 
187 void
189  // nothing to do
190 }
191 
192 void
194  writeXML(device, myGEO);
195 }
196 
197 
198 Position
200  return myShape.getPolygonCenter();
201 }
202 
203 
204 Boundary
206  // Return Boundary depending if myMovingGeometryBoundary is initialised (important for move geometry)
209  } else {
211  }
212 }
213 
214 
215 GUIGlID
217  return GUIPolygon::getGlID();
218 }
219 
220 
221 std::string
223  if (myNetElementShapeEdited != nullptr) {
225  } else {
226  return myNet->getMicrosimID();
227  }
228 }
229 
230 
233  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
234  buildPopupHeader(ret, app);
237  // build selection and show parameters menu
240  FXMenuCommand* simplifyShape = new FXMenuCommand(ret, "Simplify Shape\t\tReplace current shape with a rectangle", nullptr, &parent, MID_GNE_POLYGON_SIMPLIFY_SHAPE);
241  // disable simplify shape if polygon was already simplified
242  if (mySimplifiedShape || myShape.size() <= 2) {
243  simplifyShape->disable();
244  }
245  // create open or close polygon's shape only if myNetElementShapeEdited is nullptr
246  if (myNetElementShapeEdited == nullptr) {
247  if (myClosedShape) {
248  new FXMenuCommand(ret, "Open shape\t\tOpen polygon's shape", nullptr, &parent, MID_GNE_POLYGON_OPEN);
249  } else {
250  new FXMenuCommand(ret, "Close shape\t\tClose polygon's shape", nullptr, &parent, MID_GNE_POLYGON_CLOSE);
251  }
252  }
253  // create a extra FXMenuCommand if mouse is over a vertex
254  int index = getVertexIndex(myNet->getViewNet()->getPositionInformation(), false, false);
255  if (index != -1) {
256  FXMenuCommand* removeGeometryPoint = new FXMenuCommand(ret, "Remove geometry point\t\tRemove geometry point under mouse", nullptr, &parent, MID_GNE_POLYGON_DELETE_GEOMETRY_POINT);
257  FXMenuCommand* setFirstPoint = new FXMenuCommand(ret, "Set first geometry point\t\tSet", nullptr, &parent, MID_GNE_POLYGON_SET_FIRST_POINT);
258  // disable setFirstPoint if shape only have three points
259  if ((myClosedShape && (myShape.size() <= 4)) || (!myClosedShape && (myShape.size() <= 2))) {
260  removeGeometryPoint->disable();
261  }
262  // disable setFirstPoint if mouse is over first point
263  if (index == 0) {
264  setFirstPoint->disable();
265  }
266  }
267  return ret;
268 }
269 
270 
273  return GUIPolygon::getParameterWindow(app, parent);
274 }
275 
276 
277 void
279  // first check if poly can be drawn
281  // check if boundary has to be drawn
282  if (s.drawBoundaries) {
284  }
285  // push name (needed for getGUIGlObjectsUnderCursor(...)
286  glPushName(getGlID());
287  // first check if inner polygon can be drawn
288  if (checkDraw(s)) {
289  // draw inner polygon
291  }
292  // draw details of Netedit
293  double circleWidth = myHintSize * MIN2((double)1, s.polySize.getExaggeration(s, this));
294  double circleWidthSquared = circleWidth * circleWidth;
295  // Obtain exaggeration of the draw
296  const double exaggeration = s.addSize.getExaggeration(s, this);
297  // draw geometry details hints if is not too small and isn't in selecting mode
298  if (s.scale * circleWidth > 1.) {
299  // set values relative to mouse position regarding to shape
300  bool mouseOverVertex = false;
302  Position mousePosition = myNet->getViewNet()->getPositionInformation();
303  double distanceToShape = myShape.distance2D(mousePosition);
304  // set colors
305  RGBColor invertedColor, darkerColor;
306  if (drawUsingSelectColor()) {
307  invertedColor = s.colorSettings.selectionColor.invertedColor();
308  darkerColor = s.colorSettings.selectionColor.changedBrightness(-32);
309  } else {
310  invertedColor = GLHelper::getColor().invertedColor();
311  darkerColor = GLHelper::getColor().changedBrightness(-32);
312  }
313  // Draw geometry hints if polygon's shape isn't blocked
314  if (myBlockShape == false) {
315  // draw a boundary for moving using darkerColor
316  glPushMatrix();
317  glTranslated(0, 0, GLO_POLYGON + 0.01);
318  GLHelper::setColor(darkerColor);
320  glPopMatrix();
321  // draw shape points only in Network supemode
323  for (auto i : myShape) {
324  if (!s.drawForSelecting || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(i) <= (circleWidthSquared + 2))) {
325  glPushMatrix();
326  glTranslated(i.x(), i.y(), GLO_POLYGON + 0.02);
327  // Change color of vertex and flag mouseOverVertex if mouse is over vertex
328  if (modeMove && (i.distanceTo(mousePosition) < circleWidth)) {
329  mouseOverVertex = true;
330  GLHelper::setColor(invertedColor);
331  } else {
332  GLHelper::setColor(darkerColor);
333  }
335  glPopMatrix();
336  // draw elevation or special symbols (Start, End and Block)
338  // Push matrix
339  glPushMatrix();
340  // Traslate to center of detector
341  glTranslated(i.x(), i.y(), getType() + 1);
342  // draw Z
343  GLHelper::drawText(toString(i.z()), Position(), .1, 0.7, RGBColor::BLUE);
344  // pop matrix
345  glPopMatrix();
346  } else if ((i == myShape.front()) && !s.drawForSelecting && s.drawDetail(s.detailSettings.geometryPointsText, exaggeration)) {
347  // draw a "s" over first point
348  glPushMatrix();
349  glTranslated(i.x(), i.y(), GLO_POLYGON + 0.03);
350  GLHelper::drawText("S", Position(), .1, 2 * circleWidth, invertedColor);
351  glPopMatrix();
352  } else if ((i == myShape.back()) && (myClosedShape == false) && !s.drawForSelecting && s.drawDetail(s.detailSettings.geometryPointsText, exaggeration)) {
353  // draw a "e" over last point if polygon isn't closed
354  glPushMatrix();
355  glTranslated(i.x(), i.y(), GLO_POLYGON + 0.03);
356  GLHelper::drawText("E", Position(), .1, 2 * circleWidth, invertedColor);
357  glPopMatrix();
358  }
359  }
360  }
361  // check if draw moving hint has to be drawed
362  if (modeMove && (mouseOverVertex == false) && (myBlockMovement == false) && (distanceToShape < circleWidth)) {
363  // push matrix
364  glPushMatrix();
365  Position hintPos = myShape.size() > 1 ? myShape.positionAtOffset2D(myShape.nearest_offset_to_point2D(mousePosition)) : myShape[0];
366  glTranslated(hintPos.x(), hintPos.y(), GLO_POLYGON + 0.04);
367  GLHelper::setColor(invertedColor);
369  glPopMatrix();
370  }
371  }
372  }
373  }
374  // check if dotted contour has to be drawn
375  if (myNet->getViewNet()->getDottedAC() == this) {
377  }
378  // pop name
379  glPopName();
380  }
381 }
382 
383 
384 int
385 GNEPoly::getVertexIndex(Position pos, bool createIfNoExist, bool snapToGrid) {
386  // check if position has to be snapped to grid
387  if (snapToGrid) {
388  pos = myNet->getViewNet()->snapToActiveGrid(pos);
389  }
390  // first check if vertex already exists
391  for (auto i : myShape) {
392  if (i.distanceTo2D(pos) < myHintSize) {
393  return myShape.indexOfClosest(i);
394  }
395  }
396  // if vertex doesn't exist, insert it
397  if (createIfNoExist) {
398  return myShape.insertAtClosest(pos);
399  } else {
400  return -1;
401  }
402 }
403 
404 
405 void
406 GNEPoly::deleteGeometryPoint(const Position& pos, bool allowUndo) {
407  if (myShape.size() > 1) {
408  // obtain index
409  PositionVector modifiedShape = myShape;
410  int index = modifiedShape.indexOfClosest(pos);
411  // remove point dependending of
412  if (myClosedShape && (index == 0 || index == (int)modifiedShape.size() - 1) && (myShape.size() > 2)) {
413  modifiedShape.erase(modifiedShape.begin());
414  modifiedShape.erase(modifiedShape.end() - 1);
415  modifiedShape.push_back(modifiedShape.front());
416  } else {
417  modifiedShape.erase(modifiedShape.begin() + index);
418  }
419  // set new shape depending of allowUndo
420  if (allowUndo) {
421  myNet->getViewNet()->getUndoList()->p_begin("delete geometry point");
424  } else {
425  // first remove object from grid due shape is used for boundary
427  // set new shape
428  myShape = modifiedShape;
429  // Check if new shape is closed
430  myClosedShape = (myShape.front() == myShape.back());
431  // disable simplified shape flag
432  mySimplifiedShape = false;
433  // add object into grid again
434  myNet->addGLObjectIntoGrid(this);
435  }
436  } else {
437  WRITE_WARNING("Number of remaining points insufficient")
438  }
439 }
440 
441 
442 bool
444  return myBlockShape;
445 }
446 
447 
448 bool
450  return myClosedShape;
451 }
452 
453 
454 void
456  if (element) {
457  myNetElementShapeEdited = element;
458  } else {
459  throw InvalidArgument("Junction cannot be nullptr");
460  }
461 }
462 
463 
467 }
468 
469 
470 void
471 GNEPoly::openPolygon(bool allowUndo) {
472  // only open if shape is closed
473  if (myClosedShape) {
474  if (allowUndo) {
475  myNet->getViewNet()->getUndoList()->p_begin("open polygon");
478  } else {
479  myClosedShape = false;
480  myShape.pop_back();
481  // disable simplified shape flag
482  mySimplifiedShape = false;
483  // update geometry to avoid grabbing Problems
484  updateGeometry();
485  }
486  } else {
487  WRITE_WARNING("Polygon already opened")
488  }
489 }
490 
491 
492 void
493 GNEPoly::closePolygon(bool allowUndo) {
494  // only close if shape is opened
495  if (myClosedShape == false) {
496  if (allowUndo) {
497  myNet->getViewNet()->getUndoList()->p_begin("close shape");
500  } else {
501  myClosedShape = true;
503  // disable simplified shape flag
504  mySimplifiedShape = false;
505  // update geometry to avoid grabbing Problems
506  updateGeometry();
507  }
508  } else {
509  WRITE_WARNING("Polygon already closed")
510  }
511 }
512 
513 
514 void
515 GNEPoly::changeFirstGeometryPoint(int oldIndex, bool allowUndo) {
516  // check that old index is correct
517  if (oldIndex >= (int)myShape.size()) {
518  throw InvalidArgument("Invalid old Index");
519  } else if (oldIndex == 0) {
520  WRITE_WARNING("Selected point must be different of the first point")
521  } else {
522  // Configure new shape
523  PositionVector newShape;
524  for (int i = oldIndex; i < (int)myShape.size(); i++) {
525  newShape.push_back(myShape[i]);
526  }
527  if (myClosedShape) {
528  for (int i = 1; i < oldIndex; i++) {
529  newShape.push_back(myShape[i]);
530  }
531  newShape.push_back(newShape.front());
532  } else {
533  for (int i = 0; i < oldIndex; i++) {
534  newShape.push_back(myShape[i]);
535  }
536  }
537  // set new rotated shape
538  if (allowUndo) {
539  myNet->getViewNet()->getUndoList()->p_begin("change first geometry point");
542  } else {
543  // set new shape
544  myShape = newShape;
545  // Check if new shape is closed
546  myClosedShape = (myShape.front() == myShape.back());
547  // disable simplified shape flag
548  mySimplifiedShape = false;
549  // update geometry to avoid grabbing Problems
550  updateGeometry();
551  }
552  }
553 }
554 
555 
556 void
557 GNEPoly::simplifyShape(bool allowUndo) {
558  if (!mySimplifiedShape && myShape.size() > 2) {
559  const Boundary b = myShape.getBoxBoundary();
560  PositionVector simplifiedShape;
561  if (myShape.isClosed()) {
562  // create a square as simplified shape
563  simplifiedShape.push_back(Position(b.xmin(), b.ymin()));
564  simplifiedShape.push_back(Position(b.xmin(), b.ymax()));
565  simplifiedShape.push_back(Position(b.xmax(), b.ymax()));
566  simplifiedShape.push_back(Position(b.xmax(), b.ymin()));
567  simplifiedShape.push_back(simplifiedShape[0]);
568  } else {
569  // create a line as simplified shape
570  simplifiedShape.push_back(myShape.front());
571  simplifiedShape.push_back(myShape.back());
572  }
573  // set new shape depending of allowUndo
574  if (allowUndo) {
575  myNet->getViewNet()->getUndoList()->p_begin("simplify shape");
578  } else {
579  // set new shape
580  myShape = simplifiedShape;
581  // Check if new shape is closed
582  myClosedShape = (myShape.front() == myShape.back());
583  // update geometry to avoid grabbing Problems
584  updateGeometry();
585  }
586  // change flag after setting simplified shape
587  mySimplifiedShape = true;
588  } else {
589  WRITE_WARNING("Polygon already simplified")
590  }
591 }
592 
593 
594 std::string
596  switch (key) {
597  case SUMO_ATTR_ID:
598  return myID;
599  case SUMO_ATTR_SHAPE:
600  return toString(myShape);
601  case SUMO_ATTR_GEOSHAPE:
603  case SUMO_ATTR_COLOR:
604  return toString(getShapeColor());
605  case SUMO_ATTR_FILL:
606  return toString(myFill);
607  case SUMO_ATTR_LINEWIDTH:
608  return toString(myLineWidth);
609  case SUMO_ATTR_LAYER:
611  return "default";
612  } else {
613  return toString(getShapeLayer());
614  }
615  case SUMO_ATTR_TYPE:
616  return getShapeType();
617  case SUMO_ATTR_IMGFILE:
618  return getShapeImgFile();
620  return toString(getShapeRelativePath());
621  case SUMO_ATTR_ANGLE:
622  return toString(getShapeNaviDegree());
623  case SUMO_ATTR_GEO:
624  return toString(myGEO);
626  return toString(myBlockMovement);
628  return toString(myBlockShape);
630  return toString(myClosedShape);
631  case GNE_ATTR_SELECTED:
633  case GNE_ATTR_GENERIC:
634  return getGenericParametersStr();
635  default:
636  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
637  }
638 }
639 
640 
641 void
642 GNEPoly::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
643  if (value == getAttribute(key)) {
644  return; //avoid needless changes, later logic relies on the fact that attributes have changed
645  }
646  switch (key) {
647  case SUMO_ATTR_ID:
648  case SUMO_ATTR_SHAPE:
649  case SUMO_ATTR_GEOSHAPE:
650  case SUMO_ATTR_COLOR:
651  case SUMO_ATTR_FILL:
652  case SUMO_ATTR_LINEWIDTH:
653  case SUMO_ATTR_LAYER:
654  case SUMO_ATTR_TYPE:
655  case SUMO_ATTR_IMGFILE:
657  case SUMO_ATTR_ANGLE:
658  case SUMO_ATTR_GEO:
662  case GNE_ATTR_SELECTED:
663  case GNE_ATTR_GENERIC:
664  undoList->p_add(new GNEChange_Attribute(this, myNet, key, value));
665  break;
666  default:
667  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
668  }
669 }
670 
671 
672 bool
673 GNEPoly::isValid(SumoXMLAttr key, const std::string& value) {
674  switch (key) {
675  case SUMO_ATTR_ID:
676  return SUMOXMLDefinitions::isValidNetID(value) && (myNet->retrievePolygon(value, false) == nullptr);
677  case SUMO_ATTR_SHAPE:
678  case SUMO_ATTR_GEOSHAPE:
679  // empty shapes AREN'T allowed
680  if (value.empty()) {
681  return false;
682  } else {
683  return canParse<PositionVector>(value);
684  }
685  case SUMO_ATTR_COLOR:
686  return canParse<RGBColor>(value);
687  case SUMO_ATTR_FILL:
688  return canParse<bool>(value);
689  case SUMO_ATTR_LINEWIDTH:
690  return canParse<double>(value) && (parse<double>(value) >= 0);
691  case SUMO_ATTR_LAYER:
692  if (value == "default") {
693  return true;
694  } else {
695  return canParse<double>(value);
696  }
697  case SUMO_ATTR_TYPE:
698  return true;
699  case SUMO_ATTR_IMGFILE:
700  if (value == "") {
701  return true;
702  } else {
703  // check that image can be loaded
704  return GUITexturesHelper::getTextureID(value) != -1;
705  }
707  return canParse<bool>(value);
708  case SUMO_ATTR_ANGLE:
709  return canParse<double>(value);
710  case SUMO_ATTR_GEO:
711  return canParse<bool>(value);
713  return canParse<bool>(value);
715  return canParse<bool>(value);
717  if (canParse<bool>(value)) {
718  bool closePolygon = parse<bool>(value);
719  if (closePolygon && (myShape.begin() == myShape.end())) {
720  // Polygon already closed, then invalid value
721  return false;
722  } else if (!closePolygon && (myShape.begin() != myShape.end())) {
723  // Polygon already open, then invalid value
724  return false;
725  } else {
726  return true;
727  }
728  } else {
729  return false;
730  }
731  case GNE_ATTR_SELECTED:
732  return canParse<bool>(value);
733  case GNE_ATTR_GENERIC:
734  return isGenericParametersValid(value);
735  default:
736  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
737  }
738 }
739 
740 
741 std::string
743  std::string result;
744  // Generate an string using the following structure: "key1=value1|key2=value2|...
745  for (auto i : getParametersMap()) {
746  result += i.first + "=" + i.second + "|";
747  }
748  // remove the last "|"
749  if (!result.empty()) {
750  result.pop_back();
751  }
752  return result;
753 }
754 
755 
756 std::vector<std::pair<std::string, std::string> >
758  std::vector<std::pair<std::string, std::string> > result;
759  // iterate over parameters map and fill result
760  for (auto i : getParametersMap()) {
761  result.push_back(std::make_pair(i.first, i.second));
762  }
763  return result;
764 }
765 
766 
767 void
768 GNEPoly::setGenericParametersStr(const std::string& value) {
769  // clear parameters
770  clearParameter();
771  // separate value in a vector of string using | as separator
772  std::vector<std::string> parsedValues;
773  StringTokenizer stValues(value, "|", true);
774  while (stValues.hasNext()) {
775  parsedValues.push_back(stValues.next());
776  }
777  // check that parsed values (A=B)can be parsed in generic parameters
778  for (auto i : parsedValues) {
779  std::vector<std::string> parsedParameters;
780  StringTokenizer stParam(i, "=", true);
781  while (stParam.hasNext()) {
782  parsedParameters.push_back(stParam.next());
783  }
784  // Check that parsed parameters are exactly two and contains valid chracters
785  if (parsedParameters.size() == 2 && SUMOXMLDefinitions::isValidGenericParameterKey(parsedParameters.front()) && SUMOXMLDefinitions::isValidGenericParameterValue(parsedParameters.back())) {
786  setParameter(parsedParameters.front(), parsedParameters.back());
787  }
788  }
789 }
790 
791 // ===========================================================================
792 // private
793 // ===========================================================================
794 
795 void
796 GNEPoly::setAttribute(SumoXMLAttr key, const std::string& value) {
797  // first remove object from grid due almost modificactions affects to boundary (but avoided for certain attributes)
798  if ((key != SUMO_ATTR_ID) && (key != GNE_ATTR_GENERIC) && (key != GNE_ATTR_SELECTED)) {
800  }
801  switch (key) {
802  case SUMO_ATTR_ID: {
803  std::string oldID = myID;
804  myID = value;
805  myNet->changeShapeID(this, oldID);
806  setMicrosimID(value);
807  break;
808  }
809  case SUMO_ATTR_SHAPE: {
810  // set new shape
811  myShape = parse<PositionVector>(value);
812  // set GEO shape
814  for (int i = 0; i < (int) myGeoShape.size(); i++) {
815  GeoConvHelper::getFinal().cartesian2geo(myGeoShape[i]);
816  }
817  // Check if new shape is closed
818  myClosedShape = (myShape.front() == myShape.back());
819  // disable simplified shape flag
820  mySimplifiedShape = false;
821  // update geometry of shape edited element
824  }
825  break;
826  }
827  case SUMO_ATTR_GEOSHAPE: {
828  // set new GEO shape
829  myGeoShape = parse<PositionVector>(value);
830  // set shape
831  myShape = myGeoShape ;
832  for (int i = 0; i < (int) myShape.size(); i++) {
834  }
835  // Check if new shape is closed
836  myClosedShape = (myShape.front() == myShape.back());
837  // disable simplified shape flag
838  mySimplifiedShape = false;
839  // update geometry of shape edited element
842  }
843  break;
844  }
845  case SUMO_ATTR_COLOR:
846  setShapeColor(parse<RGBColor>(value));
847  break;
848  case SUMO_ATTR_FILL:
849  myFill = parse<bool>(value);
850  break;
851  case SUMO_ATTR_LINEWIDTH:
852  myLineWidth = parse<double>(value);
853  break;
854  case SUMO_ATTR_LAYER:
855  if (value == "default") {
857  } else {
858  setShapeLayer(parse<double>(value));
859  }
860  break;
861  case SUMO_ATTR_TYPE:
862  setShapeType(value);
863  break;
864  case SUMO_ATTR_IMGFILE:
865  setShapeImgFile(value);
866  // all textures must be refresh
868  break;
870  setShapeRelativePath(parse<bool>(value));
871  break;
872  case SUMO_ATTR_ANGLE:
873  setShapeNaviDegree(parse<double>(value));
874  break;
875  case SUMO_ATTR_GEO:
876  myGEO = parse<bool>(value);
877  break;
879  myBlockMovement = parse<bool>(value);
880  break;
882  myBlockShape = parse<bool>(value);
883  break;
885  myClosedShape = parse<bool>(value);
886  if (myClosedShape) {
889  } else {
890  myShape.pop_back();
891  myGeoShape.pop_back();
892  }
893  // disable simplified shape flag
894  mySimplifiedShape = false;
895  break;
896  case GNE_ATTR_SELECTED:
897  if (parse<bool>(value)) {
899  } else {
901  }
902  break;
903  case GNE_ATTR_GENERIC:
905  break;
906  default:
907  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
908  }
909  // add object into grid again (but avoided for certain attributes)
910  if ((key != SUMO_ATTR_ID) && (key != GNE_ATTR_GENERIC) && (key != GNE_ATTR_SELECTED)) {
911  myNet->addGLObjectIntoGrid(this);
912  }
913 }
914 
915 
916 const GUIGlObject*
918  return this;
919 }
920 
921 /****************************************************************************/
PositionVector myShape
The positions of the polygon.
Definition: SUMOPolygon.h:133
void endGeometryMoving()
begin movement (used when user click over edge to start a movement, to avoid problems with problems w...
Definition: GNEPoly.cpp:89
static const RGBColor BLUE
Definition: RGBColor.h:192
double myLineWidth
The line width for drawing an unfilled polygon.
Definition: SUMOPolygon.h:142
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:131
SumoXMLTag
Numbers representing SUMO-XML - element names.
void openPolygon(bool allowUndo=true)
open polygon
Definition: GNEPoly.cpp:471
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:125
Position snapToActiveGrid(const Position &pos, bool snapXY=true) const
Returns a position that is mapped to the closest grid point if the grid is active.
double scale
information about a lane&#39;s width (temporary, used for a single view)
bool myGEO
specify if shape is handled as GEO coordinate (Main used in netedit)
Definition: SUMOPolygon.h:136
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition: RGBColor.cpp:154
a polygon
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
bool myFill
Information whether the polygon has to be filled.
Definition: SUMOPolygon.h:139
void drawInnerPolygon(const GUIVisualizationSettings &s, bool disableSelectionColor) const
draw inner Polygon (before pushName() )
Definition: GUIPolygon.cpp:258
static void drawBoxLines(const PositionVector &geom, const std::vector< double > &rots, const std::vector< double > &lengths, double width, int cornerDetail=0, double offset=0)
Draws thick lines.
Definition: GLHelper.cpp:182
const std::string & getShapeImgFile() const
Returns the imgFile of the Shape.
Definition: Shape.h:104
void buildNameCopyPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds entries which allow to copy the name / typed name into the clipboard.
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector) ...
std::string generateChildID(SumoXMLTag childTag)
gererate a new ID for an element child
Definition: GNEPoly.cpp:72
block shape of a graphic element (Used mainly in GNEShapes)
std::string getParentName() const
Returns the name of the parent object.
Definition: GNEPoly.cpp:222
int indexOfClosest(const Position &p) const
index of the closest position to p
void setShapeColor(const RGBColor &col)
Sets a new color.
Definition: Shape.h:130
void setShapeRelativePath(bool relativePath)
Sets a new relativePath value.
Definition: Shape.h:165
const Polygons & getPolygons() const
Returns all polygons.
int size() const
Returns the number of stored items within the container.
A layer number.
Boundary myMovingGeometryBoundary
boundary used during moving of elements
Definition: GNEShape.h:208
Stores the information about how to visualize structures.
bool isPolygonClosed() const
check if polygon is closed
Definition: GNEPoly.cpp:449
void setShapeType(const std::string &type)
Sets a new type.
Definition: Shape.h:123
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
Definition: GNEShape.cpp:139
double y() const
Returns the y-position.
Definition: Position.h:62
void commitShapeChange(const PositionVector &oldShape, GNEUndoList *undoList)
commit geometry changes in the attributes of an element after use of changeShapeGeometry(...)
Definition: GNEPoly.cpp:154
void updateGeometry()
update pre-computed geometry information
Definition: GNEPoly.cpp:188
double x() const
Returns the x-position.
Definition: Position.h:57
Close shape of a polygon (Used by GNEPolys)
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, int align=0, double width=-1)
Definition: GLHelper.cpp:668
GNEPoly * retrievePolygon(const std::string &id, bool failHard=true) const
get Polygon by id
Definition: GNENet.cpp:1053
bool drawDetail(const double detail, const double exaggeration) const
check if details can be drawn for the given GUIVisualizationDetailSettings and current scale and exxa...
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:78
const PositionVector & getShape() const
Returns whether the shape of the polygon.
Definition: SUMOPolygon.h:82
bool mySimplifiedShape
flag to indicate if polygon is simplified
Definition: GNEPoly.h:243
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:73
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
bool editingElevation() const
check if we&#39;re editing elevation
PositionVector myGeoShape
Latitude of Polygon.
Definition: GNEPoly.h:234
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
bool hasNext()
returns the information whether further substrings exist
bool drawUsingSelectColor() const
check if attribute carrier must be drawn using selecting color.
Definition: GNEShape.cpp:145
bool editingNetElementShapes
flag to edit net element shapes
RGBColor invertedColor() const
obtain inverted of current RGBColor
Definition: RGBColor.cpp:143
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:348
GNEPoly(GNENet *net, const std::string &id, const std::string &type, const PositionVector &shape, bool geo, bool fill, double lineWidth, const RGBColor &color, double layer, double angle, const std::string &imgFile, bool relativePath, bool movementBlocked, bool shapeBlocked)
Constructor.
Definition: GNEPoly.cpp:47
static bool isValidGenericParameterKey(const std::string &value)
whether the given string is a valid key for a generic parameter
GNENet * myNet
the net to inform about updates
Definition: GNEShape.h:205
close opened polygon
Definition: GUIAppEnum.h:877
generic attribute
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
void selectAttributeCarrier(bool changeFlag=true)
Definition: GNEShape.cpp:109
void closePolygon(bool allowUndo=true)
close polygon
Definition: GNEPoly.cpp:493
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
mode for moving network elements
const std::string & getShapeType() const
Returns the (abstract) type of the Shape.
Definition: Shape.h:76
GUIVisualizationSizeSettings polySize
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
void setShapeImgFile(const std::string &imgFile)
Sets a new imgFile.
Definition: Shape.h:158
void p_add(GNEChange_Attribute *cmd)
special method, avoid empty changes, always execute
static void drawBoundary(const Boundary &b)
Draw a boundary (used for debugging)
Definition: GLHelper.cpp:812
int getCircleResolution() const
function to calculate circle resolution for all circles drawn in drawGL(...) functions ...
static void clearTextures()
clears loaded textures
GUIVisualizationSizeSettings addSize
GNENetElement * myNetElementShapeEdited
junction of which the shape is being edited (optional)
Definition: GNEPoly.h:231
GNEUndoList * getUndoList() const
get the undoList object
Definition: GNEViewNet.cpp:933
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
bool isPolygonBlocked() const
return true if polygon is blocked
Definition: GNEPoly.cpp:443
bool getShapeRelativePath() const
Returns the relativePath of the Shape.
Definition: Shape.h:111
void startGeometryMoving()
Definition: GNEPoly.cpp:82
static bool isValidGenericParameterValue(const std::string &value)
whether the given string is a valid value for a generic parameter
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:48
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:616
bool myBlockMovement
flag to block movement
Definition: GNEShape.h:211
void writeShape(OutputDevice &device)
writte shape element into a xml file
Definition: GNEPoly.cpp:193
void setGenericParametersStr(const std::string &value)
set generic parameters in string format
Definition: GNEPoly.cpp:768
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:80
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
RGBColor selectionColor
basic selection color
int gPrecisionGeo
Definition: StdDefs.cpp:28
A list of positions.
Supermode currentSupermode
the current supermode
static bool isGenericParametersValid(const std::string &value)
check if given string can be parsed to a map/list of generic parameters
void removeGLObjectFromGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1279
static const double myHintSize
hint size of vertex
Definition: GNEPoly.h:250
Position getPolygonCenter() const
Returns the arithmetic of all corner points.
friend class GNEChange_Attribute
declare friend class
const RGBColor & getShapeColor() const
Returns the color of the Shape.
Definition: Shape.h:83
int myCurrentMovingVertexIndex
index of vertex that is been moved (-1 means that none vertex is been moved)
Definition: GNEPoly.h:246
static int getTextureID(const std::string &filename, const bool mirrorX=false)
return texture id for the given filename (initialize on first use)
block movement of a graphic element
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
Definition: GUIPolygon.cpp:122
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEPoly.cpp:278
static void drawShapeDottedContourAroundClosedShape(const GUIVisualizationSettings &s, const int type, const PositionVector &shape)
draw a dotted contour around the given closed shape with certain width
Definition: GLHelper.cpp:496
T MIN2(T a, T b)
Definition: StdDefs.h:74
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:119
void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
bool checkDraw(const GUIVisualizationSettings &s) const
check if Polygon can be drawn
Definition: GUIPolygon.cpp:236
edge: the shape in xml-definition
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
bool isValid(SumoXMLAttr key, const std::string &value)
method for checking if the key and their conrrespond attribute are valids
Definition: GNEPoly.cpp:673
void deleteGeometryPoint(const Position &pos, bool allowUndo=true)
delete the geometry point closest to the given pos
Definition: GNEPoly.cpp:406
void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
method for setting the attribute and letting the object perform additional changes ...
Definition: GNEPoly.cpp:642
void changeShapeID(GNEShape *s, const std::string &OldID)
change Shape ID
Definition: GNENet.cpp:2572
const GUIGlObject * getGUIGlObject() const
get GUIGlObject associated to this GNEShape
Definition: GNEPoly.cpp:917
bool showShapes() const
check if shapes has to be hide
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEPoly.cpp:595
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNEPoly.cpp:232
double getShapeLayer() const
Returns the layer of the Shape.
Definition: Shape.h:90
const GNEViewNetHelper::NetworkViewOptions & getNetworkViewOptions() const
get network view options
Definition: GNEViewNet.cpp:411
static bool isValidNetID(const std::string &value)
whether the given string is a valid id for a network element
unsigned int GUIGlID
Definition: GUIGlObject.h:43
GUIVisualizationDetailSettings detailSettings
detail settings
void reset()
Resets the boundary.
Definition: Boundary.cpp:67
std::string myID
The name of the object.
Definition: Named.h:134
int moveVertexShape(const int index, const Position &oldPos, const Position &offset)
change position of a vertex of shape without commiting change
Definition: GNEPoly.cpp:103
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:331
Set a vertex of polygon as first verte.
Definition: GUIAppEnum.h:881
void setShapeEditedElement(GNENetElement *element)
retrieve the netElement of which the shape is being edited
Definition: GNEPoly.cpp:455
void simplifyShape(bool allowUndo=true)
replace the current shape with a rectangle
Definition: GNEPoly.cpp:557
virtual void updateGeometry()=0
update pre-computed geometry information
Position getPositionInView() const
Returns position of additional in view.
Definition: GNEPoly.cpp:199
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
const GNEViewNetHelper::DemandViewOptions & getDemandViewOptions() const
get demand view options
Definition: GNEViewNet.cpp:417
const GNEAttributeCarrier * getDottedAC() const
get AttributeCarrier under cursor
Definition: GNEViewNet.cpp:939
GUIGlID getGlID() const
Returns the numerical id of the object.
Definition: GNEPoly.cpp:216
const std::string & getTagStr() const
get tag assigned to this object in string format
simplify polygon geometry
Definition: GUIAppEnum.h:875
bool isClosed() const
check if PositionVector is closed
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
Definition: GNEPoly.cpp:272
Demanding mode (Routes, Vehicles etc..)
element is selected
bool isInitialised() const
check if Boundary is Initialised
Definition: Boundary.cpp:217
The popup menu of a globject.
GNENetElement * getShapeEditedElement() const
retrieve the junction of which the shape is being edited
Definition: GNEPoly.cpp:465
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions) ...
Definition: Position.h:249
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
void unselectAttributeCarrier(bool changeFlag=true)
unselect attribute carrier using GUIGlobalSelection
Definition: GNEShape.cpp:124
std::vector< std::pair< std::string, std::string > > getGenericParameters() const
return generic parameters as vector of pairs format
Definition: GNEPoly.cpp:757
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.
void writeXML(OutputDevice &out, bool geo=false)
Definition: SUMOPolygon.cpp:50
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:64
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation. ...
~GNEPoly()
Destructor.
Definition: GNEPoly.cpp:68
NetworkEditMode networkEditMode
the current Network edit mode
bool myBlockShape
flag for block shape
Definition: GNEPoly.h:237
Position getPositionInformation() const
Returns the cursor&#39;s x/y position within the network.
GUIVisualizationColorSettings colorSettings
color settings
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
open closed polygon
Definition: GUIAppEnum.h:879
bool myClosedShape
flag to indicate if polygon is open or closed
Definition: GNEPoly.h:240
std::string getGenericParametersStr() const
return generic parameters in string format
Definition: GNEPoly.cpp:742
void add(double xoff, double yoff, double zoff)
bool drawForSelecting
whether drawing is performed for the purpose of selecting objects
const GNEViewNetHelper::EditModes & getEditModes() const
get edit modes
Definition: GNEViewNet.cpp:399
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:137
double getExaggeration(const GUIVisualizationSettings &s, const GUIGlObject *o, double factor=20) const
return the drawing size including exaggeration and constantSize values
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GUIPolygon.cpp:135
static const double geometryPointsText
details for Geometry Points Texts
void closePolygon()
ensures that the last position equals the first
void addGLObjectIntoGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1273
A color information.
A window containing a gl-object&#39;s parameter.
void changeFirstGeometryPoint(int oldIndex, bool allowUndo=true)
change first geometry point
Definition: GNEPoly.cpp:515
bool drawBoundaries
enable or disable draw boundaries
void setShapeLayer(const double layer)
Sets a new layer.
Definition: Shape.h:144
const GNEViewNetHelper::EditShapes & getEditShapes() const
get Edit Shape modul
Definition: GNEViewNet.cpp:429
Fill the polygon.
double getShapeNaviDegree() const
Returns the angle of the Shape in navigational degrees.
Definition: Shape.h:97
int getVertexIndex(Position pos, bool createIfNoExist, bool snapToGrid)
return index of a vertex of shape, or of a new vertex if position is over an shape&#39;s edge ...
Definition: GNEPoly.cpp:385
void buildPopupHeader(GUIGLObjectPopupMenu *ret, GUIMainWindow &app, bool addSeparator=true)
Builds the header.
begin/end of the description of a polygon
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GNEPoly.cpp:205
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:2067
void moveEntireShape(const PositionVector &oldShape, const Position &offset)
move entire shape without commiting change
Definition: GNEPoly.cpp:138
static const double DEFAULT_LAYER
Definition: Shape.h:44
void setShapeNaviDegree(const double angle)
Sets a new angle in navigational degrees.
Definition: Shape.h:151
void clearParameter()
Clears the parameter map.
static RGBColor getColor()
gets the gl-color
Definition: GLHelper.cpp:622