Eclipse SUMO - Simulation of Urban MObility
GNEShapeFrame.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
27#include <netedit/GNENet.h>
28#include <netedit/GNEViewNet.h>
29
30#include "GNEShapeFrame.h"
31
32
33// ===========================================================================
34// FOX callback mapping
35// ===========================================================================
36
41};
42
43// Object implementation
44FXIMPLEMENT(GNEShapeFrame::GEOPOICreator, MFXGroupBoxModule, GEOPOICreatorMap, ARRAYNUMBER(GEOPOICreatorMap))
45
46
47// ===========================================================================
48// method definitions
49// ===========================================================================
50
51// ---------------------------------------------------------------------------
52// GNEShapeFrame::GEOPOICreator - methods
53// ---------------------------------------------------------------------------
54
56 MFXGroupBoxModule(polygonFrameParent, TL("GEO POI Creator")),
57 myShapeFrameParent(polygonFrameParent) {
58 // create RadioButtons for formats
59 myLonLatRadioButton = new FXRadioButton(getCollapsableFrame(), TL("Format: Lon-Lat"), this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);
60 myLatLonRadioButton = new FXRadioButton(getCollapsableFrame(), TL("Format: Lat-Lon"), this, MID_CHOOSEN_OPERATION, GUIDesignRadioButton);
61 // set lat-lon as default
62 myLatLonRadioButton->setCheck(TRUE);
63 // create text field for coordinates
64 myCoordinatesTextField = new FXTextField(getCollapsableFrame(), GUIDesignTextFieldNCol, this, MID_GNE_SET_ATTRIBUTE, GUIDesignTextField);
65 // create checkBox
66 myCenterViewAfterCreationCheckButton = new FXCheckButton(getCollapsableFrame(), TL("Center View after creation"), this, MID_GNE_SET_ATTRIBUTE, GUIDesignCheckButton);
67 // create button for create GEO POIs
68 myCreateGEOPOIButton = new FXButton(getCollapsableFrame(), TL("Create GEO POI (clipboard)"), nullptr, this, MID_GNE_CREATE, GUIDesignButton);
69 // create information label
70 myLabelCartesianPosition = new FXLabel(getCollapsableFrame(), "Cartesian equivalence:\n- X = give valid longitude\n- Y = give valid latitude", 0, GUIDesignLabelFrameInformation);
71}
72
73
75
76
77void
79 // check if there is an GEO Proj string is defined
80 if (GeoConvHelper::getFinal().getProjString() != "!") {
81 myCoordinatesTextField->enable();
82 myCoordinatesTextField->setText("");
83 myCoordinatesTextField->enable();
84 myCreateGEOPOIButton->enable();
85 } else {
86 myCoordinatesTextField->setText(TL("No geo-conversion defined"));
87 myCoordinatesTextField->disable();
88 myCreateGEOPOIButton->disable();
89 }
90 show();
91}
92
93
94void
96 hide();
97}
98
99
100long
102 // check if input contains spaces
103 std::string input = myCoordinatesTextField->getText().text();
104 std::string inputWithoutSpaces;
105 for (const auto& i : input) {
106 if (i != ' ') {
107 inputWithoutSpaces.push_back(i);
108 }
109 }
110 // if input contains spaces, call this function again, and in other case set red text color
111 if (input.size() != inputWithoutSpaces.size()) {
112 myCoordinatesTextField->setText(inputWithoutSpaces.c_str());
113 }
114 if (inputWithoutSpaces.size() > 0) {
115 myCreateGEOPOIButton->setText(TL("Create GEO POI"));
116 } else {
117 myCreateGEOPOIButton->setText(TL("Create GEO POI (clipboard)"));
118 }
119 // simply check if given value can be parsed to Position
120 if (GNEAttributeCarrier::canParse<Position>(myCoordinatesTextField->getText().text())) {
121 myCoordinatesTextField->setTextColor(FXRGB(0, 0, 0));
122 myCoordinatesTextField->killFocus();
123 // convert coordinates into lon-lat
124 Position geoPos = GNEAttributeCarrier::parse<Position>(myCoordinatesTextField->getText().text());
125 if (myLatLonRadioButton->getCheck() == TRUE) {
126 geoPos.swapXY();
127 }
129 // check if GEO Position has to be swapped
130 // update myLabelCartesianPosition
131 myLabelCartesianPosition->setText(("Cartesian equivalence:\n- X = " + toString(geoPos.x()) + "\n- Y = " + toString(geoPos.y())).c_str());
132 } else {
133 myCoordinatesTextField->setTextColor(FXRGB(255, 0, 0));
134 myLabelCartesianPosition->setText(TL("Cartesian equivalence:\n- X = give valid longitude\n- Y = give valid latitude"));
135 };
136 return 1;
137}
138
139
140long
141GNEShapeFrame::GEOPOICreator::onCmdSetFormat(FXObject* obj, FXSelector, void*) {
142 //disable other radio button depending of selected option
143 if (obj == myLonLatRadioButton) {
144 myLonLatRadioButton->setCheck(TRUE);
145 myLatLonRadioButton->setCheck(FALSE);
146 } else if (obj == myLatLonRadioButton) {
147 myLonLatRadioButton->setCheck(FALSE);
148 myLatLonRadioButton->setCheck(TRUE);
149 }
150 // in both cases call onCmdSetCoordinates(0,0,0) to set new cartesian equivalence
151 onCmdSetCoordinates(0, 0, 0);
152 return 1;
153}
154
155
156long
158 // first check if current GEO Position is valid
159 if (myShapeFrameParent->myShapeAttributes->areValuesValid()) {
160 std::string geoPosStr = myCoordinatesTextField->getText().text();
161 if (geoPosStr.empty()) {
162 // use clipboard
163 WRITE_WARNING(TL("Using clipboard"));
164 geoPosStr = GUIUserIO::copyFromClipboard(*getApp());
165 myCoordinatesTextField->setText(geoPosStr.c_str());
166 // remove spaces, update cartesian value
167 onCmdSetCoordinates(0, 0, 0);
168 geoPosStr = myCoordinatesTextField->getText().text();
169 myCoordinatesTextField->setText("");
170 myCreateGEOPOIButton->setText(TL("Create GEO POI (clipboard)"));
171 }
172 if (GNEAttributeCarrier::canParse<Position>(geoPosStr)) {
173 // create baseShape object
174 myShapeFrameParent->createBaseShapeObject(SUMO_TAG_POI);
175 // obtain shape attributes and values
176 myShapeFrameParent->myShapeAttributes->getAttributesAndValues(myShapeFrameParent->myBaseShape, true);
177 // obtain netedit attributes and values
178 myShapeFrameParent->myNeteditAttributes->getNeteditAttributesAndValues(myShapeFrameParent->myBaseShape, nullptr);
179 // Check if ID has to be generated
180 if (!myShapeFrameParent->myBaseShape->hasStringAttribute(SUMO_ATTR_ID)) {
181 myShapeFrameParent->myBaseShape->addStringAttribute(SUMO_ATTR_ID, myShapeFrameParent->myViewNet->getNet()->getAttributeCarriers()->generateAdditionalID(SUMO_TAG_POI));
182 }
183 // force GEO attribute to true and obain position
184 myShapeFrameParent->myBaseShape->addBoolAttribute(SUMO_ATTR_GEO, true);
185 Position geoPos = GNEAttributeCarrier::parse<Position>(geoPosStr);
186 // convert coordinates into lon-lat
187 if (myLatLonRadioButton->getCheck() == TRUE) {
188 geoPos.swapXY();
189 }
191 // add lon/lat
192 myShapeFrameParent->myBaseShape->addDoubleAttribute(SUMO_ATTR_LON, geoPos.x());
193 myShapeFrameParent->myBaseShape->addDoubleAttribute(SUMO_ATTR_LAT, geoPos.y());
194 // set GEO Position as true
195 myShapeFrameParent->myBaseShape->addBoolAttribute(SUMO_ATTR_GEO, true);
196 // add shape
197 myShapeFrameParent->addShape();
198 // check if view has to be centered over created GEO POI
199 if (myCenterViewAfterCreationCheckButton->getCheck() == TRUE) {
200 // create a boundary over given GEO Position and center view over it
201 Boundary centerPosition;
202 centerPosition.add(geoPos);
203 centerPosition = centerPosition.grow(10);
204 myShapeFrameParent->myViewNet->getViewParent()->getView()->centerTo(centerPosition);
205 }
206 }
207 // refresh shape attributes
208 myShapeFrameParent->myShapeAttributes->refreshAttributesCreator();
209 }
210 return 1;
211}
212
213
214// ---------------------------------------------------------------------------
215// GNEShapeFrame - methods
216// ---------------------------------------------------------------------------
217
219 GNEFrame(viewParent, viewNet, "Shapes"),
220 myBaseShape(nullptr) {
221
222 // create item Selector modul for shapes
223 myShapeTagSelector = new GNETagSelector(this, GNETagProperties::TagType::SHAPE, SUMO_TAG_POLY);
224
225 // Create shape parameters
227
228 // Create Netedit parameter
230
231 // Create drawing controls
233
235 myGEOPOICreator = new GEOPOICreator(this);
236}
237
238
240 // check if we have to delete base additional object
241 if (myBaseShape) {
242 delete myBaseShape;
243 }
244}
245
246
247void
249 // refresh tag selector
251 // show frame
253}
254
255
256bool
257GNEShapeFrame::processClick(const Position& clickedPosition, const GNEViewNetHelper::ObjectsUnderCursor& objectsUnderCursor, bool& updateTemporalShape) {
258 // reset updateTemporalShape
259 updateTemporalShape = false;
260 // check if current selected shape is valid
261 if (myShapeTagSelector->getCurrentTemplateAC() != nullptr) {
263 // show warning dialogbox and stop if input parameters are invalid
264 if (myShapeAttributes->areValuesValid() == false) {
266 return false;
267 }
268 // create baseShape object
270 // obtain shape attributes and values
272 // obtain netedit attributes and values
274 // Check if ID has to be generated
277 }
278 // add X-Y
279 myBaseShape->addDoubleAttribute(SUMO_ATTR_X, clickedPosition.x());
280 myBaseShape->addDoubleAttribute(SUMO_ATTR_Y, clickedPosition.y());
281 // set GEO Position as false (because we have created POI clicking over View
283 // add shape
284 addShape();
285 // refresh shape attributes
287 // shape added, then return true
288 return true;
290 // show warning dialogbox and stop if input parameters are invalid
291 if (myShapeAttributes->areValuesValid() == false) {
293 return false;
294 }
295 // create baseShape object
297 // obtain shape attributes and values
299 // obtain netedit attributes and values
301 // Check if ID has to be generated
304 }
305 // convert position to cartesian
306 Position GEOPos = clickedPosition;
308 // add X-Y in geo format
311 // set GEO Position as false (because we have created POI clicking over View
313 // add shape
314 addShape();
315 // refresh shape attributes
317 // shape added, then return true
318 return true;
320 // abort if lane is nullptr
321 if (objectsUnderCursor.getLaneFront() == nullptr) {
322 WRITE_WARNING(toString(GNE_TAG_POILANE) + " can be only placed over lanes");
323 return false;
324 }
325 // show warning dialogbox and stop if input parameters are invalid
326 if (myShapeAttributes->areValuesValid() == false) {
328 return false;
329 }
330 // create baseShape object
332 // obtain shape attributes and values
334 // obtain netedit attributes and values
336 // Check if ID has to be generated
339 }
340 // obtain Lane
342 // obtain position over lane
344 // add shape
345 addShape();
346 // refresh shape attributes
348 // shape added, then return true
349 return true;
351 if (myDrawingShape->isDrawing()) {
352 // add or delete a new point depending of flag "delete last created point"
355 } else {
356 myDrawingShape->addNewPoint(clickedPosition);
357 }
358 // set temporal shape
359 updateTemporalShape = true;
360 return true;
361 } else {
362 return false;
363 }
364 }
365 }
366 myViewNet->setStatusBarText("Current selected shape isn't valid.");
367 return false;
368}
369
370
371std::string
372GNEShapeFrame::getIdsSelected(const FXList* list) {
373 // Obtain Id's of list
374 std::string vectorOfIds;
375 for (int i = 0; i < list->getNumItems(); i++) {
376 if (list->isItemSelected(i)) {
377 if (vectorOfIds.size() > 0) {
378 vectorOfIds += " ";
379 }
380 vectorOfIds += (list->getItem(i)->getText()).text();
381 }
382 }
383 return vectorOfIds;
384}
385
386
389 return myDrawingShape;
390}
391
392
393void
395 // check if baseShape exist, and if yes, delete it
396 if (myBaseShape) {
397 // delete baseShape (and all children)
398 delete myBaseShape;
399 }
400 // just create a base shape
402 // set tag
403 myBaseShape->setTag(shapeTag);
404}
405
406
407bool
409 // show warning dialogbox and stop check if input parameters are valid
412 return false;
413 } else if (myDrawingShape->getTemporalShape().size() == 0) {
414 WRITE_WARNING(TL("Polygon shape cannot be empty"));
415 return false;
416 } else {
417 // create baseShape object
419 // obtain shape attributes and values
421 // obtain netedit attributes and values
423 // Check if ID has to be generated
426 }
427 // obtain shape and check if has to be closed
430 temporalShape.closePolygon();
431 }
433 // obtain geo (by default false)
435 // add shape
436 addShape();
437 // refresh shape attributes
439 // shape added, then return true;
440 return true;
441 }
442}
443
444
445void
448 // if there are parmeters, show and Recalc groupBox
450 // show netedit attributes
452 // Check if drawing mode has to be shown
455 } else {
457 }
458 // Check if GEO POI Creator has to be shown
461 } else {
463 }
464 } else {
465 // hide all widgets
470 }
471}
472
473
474void
476 // declare additional handler
477 GNEAdditionalHandler additionalHandler(myViewNet->getNet(), true, false);
478 // build shape
479 additionalHandler.parseSumoBaseObject(myBaseShape);
480}
481
482/****************************************************************************/
FXDEFMAP(GNEShapeFrame::GEOPOICreator) GEOPOICreatorMap[]
@ MID_GNE_SET_ATTRIBUTE
attribute edited
Definition: GUIAppEnum.h:870
@ MID_CHOOSEN_OPERATION
set type of selection
Definition: GUIAppEnum.h:588
@ MID_GNE_CREATE
create element
Definition: GUIAppEnum.h:872
#define GUIDesignButton
Definition: GUIDesigns.h:77
#define GUIDesignTextField
Definition: GUIDesigns.h:48
#define GUIDesignTextFieldNCol
Num of column of text field.
Definition: GUIDesigns.h:69
#define GUIDesignCheckButton
checkButton placed in left position
Definition: GUIDesigns.h:169
#define GUIDesignRadioButton
Definition: GUIDesigns.h:203
#define GUIDesignLabelFrameInformation
label extended over frame without thick and with text justify to left, used to show information in fr...
Definition: GUIDesigns.h:271
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
#define TL(string)
Definition: MsgHandler.h:282
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:78
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:300
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)
Builds additional objects for GNENet (busStops, chargingStations, detectors, etc.....
const std::string getID() const
get ID (all Attribute Carriers have one)
const GNETagProperties & getTagProperty() const
get tagProperty associated with this Attribute Carrier
void getAttributesAndValues(CommonXMLStructure::SumoBaseObject *baseObject, bool includeAll) const
get attributes and their values
bool areValuesValid() const
check if parameters of attributes are valid
void showAttributesCreatorModule(GNEAttributeCarrier *templateAC, const std::vector< SumoXMLAttr > &hiddenAttributes)
show GNEAttributesCreator modul
void hideAttributesCreatorModule()
hide group box
void showWarningMessage(std::string extra="") const
show warning message with information about non-valid attributes
void refreshAttributesCreator()
refresh attribute creator
bool isDrawing() const
return true if currently a shape is drawed
void addNewPoint(const Position &P)
add new point to temporal shape
bool getDeleteLastCreatedPoint()
get flag delete last created point
void removeLastPoint()
remove last added point
void showDrawingShape()
show Drawing mode
void hideDrawingShape()
hide Drawing mode
const PositionVector & getTemporalShape() const
get Temporal shape
GNEViewNet * myViewNet
FOX need this.
Definition: GNEFrame.h:117
virtual void show()
show Frame
Definition: GNEFrame.cpp:115
virtual void hide()
hide Frame
Definition: GNEFrame.cpp:124
const PositionVector & getLaneShape() const
get elements shape
Definition: GNELane.cpp:142
std::string generateAdditionalID(SumoXMLTag type) const
generate additional id
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:132
void showNeteditAttributesModule(GNEAttributeCarrier *templateAC)
show Netedit attributes modul
void hideNeteditAttributesModule()
hide Netedit attributes modul
bool getNeteditAttributesAndValues(CommonXMLStructure::SumoBaseObject *baseObject, const GNELane *lane) const
fill valuesMap with netedit attributes
long onCmdSetFormat(FXObject *, FXSelector, void *)
called when user select a format radio button
void hideGEOPOICreatorModule()
hide GEOPOICreator Module
long onCmdSetCoordinates(FXObject *, FXSelector, void *)
void showGEOPOICreatorModule()
Show list of GEOPOICreator Module.
long onCmdCreateGEOPOI(FXObject *, FXSelector, void *)
called when user type in search box
void tagSelected()
Tag selected in GNETagSelector.
void show()
show Frame
GNEDrawingShape * getDrawingShapeModule() const
get drawing mode editor
GNEAttributesCreator * myShapeAttributes
shape internal attributes
void addShape()
add shape (using base shape)
void createBaseShapeObject(const SumoXMLTag shapeTag)
GNEDrawingShape * myDrawingShape
Drawing shape.
CommonXMLStructure::SumoBaseObject * myBaseShape
SumoBaseObject used for create shape.
GEOPOICreator * myGEOPOICreator
GEOPOICreator.
~GNEShapeFrame()
Destructor.
GNENeteditAttributes * myNeteditAttributes
Netedit parameter.
bool processClick(const Position &clickedPosition, const GNEViewNetHelper::ObjectsUnderCursor &objectsUnderCursor, bool &updateTemporalShape)
process click over Viewnet
static std::string getIdsSelected(const FXList *list)
get list of selecte id's in string format
GNEShapeFrame(GNEViewParent *viewParent, GNEViewNet *viewNet)
Constructor.
bool shapeDrawed()
build a shaped element using the drawed shape return true if was successfully created
GNETagSelector * myShapeTagSelector
shape tag selector
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
void refreshTagSelector()
refresh tagSelector (used when frameParent is show)
GNEAttributeCarrier * getCurrentTemplateAC() const
get current templateAC
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 statusBar text
Definition: GNEViewNet.cpp:768
A single child window which contains a view of the simulation area.
Definition: GNEViewParent.h:84
static std::string copyFromClipboard(const FXApp &app)
Copies text from the clipboard.
Definition: GUIUserIO.cpp:44
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
void cartesian2geo(Position &cartesian) const
Converts the given cartesian (shifted) position to its geo (lat/long) representation.
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation.
MFXGroupBoxModule (based on FXGroupBox)
C++ TraCI client API implementation.
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:288
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