Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
GNEDemandElementFlow.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
18// An auxiliar, asbtract class for flow elements (vehicles, person and containers)
19/****************************************************************************/
20
22#include <netedit/GNEUndoList.h>
26
28
29// ===========================================================================
30// member method definitions
31// ===========================================================================
32
34 // set default flow attributes
35 setDefaultFlowAttributes(flowElement);
36}
37
38
40 SUMOVehicleParameter(vehicleParameters) {
41 // set default flow attributes
42 setDefaultFlowAttributes(flowElement);
43}
44
45
47
48
49void
50GNEDemandElementFlow::drawFlowLabel(const Position& position, const double rotation, const double width,
51 const double length, const double exaggeration) const {
52 // declare contour width
53 const double contourWidth = (0.05 * exaggeration);
54 // Push matrix
56 // Traslate to bot
57 glTranslated(position.x(), position.y(), GLO_VEHICLELABELS);
58 // glTranslated(position.x(), position.y(), GLO_ROUTE + getType() + 0.1 + GLO_PERSONFLOW + 0.1);
59 glRotated(rotation, 0, 0, -1);
60 glTranslated(-1 * ((width * 0.5 * exaggeration) + (0.35 * exaggeration)) - 0.05, 0, 0);
61 // draw external box
63 GLHelper::drawBoxLine(Position(), Position(), 0, (length * exaggeration), 0.3 * exaggeration);
64 // draw internal box
65 glTranslated(0, 0, 0.1);
67 GLHelper::drawBoxLine(Position(0, -contourWidth), Position(0, -contourWidth), 0, (length * exaggeration) - (contourWidth * 2), (0.3 * exaggeration) - contourWidth);
68 // draw stack label
69 GLHelper::drawText("Flow", Position(0, length * exaggeration * -0.5), (.1 * exaggeration), (0.6 * exaggeration), RGBColor::BLACK, 90, 0, -1);
70 // pop draw matrix
72}
73
74
75void
77 // get xph attribute
79 if (flowElement->getTagProperty()->isPerson()) {
81 } else if (flowElement->getTagProperty()->isContainer()) {
83 }
84 // first check that we're writting a flow
85 if (flowElement->getTagProperty()->isFlow()) {
86 // write routeFlow values depending if it was set
89 }
92 }
93 if (isFlowAttributeEnabled(xph)) {
94 device.writeAttr(xph, getFlowAttribute(flowElement, xph));
95 }
98 }
100 device.writeAttr(SUMO_ATTR_PERIOD, "exp(" + getFlowAttribute(flowElement, GNE_ATTR_POISSON) + ")");
101 }
104 }
105 }
106}
107
108
109std::string
111 switch (key) {
112 case SUMO_ATTR_DEPART:
113 case SUMO_ATTR_BEGIN:
115 return "triggered";
117 return "containerTriggered";
119 return "now";
121 return "split";
123 return "begin";
124 } else {
125 return time2string(depart);
126 }
127 case SUMO_ATTR_END:
133 case SUMO_ATTR_PERIOD:
135 case GNE_ATTR_POISSON:
137 case SUMO_ATTR_PROB:
139 case SUMO_ATTR_NUMBER:
145 } else {
146 return toString(SUMO_ATTR_END);
147 }
150 } else {
151 return "invalid terminate";
152 }
163 return toString(SUMO_ATTR_PROB);
166 } else {
167 return "invalid flow spacing";
168 }
169 default:
170 return flowElement->getCommonAttribute(this, key);
171 }
172}
173
174
175double
177 switch (key) {
178 case SUMO_ATTR_DEPART:
179 case SUMO_ATTR_BEGIN:
180 return STEPS2TIME(depart);
181 default:
182 throw InvalidArgument("Flow doesn't have a double attribute of type '" + toString(key) + "'");
183 }
184}
185
186
187void
188GNEDemandElementFlow::setFlowAttribute(GNEDemandElement* flowElement, SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) {
189 switch (key) {
190 case SUMO_ATTR_DEPART:
191 case SUMO_ATTR_BEGIN:
192 case SUMO_ATTR_END:
193 case SUMO_ATTR_NUMBER:
197 case SUMO_ATTR_PERIOD:
198 case GNE_ATTR_POISSON:
199 case SUMO_ATTR_PROB:
202 GNEChange_Attribute::changeAttribute(flowElement, key, value, undoList);
203 break;
204 default:
205 return flowElement->setCommonAttribute(key, value, undoList);
206 break;
207 }
208}
209
210
211bool
212GNEDemandElementFlow::isValidFlowAttribute(GNEDemandElement* flowElement, SumoXMLAttr key, const std::string& value) {
213 // declare string error
214 std::string error;
215 switch (key) {
216 case SUMO_ATTR_DEPART:
217 case SUMO_ATTR_BEGIN: {
218 SUMOTime dummyDepart;
219 DepartDefinition dummyDepartProcedure;
220 parseDepart(value, flowElement->getTagProperty()->getTagStr(), id, dummyDepart, dummyDepartProcedure, error);
221 // if error is empty, given value is valid
222 return error.empty();
223 }
224 case SUMO_ATTR_END:
225 if (GNEAttributeCarrier::canParse<SUMOTime>(value)) {
226 return (GNEAttributeCarrier::parse<SUMOTime>(value) >= 0);
227 } else {
228 return false;
229 }
233 case SUMO_ATTR_PERIOD:
234 case GNE_ATTR_POISSON:
235 if (GNEAttributeCarrier::canParse<double>(value)) {
236 return (GNEAttributeCarrier::parse<double>(value) > 0);
237 } else {
238 return false;
239 }
240 case SUMO_ATTR_PROB:
241 if (GNEAttributeCarrier::canParse<double>(value)) {
242 const double prob = GNEAttributeCarrier::parse<double>(value);
243 return ((prob >= 0) && (prob <= 1));
244 } else {
245 return false;
246 }
247 case SUMO_ATTR_NUMBER:
248 if (GNEAttributeCarrier::canParse<int>(value)) {
249 return (GNEAttributeCarrier::parse<int>(value) >= 0);
250 } else {
251 return false;
252 }
255 const auto& flowValues = flowElement->getTagProperty()->getAttributeProperties(key)->getDiscreteValues();
256 if (std::find(flowValues.begin(), flowValues.end(), value) != flowValues.end()) {
257 return true;
258 } else {
259 return false;
260 }
261 }
262 default:
263 return flowElement->isCommonValid(key, value);
264 }
265}
266
267
268void
270 switch (key) {
271 case SUMO_ATTR_END:
272 case SUMO_ATTR_NUMBER:
276 case SUMO_ATTR_PERIOD:
277 case GNE_ATTR_POISSON:
278 case SUMO_ATTR_PROB:
279 undoList->add(new GNEChange_ToggleAttribute(flowElement, key, true), true);
280 return;
281 default:
282 throw InvalidArgument(flowElement->getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
283 }
284}
285
286
287void
289 switch (key) {
290 case SUMO_ATTR_END:
291 case SUMO_ATTR_NUMBER:
295 case SUMO_ATTR_PERIOD:
296 case GNE_ATTR_POISSON:
297 case SUMO_ATTR_PROB:
298 undoList->add(new GNEChange_ToggleAttribute(flowElement, key, false), true);
299 return;
300 default:
301 throw InvalidArgument(flowElement->getTagStr() + " doesn't have an attribute of type '" + toString(key) + "'");
302 }
303}
304
305
306bool
308 switch (key) {
309 case SUMO_ATTR_END:
310 return (parametersSet & VEHPARS_END_SET) != 0;
311 case SUMO_ATTR_NUMBER:
312 return (parametersSet & VEHPARS_NUMBER_SET) != 0;
316 return (parametersSet & VEHPARS_VPH_SET) != 0;
317 case SUMO_ATTR_PERIOD:
318 return (parametersSet & VEHPARS_PERIOD_SET) != 0;
319 case GNE_ATTR_POISSON:
320 return (parametersSet & VEHPARS_POISSON_SET) != 0;
321 case SUMO_ATTR_PROB:
322 return (parametersSet & VEHPARS_PROB_SET) != 0;
325 default:
326 return true;
327 }
328}
329
330
331void
332GNEDemandElementFlow::setFlowAttribute(GNEDemandElement* flowElement, SumoXMLAttr key, const std::string& value) {
333 // declare string error
334 std::string error;
335 switch (key) {
336 case SUMO_ATTR_DEPART:
337 case SUMO_ATTR_BEGIN: {
338 parseDepart(value, flowElement->getTagProperty()->getTagStr(), id, depart, departProcedure, error);
339 break;
340 }
341 case SUMO_ATTR_END:
342 repetitionEnd = string2time(value);
343 break;
347 repetitionOffset = TIME2STEPS(3600 / GNEAttributeCarrier::parse<double>(value));
348 poissonRate = GNEAttributeCarrier::parse<double>(value) / 3600;
349 break;
350 case SUMO_ATTR_PERIOD:
353 break;
354 case GNE_ATTR_POISSON:
355 poissonRate = GNEAttributeCarrier::parse<double>(value);
357 break;
358 case SUMO_ATTR_PROB:
359 repetitionProbability = GNEAttributeCarrier::parse<double>(value);
360 break;
361 case SUMO_ATTR_NUMBER:
362 repetitionNumber = GNEAttributeCarrier::parse<int>(value);
363 break;
365 if (value == (toString(SUMO_ATTR_END) + "-" + toString(SUMO_ATTR_NUMBER))) {
368 // in this special case, disable other spacing
373 } else {
374 // if previously end-number was enabled, enable perHour
377 }
378 if (value == toString(SUMO_ATTR_END)) {
381 } else if (value == toString(SUMO_ATTR_NUMBER)) {
384 }
385 }
386 break;
388 if ((value == toString(SUMO_ATTR_VEHSPERHOUR)) ||
395 } else if (value == toString(SUMO_ATTR_PERIOD)) {
400 } else if (value == toString(GNE_ATTR_POISSON)) {
405 } else if (value == toString(SUMO_ATTR_PROB)) {
410 }
411 break;
412 default:
413 flowElement->setCommonAttribute(this, key, value);
414 break;
415 }
416}
417
418
419void
420GNEDemandElementFlow::toggleFlowAttribute(const SumoXMLAttr attribute, const bool value) {
421 // modify parameters depending of given Flow attribute
422 if (value) {
423 switch (attribute) {
424 case SUMO_ATTR_END:
426 break;
427 case SUMO_ATTR_NUMBER:
429 break;
434 break;
435 case SUMO_ATTR_PERIOD:
437 break;
438 case GNE_ATTR_POISSON:
440 break;
441 case SUMO_ATTR_PROB:
443 break;
444 default:
445 break;
446 }
447 } else {
448 switch (attribute) {
449 case SUMO_ATTR_END:
450 parametersSet &= ~VEHPARS_END_SET;
451 break;
452 case SUMO_ATTR_NUMBER:
453 parametersSet &= ~VEHPARS_NUMBER_SET;
454 break;
458 parametersSet &= ~VEHPARS_VPH_SET;
459 break;
460 case SUMO_ATTR_PERIOD:
461 parametersSet &= ~VEHPARS_PERIOD_SET;
462 break;
463 case GNE_ATTR_POISSON:
464 parametersSet &= ~VEHPARS_POISSON_SET;
465 break;
466 case SUMO_ATTR_PROB:
467 parametersSet &= ~VEHPARS_PROB_SET;
468 break;
469 default:
470 break;
471 }
472 }
473}
474
475
476void
478 // first check that this demand element is a flow
479 if (flowElement->getTagProperty()->isFlow()) {
480 // end
481 if ((parametersSet & VEHPARS_END_SET) == 0) {
483 }
484 // number
485 if ((parametersSet & VEHPARS_NUMBER_SET) == 0) {
487 }
488 // vehicles/person/container per hour
489 if (((parametersSet & VEHPARS_PERIOD_SET) == 0) &&
491 ((parametersSet & VEHPARS_VPH_SET) == 0)) {
493 }
494 // probability
495 if ((parametersSet & VEHPARS_PROB_SET) == 0) {
497 }
498 // poisson
499 if (repetitionOffset < 0) {
503 } else {
505 }
506 }
507}
508
509std::string
510GNEDemandElementFlow::adjustDecimalValue(const double value, const int precission) const {
511 // obtain value in string format with 20 decimals precision
512 auto valueStr = toString(value, precission);
513 // now clear all zeros
514 while (valueStr.size() > 1) {
515 if (valueStr.back() == '0') {
516 valueStr.pop_back();
517 } else if (valueStr.back() == '.') {
518 valueStr.pop_back();
519 return valueStr;
520 } else {
521 return valueStr;
522 }
523 }
524 return valueStr;
525}
526
527/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
@ GLO_VEHICLELABELS
stack and flow labels (used in netedit)
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define STEPS2TIME(x)
Definition SUMOTime.h:55
#define TIME2STEPS(x)
Definition SUMOTime.h:57
const long long int VEHPARS_END_SET
const long long int VEHPARS_PERIOD_SET
const long long int VEHPARS_POISSON_SET
const long long int VEHPARS_PROB_SET
const long long int VEHPARS_VPH_SET
const long long int VEHPARS_NUMBER_SET
DepartDefinition
Possible ways to depart.
@ BEGIN
The departure is at simulation start.
@ NOW
The vehicle is discarded if emission fails (not fully implemented yet)
@ SPLIT
The departure is triggered by a train split.
@ CONTAINER_TRIGGERED
The departure is container triggered.
@ TRIGGERED
The departure is person triggered.
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_NUMBER
@ SUMO_ATTR_DEPART
@ SUMO_ATTR_VEHSPERHOUR
@ SUMO_ATTR_BEGIN
weights: time range begin
@ GNE_ATTR_POISSON
poisson definition (used in flow)
@ SUMO_ATTR_CONTAINERSPERHOUR
@ SUMO_ATTR_PERIOD
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_PROB
@ GNE_ATTR_FLOW_SPACING
flow spacing
@ GNE_ATTR_FLOW_TERMINATE
flow terminating
@ SUMO_ATTR_PERSONSPERHOUR
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition GLHelper.cpp:649
static void popMatrix()
pop matrix
Definition GLHelper.cpp:131
static void drawBoxLine(const Position &beg, double rot, double visLength, double width, double offset=0)
Draws a thick line.
Definition GLHelper.cpp:296
static void pushMatrix()
push matrix
Definition GLHelper.cpp:118
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, const int align=0, double width=-1)
Definition GLHelper.cpp:748
std::string getCommonAttribute(const Parameterised *parameterised, SumoXMLAttr key) const
void setCommonAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
const std::string & getTagStr() const
get tag assigned to this object in string format
const GNETagProperties * getTagProperty() const
get tagProperty associated with this Attribute Carrier
bool isCommonValid(SumoXMLAttr key, const std::string &value) const
static void changeAttribute(GNEAttributeCarrier *AC, SumoXMLAttr key, const std::string &value, GNEUndoList *undoList, const bool force=false)
change attribute
the function-object for an editing operation (abstract base)
void toggleFlowAttribute(const SumoXMLAttr attribute, const bool value)
toggle flow parameters (used in toggleAttribute(...) function of vehicles, persons and containers
void drawFlowLabel(const Position &position, const double rotation, const double width, const double length, const double exaggeration) const
draw flow label
std::string getFlowAttribute(const GNEDemandElement *flowElement, SumoXMLAttr key) const
inherited from GNEAttributeCarrier and adapted to GNEDemandElementFlow
void disableFlowAttribute(GNEDemandElement *flowElement, SumoXMLAttr key, GNEUndoList *undoList)
bool isFlowAttributeEnabled(SumoXMLAttr key) const
double getFlowAttributeDouble(SumoXMLAttr key) const
GNEDemandElementFlow(GNEDemandElement *flowElement)
constructor
bool isValidFlowAttribute(GNEDemandElement *flowElement, SumoXMLAttr key, const std::string &value)
void writeFlowAttributes(const GNEDemandElement *flowElement, OutputDevice &device) const
write flow attributes
std::string adjustDecimalValue(const double value, const int precission) const
adjust decimal value
void enableFlowAttribute(GNEDemandElement *flowElement, SumoXMLAttr key, GNEUndoList *undoList)
void setFlowAttribute(GNEDemandElement *flowElement, SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)
void setDefaultFlowAttributes(GNEDemandElement *flowElement)
set flow default attributes
bool isContainer() const
return true if tag correspond to a container element
bool isFlow() const
return true if tag correspond to a flow element
const std::string & getTagStr() const
get Tag vinculated with this attribute Property in String Format (used to avoid multiple calls to toS...
const std::vector< const GNEAttributeProperties * > & getAttributeProperties() const
get all attribute properties
bool hasAttribute(SumoXMLAttr attr) const
check if current TagProperties owns the attribute "attr"
bool isPerson() const
return true if tag correspond to a person element
const std::string & getDefaultStringValue(SumoXMLAttr attr) const
default values
void add(GNEChange *command, bool doit=false, bool merge=true)
Add new command, executing it if desired. The new command will be merged with the previous command if...
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
double x() const
Returns the x-position.
Definition Position.h:52
double y() const
Returns the y-position.
Definition Position.h:57
static const RGBColor GREY
Definition RGBColor.h:197
static const RGBColor CYAN
Definition RGBColor.h:192
static const RGBColor BLACK
Definition RGBColor.h:196
Structure representing possible vehicle parameter.
double repetitionProbability
The probability for emitting a vehicle per second.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
long long int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
double poissonRate
The rate for emitting vehicles with a poisson distribution.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
static bool parseDepart(const std::string &val, const std::string &element, const std::string &id, SUMOTime &depart, DepartDefinition &dd, std::string &error, const std::string &attr="departure")
Validates a given depart value.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.