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