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-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 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),
55  myCurrentMovingVertexIndex(-1) {
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 void
73  // save current centering boundary
75 }
76 
77 
78 void
80  // check that endGeometryMoving was called only once
82  // Remove object from net
84  // reset myMovingGeometryBoundary
86  // update geometry without updating grid
87  updateGeometry(false);
88  // add object into grid again (using the new centering boundary)
90  }
91 }
92 
93 
94 int
95 GNEPoly::moveVertexShape(const int index, const Position& oldPos, const Position& offset) {
96  // only move shape if block movement block shape are disabled
97  if (!myBlockMovement && !myBlockShape && (index != -1)) {
98  // check that index is correct before change position
99  if (index < (int)myShape.size()) {
100  // save current moving Geometry Point
102  // if closed shape and cliked is first or last, move both giving more priority to first always
103  if (myClosedShape && (index == 0 || index == (int)myShape.size() - 1)) {
104  // Change position of first shape Geometry Point and filtern position using snap to active grid
105  myShape.front() = oldPos;
106  myShape.front().add(offset);
107  myShape.front() = myNet->getViewNet()->snapToActiveGrid(myShape[index]);
108  // Change position of last shape Geometry Point and filtern position using snap to active grid
109  myShape.back() = oldPos;
110  myShape.back().add(offset);
111  myShape.back() = myNet->getViewNet()->snapToActiveGrid(myShape[index]);
112  } else {
113  // change position of Geometry Point and filtern position using snap to active grid
114  myShape[index] = oldPos;
115  myShape[index].add(offset);
116  myShape[index] = myNet->getViewNet()->snapToActiveGrid(myShape[index]);
117  }
118  // return index of moved Geometry Point
119  return index;
120  } else {
121  throw InvalidArgument("Index greater than shape size");
122  }
123  } else {
124  return index;
125  }
126 }
127 
128 
129 void
130 GNEPoly::moveEntireShape(const PositionVector& oldShape, const Position& offset) {
131  // only move shape if block movement is disabled and block shape is enabled
132  if (!myBlockMovement && myBlockShape) {
133  // restore original shape
134  myShape = oldShape;
135  // change all points of the shape shape using offset
136  for (auto& i : myShape) {
137  i.add(offset);
138  }
139  // update Geometry after moving
140  updateGeometry(true);
141  }
142 }
143 
144 
145 void
147  if (!myBlockMovement) {
148  // disable current moving vertex
150  // restore original shape into shapeToCommit
151  PositionVector shapeToCommit = myShape;
152  // restore old shape in polygon (to avoid problems with RTree)
153  myShape = oldShape;
154  // first check if double points has to be removed
155  shapeToCommit.removeDoublePoints(myHintSize);
156  if (shapeToCommit.size() != myShape.size()) {
157  WRITE_WARNING("Merged shape's point")
158  }
159  // check if polygon has to be closed
160  if (shapeToCommit.size() > 1 && shapeToCommit.front().distanceTo2D(shapeToCommit.back()) < (2 * myHintSize)) {
161  shapeToCommit.pop_back();
162  shapeToCommit.push_back(shapeToCommit.front());
163  }
164  // only use GNEChange_Attribute if we aren't editing a junction's shape
165  if (myNetElementShapeEdited == nullptr) {
166  // commit new shape
167  undoList->p_begin("moving " + toString(SUMO_ATTR_SHAPE) + " of " + getTagStr());
168  undoList->p_add(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(shapeToCommit)));
169  undoList->p_end();
170  } else {
171  // set new shape calling private setAttribute function
172  setAttribute(SUMO_ATTR_SHAPE, toString(shapeToCommit));
173  }
174  }
175 }
176 
177 
178 void
179 GNEPoly::updateGeometry(bool /*updateGrid*/) {
180  // nothing to do
181 }
182 
183 void
185  writeXML(device, myGEO);
186 }
187 
188 
189 Position
191  return myShape.getPolygonCenter();
192 }
193 
194 
195 GUIGlID
197  return GUIPolygon::getGlID();
198 }
199 
200 
201 std::string
203  if (myNetElementShapeEdited != nullptr) {
205  } else {
206  return myNet->getMicrosimID();
207  }
208 }
209 
210 
213  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
214  buildPopupHeader(ret, app);
217  // build selection and show parameters menu
220  FXMenuCommand* simplifyShape = new FXMenuCommand(ret, "Simplify Shape\t\tReplace current shape with a rectangle", nullptr, &parent, MID_GNE_POLYGON_SIMPLIFY_SHAPE);
221  // disable simplify shape if polygon was already simplified
222  if (mySimplifiedShape || myShape.size() <= 2) {
223  simplifyShape->disable();
224  }
225  // create open or close polygon's shape only if myNetElementShapeEdited is nullptr
226  if (myNetElementShapeEdited == nullptr) {
227  if (myClosedShape) {
228  new FXMenuCommand(ret, "Open shape\t\tOpen polygon's shape", nullptr, &parent, MID_GNE_POLYGON_OPEN);
229  } else {
230  new FXMenuCommand(ret, "Close shape\t\tClose polygon's shape", nullptr, &parent, MID_GNE_POLYGON_CLOSE);
231  }
232  }
233  // create a extra FXMenuCommand if mouse is over a vertex
234  int index = getVertexIndex(myNet->getViewNet()->getPositionInformation(), false, false);
235  if (index != -1) {
236  FXMenuCommand* removeGeometryPoint = new FXMenuCommand(ret, "Remove geometry point\t\tRemove geometry point under mouse", nullptr, &parent, MID_GNE_POLYGON_DELETE_GEOMETRY_POINT);
237  FXMenuCommand* setFirstPoint = new FXMenuCommand(ret, "Set first geometry point\t\tSet", nullptr, &parent, MID_GNE_POLYGON_SET_FIRST_POINT);
238  // disable setFirstPoint if shape only have three points
239  if ((myClosedShape && (myShape.size() <= 4)) || (!myClosedShape && (myShape.size() <= 2))) {
240  removeGeometryPoint->disable();
241  }
242  // disable setFirstPoint if mouse is over first point
243  if (index == 0) {
244  setFirstPoint->disable();
245  }
246  }
247  return ret;
248 }
249 
250 
253  return GUIPolygon::getParameterWindow(app, parent);
254 }
255 
256 
257 Boundary
259  // Return Boundary depending if myMovingGeometryBoundary is initialised (important for move geometry)
262  } else {
264  }
265 }
266 
267 
268 void
270  // push name (needed for getGUIGlObjectsUnderCursor(...)
271  glPushName(getGlID());
272  // first check if inner polygon can be drawn
273  if(checkDraw(s)) {
274  drawInnerPolygon(s);
275  }
276  // draw details of Netedit
277  double circleWidth = myHintSize * MIN2((double)1, s.polySize.getExaggeration(s, this));
278  double circleWidthSquared = circleWidth * circleWidth;
279  int circleResolution = GNEAttributeCarrier::getCircleResolution(s);
280  // draw geometry details hints if is not too small and isn't in selecting mode
281  if (s.scale * circleWidth > 1.) {
282  // set values relative to mouse position regarding to shape
283  bool mouseOverVertex = false;
284  bool modeMove = myNet->getViewNet()->getCurrentEditMode() == GNE_MODE_MOVE;
285  Position mousePosition = myNet->getViewNet()->getPositionInformation();
286  double distanceToShape = myShape.distance2D(mousePosition);
287  // set colors
288  RGBColor invertedColor, darkerColor;
290  invertedColor = s.selectionColor.invertedColor();
291  darkerColor = s.selectionColor.changedBrightness(-32);
292  } else {
293  invertedColor = GLHelper::getColor().invertedColor();
294  darkerColor = GLHelper::getColor().changedBrightness(-32);
295  }
296  // Draw geometry hints if polygon's shape isn't blocked
297  if (myBlockShape == false) {
298  // draw a boundary for moving using darkerColor
299  glPushMatrix();
300  glTranslated(0, 0, GLO_POLYGON + 0.01);
301  GLHelper::setColor(darkerColor);
303  glPopMatrix();
304  // draw points of shape
305  for (auto i : myShape) {
306  if (!s.drawForSelecting || (myNet->getViewNet()->getPositionInformation().distanceSquaredTo2D(i) <= (circleWidthSquared + 2))) {
307  glPushMatrix();
308  glTranslated(i.x(), i.y(), GLO_POLYGON + 0.02);
309  // Change color of vertex and flag mouseOverVertex if mouse is over vertex
310  if (modeMove && (i.distanceTo(mousePosition) < circleWidth)) {
311  mouseOverVertex = true;
312  GLHelper::setColor(invertedColor);
313  } else {
314  GLHelper::setColor(darkerColor);
315  }
316  GLHelper::drawFilledCircle(circleWidth, circleResolution);
317  glPopMatrix();
318  // draw elevation or special symbols (Start, End and Block)
320  // Push matrix
321  glPushMatrix();
322  // Traslate to center of detector
323  glTranslated(i.x(), i.y(), getType() + 1);
324  // draw Z
325  GLHelper::drawText(toString(i.z()), Position(), .1, 0.7, RGBColor::BLUE);
326  // pop matrix
327  glPopMatrix();
328  } else if ((i == myShape.front()) && !s.drawForSelecting) {
329  // draw a "s" over first point
330  glPushMatrix();
331  glTranslated(i.x(), i.y(), GLO_POLYGON + 0.03);
332  GLHelper::drawText("S", Position(), .1, 2 * circleWidth, invertedColor);
333  glPopMatrix();
334  } else if ((i == myShape.back()) && (myClosedShape == false) && !s.drawForSelecting) {
335  // draw a "e" over last point if polygon isn't closed
336  glPushMatrix();
337  glTranslated(i.x(), i.y(), GLO_POLYGON + 0.03);
338  GLHelper::drawText("E", Position(), .1, 2 * circleWidth, invertedColor);
339  glPopMatrix();
340  }
341  }
342  }
343  // check if draw moving hint has to be drawed
344  if (modeMove && (mouseOverVertex == false) && (myBlockMovement == false) && (distanceToShape < circleWidth)) {
345  // push matrix
346  glPushMatrix();
347  Position hintPos = myShape.size() > 1 ? myShape.positionAtOffset2D(myShape.nearest_offset_to_point2D(mousePosition)) : myShape[0];
348  glTranslated(hintPos.x(), hintPos.y(), GLO_POLYGON + 0.04);
349  GLHelper::setColor(invertedColor);
350  GLHelper:: drawFilledCircle(circleWidth, circleResolution);
351  glPopMatrix();
352  }
353  }
354  }
355  // check if dotted contour has to be drawn
356  if (myNet->getViewNet()->getDottedAC() == this) {
358  }
359  // pop name
360  glPopName();
361 }
362 
363 
364 int
365 GNEPoly::getVertexIndex(Position pos, bool createIfNoExist, bool snapToGrid) {
366  // check if position has to be snapped to grid
367  if (snapToGrid) {
368  pos = myNet->getViewNet()->snapToActiveGrid(pos);
369  }
370  // first check if vertex already exists
371  for (auto i : myShape) {
372  if (i.distanceTo2D(pos) < myHintSize) {
373  return myShape.indexOfClosest(i);
374  }
375  }
376  // if vertex doesn't exist, insert it
377  if (createIfNoExist) {
378  return myShape.insertAtClosest(pos);
379  } else {
380  return -1;
381  }
382 }
383 
384 
385 void
386 GNEPoly::deleteGeometryPoint(const Position& pos, bool allowUndo) {
387  if (myShape.size() > 1) {
388  // obtain index
389  PositionVector modifiedShape = myShape;
390  int index = modifiedShape.indexOfClosest(pos);
391  // remove point dependending of
392  if (myClosedShape && (index == 0 || index == (int)modifiedShape.size() - 1) && (myShape.size() > 2)) {
393  modifiedShape.erase(modifiedShape.begin());
394  modifiedShape.erase(modifiedShape.end() - 1);
395  modifiedShape.push_back(modifiedShape.front());
396  } else {
397  modifiedShape.erase(modifiedShape.begin() + index);
398  }
399  // set new shape depending of allowUndo
400  if (allowUndo) {
401  myNet->getViewNet()->getUndoList()->p_begin("delete geometry point");
404  } else {
405  // first remove object from grid due shape is used for boundary
407  // set new shape
408  myShape = modifiedShape;
409  // Check if new shape is closed
410  myClosedShape = (myShape.front() == myShape.back());
411  // disable simplified shape flag
412  mySimplifiedShape = false;
413  // add object into grid again
414  myNet->addGLObjectIntoGrid(this);
415  }
416  } else {
417  WRITE_WARNING("Number of remaining points insufficient")
418  }
419 }
420 
421 
422 bool
424  return myBlockShape;
425 }
426 
427 
428 bool
430  return myClosedShape;
431 }
432 
433 
434 void
436  if (element) {
437  myNetElementShapeEdited = element;
438  } else {
439  throw InvalidArgument("Junction cannot be nullptr");
440  }
441 }
442 
443 
447 }
448 
449 
450 void
451 GNEPoly::openPolygon(bool allowUndo) {
452  // only open if shape is closed
453  if (myClosedShape) {
454  if (allowUndo) {
455  myNet->getViewNet()->getUndoList()->p_begin("open polygon");
458  } else {
459  myClosedShape = false;
460  myShape.pop_back();
461  // disable simplified shape flag
462  mySimplifiedShape = false;
463  // update geometry to avoid grabbing Problems
464  updateGeometry(true);
465  }
466  } else {
467  WRITE_WARNING("Polygon already opened")
468  }
469 }
470 
471 
472 void
473 GNEPoly::closePolygon(bool allowUndo) {
474  // only close if shape is opened
475  if (myClosedShape == false) {
476  if (allowUndo) {
477  myNet->getViewNet()->getUndoList()->p_begin("close shape");
480  } else {
481  myClosedShape = true;
483  // disable simplified shape flag
484  mySimplifiedShape = false;
485  // update geometry to avoid grabbing Problems
486  updateGeometry(true);
487  }
488  } else {
489  WRITE_WARNING("Polygon already closed")
490  }
491 }
492 
493 
494 void
495 GNEPoly::changeFirstGeometryPoint(int oldIndex, bool allowUndo) {
496  // check that old index is correct
497  if (oldIndex >= (int)myShape.size()) {
498  throw InvalidArgument("Invalid old Index");
499  } else if (oldIndex == 0) {
500  WRITE_WARNING("Selected point must be different of the first point")
501  } else {
502  // Configure new shape
503  PositionVector newShape;
504  for (int i = oldIndex; i < (int)myShape.size(); i++) {
505  newShape.push_back(myShape[i]);
506  }
507  if (myClosedShape) {
508  for (int i = 1; i < oldIndex; i++) {
509  newShape.push_back(myShape[i]);
510  }
511  newShape.push_back(newShape.front());
512  } else {
513  for (int i = 0; i < oldIndex; i++) {
514  newShape.push_back(myShape[i]);
515  }
516  }
517  // set new rotated shape
518  if (allowUndo) {
519  myNet->getViewNet()->getUndoList()->p_begin("change first geometry point");
522  } else {
523  // set new shape
524  myShape = newShape;
525  // Check if new shape is closed
526  myClosedShape = (myShape.front() == myShape.back());
527  // disable simplified shape flag
528  mySimplifiedShape = false;
529  // update geometry to avoid grabbing Problems
530  updateGeometry(true);
531  }
532  }
533 }
534 
535 
536 void
537 GNEPoly::simplifyShape(bool allowUndo) {
538  if (!mySimplifiedShape && myShape.size() > 2) {
539  const Boundary b = myShape.getBoxBoundary();
540  PositionVector simplifiedShape;
541  if (myShape.isClosed()) {
542  // create a square as simplified shape
543  simplifiedShape.push_back(Position(b.xmin(), b.ymin()));
544  simplifiedShape.push_back(Position(b.xmin(), b.ymax()));
545  simplifiedShape.push_back(Position(b.xmax(), b.ymax()));
546  simplifiedShape.push_back(Position(b.xmax(), b.ymin()));
547  simplifiedShape.push_back(simplifiedShape[0]);
548  } else {
549  // create a line as simplified shape
550  simplifiedShape.push_back(myShape.front());
551  simplifiedShape.push_back(myShape.back());
552  }
553  // set new shape depending of allowUndo
554  if (allowUndo) {
555  myNet->getViewNet()->getUndoList()->p_begin("simplify shape");
558  } else {
559  // set new shape
560  myShape = simplifiedShape;
561  // Check if new shape is closed
562  myClosedShape = (myShape.front() == myShape.back());
563  // update geometry to avoid grabbing Problems
564  updateGeometry(true);
565  }
566  // change flag after setting simplified shape
567  mySimplifiedShape = true;
568  } else {
569  WRITE_WARNING("Polygon already simplified")
570  }
571 }
572 
573 
574 std::string
576  switch (key) {
577  case SUMO_ATTR_ID:
578  return myID;
579  case SUMO_ATTR_SHAPE:
580  return toString(myShape);
581  case SUMO_ATTR_GEOSHAPE:
583  case SUMO_ATTR_COLOR:
584  return toString(getShapeColor());
585  case SUMO_ATTR_FILL:
586  return toString(myFill);
587  case SUMO_ATTR_LINEWIDTH:
588  return toString(myLineWidth);
589  case SUMO_ATTR_LAYER:
591  return "default";
592  } else {
593  return toString(getShapeLayer());
594  }
595  case SUMO_ATTR_TYPE:
596  return getShapeType();
597  case SUMO_ATTR_IMGFILE:
598  return getShapeImgFile();
600  return toString(getShapeRelativePath());
601  case SUMO_ATTR_ANGLE:
602  return toString(getShapeNaviDegree());
603  case SUMO_ATTR_GEO:
604  return toString(myGEO);
606  return toString(myBlockMovement);
608  return toString(myBlockShape);
610  return toString(myClosedShape);
611  case GNE_ATTR_SELECTED:
613  case GNE_ATTR_GENERIC:
614  return getGenericParametersStr();
615  default:
616  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
617  }
618 }
619 
620 
621 void
622 GNEPoly::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
623  if (value == getAttribute(key)) {
624  return; //avoid needless changes, later logic relies on the fact that attributes have changed
625  }
626  switch (key) {
627  case SUMO_ATTR_ID:
628  case SUMO_ATTR_SHAPE:
629  case SUMO_ATTR_GEOSHAPE:
630  case SUMO_ATTR_COLOR:
631  case SUMO_ATTR_FILL:
632  case SUMO_ATTR_LINEWIDTH:
633  case SUMO_ATTR_LAYER:
634  case SUMO_ATTR_TYPE:
635  case SUMO_ATTR_IMGFILE:
637  case SUMO_ATTR_ANGLE:
638  case SUMO_ATTR_GEO:
642  case GNE_ATTR_SELECTED:
643  case GNE_ATTR_GENERIC:
644  undoList->p_add(new GNEChange_Attribute(this, key, value));
645  break;
646  default:
647  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
648  }
649 }
650 
651 
652 bool
653 GNEPoly::isValid(SumoXMLAttr key, const std::string& value) {
654  switch (key) {
655  case SUMO_ATTR_ID:
656  return SUMOXMLDefinitions::isValidNetID(value) && (myNet->retrievePolygon(value, false) == nullptr);
657  case SUMO_ATTR_SHAPE:
658  case SUMO_ATTR_GEOSHAPE:
659  // empty shapes AREN'T allowed
660  if (value.empty()) {
661  return false;
662  } else {
663  return canParse<PositionVector>(value);
664  }
665  case SUMO_ATTR_COLOR:
666  return canParse<RGBColor>(value);
667  case SUMO_ATTR_FILL:
668  return canParse<bool>(value);
669  case SUMO_ATTR_LINEWIDTH:
670  return canParse<double>(value) && (parse<double>(value) >= 0);
671  case SUMO_ATTR_LAYER:
672  if (value == "default") {
673  return true;
674  } else {
675  return canParse<double>(value);
676  }
677  case SUMO_ATTR_TYPE:
678  return true;
679  case SUMO_ATTR_IMGFILE:
680  if (value == "") {
681  return true;
682  } else {
683  // check that image can be loaded
684  return GUITexturesHelper::getTextureID(value) != -1;
685  }
687  return canParse<bool>(value);
688  case SUMO_ATTR_ANGLE:
689  return canParse<double>(value);
690  case SUMO_ATTR_GEO:
691  return canParse<bool>(value);
693  return canParse<bool>(value);
695  return canParse<bool>(value);
697  if (canParse<bool>(value)) {
698  bool closePolygon = parse<bool>(value);
699  if (closePolygon && (myShape.begin() == myShape.end())) {
700  // Polygon already closed, then invalid value
701  return false;
702  } else if (!closePolygon && (myShape.begin() != myShape.end())) {
703  // Polygon already open, then invalid value
704  return false;
705  } else {
706  return true;
707  }
708  } else {
709  return false;
710  }
711  case GNE_ATTR_SELECTED:
712  return canParse<bool>(value);
713  case GNE_ATTR_GENERIC:
714  return isGenericParametersValid(value);
715  default:
716  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
717  }
718 }
719 
720 
721 std::string
723  std::string result;
724  // Generate an string using the following structure: "key1=value1|key2=value2|...
725  for (auto i : getParametersMap()) {
726  result += i.first + "=" + i.second + "|";
727  }
728  // remove the last "|"
729  if (!result.empty()) {
730  result.pop_back();
731  }
732  return result;
733 }
734 
735 
736 std::vector<std::pair<std::string, std::string> >
738  std::vector<std::pair<std::string, std::string> > result;
739  // iterate over parameters map and fill result
740  for (auto i : getParametersMap()) {
741  result.push_back(std::make_pair(i.first, i.second));
742  }
743  return result;
744 }
745 
746 
747 void
748 GNEPoly::setGenericParametersStr(const std::string& value) {
749  // clear parameters
750  clearParameter();
751  // separate value in a vector of string using | as separator
752  std::vector<std::string> parsedValues;
753  StringTokenizer stValues(value, "|", true);
754  while (stValues.hasNext()) {
755  parsedValues.push_back(stValues.next());
756  }
757  // check that parsed values (A=B)can be parsed in generic parameters
758  for (auto i : parsedValues) {
759  std::vector<std::string> parsedParameters;
760  StringTokenizer stParam(i, "=", true);
761  while (stParam.hasNext()) {
762  parsedParameters.push_back(stParam.next());
763  }
764  // Check that parsed parameters are exactly two and contains valid chracters
765  if (parsedParameters.size() == 2 && SUMOXMLDefinitions::isValidGenericParameterKey(parsedParameters.front()) && SUMOXMLDefinitions::isValidGenericParameterValue(parsedParameters.back())) {
766  setParameter(parsedParameters.front(), parsedParameters.back());
767  }
768  }
769 }
770 
771 // ===========================================================================
772 // private
773 // ===========================================================================
774 
775 void
776 GNEPoly::setAttribute(SumoXMLAttr key, const std::string& value) {
777  // first remove object from grid due almost modificactions affects to boundary (but avoided for certain attributes)
778  if((key != SUMO_ATTR_ID) && (key != GNE_ATTR_GENERIC) && (key != GNE_ATTR_SELECTED)) {
780  }
781  switch (key) {
782  case SUMO_ATTR_ID: {
783  std::string oldID = myID;
784  myID = value;
785  myNet->changeShapeID(this, oldID);
786  setMicrosimID(value);
787  break;
788  }
789  case SUMO_ATTR_SHAPE: {
790  // set new shape
791  myShape = parse<PositionVector>(value);
792  // set GEO shape
794  for (int i = 0; i < (int) myGeoShape.size(); i++) {
795  GeoConvHelper::getFinal().cartesian2geo(myGeoShape[i]);
796  }
797  // Check if new shape is closed
798  myClosedShape = (myShape.front() == myShape.back());
799  // disable simplified shape flag
800  mySimplifiedShape = false;
801  // update geometry of shape edited element
804  }
805  break;
806  }
807  case SUMO_ATTR_GEOSHAPE: {
808  // set new GEO shape
809  myGeoShape = parse<PositionVector>(value);
810  // set shape
811  myShape = myGeoShape ;
812  for (int i = 0; i < (int) myShape.size(); i++) {
814  }
815  // Check if new shape is closed
816  myClosedShape = (myShape.front() == myShape.back());
817  // disable simplified shape flag
818  mySimplifiedShape = false;
819  // update geometry of shape edited element
822  }
823  break;
824  }
825  case SUMO_ATTR_COLOR:
826  setShapeColor(parse<RGBColor>(value));
827  break;
828  case SUMO_ATTR_FILL:
829  myFill = parse<bool>(value);
830  break;
831  case SUMO_ATTR_LINEWIDTH:
832  myLineWidth = parse<double>(value);
833  break;
834  case SUMO_ATTR_LAYER:
835  if (value == "default") {
837  } else {
838  setShapeLayer(parse<double>(value));
839  }
840  break;
841  case SUMO_ATTR_TYPE:
842  setShapeType(value);
843  break;
844  case SUMO_ATTR_IMGFILE:
845  setShapeImgFile(value);
846  // all textures must be refresh
848  break;
850  setShapeRelativePath(parse<bool>(value));
851  break;
852  case SUMO_ATTR_ANGLE:
853  setShapeNaviDegree(parse<double>(value));
854  break;
855  case SUMO_ATTR_GEO:
856  myGEO = parse<bool>(value);
857  break;
859  myBlockMovement = parse<bool>(value);
860  break;
862  myBlockShape = parse<bool>(value);
863  break;
865  myClosedShape = parse<bool>(value);
866  if (myClosedShape) {
869  } else {
870  myShape.pop_back();
871  myGeoShape.pop_back();
872  }
873  // disable simplified shape flag
874  mySimplifiedShape = false;
875  break;
876  case GNE_ATTR_SELECTED:
877  if (parse<bool>(value)) {
879  } else {
881  }
882  break;
883  case GNE_ATTR_GENERIC:
885  break;
886  default:
887  throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
888  }
889  // add object into grid again (but avoided for certain attributes)
890  if((key != SUMO_ATTR_ID) && (key != GNE_ATTR_GENERIC) && (key != GNE_ATTR_SELECTED)) {
891  myNet->addGLObjectIntoGrid(this);
892  }
893 }
894 
895 
896 void
898  // only continue if there isn't already a AC under cursor
899  if (myNet->getViewNet()->getDottedAC() == nullptr) {
900  // check if cursor is within the shape
902  myNet->getViewNet()->setDottedAC(this);
903  }
904  }
905 }
906 
907 
908 /****************************************************************************/
bool around(const Position &p, double offset=0) const
Returns the information whether the position vector describes a polygon lying around the given point...
PositionVector myShape
The positions of the polygon.
Definition: SUMOPolygon.h:132
void endGeometryMoving()
begin movement (used when user click over edge to start a movement, to avoid problems with problems w...
Definition: GNEPoly.cpp:79
static const RGBColor BLUE
Definition: RGBColor.h:186
double myLineWidth
The line width for drawing an unfilled polygon.
Definition: SUMOPolygon.h:141
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:131
void openPolygon(bool allowUndo=true)
open polygon
Definition: GNEPoly.cpp:451
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:125
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:135
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition: RGBColor.cpp:154
a polygon
mode for moving things
Definition: GNEViewNet.h:48
std::string next()
bool myFill
Information whether the polygon has to be filled.
Definition: SUMOPolygon.h:138
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:178
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) ...
block shape of a graphic element (Used mainly in GNEShapes)
std::string getParentName() const
Returns the name of the parent object.
Definition: GNEPoly.cpp:202
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:158
virtual void updateGeometry(bool updateGrid)=0
update pre-computed geometry information
A layer number.
Boundary myMovingGeometryBoundary
boundary used during moving of elements
Definition: GNEShape.h:168
Stores the information about how to visualize structures.
bool isPolygonClosed() const
check if polygon is closed
Definition: GNEPoly.cpp:429
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:128
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:146
Position snapToActiveGrid(const Position &pos) const
Returns a position that is mapped to the closest grid point if the grid is active.
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:611
GNEPoly * retrievePolygon(const std::string &id, bool failHard=true) const
get Polygon by id
Definition: GNENet.cpp:933
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:77
const PositionVector & getShape() const
Returns whether the shape of the polygon.
Definition: SUMOPolygon.h:81
bool mySimplifiedShape
flag to indicate if polygon is simplified
Definition: GNEPoly.h:240
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.
PositionVector myGeoShape
Latitude of Polygon.
Definition: GNEPoly.h:231
void buildShowParamsPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to open the parameter window.
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:344
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:165
close opened polygon
Definition: GUIAppEnum.h:762
generic attribute
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
void selectAttributeCarrier(bool changeFlag=true)
Definition: GNEShape.cpp:96
void closePolygon(bool allowUndo=true)
close polygon
Definition: GNEPoly.cpp:473
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
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:151
void p_add(GNEChange_Attribute *cmd)
special method, avoid empty changes, always execute
static void clearTextures()
clears loaded textures
GNENetElement * myNetElementShapeEdited
junction of which the shape is being edited (optional)
Definition: GNEPoly.h:228
GNEUndoList * getUndoList() const
get the undoList object
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:423
bool getShapeRelativePath() const
Returns the relativePath of the Shape.
Definition: Shape.h:111
void startGeometryMoving()
Definition: GNEPoly.cpp:72
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:49
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:573
bool myBlockMovement
flag to block movement
Definition: GNEShape.h:171
void writeShape(OutputDevice &device)
writte shape element into a xml file
Definition: GNEPoly.cpp:184
void setGenericParametersStr(const std::string &value)
set generic parameters in string format
Definition: GNEPoly.cpp:748
void mouseOverObject(const GUIVisualizationSettings &s) const
method for check if mouse is over objects
Definition: GNEPoly.cpp:897
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
int gPrecisionGeo
Definition: StdDefs.cpp:28
A list of positions.
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:1160
static const double myHintSize
hint size of vertex
Definition: GNEPoly.h:247
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:243
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
RGBColor selectionColor
NETEDIT special colors.
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
Definition: GUIPolygon.cpp:122
void setDottedAC(const GNEAttributeCarrier *AC)
set attributeCarrier under cursor
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEPoly.cpp:269
T MIN2(T a, T b)
Definition: StdDefs.h:70
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.
bool isValid(SumoXMLAttr key, const std::string &value)
method for checking if the key and their conrrespond attribute are valids
Definition: GNEPoly.cpp:653
void deleteGeometryPoint(const Position &pos, bool allowUndo=true)
delete the geometry point closest to the given pos
Definition: GNEPoly.cpp:386
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:622
void changeShapeID(GNEShape *s, const std::string &OldID)
change Shape ID
Definition: GNENet.cpp:2034
void drawInnerPolygon(const GUIVisualizationSettings &s) const
draw inner Polygon (before pushName() )
Definition: GUIPolygon.cpp:258
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEPoly.cpp:575
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNEPoly.cpp:212
double getShapeLayer() const
Returns the layer of the Shape.
Definition: Shape.h:90
EditMode getCurrentEditMode() const
get the current edit mode
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
void reset()
Resets the boundary.
Definition: Boundary.cpp:67
std::string myID
The name of the object.
Definition: Named.h:130
int moveVertexShape(const int index, const Position &oldPos, const Position &offset)
change position of a vertex of shape without commiting change
Definition: GNEPoly.cpp:95
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:617
Set a vertex of polygon as first verte.
Definition: GUIAppEnum.h:766
void setShapeEditedElement(GNENetElement *element)
retrieve the netElement of which the shape is being edited
Definition: GNEPoly.cpp:435
void simplifyShape(bool allowUndo=true)
replace the current shape with a rectangle
Definition: GNEPoly.cpp:537
Position getPositionInView() const
Returns position of additional in view.
Definition: GNEPoly.cpp:190
virtual void setMicrosimID(const std::string &newID)
Changes the microsimID of the object.
static void drawShapeDottedContour(const int type, const PositionVector &shape, const double width)
draw a dotted contour around the given Non closed shape with certain width
Definition: GLHelper.cpp:471
const GNEAttributeCarrier * getDottedAC() const
get AttributeCarrier under cursor
bool editingElevation() const
return true if elevation is being edited
Definition: GNEViewNet.cpp:739
GUIGlID getGlID() const
Returns the numerical id of the object.
Definition: GNEPoly.cpp:196
const std::string & getTagStr() const
get tag assigned to this object in string format
simplify polygon geometry
Definition: GUIAppEnum.h:760
bool isClosed() const
check if PositionVector is closed
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
Definition: GNEPoly.cpp:252
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:445
static int getCircleResolution(const GUIVisualizationSettings &settings)
function to calculate circle resolution for all circles drawn in drawGL(...) functions ...
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:112
std::vector< std::pair< std::string, std::string > > getGenericParameters() const
return generic parameters as vector of pairs format
Definition: GNEPoly.cpp:737
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:51
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
bool myBlockShape
flag for block shape
Definition: GNEPoly.h:234
Position getPositionInformation() const
Returns the cursor&#39;s x/y position within the network.
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
open closed polygon
Definition: GUIAppEnum.h:764
bool myClosedShape
flag to indicate if polygon is open or closed
Definition: GNEPoly.h:237
std::string getGenericParametersStr() const
return generic parameters in string format
Definition: GNEPoly.cpp:722
void add(double xoff, double yoff, double zoff)
bool drawForSelecting
whether drawing is performed for the purpose of selecting objects
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
void closePolygon()
ensures that the last position equals the first
void addGLObjectIntoGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1153
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:495
void setShapeLayer(const double layer)
Sets a new layer.
Definition: Shape.h:137
void updateGeometry(bool updateGrid)
update pre-computed geometry information
Definition: GNEPoly.cpp:179
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:365
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:258
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1730
void moveEntireShape(const PositionVector &oldShape, const Position &offset)
move entire shape without commiting change
Definition: GNEPoly.cpp:130
static const double DEFAULT_LAYER
Definition: Shape.h:44
void setShapeNaviDegree(const double angle)
Sets a new angle in navigational degrees.
Definition: Shape.h:144
void clearParameter()
Clears the parameter map.
static RGBColor getColor()
gets the gl-color
Definition: GLHelper.cpp:579