Eclipse SUMO - Simulation of Urban MObility
GNEPolygonFrame.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-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
18 // The Widget for add polygons
19 /****************************************************************************/
20 #include <config.h>
21 
26 #include <netedit/GNEViewParent.h>
27 #include <netedit/GNENet.h>
28 #include <netedit/GNEViewNet.h>
29 #include <netedit/GNEUndoList.h>
31 
32 #include "GNEPolygonFrame.h"
33 
34 
35 // ===========================================================================
36 // FOX callback mapping
37 // ===========================================================================
38 
43 };
44 
45 // Object implementation
46 FXIMPLEMENT(GNEPolygonFrame::GEOPOICreator, FXGroupBoxModule, GEOPOICreatorMap, ARRAYNUMBER(GEOPOICreatorMap))
47 
48 
49 // ===========================================================================
50 // method definitions
51 // ===========================================================================
52 
53 // ---------------------------------------------------------------------------
54 // GNEPolygonFrame::GEOPOICreator - methods
55 // ---------------------------------------------------------------------------
56 
58  FXGroupBoxModule(polygonFrameParent->myContentFrame, "GEO POI Creator"),
59  myPolygonFrameParent(polygonFrameParent) {
60  // create RadioButtons for formats
61  myLonLatRadioButton = new FXRadioButton(getCollapsableFrame(), "Format: Lon-Lat", this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);
62  myLatLonRadioButton = new FXRadioButton(getCollapsableFrame(), "Format: Lat-Lon", this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);
63  // set lat-lon as default
64  myLatLonRadioButton->setCheck(TRUE);
65  // create text field for coordinates
66  myCoordinatesTextField = new FXTextField(getCollapsableFrame(), GUIDesignTextFieldNCol, this, MID_GNE_SET_ATTRIBUTE, GUIDesignTextField);
67  // create checkBox
68  myCenterViewAfterCreationCheckButton = new FXCheckButton(getCollapsableFrame(), "Center View after creation", this, MID_GNE_SET_ATTRIBUTE, GUIDesignCheckButton);
69  // create button for create GEO POIs
70  myCreateGEOPOIButton = new FXButton(getCollapsableFrame(), "Create GEO POI (clipboard)", nullptr, this, MID_GNE_CREATE, GUIDesignButton);
71  // create information label
72  myLabelCartesianPosition = new FXLabel(getCollapsableFrame(), "Cartesian equivalence:\n- X = give valid longitude\n- Y = give valid latitude", 0, GUIDesignLabelFrameInformation);
73 }
74 
75 
77 
78 
79 void
81  // check if there is an GEO Proj string is defined
82  if (GeoConvHelper::getFinal().getProjString() != "!") {
83  myCoordinatesTextField->enable();
84  myCoordinatesTextField->setText("");
85  myCoordinatesTextField->enable();
86  myCreateGEOPOIButton->enable();
87  } else {
88  myCoordinatesTextField->setText("No geo-conversion defined");
89  myCoordinatesTextField->disable();
90  myCreateGEOPOIButton->disable();
91  }
92  show();
93 }
94 
95 
96 void
98  hide();
99 }
100 
101 
102 long
104  // check if input contains spaces
105  std::string input = myCoordinatesTextField->getText().text();
106  std::string inputWithoutSpaces;
107  for (const auto& i : input) {
108  if (i != ' ') {
109  inputWithoutSpaces.push_back(i);
110  }
111  }
112  // if input contains spaces, call this function again, and in other case set red text color
113  if (input.size() != inputWithoutSpaces.size()) {
114  myCoordinatesTextField->setText(inputWithoutSpaces.c_str());
115  }
116  if (inputWithoutSpaces.size() > 0) {
117  myCreateGEOPOIButton->setText("Create GEO POI");
118  } else {
119  myCreateGEOPOIButton->setText("Create GEO POI (clipboard)");
120  }
121  // simply check if given value can be parsed to Position
122  if (GNEAttributeCarrier::canParse<Position>(myCoordinatesTextField->getText().text())) {
123  myCoordinatesTextField->setTextColor(FXRGB(0, 0, 0));
124  myCoordinatesTextField->killFocus();
125  // convert coordinates into lon-lat
126  Position geoPos = GNEAttributeCarrier::parse<Position>(myCoordinatesTextField->getText().text());
127  if (myLatLonRadioButton->getCheck() == TRUE) {
128  geoPos.swapXY();
129  }
131  // check if GEO Position has to be swapped
132  // update myLabelCartesianPosition
133  myLabelCartesianPosition->setText(("Cartesian equivalence:\n- X = " + toString(geoPos.x()) + "\n- Y = " + toString(geoPos.y())).c_str());
134  } else {
135  myCoordinatesTextField->setTextColor(FXRGB(255, 0, 0));
136  myLabelCartesianPosition->setText("Cartesian equivalence:\n- X = give valid longitude\n- Y = give valid latitude");
137  };
138  return 1;
139 }
140 
141 
142 long
143 GNEPolygonFrame::GEOPOICreator::onCmdSetFormat(FXObject* obj, FXSelector, void*) {
144  //disable other radio button depending of selected option
145  if (obj == myLonLatRadioButton) {
146  myLonLatRadioButton->setCheck(TRUE);
147  myLatLonRadioButton->setCheck(FALSE);
148  } else if (obj == myLatLonRadioButton) {
149  myLonLatRadioButton->setCheck(FALSE);
150  myLatLonRadioButton->setCheck(TRUE);
151  }
152  // in both cases call onCmdSetCoordinates(0,0,0) to set new cartesian equivalence
153  onCmdSetCoordinates(0, 0, 0);
154  return 1;
155 }
156 
157 
158 long
160  // first check if current GEO Position is valid
161  if (myPolygonFrameParent->myShapeAttributes->areValuesValid()) {
162  std::string geoPosStr = myCoordinatesTextField->getText().text();
163  if (geoPosStr.empty()) {
164  // use clipboard
165  WRITE_WARNING("Using clipboard");
166  geoPosStr = GUIUserIO::copyFromClipboard(*getApp());
167  myCoordinatesTextField->setText(geoPosStr.c_str());
168  // remove spaces, update cartesian value
169  onCmdSetCoordinates(0, 0, 0);
170  geoPosStr = myCoordinatesTextField->getText().text();
171  myCoordinatesTextField->setText("");
172  myCreateGEOPOIButton->setText("Create GEO POI (clipboard)");
173  }
174  if (GNEAttributeCarrier::canParse<Position>(geoPosStr)) {
175  // create baseShape object
176  myPolygonFrameParent->createBaseShapeObject(SUMO_TAG_POI);
177  // obtain shape attributes and values
178  myPolygonFrameParent->myShapeAttributes->getAttributesAndValues(myPolygonFrameParent->myBaseShape, true);
179  // obtain netedit attributes and values
180  myPolygonFrameParent->myNeteditAttributes->getNeteditAttributesAndValues(myPolygonFrameParent->myBaseShape, nullptr);
181  // Check if ID has to be generated
182  if (!myPolygonFrameParent->myBaseShape->hasStringAttribute(SUMO_ATTR_ID)) {
183  myPolygonFrameParent->myBaseShape->addStringAttribute(SUMO_ATTR_ID, myPolygonFrameParent->myViewNet->getNet()->getAttributeCarriers()->generateShapeID(SUMO_TAG_POI));
184  }
185  // force GEO attribute to true and obain position
186  myPolygonFrameParent->myBaseShape->addBoolAttribute(SUMO_ATTR_GEO, true);
187  Position geoPos = GNEAttributeCarrier::parse<Position>(geoPosStr);
188  // convert coordinates into lon-lat
189  if (myLatLonRadioButton->getCheck() == TRUE) {
190  geoPos.swapXY();
191  }
193  myPolygonFrameParent->myBaseShape->addPositionAttribute(SUMO_ATTR_POSITION, geoPos);
194  // add shape
195  myPolygonFrameParent->addShape();
196  // check if view has to be centered over created GEO POI
197  if (myCenterViewAfterCreationCheckButton->getCheck() == TRUE) {
198  // create a boundary over given GEO Position and center view over it
199  Boundary centerPosition;
200  centerPosition.add(geoPos);
201  centerPosition = centerPosition.grow(10);
202  myPolygonFrameParent->myViewNet->getViewParent()->getView()->centerTo(centerPosition);
203  }
204  }
205  // refresh shape attributes
206  myPolygonFrameParent->myShapeAttributes->refreshAttributesCreator();
207  }
208  return 1;
209 }
210 
211 
212 // ---------------------------------------------------------------------------
213 // GNEPolygonFrame - methods
214 // ---------------------------------------------------------------------------
215 
216 GNEPolygonFrame::GNEPolygonFrame(FXHorizontalFrame* horizontalFrameParent, GNEViewNet* viewNet) :
217  GNEFrame(horizontalFrameParent, viewNet, "Shapes"),
218  myBaseShape(nullptr) {
219 
220  // create item Selector modul for shapes
221  myShapeTagSelector = new GNEFrameModules::TagSelector(this, GNETagProperties::TagType::SHAPE, SUMO_TAG_POLY);
222 
223  // Create shape parameters
225 
226  // Create Netedit parameter
228 
229  // Create drawing controls
231 
233  myGEOPOICreator = new GEOPOICreator(this);
234 }
235 
236 
238  // check if we have to delete base additional object
239  if (myBaseShape) {
240  delete myBaseShape;
241  }
242 }
243 
244 
245 void
247  // refresh tag selector
249  // show frame
250  GNEFrame::show();
251 }
252 
253 
254 bool
255 GNEPolygonFrame::processClick(const Position& clickedPosition, const GNEViewNetHelper::ObjectsUnderCursor& objectsUnderCursor, bool& updateTemporalShape) {
256  // reset updateTemporalShape
257  updateTemporalShape = false;
258  // check if current selected shape is valid
259  if (myShapeTagSelector->getCurrentTemplateAC() != nullptr) {
261  // show warning dialogbox and stop if input parameters are invalid
262  if (myShapeAttributes->areValuesValid() == false) {
264  return false;
265  }
266  // create baseShape object
268  // obtain shape attributes and values
270  // obtain netedit attributes and values
272  // Check if ID has to be generated
275  }
276  // add X-Y
277  myBaseShape->addDoubleAttribute(SUMO_ATTR_X, clickedPosition.x());
278  myBaseShape->addDoubleAttribute(SUMO_ATTR_Y, clickedPosition.y());
279  // set GEO Position as false (because we have created POI clicking over View
281  // add shape
282  addShape();
283  // refresh shape attributes
285  // shape added, then return true
286  return true;
288  // show warning dialogbox and stop if input parameters are invalid
289  if (myShapeAttributes->areValuesValid() == false) {
291  return false;
292  }
293  // create baseShape object
295  // obtain shape attributes and values
297  // obtain netedit attributes and values
299  // Check if ID has to be generated
302  }
303  // convert position to cartesian
304  Position GEOPos = clickedPosition;
306  // add X-Y in geo format
309  // set GEO Position as false (because we have created POI clicking over View
311  // add shape
312  addShape();
313  // refresh shape attributes
315  // shape added, then return true
316  return true;
318  // abort if lane is nullptr
319  if (objectsUnderCursor.getLaneFront() == nullptr) {
320  WRITE_WARNING(toString(GNE_TAG_POILANE) + " can be only placed over lanes");
321  return false;
322  }
323  // show warning dialogbox and stop if input parameters are invalid
324  if (myShapeAttributes->areValuesValid() == false) {
326  return false;
327  }
328  // create baseShape object
330  // obtain shape attributes and values
332  // obtain netedit attributes and values
334  // Check if ID has to be generated
337  }
338  // obtain Lane
340  // obtain position over lane
342  // add shape
343  addShape();
344  // refresh shape attributes
346  // shape added, then return true
347  return true;
349  if (myDrawingShape->isDrawing()) {
350  // add or delete a new point depending of flag "delete last created point"
353  } else {
354  myDrawingShape->addNewPoint(clickedPosition);
355  }
356  // set temporal shape
357  updateTemporalShape = true;
358  return true;
359  } else {
360  return false;
361  }
362  }
363  }
364  myViewNet->setStatusBarText("Current selected shape isn't valid.");
365  return false;
366 }
367 
368 
369 std::string
370 GNEPolygonFrame::getIdsSelected(const FXList* list) {
371  // Obtain Id's of list
372  std::string vectorOfIds;
373  for (int i = 0; i < list->getNumItems(); i++) {
374  if (list->isItemSelected(i)) {
375  if (vectorOfIds.size() > 0) {
376  vectorOfIds += " ";
377  }
378  vectorOfIds += (list->getItem(i)->getText()).text();
379  }
380  }
381  return vectorOfIds;
382 }
383 
384 
387  return myDrawingShape;
388 }
389 
390 
391 void
393  // check if baseShape exist, and if yes, delete it
394  if (myBaseShape) {
395  // delete baseShape (and all children)
396  delete myBaseShape;
397  }
398  // just create a base shape
400  // set tag
401  myBaseShape->setTag(shapeTag);
402 }
403 
404 
405 bool
407  // show warning dialogbox and stop check if input parameters are valid
410  return false;
411  } else if (myDrawingShape->getTemporalShape().size() == 0) {
412  WRITE_WARNING("Polygon shape cannot be empty");
413  return false;
414  } else {
415  // create baseShape object
417  // obtain shape attributes and values
419  // obtain netedit attributes and values
421  // Check if ID has to be generated
424  }
425  // obtain shape and check if has to be closed
428  temporalShape.closePolygon();
429  }
431  // obtain geo (by default false)
433  // add shape
434  addShape();
435  // refresh shape attributes
437  // shape added, then return true;
438  return true;
439  }
440 }
441 
442 
443 void
446  // if there are parmeters, show and Recalc groupBox
448  // show netedit attributes
450  // Check if drawing mode has to be shown
453  } else {
455  }
456  // Check if GEO POI Creator has to be shown
459  } else {
461  }
462  } else {
463  // hide all widgets
468  }
469 }
470 
471 
472 void
474  // declare additional handler
475  GNEAdditionalHandler additionalHandler(myViewNet->getNet(), true);
476  // build shape
477  additionalHandler.parseSumoBaseObject(myBaseShape);
478 }
479 
480 /****************************************************************************/
FXDEFMAP(GNEPolygonFrame::GEOPOICreator) GEOPOICreatorMap[]
@ MID_GNE_SET_ATTRIBUTE
attribute edited
Definition: GUIAppEnum.h:797
@ MID_CHOOSEN_OPERATION
set type of selection
Definition: GUIAppEnum.h:551
@ MID_GNE_CREATE
create element
Definition: GUIAppEnum.h:799
#define GUIDesignButton
Definition: GUIDesigns.h:68
#define GUIDesignTextField
Definition: GUIDesigns.h:42
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:60
#define GUIDesignCheckButton
checkButton placed in left position
Definition: GUIDesigns.h:145
#define GUIDesignRadioButton
Definition: GUIDesigns.h:179
#define GUIDesignLabelFrameInformation
label extended over frame without thick and with text justify to left, used to show information in fr...
Definition: GUIDesigns.h:244
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_POI
begin/end of the description of a Point of interest
@ GNE_TAG_POIGEO
Point of interest over view with GEO attributes.
@ SUMO_TAG_POLY
begin/end of the description of a polygon
@ GNE_TAG_POILANE
Point of interest over Lane.
@ SUMO_ATTR_LANE
@ SUMO_ATTR_LON
@ SUMO_ATTR_Y
@ SUMO_ATTR_X
@ SUMO_ATTR_GEO
@ GNE_ATTR_CLOSE_SHAPE
Close shape of a polygon (Used by GNEPolys)
@ SUMO_ATTR_SHAPE
edge: the shape in xml-definition
@ SUMO_ATTR_LAT
@ SUMO_ATTR_ID
@ SUMO_ATTR_POSITION
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void parseSumoBaseObject(CommonXMLStructure::SumoBaseObject *obj)
parse SumoBaseObject (it's called recursivelly)
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Definition: Boundary.cpp:77
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:299
bool hasStringAttribute(const SumoXMLAttr attr) const
has function
void setTag(const SumoXMLTag tag)
set SumoBaseObject tag
void addPositionVectorAttribute(const SumoXMLAttr attr, const PositionVector &value)
add PositionVector attribute into current SumoBaseObject node
void addBoolAttribute(const SumoXMLAttr attr, const bool value)
add bool attribute into current SumoBaseObject node
void addDoubleAttribute(const SumoXMLAttr attr, const double value)
add double attribute into current SumoBaseObject node
bool getBoolAttribute(const SumoXMLAttr attr) const
get bool attribute
void addStringAttribute(const SumoXMLAttr attr, const std::string &value)
FXGroupBoxModule (based on FXGroupBox)
Builds additional objects for GNENet (busStops, chargingStations, detectors, etc.....
const GNETagProperties & getTagProperty() const
get tagProperty associated with this Attribute Carrier
void showWarningMessage(std::string extra="") const
show warning message with information about non-valid attributes
bool areValuesValid() const
check if parameters of attributes are valid
void refreshAttributesCreator()
refresh attribute creator
void showAttributesCreatorModule(GNEAttributeCarrier *templateAC, const std::vector< SumoXMLAttr > &hiddenAttributes)
show AttributesCreator modul
void getAttributesAndValues(CommonXMLStructure::SumoBaseObject *baseObject, bool includeAll) const
get attributes and their values
void hideNeteditAttributesModule()
hide Netedit attributes modul
bool getNeteditAttributesAndValues(CommonXMLStructure::SumoBaseObject *baseObject, const GNELane *lane) const
fill valuesMap with netedit attributes
void showNeteditAttributesModule(const GNETagProperties &tagValue)
show Netedit attributes modul
GNEViewNet * myViewNet
View Net.
Definition: GNEFrame.h:114
virtual void show()
show Frame
Definition: GNEFrame.cpp:108
virtual void hide()
hide Frame
Definition: GNEFrame.cpp:117
bool getDeleteLastCreatedPoint()
get flag delete last created point
const PositionVector & getTemporalShape() const
get Temporal shape
void hideDrawingShape()
hide Drawing mode
void addNewPoint(const Position &P)
add new point to temporal shape
void removeLastPoint()
remove last added point
void showDrawingShape()
show Drawing mode
bool isDrawing() const
return true if currently a shape is drawed
void refreshTagSelector()
refresh tagSelector (used when frameParent is show)
GNEAttributeCarrier * getCurrentTemplateAC() const
get current templateAC
const PositionVector & getLaneShape() const
get elements shape
Definition: GNELane.cpp:131
std::string generateShapeID(SumoXMLTag shapeTag) const
generate Shape ID
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:125
const std::string & getID() const
get ID
long onCmdCreateGEOPOI(FXObject *, FXSelector, void *)
called when user type in search box
void hideGEOPOICreatorModule()
hide GEOPOICreator Module
void showGEOPOICreatorModule()
Show list of GEOPOICreator Module.
long onCmdSetFormat(FXObject *, FXSelector, void *)
called when user select a format radio button
long onCmdSetCoordinates(FXObject *, FXSelector, void *)
bool processClick(const Position &clickedPosition, const GNEViewNetHelper::ObjectsUnderCursor &objectsUnderCursor, bool &updateTemporalShape)
process click over Viewnet
void createBaseShapeObject(const SumoXMLTag shapeTag)
GNEFrameAttributeModules::AttributesCreator * myShapeAttributes
shape internal attributes
CommonXMLStructure::SumoBaseObject * myBaseShape
SumoBaseObject used for create shape.
void show()
show Frame
static std::string getIdsSelected(const FXList *list)
get list of selecte id's in string format
void tagSelected()
Tag selected in TagSelector.
GNEFrameAttributeModules::NeteditAttributes * myNeteditAttributes
Netedit parameter.
GNEFrameModules::DrawingShape * myDrawingShape
Drawing shape.
~GNEPolygonFrame()
Destructor.
GNEFrameModules::TagSelector * myShapeTagSelector
shape tag selector
GNEPolygonFrame(FXHorizontalFrame *horizontalFrameParent, GNEViewNet *viewNet)
Constructor.
GNEFrameModules::DrawingShape * getDrawingShapeModule() const
get drawing mode editor
GEOPOICreator * myGEOPOICreator
GEOPOICreator.
bool shapeDrawed()
build a shaped element using the drawed shape return true if was successfully created
void addShape()
add shape (using base shape)
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
class used to group all variables related with objects under cursor after a click over view
GNELane * getLaneFront() const
get front lane or a pointer to nullptr
GNENet * getNet() const
get the net object
void setStatusBarText(const std::string &text)
set staturBar text
Definition: GNEViewNet.cpp:629
static std::string copyFromClipboard(const FXApp &app)
Copies text from the clipboard.
Definition: GUIUserIO.cpp:44
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation.
C++ TraCI client API implementation.
Definition: GUI.h:31
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double x() const
Returns the x-position.
Definition: Position.h:55
void swapXY()
swap position X and Y
Definition: Position.h:283
double y() const
Returns the y-position.
Definition: Position.h:60
A list of positions.
void closePolygon()
ensures that the last position equals the first
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D