1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file GNEDetectorE3.cpp
11 /// @author Pablo Alvarez Lopez
12 /// @date Nov 2015
13 /// @version $Id$
14 ///
15 //
16 /****************************************************************************/
17
18 // ===========================================================================
19 // included modules
20 // ===========================================================================
21
22 #include <netedit/GNENet.h>
23 #include <netedit/GNEUndoList.h>
24 #include <netedit/GNEViewNet.h>
25 #include <netedit/changes/GNEChange_Attribute.h>
26 #include <netedit/netelements/GNEEdge.h>
27 #include <utils/gui/div/GLHelper.h>
28 #include <utils/gui/images/GUITextureSubSys.h>
29 #include <utils/gui/globjects/GLIncludes.h>
30
31 #include "GNEDetectorE3.h"
32
33
34 // ===========================================================================
35 // member method definitions
36 // ===========================================================================
37
GNEDetectorE3(const std::string & id,GNEViewNet * viewNet,Position pos,double freq,const std::string & filename,const std::string & vehicleTypes,const std::string & name,const double timeThreshold,double speedThreshold,bool blockMovement)38 GNEDetectorE3::GNEDetectorE3(const std::string& id, GNEViewNet* viewNet, Position pos, double freq, const std::string& filename, const std::string& vehicleTypes, const std::string& name, const double timeThreshold, double speedThreshold, bool blockMovement) :
39 GNEAdditional(id, viewNet, GLO_E3DETECTOR, SUMO_TAG_E3DETECTOR, name, blockMovement, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}),
40 myPosition(pos),
41 myFreq(freq),
42 myFilename(filename),
43 myVehicleTypes(vehicleTypes),
44 myTimeThreshold(timeThreshold),
45 mySpeedThreshold(speedThreshold) {
46 }
47
48
~GNEDetectorE3()49 GNEDetectorE3::~GNEDetectorE3() {}
50
51
52 void
updateGeometry(bool updateGrid)53 GNEDetectorE3::updateGeometry(bool updateGrid) {
54 // first check if object has to be removed from grid (SUMOTree)
55 if (updateGrid) {
56 myViewNet->getNet()->removeGLObjectFromGrid(this);
57 }
58
59 // Clear shape
60 myGeometry.shape.clear();
61
62 // Set block icon position
63 myBlockIcon.position = myPosition;
64
65 // Set block icon offset
66 myBlockIcon.offset = Position(-0.5, -0.5);
67
68 // Set block icon rotation, and using their rotation for draw logo
69 myBlockIcon.setRotation();
70
71 // Set position
72 myGeometry.shape.push_back(myPosition);
73
74 // Update connection's geometry
75 myChildConnections.update();
76
77 // last step is to check if object has to be added into grid (SUMOTree) again
78 if (updateGrid) {
79 myViewNet->getNet()->addGLObjectIntoGrid(this);
80 }
81 }
82
83
84 Position
getPositionInView() const85 GNEDetectorE3::getPositionInView() const {
86 return myPosition;
87 }
88
89
90 void
moveGeometry(const Position & offset)91 GNEDetectorE3::moveGeometry(const Position& offset) {
92 // restore old position, apply offset and update Geometry
93 myPosition = myMove.originalViewPosition;
94 myPosition.add(offset);
95 // filtern position using snap to active grid
96 // filtern position using snap to active grid
97 myPosition = myViewNet->snapToActiveGrid(myPosition);
98 updateGeometry(false);
99 }
100
101
102 void
commitGeometryMoving(GNEUndoList * undoList)103 GNEDetectorE3::commitGeometryMoving(GNEUndoList* undoList) {
104 // commit new position allowing undo/redo
105 undoList->p_begin("position of " + getTagStr());
106 undoList->p_add(new GNEChange_Attribute(this, myViewNet->getNet(), SUMO_ATTR_POSITION, toString(myPosition), true, toString(myMove.originalViewPosition)));
107 undoList->p_end();
108 }
109
110
111 std::string
getParentName() const112 GNEDetectorE3::getParentName() const {
113 return myViewNet->getNet()->getMicrosimID();
114 }
115
116
117 void
drawGL(const GUIVisualizationSettings & s) const118 GNEDetectorE3::drawGL(const GUIVisualizationSettings& s) const {
119 // Start drawing adding an gl identificator
120 glPushName(getGlID());
121
122 // Add a draw matrix for drawing logo
123 glPushMatrix();
124 glTranslated(myGeometry.shape[0].x(), myGeometry.shape[0].y(), getType());
125
126 // Draw icon depending of detector is selected and if isn't being drawn for selecting
127 if (s.drawForSelecting) {
128 GLHelper::setColor(RGBColor::GREY);
129 GLHelper::drawBoxLine(Position(0, 1), 0, 2, 1);
130 } else {
131 glColor3d(1, 1, 1);
132 glRotated(180, 0, 0, 1);
133 if (drawUsingSelectColor()) {
134 GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GNETEXTURE_E3SELECTED), 1);
135 } else {
136 GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GNETEXTURE_E3), 1);
137 }
138 }
139
140 // Pop logo matrix
141 glPopMatrix();
142 if (!s.drawForSelecting) {
143 // Show Lock icon depending of the Edit mode
144 myBlockIcon.draw(0.4);
145 // Draw connections
146 myChildConnections.draw(getType());
147 }
148 // Draw name if isn't being drawn for selecting
149 if (!s.drawForSelecting) {
150 drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
151 }
152 // check if dotted contour has to be drawn
153 if (!s.drawForSelecting && (myViewNet->getDottedAC() == this)) {
154 GLHelper::drawShapeDottedContour(getType(), myPosition, 2, 2);
155 // draw shape dotte contour aroud alld connections between child and parents
156 for (auto i : myChildConnections.connectionPositions) {
157 GLHelper::drawShapeDottedContour(getType(), i, 0);
158 }
159 }
160 // Pop name
161 glPopName();
162 }
163
164
165 std::string
getAttribute(SumoXMLAttr key) const166 GNEDetectorE3::getAttribute(SumoXMLAttr key) const {
167 switch (key) {
168 case SUMO_ATTR_ID:
169 return getAdditionalID();
170 case SUMO_ATTR_POSITION:
171 return toString(myPosition);
172 case SUMO_ATTR_FREQUENCY:
173 return toString(myFreq);
174 case SUMO_ATTR_NAME:
175 return myAdditionalName;
176 case SUMO_ATTR_FILE:
177 return myFilename;
178 case SUMO_ATTR_VTYPES:
179 return myVehicleTypes;
180 case SUMO_ATTR_HALTING_TIME_THRESHOLD:
181 return toString(myTimeThreshold);
182 case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
183 return toString(mySpeedThreshold);
184 case GNE_ATTR_BLOCK_MOVEMENT:
185 return toString(myBlockMovement);
186 case GNE_ATTR_SELECTED:
187 return toString(isAttributeCarrierSelected());
188 case GNE_ATTR_GENERIC:
189 return getGenericParametersStr();
190 default:
191 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
192 }
193 }
194
195
196 void
setAttribute(SumoXMLAttr key,const std::string & value,GNEUndoList * undoList)197 GNEDetectorE3::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
198 if (value == getAttribute(key)) {
199 return; //avoid needless changes, later logic relies on the fact that attributes have changed
200 }
201 switch (key) {
202 case SUMO_ATTR_ID: {
203 // change ID of Entry
204 undoList->p_add(new GNEChange_Attribute(this, myViewNet->getNet(), key, value));
205 // Change Ids of all Entry/Exits childs
206 for (auto i : getAdditionalChilds()) {
207 i->setAttribute(SUMO_ATTR_ID, generateChildID(i->getTagProperty().getTag()), undoList);
208 }
209 break;
210 }
211 case SUMO_ATTR_FREQUENCY:
212 case SUMO_ATTR_POSITION:
213 case SUMO_ATTR_NAME:
214 case SUMO_ATTR_FILE:
215 case SUMO_ATTR_VTYPES:
216 case SUMO_ATTR_HALTING_TIME_THRESHOLD:
217 case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
218 case GNE_ATTR_BLOCK_MOVEMENT:
219 case GNE_ATTR_SELECTED:
220 case GNE_ATTR_GENERIC:
221 undoList->p_add(new GNEChange_Attribute(this, myViewNet->getNet(), key, value));
222 break;
223 default:
224 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
225 }
226 }
227
228
229 bool
isValid(SumoXMLAttr key,const std::string & value)230 GNEDetectorE3::isValid(SumoXMLAttr key, const std::string& value) {
231 switch (key) {
232 case SUMO_ATTR_ID:
233 return isValidDetectorID(value);
234 case SUMO_ATTR_POSITION:
235 return canParse<Position>(value);
236 case SUMO_ATTR_FREQUENCY:
237 return canParse<double>(value) && (parse<double>(value) >= 0);
238 case SUMO_ATTR_NAME:
239 return SUMOXMLDefinitions::isValidAttribute(value);
240 case SUMO_ATTR_FILE:
241 return SUMOXMLDefinitions::isValidFilename(value);
242 case SUMO_ATTR_VTYPES:
243 if (value.empty()) {
244 return true;
245 } else {
246 return SUMOXMLDefinitions::isValidListOfTypeID(value);
247 }
248 case SUMO_ATTR_HALTING_TIME_THRESHOLD:
249 return canParse<double>(value) && (parse<double>(value) >= 0);
250 case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
251 return canParse<double>(value) && (parse<double>(value) >= 0);
252 case GNE_ATTR_BLOCK_MOVEMENT:
253 return canParse<bool>(value);
254 case GNE_ATTR_SELECTED:
255 return canParse<bool>(value);
256 case GNE_ATTR_GENERIC:
257 return isGenericParametersValid(value);
258 default:
259 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
260 }
261 }
262
263
264 bool
checkAdditionalChildRestriction() const265 GNEDetectorE3::checkAdditionalChildRestriction() const {
266 int numEntrys = 0;
267 int numExits = 0;
268 // iterate over additional chidls and obtain number of entrys and exits
269 for (auto i : getAdditionalChilds()) {
270 if (i->getTagProperty().getTag() == SUMO_TAG_DET_ENTRY) {
271 numEntrys++;
272 } else if (i->getTagProperty().getTag() == SUMO_TAG_DET_EXIT) {
273 numExits++;
274 }
275 }
276 // write warnings
277 if (numEntrys == 0) {
278 WRITE_WARNING("An " + toString(SUMO_TAG_E3DETECTOR) + " need at least one " + toString(SUMO_TAG_DET_ENTRY) + " detector");
279 }
280 if (numExits == 0) {
281 WRITE_WARNING("An " + toString(SUMO_TAG_E3DETECTOR) + " need at least one " + toString(SUMO_TAG_DET_EXIT) + " detector");
282 }
283 // return false depending of number of Entrys and Exits
284 return ((numEntrys != 0) && (numExits != 0));
285 }
286
287
288 std::string
getPopUpID() const289 GNEDetectorE3::getPopUpID() const {
290 return getTagStr() + ":" + getID();
291 }
292
293
294 std::string
getHierarchyName() const295 GNEDetectorE3::getHierarchyName() const {
296 return getTagStr();
297 }
298
299 // ===========================================================================
300 // private
301 // ===========================================================================
302
303 void
setAttribute(SumoXMLAttr key,const std::string & value)304 GNEDetectorE3::setAttribute(SumoXMLAttr key, const std::string& value) {
305 switch (key) {
306 case SUMO_ATTR_ID:
307 changeAdditionalID(value);
308 break;
309 case SUMO_ATTR_POSITION:
310 myPosition = parse<Position>(value);
311 break;
312 case SUMO_ATTR_FREQUENCY:
313 myFreq = parse<double>(value);
314 break;
315 case SUMO_ATTR_NAME:
316 myAdditionalName = value;
317 break;
318 case SUMO_ATTR_FILE:
319 myFilename = value;
320 break;
321 case SUMO_ATTR_VTYPES:
322 myVehicleTypes = value;
323 break;
324 case SUMO_ATTR_HALTING_TIME_THRESHOLD:
325 myTimeThreshold = parse<double>(value);
326 break;
327 case SUMO_ATTR_HALTING_SPEED_THRESHOLD:
328 mySpeedThreshold = parse<double>(value);
329 break;
330 case GNE_ATTR_BLOCK_MOVEMENT:
331 myBlockMovement = parse<bool>(value);
332 break;
333 case GNE_ATTR_SELECTED:
334 if (parse<bool>(value)) {
335 selectAttributeCarrier();
336 } else {
337 unselectAttributeCarrier();
338 }
339 break;
340 case GNE_ATTR_GENERIC:
341 setGenericParametersStr(value);
342 break;
343 default:
344 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
345 }
346 // check if updated attribute requieres update geometry
347 if (myTagProperty.hasAttribute(key) && myTagProperty.getAttributeProperties(key).requiereUpdateGeometry()) {
348 updateGeometry(true);
349 }
350 }
351
352 /****************************************************************************/
353