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 <config.h>
24 
25 #include <string>
26 #include <utility>
29 #include <utils/geom/Position.h>
33 #include <utils/xml/XMLSubSys.h>
39 #include <utils/gui/div/GLHelper.h>
45 #include <netwrite/NWWriter_SUMO.h>
46 #include <netedit/GNENet.h>
48 #include <netedit/GNEUndoList.h>
49 #include <netedit/GNEViewNet.h>
52 #include <netedit/GNEViewParent.h>
53 
54 #include "GNEPoly.h"
55 
56 
57 // ===========================================================================
58 // static members
59 // ===========================================================================
60 
61 const double GNEPoly::myHintSize = 0.8;
62 const double GNEPoly::myHintSizeSquared = 0.64;
63 
64 // ===========================================================================
65 // method definitions
66 // ===========================================================================
67 GNEPoly::GNEPoly(GNENet* net, const std::string& id, const std::string& type, const PositionVector& shape, bool geo, bool fill,
68  const RGBColor& color, double layer, double angle, const std::string& imgFile, bool relativePath, bool movementBlocked, bool shapeBlocked) :
69  GUIPolygon(id, type, color, shape, geo, fill, layer, angle, imgFile, relativePath),
70  GNEShape(net, SUMO_TAG_POLY, movementBlocked, shapeBlocked),
71  myNetElementShapeEdited(nullptr),
72  myClosedShape(shape.front() == shape.back()),
73  mySimplifiedShape(false),
74  myCurrentMovingVertexIndex(-1) {
75  // check if imgFile is valid
76  if (!imgFile.empty() && GUITexturesHelper::getTextureID(imgFile) == -1) {
77  setShapeImgFile("");
78  }
79  // set GEO shape
81  for (int i = 0; i < (int) myGeoShape.size(); i++) {
83  }
84 }
85 
86 
88 
89 
90 void
92  // nothing to do (will be used in future implementations)
93 }
94 
95 
96 void
98  // nothing to do (will be used in future implementations)
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  // Declare value for saving Z value (needed because movement is only in X-Y)
111  double zValue = 0;
112  // if closed shape and cliked is first or last, move both giving more priority to first always
113  if (myClosedShape && (index == 0 || index == (int)myShape.size() - 1)) {
114  // save Z value of first shape Geometry Point
115  zValue = myShape.front().z();
116  // Change position of first shape Geometry Point
117  myShape.front() = oldPos;
118  myShape.front().add(offset);
119  // restore Z value of first shape Geometry Point
120  myShape.front().setz(zValue);
121  // save Z value of last shape Geometry Point
122  zValue = myShape.back().z();
123  // Change position of last shape Geometry Point
124  myShape.back() = oldPos;
125  myShape.back().add(offset);
126  // restore Z value of last shape Geometry Point
127  myShape.back().setz(zValue);
128  } else {
129  // save Z value of Geometry Point
130  zValue = myShape.back().z();
131  // change position of Geometry Point
132  myShape[index] = oldPos;
133  myShape[index].add(offset);
134  // restore Z value of Geometry Point
135  myShape.back().setz(zValue);
136  }
137  // return index of moved Geometry Point
138  return index;
139  } else {
140  throw InvalidArgument("Index greater than shape size");
141  }
142  } else {
143  return index;
144  }
145 }
146 
147 
148 void
149 GNEPoly::moveEntireShape(const PositionVector& oldShape, const Position& offset) {
150  // only move shape if block movement is disabled and block shape is enabled
151  if (!myBlockMovement && myBlockShape) {
152  // restore original shape
153  myShape = oldShape;
154  // change all points of the shape shape using offset
155  for (auto& i : myShape) {
156  i.add(offset);
157  }
158  // update Geometry after moving
159  updateGeometry(true);
160  }
161 }
162 
163 
164 void
166  if (!myBlockMovement) {
167  // disable current moving vertex
169  // restore original shape into shapeToCommit
170  PositionVector shapeToCommit = myShape;
171  // restore old shape in polygon (to avoid problems with RTree)
172  myShape = oldShape;
173  // first check if double points has to be removed
174  shapeToCommit.removeDoublePoints(myHintSize);
175  if (shapeToCommit.size() != myShape.size()) {
176  WRITE_WARNING("Merged shape's point")
177  }
178  // check if polygon has to be closed
179  if (shapeToCommit.size() > 1 && shapeToCommit.front().distanceTo2D(shapeToCommit.back()) < (2 * myHintSize)) {
180  shapeToCommit.pop_back();
181  shapeToCommit.push_back(shapeToCommit.front());
182  }
183  // only use GNEChange_Attribute if we aren't editing a junction's shape
184  if (myNetElementShapeEdited == nullptr) {
185  // commit new shape
186  undoList->p_begin("moving " + toString(SUMO_ATTR_SHAPE) + " of " + toString(getTag()));
187  undoList->p_add(new GNEChange_Attribute(this, SUMO_ATTR_SHAPE, toString(shapeToCommit)));
188  undoList->p_end();
189  } else {
190  // set new shape calling private setAttribute function
191  setAttribute(SUMO_ATTR_SHAPE, toString(shapeToCommit));
192  }
193  }
194 }
195 
196 
197 void
198 GNEPoly::updateGeometry(bool /*updateGrid*/) {
199  // nothing to do
200 }
201 
202 void
204  writeXML(device, myGEO);
205 }
206 
207 
208 Position
210  return myShape.getPolygonCenter();
211 }
212 
213 
214 GUIGlID
216  return GUIPolygon::getGlID();
217 }
218 
219 
220 std::string
222  if (myNetElementShapeEdited != nullptr) {
224  } else {
225  return myNet->getMicrosimID();
226  }
227 }
228 
229 
232  GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
233  buildPopupHeader(ret, app);
236  // build selection and show parameters menu
239  FXMenuCommand* simplifyShape = new FXMenuCommand(ret, "Simplify Shape\t\tReplace current shape with a rectangle", 0, &parent, MID_GNE_POLYGON_SIMPLIFY_SHAPE);
240  // disable simplify shape if polygon was already simplified
241  if (mySimplifiedShape || myShape.size() <= 2) {
242  simplifyShape->disable();
243  }
244  // create open or close polygon's shape only if myNetElementShapeEdited is nullptr
245  if (myNetElementShapeEdited == nullptr) {
246  if (myClosedShape) {
247  new FXMenuCommand(ret, "Open shape\t\tOpen polygon's shape", 0, &parent, MID_GNE_POLYGON_OPEN);
248  } else {
249  new FXMenuCommand(ret, "Close shape\t\tClose polygon's shape", 0, &parent, MID_GNE_POLYGON_CLOSE);
250  }
251  }
252  // create a extra FXMenuCommand if mouse is over a vertex
253  int index = getVertexIndex(myNet->getViewNet()->getPositionInformation(), false);
254  if (index != -1) {
255  FXMenuCommand* removeGeometryPoint = new FXMenuCommand(ret, "Remove geometry point\t\tRemove geometry point under mouse", 0, &parent, MID_GNE_POLYGON_DELETE_GEOMETRY_POINT);
256  FXMenuCommand* setFirstPoint = new FXMenuCommand(ret, "Set first geometry point\t\tSet", 0, &parent, MID_GNE_POLYGON_SET_FIRST_POINT);
257  // disable setFirstPoint if shape only have three points
258  if ((myClosedShape && (myShape.size() <= 4)) || (!myClosedShape && (myShape.size() <= 2))) {
259  removeGeometryPoint->disable();
260  }
261  // disable setFirstPoint if mouse is over first point
262  if (index == 0) {
263  setFirstPoint->disable();
264  }
265  }
266  return ret;
267 }
268 
269 
272  return GUIPolygon::getParameterWindow(app, parent);
273 }
274 
275 
276 Boundary
279 }
280 
281 
282 void
284  /*
285  // first call function mouseOverObject (to check if this object is under cursor)
286  // @note currently disabled. It will be implemented in an different ticket of #2905
287  mouseOverObject(s);
288  */
289  // simply use GUIPolygon::drawGL
291  int circleResolution = GNEAttributeCarrier::getCircleResolution(s);
292  // push matrix
293  glPushName(getGlID());
294  // draw geometry details hints if is not too small and isn't in selecting mode
295  if (s.scale * myHintSize > 1.) {
296  // set values relative to mouse position regarding to shape
297  bool mouseOverVertex = false;
298  bool modeMove = myNet->getViewNet()->getCurrentEditMode() == GNE_MODE_MOVE;
299  Position mousePosition = myNet->getViewNet()->getPositionInformation();
300  double distanceToShape = myShape.distance2D(mousePosition);
301  // set colors
302  RGBColor invertedColor, darkerColor;
304  invertedColor = myNet->selectionColor.invertedColor();
305  darkerColor = myNet->selectedLaneColor;
306  } else {
307  invertedColor = GLHelper::getColor().invertedColor();
308  darkerColor = GLHelper::getColor().changedBrightness(-32);
309  }
310  // Draw geometry hints if polygon's shape isn't blocked
311  if (myBlockShape == false) {
312  // draw a boundary for moving using darkerColor
313  glPushMatrix();
314  glTranslated(0, 0, GLO_POLYGON + 0.01);
315  GLHelper::setColor(darkerColor);
317  glPopMatrix();
318  // draw points of shape
319  for (auto i : myShape) {
321  glPushMatrix();
322  glTranslated(i.x(), i.y(), GLO_POLYGON + 0.02);
323  // Change color of vertex and flag mouseOverVertex if mouse is over vertex
324  if (modeMove && (i.distanceTo(mousePosition) < myHintSize)) {
325  mouseOverVertex = true;
326  GLHelper::setColor(invertedColor);
327  } else {
328  GLHelper::setColor(darkerColor);
329  }
330  GLHelper::drawFilledCircle(myHintSize, circleResolution);
331  glPopMatrix();
332  // draw special symbols (Start, End and Block)
333  if ((i == myShape.front()) && !s.drawForSelecting) {
334  // draw a "s" over first point
335  glPushMatrix();
336  glTranslated(i.x(), i.y(), GLO_POLYGON + 0.03);
337  GLHelper::drawText("S", Position(), .1, 2 * myHintSize, invertedColor);
338  glPopMatrix();
339  } else if ((i == myShape.back()) && (myClosedShape == false) && !s.drawForSelecting) {
340  // draw a "e" over last point if polygon isn't closed
341  glPushMatrix();
342  glTranslated(i.x(), i.y(), GLO_POLYGON + 0.03);
343  GLHelper::drawText("E", Position(), .1, 2 * myHintSize, invertedColor);
344  glPopMatrix();
345  }
346  }
347  }
348  // check if draw moving hint has to be drawed
349  if (modeMove && (mouseOverVertex == false) && (myBlockMovement == false) && (distanceToShape < myHintSize)) {
350  // push matrix
351  glPushMatrix();
352  Position hintPos = myShape.size() > 1 ? myShape.positionAtOffset2D(myShape.nearest_offset_to_point2D(mousePosition)) : myShape[0];
353  glTranslated(hintPos.x(), hintPos.y(), GLO_POLYGON + 0.04);
354  GLHelper::setColor(invertedColor);
355  GLHelper:: drawFilledCircle(myHintSize, circleResolution);
356  glPopMatrix();
357  }
358  }
359  }
360  // check if dotted contour has to be drawn
361  if (myNet->getViewNet()->getACUnderCursor() == this) {
363  }
364  // pop name
365  glPopName();
366 }
367 
368 
369 int
370 GNEPoly::getVertexIndex(const Position& pos, bool createIfNoExist) {
371  // first check if vertex already exists
372  for (auto i : myShape) {
373  if (i.distanceTo2D(pos) < myHintSize) {
374  return myShape.indexOfClosest(i);
375  }
376  }
377  // if vertex doesn't exist, insert it
378  if (createIfNoExist && (myShape.distance2D(pos) < myHintSize)) {
379  return myShape.insertAtClosest(pos);
380  } else {
381  return -1;
382  }
383 }
384 
385 
386 void
387 GNEPoly::deleteGeometryPoint(const Position& pos, bool allowUndo) {
388  if (myShape.size() > 1) {
389  // obtain index
390  PositionVector modifiedShape = myShape;
391  int index = modifiedShape.indexOfClosest(pos);
392  // remove point dependending of
393  if (myClosedShape && (index == 0 || index == (int)modifiedShape.size() - 1)) {
394  modifiedShape.erase(modifiedShape.begin());
395  modifiedShape.erase(modifiedShape.end() - 1);
396  myShape.push_back(modifiedShape.front());
397  } else {
398  modifiedShape.erase(modifiedShape.begin() + index);
399  }
400  // set new shape depending of allowUndo
401  if (allowUndo) {
402  myNet->getViewNet()->getUndoList()->p_begin("delete geometry point");
405  } else {
406  // first remove object from grid due shape is used for boundary
408  // set new shape
409  myShape = modifiedShape;
410  // Check if new shape is closed
411  myClosedShape = (myShape.front() == myShape.back());
412  // disable simplified shape flag
413  mySimplifiedShape = false;
414  // add object into grid again
415  myNet->addGLObjectIntoGrid(this);
416  }
417  } else {
418  WRITE_WARNING("Number of remaining points insufficient")
419  }
420 }
421 
422 
423 bool
425  return myClosedShape;
426 }
427 
428 
429 void
431  if (element) {
432  myNetElementShapeEdited = element;
433  } else {
434  throw InvalidArgument("Junction cannot be nullptr");
435  }
436 }
437 
438 
442 }
443 
444 
445 void
446 GNEPoly::openPolygon(bool allowUndo) {
447  // only open if shape is closed
448  if (myClosedShape) {
449  if (allowUndo) {
450  myNet->getViewNet()->getUndoList()->p_begin("open polygon");
453  } else {
454  myClosedShape = false;
455  myShape.pop_back();
456  // disable simplified shape flag
457  mySimplifiedShape = false;
458  // update geometry to avoid grabbing Problems
459  updateGeometry(true);
460  }
461  } else {
462  WRITE_WARNING("Polygon already opened")
463  }
464 }
465 
466 
467 void
468 GNEPoly::closePolygon(bool allowUndo) {
469  // only close if shape is opened
470  if (myClosedShape == false) {
471  if (allowUndo) {
472  myNet->getViewNet()->getUndoList()->p_begin("close shape");
475  } else {
476  myClosedShape = true;
478  // disable simplified shape flag
479  mySimplifiedShape = false;
480  // update geometry to avoid grabbing Problems
481  updateGeometry(true);
482  }
483  } else {
484  WRITE_WARNING("Polygon already closed")
485  }
486 }
487 
488 
489 void
490 GNEPoly::changeFirstGeometryPoint(int oldIndex, bool allowUndo) {
491  // check that old index is correct
492  if (oldIndex >= (int)myShape.size()) {
493  throw InvalidArgument("Invalid old Index");
494  } else if (oldIndex == 0) {
495  WRITE_WARNING("Selected point must be different of the first point")
496  } else {
497  // Configure new shape
498  PositionVector newShape;
499  for (int i = oldIndex; i < (int)myShape.size(); i++) {
500  newShape.push_back(myShape[i]);
501  }
502  if (myClosedShape) {
503  for (int i = 1; i < oldIndex; i++) {
504  newShape.push_back(myShape[i]);
505  }
506  newShape.push_back(newShape.front());
507  } else {
508  for (int i = 0; i < oldIndex; i++) {
509  newShape.push_back(myShape[i]);
510  }
511  }
512  // set new rotated shape
513  if (allowUndo) {
514  myNet->getViewNet()->getUndoList()->p_begin("change first geometry point");
517  } else {
518  // set new shape
519  myShape = newShape;
520  // Check if new shape is closed
521  myClosedShape = (myShape.front() == myShape.back());
522  // disable simplified shape flag
523  mySimplifiedShape = false;
524  // update geometry to avoid grabbing Problems
525  updateGeometry(true);
526  }
527  }
528 }
529 
530 
531 void
532 GNEPoly::simplifyShape(bool allowUndo) {
533  if (!mySimplifiedShape && myShape.size() > 2) {
534  const Boundary b = myShape.getBoxBoundary();
535  PositionVector simplifiedShape;
536  if (myShape.isClosed()) {
537  // create a square as simplified shape
538  simplifiedShape.push_back(Position(b.xmin(), b.ymin()));
539  simplifiedShape.push_back(Position(b.xmin(), b.ymax()));
540  simplifiedShape.push_back(Position(b.xmax(), b.ymax()));
541  simplifiedShape.push_back(Position(b.xmax(), b.ymin()));
542  simplifiedShape.push_back(simplifiedShape[0]);
543  } else {
544  // create a line as simplified shape
545  simplifiedShape.push_back(myShape.front());
546  simplifiedShape.push_back(myShape.back());
547  }
548  // set new shape depending of allowUndo
549  if (allowUndo) {
550  myNet->getViewNet()->getUndoList()->p_begin("simplify shape");
553  } else {
554  // set new shape
555  myShape = simplifiedShape;
556  // Check if new shape is closed
557  myClosedShape = (myShape.front() == myShape.back());
558  // update geometry to avoid grabbing Problems
559  updateGeometry(true);
560  }
561  // change flag after setting simplified shape
562  mySimplifiedShape = true;
563  } else {
564  WRITE_WARNING("Polygon already simplified")
565  }
566 }
567 
568 
569 std::string
571  switch (key) {
572  case SUMO_ATTR_ID:
573  return myID;
574  case SUMO_ATTR_SHAPE:
575  return toString(myShape);
576  case SUMO_ATTR_GEOSHAPE:
578  case SUMO_ATTR_COLOR:
579  return toString(getShapeColor());
580  case SUMO_ATTR_FILL:
581  return toString(myFill);
582  case SUMO_ATTR_LAYER:
584  return "default";
585  } else {
586  return toString(getShapeLayer());
587  }
588  case SUMO_ATTR_TYPE:
589  return getShapeType();
590  case SUMO_ATTR_IMGFILE:
591  return getShapeImgFile();
593  return toString(getShapeRelativePath());
594  case SUMO_ATTR_ANGLE:
595  return toString(getShapeNaviDegree());
596  case SUMO_ATTR_GEO:
597  return toString(myGEO);
599  return toString(myBlockMovement);
601  return toString(myBlockShape);
603  return toString(myClosedShape);
604  case GNE_ATTR_SELECTED:
606  case GNE_ATTR_GENERIC:
607  return getGenericParametersStr();
608  default:
609  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
610  }
611 }
612 
613 
614 void
615 GNEPoly::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
616  if (value == getAttribute(key)) {
617  return; //avoid needless changes, later logic relies on the fact that attributes have changed
618  }
619  switch (key) {
620  case SUMO_ATTR_ID:
621  case SUMO_ATTR_SHAPE:
622  case SUMO_ATTR_GEOSHAPE:
623  case SUMO_ATTR_COLOR:
624  case SUMO_ATTR_FILL:
625  case SUMO_ATTR_LAYER:
626  case SUMO_ATTR_TYPE:
627  case SUMO_ATTR_IMGFILE:
629  case SUMO_ATTR_ANGLE:
630  case SUMO_ATTR_GEO:
634  case GNE_ATTR_SELECTED:
635  case GNE_ATTR_GENERIC:
636  undoList->p_add(new GNEChange_Attribute(this, key, value));
637  break;
638  default:
639  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
640  }
641 }
642 
643 
644 bool
645 GNEPoly::isValid(SumoXMLAttr key, const std::string& value) {
646  switch (key) {
647  case SUMO_ATTR_ID:
648  return SUMOXMLDefinitions::isValidNetID(value) && (myNet->retrievePolygon(value, false) == 0);
649  case SUMO_ATTR_SHAPE:
650  case SUMO_ATTR_GEOSHAPE: {
651  bool ok = true;
652  // check if shape can be parsed
653  PositionVector shape = GeomConvHelper::parseShapeReporting(value, "user-supplied position", 0, ok, true);
654  return (shape.size() > 0);
655  }
656  case SUMO_ATTR_COLOR:
657  return canParse<RGBColor>(value);
658  case SUMO_ATTR_FILL:
659  return canParse<bool>(value);
660  case SUMO_ATTR_LAYER:
661  if (value == "default") {
662  return true;
663  } else {
664  return canParse<double>(value);
665  }
666  case SUMO_ATTR_TYPE:
667  return true;
668  case SUMO_ATTR_IMGFILE:
669  if (value == "") {
670  return true;
671  } else {
672  // check that image can be loaded
673  return GUITexturesHelper::getTextureID(value) != -1;
674  }
676  return canParse<bool>(value);
677  case SUMO_ATTR_ANGLE:
678  return canParse<double>(value);
679  case SUMO_ATTR_GEO:
680  return canParse<bool>(value);
682  return canParse<bool>(value);
684  return canParse<bool>(value);
686  if (canParse<bool>(value)) {
687  bool closePolygon = parse<bool>(value);
688  if (closePolygon && (myShape.begin() == myShape.end())) {
689  // Polygon already closed, then invalid value
690  return false;
691  } else if (!closePolygon && (myShape.begin() != myShape.end())) {
692  // Polygon already open, then invalid value
693  return false;
694  } else {
695  return true;
696  }
697  } else {
698  return false;
699  }
700  case GNE_ATTR_SELECTED:
701  return canParse<bool>(value);
702  case GNE_ATTR_GENERIC:
703  return isGenericParametersValid(value);
704  default:
705  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
706  }
707 }
708 
709 
710 bool
711 GNEPoly::addGenericParameter(const std::string& key, const std::string& value) {
712  if (!knowsParameter(key)) {
713  setParameter(key, value);
714  return true;
715  } else {
716  return false;
717  }
718 }
719 
720 
721 bool
722 GNEPoly::removeGenericParameter(const std::string& key) {
723  if (knowsParameter(key)) {
724  unsetParameter(key);
725  return true;
726  } else {
727  return false;
728  }
729 }
730 
731 
732 bool
733 GNEPoly::updateGenericParameter(const std::string& oldKey, const std::string& newKey) {
734  if (knowsParameter(oldKey) && !knowsParameter(newKey)) {
735  std::string value = getParameter(oldKey);
736  unsetParameter(oldKey);
737  setParameter(newKey, value);
738  return true;
739  } else {
740  return false;
741  }
742 }
743 
744 
745 bool
746 GNEPoly::updateGenericParameterValue(const std::string& key, const std::string& newValue) {
747  if (knowsParameter(key)) {
748  setParameter(key, newValue);
749  return true;
750  } else {
751  return false;
752  }
753 }
754 
755 
756 std::string
758  std::string result;
759  // Generate an string using the following structure: "key1=value1|key2=value2|...
760  for (auto i : getParametersMap()) {
761  result += i.first + "=" + i.second + "|";
762  }
763  // remove the last "|"
764  if (!result.empty()) {
765  result.pop_back();
766  }
767  return result;
768 }
769 
770 
771 std::vector<std::pair<std::string, std::string> >
773  std::vector<std::pair<std::string, std::string> > result;
774  // iterate over parameters map and fill result
775  for (auto i : getParametersMap()) {
776  result.push_back(std::make_pair(i.first, i.second));
777  }
778  return result;
779 }
780 
781 
782 void
783 GNEPoly::setGenericParametersStr(const std::string& value) {
784  // clear parameters
785  clearParameter();
786  // separate value in a vector of string using | as separator
787  std::vector<std::string> parsedValues;
788  StringTokenizer stValues(value, "|", true);
789  while (stValues.hasNext()) {
790  parsedValues.push_back(stValues.next());
791  }
792  // check that parsed values (A=B)can be parsed in generic parameters
793  for (auto i : parsedValues) {
794  std::vector<std::string> parsedParameters;
795  StringTokenizer stParam(i, "=", true);
796  while (stParam.hasNext()) {
797  parsedParameters.push_back(stParam.next());
798  }
799  // Check that parsed parameters are exactly two and contains valid chracters
800  if (parsedParameters.size() == 2 && SUMOXMLDefinitions::isValidGenericParameterKey(parsedParameters.front()) && SUMOXMLDefinitions::isValidGenericParameterValue(parsedParameters.back())) {
801  setParameter(parsedParameters.front(), parsedParameters.back());
802  }
803  }
804 }
805 
806 // ===========================================================================
807 // private
808 // ===========================================================================
809 
810 void
811 GNEPoly::setAttribute(SumoXMLAttr key, const std::string& value) {
812  // first remove object from grid due almost modificactions affects to boundary
814  switch (key) {
815  case SUMO_ATTR_ID: {
816  std::string oldID = myID;
817  myID = value;
818  myNet->changeShapeID(this, oldID);
819  setMicrosimID(value);
820  break;
821  }
822  case SUMO_ATTR_SHAPE: {
823  bool ok = true;
824  // set new shape
825  myShape = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, true);
826  // set GEO shape
828  for (int i = 0; i < (int) myGeoShape.size(); i++) {
830  }
831  // Check if new shape is closed
832  myClosedShape = (myShape.front() == myShape.back());
833  // disable simplified shape flag
834  mySimplifiedShape = false;
835  // update geometry of shape edited element
838  }
839  break;
840  }
841  case SUMO_ATTR_GEOSHAPE: {
842  bool ok = true;
843  // set new GEO shape
844  myGeoShape = GeomConvHelper::parseShapeReporting(value, "netedit-given", 0, ok, true);
845  // set shape
846  myShape = myGeoShape ;
847  for (int i = 0; i < (int) myShape.size(); i++) {
849  }
850  // Check if new shape is closed
851  myClosedShape = (myShape.front() == myShape.back());
852  // disable simplified shape flag
853  mySimplifiedShape = false;
854  // update geometry of shape edited element
857  }
858  break;
859  }
860  case SUMO_ATTR_COLOR:
861  setShapeColor(parse<RGBColor>(value));
862  break;
863  case SUMO_ATTR_FILL:
864  myFill = parse<bool>(value);
865  break;
866  case SUMO_ATTR_LAYER:
867  if (value == "default") {
869  } else {
870  setShapeLayer(parse<double>(value));
871  }
872  break;
873  case SUMO_ATTR_TYPE:
874  setShapeType(value);
875  break;
876  case SUMO_ATTR_IMGFILE:
877  setShapeImgFile(value);
878  // all textures must be refresh
880  break;
882  setShapeRelativePath(parse<bool>(value));
883  break;
884  case SUMO_ATTR_ANGLE:
885  setShapeNaviDegree(parse<double>(value));
886  break;
887  case SUMO_ATTR_GEO:
888  myGEO = parse<bool>(value);
889  break;
891  myBlockMovement = parse<bool>(value);
892  break;
894  myBlockShape = parse<bool>(value);
895  break;
897  myClosedShape = parse<bool>(value);
898  if (myClosedShape) {
901  } else {
902  myShape.pop_back();
903  myGeoShape.pop_back();
904  }
905  // disable simplified shape flag
906  mySimplifiedShape = false;
907  break;
908  case GNE_ATTR_SELECTED:
909  if (parse<bool>(value)) {
911  } else {
913  }
914  break;
915  case GNE_ATTR_GENERIC:
917  break;
918  default:
919  throw InvalidArgument(toString(getTag()) + " doesn't have an attribute of type '" + toString(key) + "'");
920  }
921  // add object into grid again
922  myNet->addGLObjectIntoGrid(this);
923 }
924 
925 
926 void
928  // only continue if there isn't already a AC under cursor
929  if (myNet->getViewNet()->getACUnderCursor() == nullptr) {
930  // check if cursor is within the shape
933  }
934  }
935 }
936 
937 
938 /****************************************************************************/
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:120
void endGeometryMoving()
begin movement (used when user click over edge to start a movement, to avoid problems with problems w...
Definition: GNEPoly.cpp:97
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:131
const GNEAttributeCarrier * getACUnderCursor() const
get AttributeCarrier under cursor
void openPolygon(bool allowUndo=true)
open polygon
Definition: GNEPoly.cpp:446
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:123
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition: RGBColor.cpp:150
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:126
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:103
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:221
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:129
void setShapeRelativePath(bool relativePath)
Sets a new relativePath value.
Definition: Shape.h:157
GNEPoly(GNENet *net, const std::string &id, const std::string &type, const PositionVector &shape, bool geo, bool fill, const RGBColor &color, double layer, double angle, const std::string &imgFile, bool relativePath, bool movementBlocked, bool shapeBlocked)
Constructor.
Definition: GNEPoly.cpp:67
static const RGBColor selectedLaneColor
color of selected lane
Definition: GNENet.h:99
virtual void updateGeometry(bool updateGrid)=0
update pre-computed geometry information
bool addGenericParameter(const std::string &key, const std::string &value)
add generic parameter
Definition: GNEPoly.cpp:711
A layer number.
Stores the information about how to visualize structures.
bool isPolygonClosed() const
check if polygon is closed
Definition: GNEPoly.cpp:424
void setShapeType(const std::string &type)
Sets a new type.
Definition: Shape.h:122
bool isAttributeCarrierSelected() const
check if attribute carrier is selected
Definition: GNEShape.cpp:130
double y() const
Returns the y-position.
Definition: Position.h:61
void commitShapeChange(const PositionVector &oldShape, GNEUndoList *undoList)
commit geometry changes in the attributes of an element after use of changeShapeGeometry(...)
Definition: GNEPoly.cpp:165
void unsetParameter(const std::string &key)
Removes a parameter.
double x() const
Returns the x-position.
Definition: Position.h:56
Close shape of a polygon (Used by GNEPolys)
int getVertexIndex(const Position &pos, bool createIfNoExist=true)
return index of a vertex of shape, or of a new vertex if position is over an shape&#39;s edge ...
Definition: GNEPoly.cpp:370
void buildCenterPopupEntry(GUIGLObjectPopupMenu *ret, bool addSeparator=true)
Builds an entry which allows to center to the object.
bool removeGenericParameter(const std::string &key)
remove generic parameter
Definition: GNEPoly.cpp:722
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:948
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:80
const PositionVector & getShape() const
Returns whether the shape of the polygon.
Definition: SUMOPolygon.h:80
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:78
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
PositionVector myGeoShape
Latitude of Polygon.
Definition: GNEPoly.h:237
static const double myHintSizeSquared
squaredhint size of vertex
Definition: GNEPoly.h:253
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:139
static void drawFilledCircle(double width, int steps=8)
Draws a filled circle around (0,0)
Definition: GLHelper.cpp:344
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:196
close opened polygon
Definition: GUIAppEnum.h:752
generic attribute
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
void selectAttributeCarrier(bool changeFlag=true)
Definition: GNEShape.cpp:104
void closePolygon(bool allowUndo=true)
close polygon
Definition: GNEPoly.cpp:468
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:242
const std::string & getShapeType() const
Returns the (abstract) type of the Shape.
Definition: Shape.h:75
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:150
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:234
GNEUndoList * getUndoList() const
get the undoList object
void removeDoublePoints(double minDist=POSITION_EPS, bool assertLength=false)
Removes positions if too near.
bool getShapeRelativePath() const
Returns the relativePath of the Shape.
Definition: Shape.h:110
void startGeometryMoving()
Definition: GNEPoly.cpp:91
bool myBlockShape
flag for block shape
Definition: GNEShape.h:205
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.
bool knowsParameter(const std::string &key) const
Returns whether the parameter is known.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:573
bool myBlockMovement
flag to block movement
Definition: GNEShape.h:202
void writeShape(OutputDevice &device)
writte shape element into a xml file
Definition: GNEPoly.cpp:203
void setGenericParametersStr(const std::string &value)
set generic parameters in string format
Definition: GNEPoly.cpp:783
void mouseOverObject(const GUIVisualizationSettings &s) const
method for check if mouse is over objects
Definition: GNEPoly.cpp:927
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:85
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
int gPrecisionGeo
Definition: StdDefs.cpp:28
bool updateGenericParameterValue(const std::string &key, const std::string &newValue)
update value generic parameter
Definition: GNEPoly.cpp:746
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:1175
static const double myHintSize
hint size of vertex
Definition: GNEPoly.h:250
double distanceSquaredTo(const Position &p2) const
returns the square of the distance to another position
Definition: Position.h:238
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:82
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:75
void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GNEPoly.cpp:283
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 updateGenericParameter(const std::string &oldKey, const std::string &newKey)
update generic parameter
Definition: GNEPoly.cpp:733
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:645
void deleteGeometryPoint(const Position &pos, bool allowUndo=true)
delete the geometry point closest to the given pos
Definition: GNEPoly.cpp:387
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:615
void changeShapeID(GNEShape *s, const std::string &OldID)
change Shape ID
Definition: GNENet.cpp:2047
std::string getAttribute(SumoXMLAttr key) const
Definition: GNEPoly.cpp:570
GUIGLObjectPopupMenu * getPopUpMenu(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own popup-menu.
Definition: GNEPoly.cpp:231
double getShapeLayer() const
Returns the layer of the Shape.
Definition: Shape.h:89
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
std::string myID
The name of the object.
Definition: Named.h:121
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
virtual void drawGL(const GUIVisualizationSettings &s) const
Draws the object.
Definition: GUIPolygon.cpp:137
void setACUnderCursor(const GNEAttributeCarrier *AC)
set attributeCarrier under cursor
void buildSelectionACPopupEntry(GUIGLObjectPopupMenu *ret, GNEAttributeCarrier *AC)
Builds an entry which allows to (de)select the object.
Definition: GNEViewNet.cpp:263
Set a vertex of polygon as first verte.
Definition: GUIAppEnum.h:756
void setShapeEditedElement(GNENetElement *element)
retrieve the netElement of which the shape is being edited
Definition: GNEPoly.cpp:430
void simplifyShape(bool allowUndo=true)
replace the current shape with a rectangle
Definition: GNEPoly.cpp:532
Position getPositionInView() const
Returns position of additional in view.
Definition: GNEPoly.cpp:209
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
GUIGlID getGlID() const
Returns the numerical id of the object.
Definition: GNEPoly.cpp:215
simplify polygon geometry
Definition: GUIAppEnum.h:750
bool isClosed() const
check if PositionVector is closed
GUIParameterTableWindow * getParameterWindow(GUIMainWindow &app, GUISUMOAbstractView &parent)
Returns an own parameter window.
Definition: GNEPoly.cpp:271
element is selected
The popup menu of a globject.
GNENetElement * getShapeEditedElement() const
retrieve the junction of which the shape is being edited
Definition: GNEPoly.cpp:440
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
static int getCircleResolution(const GUIVisualizationSettings &settings)
function to calculate circle resolution for all circles drawn in drawGL(...) functions ...
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:117
std::vector< std::pair< std::string, std::string > > getGenericParameters() const
return generic parameters as vector of pairs format
Definition: GNEPoly.cpp:772
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:49
double getExaggeration(const GUIVisualizationSettings &s, double factor=20) const
return the drawing size including exaggeration and constantSize values
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:87
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.
static const RGBColor selectionColor
Definition: GNENet.h:96
open closed polygon
Definition: GUIAppEnum.h:754
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:757
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
Boundary getCenteringBoundary() const
Returns the boundary to which the view shall be centered in order to show the object.
Definition: GUIPolygon.cpp:88
void closePolygon()
ensures that the last position equals the first
void addGLObjectIntoGrid(GUIGlObject *o)
add GL Object into net
Definition: GNENet.cpp:1168
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:490
void setShapeLayer(const double layer)
Sets a new layer.
Definition: Shape.h:136
void updateGeometry(bool updateGrid)
update pre-computed geometry information
Definition: GNEPoly.cpp:198
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 occurred errors.
Fill the polygon.
double getShapeNaviDegree() const
Returns the angle of the Shape in navigational degrees.
Definition: Shape.h:96
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:277
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1745
void moveEntireShape(const PositionVector &oldShape, const Position &offset)
move entire shape without commiting change
Definition: GNEPoly.cpp:149
static const double DEFAULT_LAYER
Definition: Shape.h:44
void setShapeNaviDegree(const double angle)
Sets a new angle in navigational degrees.
Definition: Shape.h:143
void clearParameter()
Clears the parameter map.
static RGBColor getColor()
gets the gl-color
Definition: GLHelper.cpp:579
SumoXMLTag getTag() const
get XML Tag assigned to this object