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    GNEVaporizer.cpp
11 /// @author  Pablo Alvarez Lopez
12 /// @date    Jun 2016
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 <netedit/netelements/GNELane.h>
28 #include <utils/gui/div/GLHelper.h>
29 #include <utils/gui/images/GUITextureSubSys.h>
30 #include <utils/gui/globjects/GLIncludes.h>
31 
32 #include "GNEVaporizer.h"
33 
34 
35 // ===========================================================================
36 // member method definitions
37 // ===========================================================================
38 
GNEVaporizer(GNEViewNet * viewNet,GNEEdge * edge,double begin,double end,const std::string & name)39 GNEVaporizer::GNEVaporizer(GNEViewNet* viewNet, GNEEdge* edge, double begin, double end, const std::string& name) :
40     GNEAdditional(edge->getID(), viewNet, GLO_VAPORIZER, SUMO_TAG_VAPORIZER, name, false, {
41     edge
42 }, {}, {}, {}, {}, {}, {}, {}, {}, {}),
43 myBegin(begin),
44 myEnd(end) {
45 }
46 
47 
~GNEVaporizer()48 GNEVaporizer::~GNEVaporizer() {
49 }
50 
51 
52 void
updateGeometry(bool updateGrid)53 GNEVaporizer::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 all containers
60     myGeometry.clearGeometry();
61 
62     // get lanes of edge
63     GNELane* firstLane = getEdgeParents().front()->getLanes().at(0);
64 
65     // Get shape of lane parent
66     double offset = firstLane->getShape().length() < 2.5 ? firstLane->getShape().length() : 2.5;
67     myGeometry.shape.push_back(firstLane->getShape().positionAtOffset(offset));
68 
69     // Save rotation (angle) of the vector constructed by points f and s
70     myGeometry.shapeRotations.push_back(firstLane->getShape().rotationDegreeAtOffset(0) * -1);
71 
72     // Set block icon position
73     myBlockIcon.position = myGeometry.shape.getLineCenter();
74 
75     // Set offset of the block icon
76     myBlockIcon.offset = Position(1.1, (-3.06));
77 
78     // Set block icon rotation, and using their rotation for logo
79     myBlockIcon.setRotation(firstLane);
80 
81     // last step is to check if object has to be added into grid (SUMOTree) again
82     if (updateGrid) {
83         myViewNet->getNet()->addGLObjectIntoGrid(this);
84     }
85 }
86 
87 
88 Position
getPositionInView() const89 GNEVaporizer::getPositionInView() const {
90     if (getEdgeParents().front()->getLanes().front()->getShape().length() < 2.5) {
91         return getEdgeParents().front()->getLanes().front()->getShape().front();
92     } else {
93         Position A = getEdgeParents().front()->getLanes().front()->getShape().positionAtOffset(2.5);
94         Position B = getEdgeParents().front()->getLanes().back()->getShape().positionAtOffset(2.5);
95 
96         // return Middle point
97         return Position((A.x() + B.x()) / 2, (A.y() + B.y()) / 2);
98     }
99 }
100 
101 
102 void
moveGeometry(const Position &)103 GNEVaporizer::moveGeometry(const Position&) {
104     // This additional cannot be moved
105 }
106 
107 
108 void
commitGeometryMoving(GNEUndoList *)109 GNEVaporizer::commitGeometryMoving(GNEUndoList*) {
110     // This additional cannot be moved
111 }
112 
113 
114 std::string
getParentName() const115 GNEVaporizer::getParentName() const {
116     return getEdgeParents().front()->getMicrosimID();
117 }
118 
119 
120 void
drawGL(const GUIVisualizationSettings & s) const121 GNEVaporizer::drawGL(const GUIVisualizationSettings& s) const {
122     // get values
123     glPushName(getGlID());
124     double width = (double) 2.0 * s.scale;
125     glLineWidth(1.0);
126     const double exaggeration = s.addSize.getExaggeration(s, this);
127     const int numberOfLanes = int(getEdgeParents().front()->getLanes().size());
128 
129     // set color
130     if (drawUsingSelectColor()) {
131         GLHelper::setColor(s.selectedAdditionalColor);
132     } else {
133         GLHelper::setColor(RGBColor(120, 216, 0));
134     }
135     // draw shape
136     glPushMatrix();
137     glTranslated(0, 0, getType());
138     glTranslated(myGeometry.shape[0].x(), myGeometry.shape[0].y(), 0);
139     glRotated(myGeometry.shapeRotations[0], 0, 0, 1);
140     glScaled(exaggeration, exaggeration, 1);
141     glTranslated(-1.6, -1.6, 0);
142     glBegin(GL_QUADS);
143     glVertex2d(0,  0.25);
144     glVertex2d(0, -0.25);
145     glVertex2d((numberOfLanes * 3.3), -0.25);
146     glVertex2d((numberOfLanes * 3.3),  0.25);
147     glEnd();
148     glTranslated(0, 0, .01);
149     glBegin(GL_LINES);
150     glVertex2d(0, 0.25 - .1);
151     glVertex2d(0, -0.25 + .1);
152     glEnd();
153 
154     // draw position indicator (White) if isn't being drawn for selecting
155     if ((width * exaggeration > 1) && !s.drawForSelecting) {
156         if (drawUsingSelectColor()) {
157             GLHelper::setColor(s.selectionColor);
158         } else {
159             GLHelper::setColor(RGBColor::WHITE);
160         }
161         glRotated(90, 0, 0, -1);
162         glBegin(GL_LINES);
163         glVertex2d(0, 0);
164         glVertex2d(0, (numberOfLanes * 3.3));
165         glEnd();
166     }
167 
168     // Pop shape matrix
169     glPopMatrix();
170 
171     // Add a draw matrix for drawing logo
172     glPushMatrix();
173     glTranslated(myGeometry.shape[0].x(), myGeometry.shape[0].y(), getType());
174     glRotated(myGeometry.shapeRotations[0], 0, 0, 1);
175     glTranslated((-2.56), (-1.6), 0);
176 
177     // Draw icon depending of Vaporizer is selected and if isn't being drawn for selecting
178     if (s.drawForSelecting) {
179         GLHelper::setColor(RGBColor::GREEN);
180         GLHelper::drawBoxLine(Position(0, 1), 0, 2, 1);
181     } else {
182         glColor3d(1, 1, 1);
183         glRotated(-90, 0, 0, 1);
184         if (drawUsingSelectColor()) {
185             GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GNETEXTURE_VAPORIZERSELECTED), 1);
186         } else {
187             GUITexturesHelper::drawTexturedBox(GUITextureSubSys::getTexture(GNETEXTURE_VAPORIZER), 1);
188         }
189     }
190 
191     // Pop logo matrix
192     glPopMatrix();
193 
194     // Check if the distance is enought to draw details
195     if ((s.scale * exaggeration >= 10) && !s.drawForSelecting) {
196         // Show Lock icon depending of the Edit mode
197         myBlockIcon.draw(0.4);
198     }
199 
200     // draw name
201     drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
202 
203     // check if dotted contour has to be drawn
204     if (!s.drawForSelecting && (myViewNet->getDottedAC() == this)) {
205         GLHelper::drawShapeDottedContour(getType(), myGeometry.shape[0], 2, 2, myGeometry.shapeRotations[0], -2.56, -1.6);
206     }
207 
208     // pop name
209     glPopName();
210 }
211 
212 
213 std::string
getAttribute(SumoXMLAttr key) const214 GNEVaporizer::getAttribute(SumoXMLAttr key) const {
215     switch (key) {
216         case SUMO_ATTR_ID:
217         case SUMO_ATTR_EDGE:
218             return getAdditionalID();
219         case SUMO_ATTR_BEGIN:
220             return toString(myBegin);
221         case SUMO_ATTR_END:
222             return toString(myEnd);
223         case SUMO_ATTR_NAME:
224             return myAdditionalName;
225         case GNE_ATTR_SELECTED:
226             return toString(isAttributeCarrierSelected());
227         case GNE_ATTR_GENERIC:
228             return getGenericParametersStr();
229         default:
230             throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
231     }
232 }
233 
234 
235 void
setAttribute(SumoXMLAttr key,const std::string & value,GNEUndoList * undoList)236 GNEVaporizer::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
237     if (value == getAttribute(key)) {
238         return; //avoid needless changes, later logic relies on the fact that attributes have changed
239     }
240     switch (key) {
241         case SUMO_ATTR_ID:
242         case SUMO_ATTR_EDGE:
243         case SUMO_ATTR_BEGIN:
244         case SUMO_ATTR_END:
245         case SUMO_ATTR_NAME:
246         case GNE_ATTR_SELECTED:
247         case GNE_ATTR_GENERIC:
248             undoList->p_add(new GNEChange_Attribute(this, myViewNet->getNet(), key, value));
249             break;
250         default:
251             throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
252     }
253 }
254 
255 
256 bool
isValid(SumoXMLAttr key,const std::string & value)257 GNEVaporizer::isValid(SumoXMLAttr key, const std::string& value) {
258     switch (key) {
259         case SUMO_ATTR_ID:
260         case SUMO_ATTR_EDGE:
261             if (myViewNet->getNet()->retrieveEdge(value, false) != nullptr) {
262                 return isValidAdditionalID(value);
263             } else {
264                 return false;
265             }
266         case SUMO_ATTR_BEGIN:
267             if (canParse<double>(value) && (parse<double>(value) >= 0)) {
268                 return (parse<double>(value) <= myEnd);
269             } else {
270                 return false;
271             }
272         case SUMO_ATTR_END:
273             if (canParse<double>(value) && (parse<double>(value) >= 0)) {
274                 return (myBegin <= parse<double>(value));
275             } else {
276                 return false;
277             }
278         case SUMO_ATTR_NAME:
279             return SUMOXMLDefinitions::isValidAttribute(value);
280         case GNE_ATTR_SELECTED:
281             return canParse<bool>(value);
282         case GNE_ATTR_GENERIC:
283             return isGenericParametersValid(value);
284         default:
285             throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
286     }
287 }
288 
289 
290 std::string
getPopUpID() const291 GNEVaporizer::getPopUpID() const {
292     return getTagStr();
293 }
294 
295 
296 std::string
getHierarchyName() const297 GNEVaporizer::getHierarchyName() const {
298     return getTagStr() + ": " + getAttribute(SUMO_ATTR_BEGIN) + " -> " + getAttribute(SUMO_ATTR_END);
299 }
300 
301 // ===========================================================================
302 // private
303 // ===========================================================================
304 
305 void
setAttribute(SumoXMLAttr key,const std::string & value)306 GNEVaporizer::setAttribute(SumoXMLAttr key, const std::string& value) {
307     switch (key) {
308         case SUMO_ATTR_ID:
309         case SUMO_ATTR_EDGE:
310             changeAdditionalID(value);
311             changeEdgeParents(this, value);
312             break;
313         case SUMO_ATTR_BEGIN:
314             myBegin = parse<double>(value);
315             break;
316         case SUMO_ATTR_END:
317             myEnd = parse<double>(value);
318             break;
319         case SUMO_ATTR_NAME:
320             myAdditionalName = value;
321             break;
322         case GNE_ATTR_SELECTED:
323             if (parse<bool>(value)) {
324                 selectAttributeCarrier();
325             } else {
326                 unselectAttributeCarrier();
327             }
328             break;
329         case GNE_ATTR_GENERIC:
330             setGenericParametersStr(value);
331             break;
332         default:
333             throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
334     }
335     // check if updated attribute requieres update geometry
336     if (myTagProperty.hasAttribute(key) && myTagProperty.getAttributeProperties(key).requiereUpdateGeometry()) {
337         updateGeometry(true);
338     }
339 }
340 
341 /****************************************************************************/
342