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