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 GNEParkingArea.cpp
11 /// @author Pablo Alvarez Lopez
12 /// @date Feb 2018
13 /// @version $Id$
14 ///
15 // A lane area vehicles can park at (GNE version)
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/options/OptionsCont.h>
30 #include <utils/gui/globjects/GLIncludes.h>
31
32 #include "GNEParkingArea.h"
33
34
35 // ===========================================================================
36 // method definitions
37 // ===========================================================================
38
GNEParkingArea(const std::string & id,GNELane * lane,GNEViewNet * viewNet,const std::string & startPos,const std::string & endPos,const std::string & name,bool friendlyPosition,int roadSideCapacity,bool onRoad,double width,const std::string & length,double angle,bool blockMovement)39 GNEParkingArea::GNEParkingArea(const std::string& id, GNELane* lane, GNEViewNet* viewNet, const std::string& startPos, const std::string& endPos, const std::string& name,
40 bool friendlyPosition, int roadSideCapacity, bool onRoad, double width, const std::string& length, double angle, bool blockMovement) :
41 GNEStoppingPlace(id, viewNet, GLO_PARKING_AREA, SUMO_TAG_PARKING_AREA, lane, startPos, endPos, name, friendlyPosition, blockMovement),
42 myRoadSideCapacity(roadSideCapacity),
43 myOnRoad(onRoad),
44 myWidth(width),
45 myLength(length),
46 myAngle(angle) {
47 }
48
49
~GNEParkingArea()50 GNEParkingArea::~GNEParkingArea() {}
51
52
53 void
updateGeometry(bool updateGrid)54 GNEParkingArea::updateGeometry(bool updateGrid) {
55 // first check if object has to be removed from grid (SUMOTree)
56 if (updateGrid) {
57 myViewNet->getNet()->removeGLObjectFromGrid(this);
58 }
59
60 // Get value of option "lefthand"
61 double offsetSign = OptionsCont::getOptions().getBool("lefthand") ? -1 : 1;
62
63 // Update common geometry of stopping place
64 setStoppingPlaceGeometry(getLaneParents().front()->getParentEdge().getNBEdge()->getLaneWidth(getLaneParents().front()->getIndex()) / 2 + myWidth);
65
66 // Obtain a copy of the shape
67 PositionVector tmpShape = myGeometry.shape;
68
69 // Move shape to side
70 tmpShape.move2side(1.5 * offsetSign);
71
72 // Get position of the sign
73 mySignPos = tmpShape.getLineCenter();
74
75 // Set block icon position
76 myBlockIcon.position = myGeometry.shape.getLineCenter();
77
78 // Set block icon rotation, and using their rotation for sign
79 myBlockIcon.setRotation(getLaneParents().front());
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 void
drawGL(const GUIVisualizationSettings & s) const89 GNEParkingArea::drawGL(const GUIVisualizationSettings& s) const {
90 // obtain circle resolution
91 int circleResolution = getCircleResolution(s);
92 // Obtain exaggeration of the draw
93 const double exaggeration = s.addSize.getExaggeration(s, this);
94 // Push name
95 glPushName(getGlID());
96 // Push base matrix
97 glPushMatrix();
98 // Traslate matrix
99 glTranslated(0, 0, getType());
100 // Set Color
101 if (drawUsingSelectColor()) {
102 GLHelper::setColor(s.selectedAdditionalColor);
103 } else {
104 GLHelper::setColor(RGBColor(83, 89, 172, 255));
105 }
106 // Draw base
107 GLHelper::drawBoxLines(myGeometry.shape, myGeometry.shapeRotations, myGeometry.shapeLengths, myWidth * exaggeration);
108 // Check if the distance is enought to draw details and if is being drawn for selecting
109 if (s.drawForSelecting) {
110 // only draw circle depending of distance between sign and mouse cursor
111 if (myViewNet->getPositionInformation().distanceSquaredTo2D(mySignPos) <= (myCircleWidthSquared + 2)) {
112 // Add a draw matrix for details
113 glPushMatrix();
114 // Start drawing sign traslating matrix to signal position
115 glTranslated(mySignPos.x(), mySignPos.y(), 0);
116 // scale matrix depending of the exaggeration
117 glScaled(exaggeration, exaggeration, 1);
118 // set color
119 GLHelper::setColor(s.SUMO_color_busStop);
120 // Draw circle
121 GLHelper::drawFilledCircle(myCircleWidth, circleResolution);
122 // pop draw matrix
123 glPopMatrix();
124 }
125 } else if (s.scale * exaggeration >= 10) {
126 // Push matrix for details
127 glPushMatrix();
128 // Set position over sign
129 glTranslated(mySignPos.x(), mySignPos.y(), 0);
130 // Scale matrix
131 glScaled(exaggeration, exaggeration, 1);
132 // Set base color
133 if (drawUsingSelectColor()) {
134 GLHelper::setColor(s.selectedAdditionalColor);
135 } else {
136 GLHelper::setColor(RGBColor(83, 89, 172, 255));
137 }
138 // Draw extern
139 GLHelper::drawFilledCircle(myCircleWidth, circleResolution);
140 // Move to top
141 glTranslated(0, 0, .1);
142 // Set sign color
143 if (drawUsingSelectColor()) {
144 GLHelper::setColor(s.selectionColor);
145 } else {
146 GLHelper::setColor(RGBColor(177, 184, 186, 171));
147 }
148 // Draw internt sign
149 GLHelper::drawFilledCircle(myCircleInWidth, circleResolution);
150 // Draw sign 'C'
151 if (s.scale * exaggeration >= 4.5) {
152 if (drawUsingSelectColor()) {
153 GLHelper::drawText("P", Position(), .1, myCircleInText, s.selectedAdditionalColor, myBlockIcon.rotation);
154 } else {
155 GLHelper::drawText("P", Position(), .1, myCircleInText, RGBColor(83, 89, 172, 255), myBlockIcon.rotation);
156 }
157 }
158 // Pop sign matrix
159 glPopMatrix();
160 // Draw icon
161 myBlockIcon.draw();
162 }
163 // Pop base matrix
164 glPopMatrix();
165 // Draw name if isn't being drawn for selecting
166 drawName(getCenteringBoundary().getCenter(), s.scale, s.addName);
167 if (s.addFullName.show && (myAdditionalName != "") && !s.drawForSelecting) {
168 GLHelper::drawText(myAdditionalName, mySignPos, GLO_MAX - getType(), s.addFullName.scaledSize(s.scale), s.addFullName.color, myBlockIcon.rotation);
169 }
170 // check if dotted contour has to be drawn
171 if (!s.drawForSelecting && (myViewNet->getDottedAC() == this)) {
172 GLHelper::drawShapeDottedContour(getType(), myGeometry.shape, myWidth * exaggeration);
173 }
174 // Pop name matrix
175 glPopName();
176 }
177
178
179 std::string
getAttribute(SumoXMLAttr key) const180 GNEParkingArea::getAttribute(SumoXMLAttr key) const {
181 switch (key) {
182 case SUMO_ATTR_ID:
183 return getAdditionalID();
184 case SUMO_ATTR_LANE:
185 return getLaneParents().front()->getID();
186 case SUMO_ATTR_STARTPOS:
187 return toString(myStartPosition);
188 case SUMO_ATTR_ENDPOS:
189 return myEndPosition;
190 case SUMO_ATTR_NAME:
191 return myAdditionalName;
192 case SUMO_ATTR_FRIENDLY_POS:
193 return toString(myFriendlyPosition);
194 case SUMO_ATTR_ROADSIDE_CAPACITY:
195 return toString(myRoadSideCapacity);
196 case SUMO_ATTR_ONROAD:
197 return toString(myOnRoad);
198 case SUMO_ATTR_WIDTH:
199 return toString(myWidth);
200 case SUMO_ATTR_LENGTH:
201 return myLength;
202 case SUMO_ATTR_ANGLE:
203 return toString(myAngle);
204 case GNE_ATTR_BLOCK_MOVEMENT:
205 return toString(myBlockMovement);
206 case GNE_ATTR_SELECTED:
207 return toString(isAttributeCarrierSelected());
208 case GNE_ATTR_GENERIC:
209 return getGenericParametersStr();
210 default:
211 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
212 }
213 }
214
215
216 void
setAttribute(SumoXMLAttr key,const std::string & value,GNEUndoList * undoList)217 GNEParkingArea::setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
218 if (value == getAttribute(key)) {
219 return; //avoid needless changes, later logic relies on the fact that attributes have changed
220 }
221 switch (key) {
222 case SUMO_ATTR_ID: {
223 // change ID of Entry
224 undoList->p_add(new GNEChange_Attribute(this, myViewNet->getNet(), key, value));
225 // Change Ids of all Parking Spaces
226 for (auto i : getAdditionalChilds()) {
227 i->setAttribute(SUMO_ATTR_ID, generateChildID(SUMO_TAG_PARKING_SPACE), undoList);
228 }
229 break;
230 }
231 case SUMO_ATTR_LANE:
232 case SUMO_ATTR_STARTPOS:
233 case SUMO_ATTR_ENDPOS:
234 case SUMO_ATTR_NAME:
235 case SUMO_ATTR_FRIENDLY_POS:
236 case SUMO_ATTR_ROADSIDE_CAPACITY:
237 case SUMO_ATTR_ONROAD:
238 case SUMO_ATTR_WIDTH:
239 case SUMO_ATTR_LENGTH:
240 case SUMO_ATTR_ANGLE:
241 case GNE_ATTR_BLOCK_MOVEMENT:
242 case GNE_ATTR_SELECTED:
243 case GNE_ATTR_GENERIC:
244 undoList->p_add(new GNEChange_Attribute(this, myViewNet->getNet(), key, value));
245 break;
246 default:
247 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
248 }
249 }
250
251
252 bool
isValid(SumoXMLAttr key,const std::string & value)253 GNEParkingArea::isValid(SumoXMLAttr key, const std::string& value) {
254 switch (key) {
255 case SUMO_ATTR_ID:
256 return isValidAdditionalID(value);
257 case SUMO_ATTR_LANE:
258 if (myViewNet->getNet()->retrieveLane(value, false) != nullptr) {
259 return true;
260 } else {
261 return false;
262 }
263 case SUMO_ATTR_STARTPOS:
264 if (value.empty()) {
265 return true;
266 } else if (canParse<double>(value)) {
267 return checkStoppinPlacePosition(value, myEndPosition, getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength(), myFriendlyPosition);
268 } else {
269 return false;
270 }
271 case SUMO_ATTR_ENDPOS:
272 if (value.empty()) {
273 return true;
274 } else if (canParse<double>(value)) {
275 return checkStoppinPlacePosition(myStartPosition, value, getLaneParents().front()->getParentEdge().getNBEdge()->getFinalLength(), myFriendlyPosition);
276 } else {
277 return false;
278 }
279 case SUMO_ATTR_NAME:
280 return SUMOXMLDefinitions::isValidAttribute(value);
281 case SUMO_ATTR_FRIENDLY_POS:
282 return canParse<bool>(value);
283 case SUMO_ATTR_ROADSIDE_CAPACITY:
284 return canParse<double>(value) && (parse<double>(value) >= 0);
285 case SUMO_ATTR_ONROAD:
286 return canParse<bool>(value);
287 case SUMO_ATTR_WIDTH:
288 return canParse<double>(value) && (parse<double>(value) >= 0);
289 case SUMO_ATTR_LENGTH:
290 if (value.empty()) {
291 return true;
292 } else {
293 return canParse<double>(value) && (parse<double>(value) >= 0);
294 }
295 case SUMO_ATTR_ANGLE:
296 return canParse<double>(value);
297 case GNE_ATTR_BLOCK_MOVEMENT:
298 return canParse<bool>(value);
299 case GNE_ATTR_SELECTED:
300 return canParse<bool>(value);
301 case GNE_ATTR_GENERIC:
302 return isGenericParametersValid(value);
303 default:
304 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
305 }
306 }
307
308 // ===========================================================================
309 // private
310 // ===========================================================================
311
312 void
setAttribute(SumoXMLAttr key,const std::string & value)313 GNEParkingArea::setAttribute(SumoXMLAttr key, const std::string& value) {
314 switch (key) {
315 case SUMO_ATTR_ID:
316 changeAdditionalID(value);
317 break;
318 case SUMO_ATTR_LANE:
319 changeLaneParents(this, value);
320 break;
321 case SUMO_ATTR_STARTPOS:
322 myStartPosition = value;
323 break;
324 case SUMO_ATTR_ENDPOS:
325 myEndPosition = value;
326 break;
327 case SUMO_ATTR_NAME:
328 myAdditionalName = value;
329 break;
330 case SUMO_ATTR_FRIENDLY_POS:
331 myFriendlyPosition = parse<bool>(value);
332 break;
333 case SUMO_ATTR_ROADSIDE_CAPACITY:
334 myRoadSideCapacity = parse<int>(value);
335 break;
336 case SUMO_ATTR_ONROAD:
337 myOnRoad = parse<bool>(value);
338 break;
339 case SUMO_ATTR_WIDTH:
340 myWidth = parse<double>(value);
341 break;
342 case SUMO_ATTR_LENGTH:
343 myLength = value;
344 break;
345 case SUMO_ATTR_ANGLE:
346 myAngle = parse<double>(value);
347 break;
348 case GNE_ATTR_BLOCK_MOVEMENT:
349 myBlockMovement = parse<bool>(value);
350 break;
351 case GNE_ATTR_SELECTED:
352 if (parse<bool>(value)) {
353 selectAttributeCarrier();
354 } else {
355 unselectAttributeCarrier();
356 }
357 break;
358 case GNE_ATTR_GENERIC:
359 setGenericParametersStr(value);
360 break;
361 default:
362 throw InvalidArgument(getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
363 }
364 // check if updated attribute requieres update geometry
365 if (myTagProperty.hasAttribute(key) && myTagProperty.getAttributeProperties(key).requiereUpdateGeometry()) {
366 updateGeometry(true);
367 }
368 }
369
370
371 /****************************************************************************/
372