Eclipse SUMO - Simulation of Urban MObility
GNERouteHandler.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2022 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 // Builds demand objects for netedit
19 /****************************************************************************/
20 #include <config.h>
21 #include <netedit/GNENet.h>
22 #include <netedit/GNEUndoList.h>
23 #include <netedit/GNEViewNet.h>
24 #include <netedit/GNEViewParent.h>
27 
28 #include "GNEContainer.h"
29 #include "GNEPerson.h"
30 #include "GNEPersonTrip.h"
31 #include "GNERide.h"
32 #include "GNERoute.h"
33 #include "GNERouteHandler.h"
34 #include "GNEStop.h"
35 #include "GNETranship.h"
36 #include "GNETransport.h"
37 #include "GNEVehicle.h"
38 #include "GNEVType.h"
39 #include "GNEVTypeDistribution.h"
40 #include "GNEWalk.h"
41 
42 
43 // ===========================================================================
44 // member method definitions
45 // ===========================================================================
46 
47 GNERouteHandler::GNERouteHandler(const std::string& file, GNENet* net, bool undoDemandElements) :
48  RouteHandler(file, false),
49  myNet(net),
50  myPlanObject(new CommonXMLStructure::SumoBaseObject(nullptr)),
51  myUndoDemandElements(undoDemandElements) {
52 }
53 
54 
56  delete myPlanObject;
57 }
58 
59 
60 void
62  // check vTypeDistribution
63  const bool vTypeDistribution = sumoBaseObject->getParentSumoBaseObject() && (sumoBaseObject->getParentSumoBaseObject()->getTag() == SUMO_TAG_VTYPE_DISTRIBUTION);
64  // check if loaded type is a default type
65  if (DEFAULT_VTYPES.count(vTypeParameter.id) > 0) {
66  // overwrite default vehicle type
68  } else if (myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE, vTypeParameter.id, false) != nullptr) {
69  WRITE_ERROR("There is another " + toString(SUMO_TAG_VTYPE) + " with the same ID='" + vTypeParameter.id + "'.");
70  } else {
71  // create vType/pType using myCurrentVType
72  GNEDemandElement* vType = new GNEVType(myNet, vTypeParameter);
74  myNet->getViewNet()->getUndoList()->begin(GUIIcon::VTYPE, "add " + vType->getTagStr());
75  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(vType, true), true);
76  // check if place this vType within a vTypeDistribution
77  if (vTypeDistribution) {
79  }
81  } else {
83  if (vTypeDistribution) {
85  }
86  vType->incRef("buildVType");
87  }
88  }
89 }
90 
91 
92 void
94  const std::vector<std::string>& vTypes) {
95  // first check conditions
97  WRITE_ERROR("There is another " + toString(SUMO_TAG_VTYPE) + " with the same ID='" + id + "'.");
98  } else if (vTypes.empty() && sumoBaseObject->getSumoBaseObjectChildren().empty()) {
100  } else {
101  bool checkVTypesOK = true;
102  // check vTypes
103  for (const auto& vType : vTypes) {
104  if (myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE, vType, false) == nullptr) {
105  WRITE_ERROR(toString(SUMO_TAG_VTYPE) + " with id '" + vType + "' doesn't exist in " + toString(SUMO_TAG_VTYPE_DISTRIBUTION) + " '" + id + "'");
106  checkVTypesOK = false;
107  }
108  }
109  // now check childrens
110  for (const auto& child : sumoBaseObject->getSumoBaseObjectChildren()) {
111  if (child->hasStringAttribute(SUMO_ATTR_ID) == false) {
112  WRITE_ERROR("Invalid definition for " + toString(SUMO_TAG_VTYPE) + " in " + toString(SUMO_TAG_VTYPE_DISTRIBUTION) + " '" + id + "'");
113  checkVTypesOK = false;
114  } else if (myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE, child->getStringAttribute(SUMO_ATTR_ID), false) != nullptr) {
115  WRITE_ERROR(toString(SUMO_TAG_VTYPE) + " with id '" + child->getStringAttribute(SUMO_ATTR_ID) + "' cannot be created in " + toString(SUMO_TAG_VTYPE_DISTRIBUTION) + " '" + id + "'");
116  checkVTypesOK = false;
117  }
118  }
119  // if all ok, then create vTypeDistribution
120  if (checkVTypesOK) {
121  GNEVTypeDistribution* vTypeDistribution = new GNEVTypeDistribution(myNet, id);
122  if (myUndoDemandElements) {
123  myNet->getViewNet()->getUndoList()->begin(GUIIcon::VTYPEDISTRIBUTION, "add " + vTypeDistribution->getTagStr());
124  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(vTypeDistribution, true), true);
125  // set this vTypeDistribution as parent of the other vTypes
126  for (const auto& vTypeID : vTypes) {
129  }
130  myNet->getViewNet()->getUndoList()->end();
131  } else {
132  myNet->getAttributeCarriers()->insertDemandElement(vTypeDistribution);
133  vTypeDistribution->incRef("buildVType");
134  for (const auto& vTypeID : vTypes) {
137  }
138  }
139  }
140  }
141 }
142 
143 
144 void
145 GNERouteHandler::buildRoute(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& id, SUMOVehicleClass vClass,
146  const std::vector<std::string>& edgeIDs, const RGBColor& color, const int repeat, const SUMOTime cycleTime,
147  const std::map<std::string, std::string>& routeParameters) {
148  // parse edges
149  const auto edges = parseEdges(SUMO_TAG_ROUTE, edgeIDs);
150  // check conditions
151  if (myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_ROUTE, id, false) != nullptr) {
152  WRITE_ERROR("There is another " + toString(SUMO_TAG_ROUTE) + " with the same ID='" + id + "'.");
153  } else {
154  // create GNERoute
155  GNEDemandElement* route = new GNERoute(myNet, id, vClass, edges, color, repeat, cycleTime, routeParameters);
156  if (myUndoDemandElements) {
157  myNet->getViewNet()->getUndoList()->begin(GUIIcon::ROUTE, "add " + route->getTagStr());
158  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(route, true), true);
159  myNet->getViewNet()->getUndoList()->end();
160  } else {
162  for (const auto& edge : edges) {
163  edge->addChildElement(route);
164  }
165  route->incRef("buildRoute");
166  }
167  }
168 }
169 
170 
171 void
172 GNERouteHandler::buildEmbeddedRoute(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::vector<std::string>& edgeIDs,
173  const RGBColor& color, const int repeat, const SUMOTime cycleTime, const std::map<std::string, std::string>& routeParameters) {
174  // first create vehicle/flow
175  const SUMOVehicleParameter& vehicleParameters = sumoBaseObject->getParentSumoBaseObject()->getVehicleParameter();
176  const SumoXMLTag vehicleTag = (sumoBaseObject->getParentSumoBaseObject()->getTag() == SUMO_TAG_VEHICLE) ? GNE_TAG_VEHICLE_WITHROUTE :
178  sumoBaseObject->getParentSumoBaseObject()->getTag();
179  // parse route edges
180  const auto edges = parseEdges(SUMO_TAG_ROUTE, edgeIDs);
181  // check if ID is duplicated
182  if ((edges.size() > 0) && !isVehicleIdDuplicated(myNet, vehicleParameters.id)) {
183  // obtain routes and vtypes
185  if (vType == nullptr) {
186  WRITE_ERROR("Invalid vehicle type '" + vehicleParameters.vtypeid + "' used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'.");
187  } else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && (vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN) && ((int)edges.front()->getLanes().size() < vehicleParameters.departLane)) {
188  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_DEPARTLANE) + " used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'. " + toString(vehicleParameters.departLane) + " is greater than number of lanes");
189  } else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (vType->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {
190  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_DEPARTSPEED) + " used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'. " + toString(vehicleParameters.departSpeed) + " is greater than vType" + toString(SUMO_ATTR_MAXSPEED));
191  } else {
192  // create vehicle using vehicleParameters
193  GNEDemandElement* vehicle = new GNEVehicle(vehicleTag, myNet, vType, vehicleParameters);
194  // create embedded route
195  GNEDemandElement* route = new GNERoute(myNet, vehicle, edges, color, repeat, cycleTime, routeParameters);
196  if (myUndoDemandElements) {
197  myNet->getViewNet()->getUndoList()->begin(GUIIcon::ROUTE, "add " + route->getTagStr());
198  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(vehicle, true), true);
199  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(route, true), true);
200  myNet->getViewNet()->getUndoList()->end();
201  } else {
204  vType->addChildElement(vehicle);
205  vehicle->addChildElement(route);
206  for (const auto& edge : edges) {
207  edge->addChildElement(route);
208  }
209  route->incRef("buildRoute");
210  }
211  // compute path
212  vehicle->computePathElement();
213  }
214  }
215 }
216 
217 
218 void
219 GNERouteHandler::buildRouteDistribution(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const std::string& /*id*/) {
220  // unsuported
221  WRITE_ERROR("NETEDIT doesn't support route distributions");
222 }
223 
224 
225 void
227  // first check if ID is duplicated
228  if (!isVehicleIdDuplicated(myNet, vehicleParameters.id)) {
229  // obtain routes and vtypes
232  if (vType == nullptr) {
233  WRITE_ERROR("Invalid vehicle type '" + vehicleParameters.vtypeid + "' used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'.");
234  } else if (route == nullptr) {
235  WRITE_ERROR("Invalid route '" + vehicleParameters.routeid + "' used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'.");
236  } else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && (vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN) && ((int)route->getParentEdges().front()->getLanes().size() < vehicleParameters.departLane)) {
237  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_DEPARTLANE) + " used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'. " + toString(vehicleParameters.departLane) + " is greater than number of lanes");
238  } else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (vType->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {
239  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_DEPARTSPEED) + " used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'. " + toString(vehicleParameters.departSpeed) + " is greater than vType" + toString(SUMO_ATTR_MAXSPEED));
240  } else {
241  // create vehicle using vehicleParameters
242  GNEDemandElement* vehicle = new GNEVehicle(SUMO_TAG_VEHICLE, myNet, vType, route, vehicleParameters);
243  if (myUndoDemandElements) {
244  myNet->getViewNet()->getUndoList()->begin(vehicle->getTagProperty().getGUIIcon(), "add " + vehicle->getTagStr());
245  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(vehicle, true), true);
246  myNet->getViewNet()->getUndoList()->end();
247  } else {
249  // set vehicle as child of vType and Route
250  vType->addChildElement(vehicle);
251  route->addChildElement(vehicle);
252  vehicle->incRef("buildVehicleOverRoute");
253  }
254  // compute path
255  vehicle->computePathElement();
256  }
257  }
258 }
259 
260 
261 void
263  // first check if ID is duplicated
264  if (!isVehicleIdDuplicated(myNet, vehicleParameters.id)) {
265  // obtain routes and vtypes
268  if (vType == nullptr) {
269  WRITE_ERROR("Invalid vehicle type '" + vehicleParameters.vtypeid + "' used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'.");
270  } else if (route == nullptr) {
271  WRITE_ERROR("Invalid route '" + vehicleParameters.routeid + "' used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'.");
272  } else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && (vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN) && ((int)route->getParentEdges().front()->getLanes().size() < vehicleParameters.departLane)) {
273  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_DEPARTLANE) + " used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'. " + toString(vehicleParameters.departLane) + " is greater than number of lanes");
274  } else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (vType->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {
275  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_DEPARTSPEED) + " used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'. " + toString(vehicleParameters.departSpeed) + " is greater than vType" + toString(SUMO_ATTR_MAXSPEED));
276  } else {
277  // create flow or trips using vehicleParameters
278  GNEDemandElement* flow = new GNEVehicle(GNE_TAG_FLOW_ROUTE, myNet, vType, route, vehicleParameters);
279  if (myUndoDemandElements) {
280  myNet->getViewNet()->getUndoList()->begin(flow->getTagProperty().getGUIIcon(), "add " + flow->getTagStr());
281  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(flow, true), true);
282  myNet->getViewNet()->getUndoList()->end();
283  } else {
285  // set flow as child of vType and Route
286  vType->addChildElement(flow);
287  route->addChildElement(flow);
288  flow->incRef("buildFlowOverRoute");
289  }
290  // compute path
291  flow->computePathElement();
292  }
293  }
294 }
295 
296 
297 void
298 GNERouteHandler::buildTrip(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters,
299  const std::string& fromEdgeID, const std::string& toEdgeID, const std::vector<std::string>& viaIDs) {
300  // parse edges
301  const auto fromEdge = parseEdge(SUMO_TAG_TRIP, fromEdgeID);
302  const auto toEdge = parseEdge(SUMO_TAG_TRIP, toEdgeID);
303  const auto via = parseEdges(SUMO_TAG_TRIP, viaIDs);
304  // check if exist another vehicle with the same ID (note: Vehicles, Flows and Trips share namespace)
305  if (fromEdge && toEdge && !isVehicleIdDuplicated(myNet, vehicleParameters.id)) {
306  // obtain vtypes
308  if (vType == nullptr) {
309  WRITE_ERROR("Invalid vehicle type '" + vehicleParameters.vtypeid + "' used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'.");
310  } else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && ((vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN)) && ((int)fromEdge->getLanes().size() < vehicleParameters.departLane)) {
311  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_DEPARTLANE) + " used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'. " + toString(vehicleParameters.departLane) + " is greater than number of lanes");
312  } else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (vType->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {
313  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_DEPARTSPEED) + " used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'. " + toString(vehicleParameters.departSpeed) + " is greater than vType" + toString(SUMO_ATTR_MAXSPEED));
314  } else {
315  // add "via" edges in vehicleParameters
316  for (const auto& viaEdge : via) {
317  vehicleParameters.via.push_back(viaEdge->getID());
318  }
319  // create trip or flow using tripParameters
320  GNEDemandElement* trip = new GNEVehicle(SUMO_TAG_TRIP, myNet, vType, fromEdge, toEdge, via, vehicleParameters);
321  if (myUndoDemandElements) {
322  myNet->getViewNet()->getUndoList()->begin(trip->getTagProperty().getGUIIcon(), "add " + trip->getTagStr());
323  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(trip, true), true);
324  myNet->getViewNet()->getUndoList()->end();
325  } else {
327  // set vehicle as child of vType
328  vType->addChildElement(trip);
329  trip->incRef("buildTrip");
330  // add reference in all edges
331  fromEdge->addChildElement(trip);
332  toEdge->addChildElement(trip);
333  for (const auto& viaEdge : via) {
334  viaEdge->addChildElement(trip);
335  }
336  }
337  // compute path
338  trip->computePathElement();
339  }
340  }
341 }
342 
343 
344 void
345 GNERouteHandler::buildTrip(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters,
346  const std::string& fromJunctionID, const std::string& toJunctionID) {
347  // parse junctions
348  const auto fromJunction = parseJunction(SUMO_TAG_TRIP, fromJunctionID);
349  const auto toJunction = parseJunction(SUMO_TAG_TRIP, toJunctionID);
350  // check if exist another vehicle with the same ID (note: Vehicles, Flows and Trips share namespace)
351  if (fromJunction && toJunction && !isVehicleIdDuplicated(myNet, vehicleParameters.id)) {
352  // obtain vtypes
354  if (vType == nullptr) {
355  WRITE_ERROR("Invalid vehicle type '" + vehicleParameters.vtypeid + "' used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'.");
356  } else {
357  // create trip using vehicleParameters
358  GNEDemandElement* flow = new GNEVehicle(GNE_TAG_TRIP_JUNCTIONS, myNet, vType, fromJunction, toJunction, vehicleParameters);
359  if (myUndoDemandElements) {
360  myNet->getViewNet()->getUndoList()->begin(flow->getTagProperty().getGUIIcon(), "add " + flow->getTagStr());
361  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(flow, true), true);
362  myNet->getViewNet()->getUndoList()->end();
363  } else {
365  // set vehicle as child of vType
366  vType->addChildElement(flow);
367  flow->incRef("buildFlow");
368  // add reference in all junctions
369  fromJunction->addChildElement(flow);
370  toJunction->addChildElement(flow);
371  }
372  // compute path
373  flow->computePathElement();
374  }
375  }
376 }
377 
378 void
379 GNERouteHandler::buildFlow(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters,
380  const std::string& fromEdgeID, const std::string& toEdgeID, const std::vector<std::string>& viaIDs) {
381  // parse edges
382  const auto fromEdge = parseEdge(SUMO_TAG_FLOW, fromEdgeID);
383  const auto toEdge = parseEdge(SUMO_TAG_FLOW, toEdgeID);
384  const auto via = parseEdges(SUMO_TAG_FLOW, viaIDs);
385  // check if exist another vehicle with the same ID (note: Vehicles, Flows and Trips share namespace)
386  if (fromEdge && toEdge && !isVehicleIdDuplicated(myNet, vehicleParameters.id)) {
387  // obtain vtypes
389  if (vType == nullptr) {
390  WRITE_ERROR("Invalid vehicle type '" + vehicleParameters.vtypeid + "' used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'.");
391  } else if (vehicleParameters.wasSet(VEHPARS_DEPARTLANE_SET) && (vehicleParameters.departLaneProcedure == DepartLaneDefinition::GIVEN) && ((int)fromEdge->getLanes().size() < vehicleParameters.departLane)) {
392  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_DEPARTLANE) + " used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'. " + toString(vehicleParameters.departLane) + " is greater than number of lanes");
393  } else if (vehicleParameters.wasSet(VEHPARS_DEPARTSPEED_SET) && (vehicleParameters.departSpeedProcedure == DepartSpeedDefinition::GIVEN) && (vType->getAttributeDouble(SUMO_ATTR_MAXSPEED) < vehicleParameters.departSpeed)) {
394  WRITE_ERROR("Invalid " + toString(SUMO_ATTR_DEPARTSPEED) + " used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'. " + toString(vehicleParameters.departSpeed) + " is greater than vType" + toString(SUMO_ATTR_MAXSPEED));
395  } else {
396  // add "via" edges in vehicleParameters
397  for (const auto& viaEdge : via) {
398  vehicleParameters.via.push_back(viaEdge->getID());
399  }
400  // create trip or flow using tripParameters
401  GNEDemandElement* flow = new GNEVehicle(SUMO_TAG_FLOW, myNet, vType, fromEdge, toEdge, via, vehicleParameters);
402  if (myUndoDemandElements) {
403  myNet->getViewNet()->getUndoList()->begin(flow->getTagProperty().getGUIIcon(), "add " + flow->getTagStr());
404  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(flow, true), true);
405  myNet->getViewNet()->getUndoList()->end();
406  } else {
408  // set vehicle as child of vType
409  vType->addChildElement(flow);
410  flow->incRef("buildFlow");
411  // add reference in all edges
412  fromEdge->addChildElement(flow);
413  toEdge->addChildElement(flow);
414  for (const auto& viaEdge : via) {
415  viaEdge->addChildElement(flow);
416  }
417  }
418  // compute path
419  flow->computePathElement();
420  }
421  }
422 }
423 
424 
425 void
426 GNERouteHandler::buildFlow(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& vehicleParameters,
427  const std::string& fromJunctionID, const std::string& toJunctionID) {
428  // parse junctions
429  const auto fromJunction = parseJunction(SUMO_TAG_TRIP, fromJunctionID);
430  const auto toJunction = parseJunction(SUMO_TAG_TRIP, toJunctionID);
431  // check if exist another vehicle with the same ID (note: Vehicles, Flows and Trips share namespace)
432  if (fromJunction && toJunction && !isVehicleIdDuplicated(myNet, vehicleParameters.id)) {
433  // obtain vtypes
435  if (vType == nullptr) {
436  WRITE_ERROR("Invalid vehicle type '" + vehicleParameters.vtypeid + "' used in " + toString(vehicleParameters.tag) + " '" + vehicleParameters.id + "'.");
437  } else {
438  // create flow using vehicleParameters
439  GNEDemandElement* flow = new GNEVehicle(GNE_TAG_FLOW_JUNCTIONS, myNet, vType, fromJunction, toJunction, vehicleParameters);
440  if (myUndoDemandElements) {
441  myNet->getViewNet()->getUndoList()->begin(flow->getTagProperty().getGUIIcon(), "add " + flow->getTagStr());
442  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(flow, true), true);
443  myNet->getViewNet()->getUndoList()->end();
444  } else {
446  // set vehicle as child of vType
447  vType->addChildElement(flow);
448  flow->incRef("buildFlow");
449  // add reference in all junctions
450  fromJunction->addChildElement(flow);
451  toJunction->addChildElement(flow);
452  }
453  // compute path
454  flow->computePathElement();
455  }
456  }
457 }
458 
459 
460 void
461 GNERouteHandler::buildPerson(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& personParameters) {
462  // first check if ID is duplicated
463  if (!isPersonIdDuplicated(myNet, personParameters.id)) {
464  // obtain type
466  if (type == nullptr) {
467  WRITE_ERROR("Invalid person type '" + personParameters.vtypeid + "' used in " + toString(personParameters.tag) + " '" + personParameters.id + "'.");
468  } else {
469  // create person using personParameters
470  GNEDemandElement* person = new GNEPerson(SUMO_TAG_PERSON, myNet, type, personParameters);
471  if (myUndoDemandElements) {
472  myNet->getViewNet()->getUndoList()->begin(person->getTagProperty().getGUIIcon(), "add " + person->getTagStr());
473  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(person, true), true);
474  myNet->getViewNet()->getUndoList()->end();
475  } else {
477  // set person as child of type
478  type->addChildElement(person);
479  person->incRef("buildPerson");
480  }
481  }
482  }
483 }
484 
485 
486 void
487 GNERouteHandler::buildPersonFlow(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& personFlowParameters) {
488  // first check if ID is duplicated
489  if (!isPersonIdDuplicated(myNet, personFlowParameters.id)) {
490  // obtain type
492  if (type == nullptr) {
493  WRITE_ERROR("Invalid personFlow type '" + personFlowParameters.vtypeid + "' used in " + toString(personFlowParameters.tag) + " '" + personFlowParameters.id + "'.");
494  } else {
495  // create personFlow using personFlowParameters
496  GNEDemandElement* personFlow = new GNEPerson(SUMO_TAG_PERSONFLOW, myNet, type, personFlowParameters);
497  if (myUndoDemandElements) {
498  myNet->getViewNet()->getUndoList()->begin(personFlow->getTagProperty().getGUIIcon(), "add " + personFlow->getTagStr());
499  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(personFlow, true), true);
500  myNet->getViewNet()->getUndoList()->end();
501  } else {
503  // set personFlow as child of type
504  type->addChildElement(personFlow);
505  personFlow->incRef("buildPersonFlow");
506  }
507  }
508  }
509 }
510 
511 
512 void
513 GNERouteHandler::buildPersonTrip(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& fromEdgeID, const std::string& toEdgeID,
514  const std::string& fromJunctionID, const std::string& toJunctionID, const std::string& toBusStopID, double arrivalPos,
515  const std::vector<std::string>& types, const std::vector<std::string>& modes) {
516  // first parse parents
517  GNEDemandElement* personParent = getPersonParent(sumoBaseObject);
518  GNEEdge* fromEdge = fromEdgeID.empty() ? getPreviousPlanEdge(true, sumoBaseObject) : myNet->getAttributeCarriers()->retrieveEdge(fromEdgeID, false);
519  GNEEdge* toEdge = myNet->getAttributeCarriers()->retrieveEdge(toEdgeID, false);
520  GNEJunction* fromJunction = myNet->getAttributeCarriers()->retrieveJunction(fromJunctionID, false);
521  GNEJunction* toJunction = myNet->getAttributeCarriers()->retrieveJunction(toJunctionID, false);
522  GNEAdditional* toBusStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, toBusStopID, false);
523  // check conditions
524  if (personParent) {
525  if (fromEdge && toEdge) {
526  // create personTrip from->to (edges)
527  GNEDemandElement* personTrip = new GNEPersonTrip(myNet, personParent, fromEdge, toEdge, arrivalPos, types, modes);
528  if (myUndoDemandElements) {
529  myNet->getViewNet()->getUndoList()->begin(personTrip->getTagProperty().getGUIIcon(), "add " + personTrip->getTagStr());
530  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(personTrip, true), true);
531  myNet->getViewNet()->getUndoList()->end();
532  } else {
534  // set child references
535  personParent->addChildElement(personTrip);
536  fromEdge->addChildElement(personTrip);
537  toEdge->addChildElement(personTrip);
538  personTrip->incRef("buildPersonTripFromTo");
539  }
540  } else if (fromEdge && toBusStop) {
541  // create personTrip from->busStop
542  GNEDemandElement* personTrip = new GNEPersonTrip(myNet, personParent, fromEdge, toBusStop, arrivalPos, types, modes);
543  if (myUndoDemandElements) {
544  myNet->getViewNet()->getUndoList()->begin(personTrip->getTagProperty().getGUIIcon(), "add " + personTrip->getTagStr());
545  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(personTrip, true), true);
546  myNet->getViewNet()->getUndoList()->end();
547  } else {
549  // set child references
550  personParent->addChildElement(personTrip);
551  fromEdge->addChildElement(personTrip);
552  toBusStop->addChildElement(personTrip);
553  personTrip->incRef("buildPersonTripFromBusStop");
554  }
555  } else if (fromJunction && toJunction) {
556  // create personTrip from->to (junctions)
557  GNEDemandElement* personTrip = new GNEPersonTrip(myNet, personParent, fromJunction, toJunction, arrivalPos, types, modes);
558  if (myUndoDemandElements) {
559  myNet->getViewNet()->getUndoList()->begin(personTrip->getTagProperty().getGUIIcon(), "add " + personTrip->getTagStr());
560  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(personTrip, true), true);
561  myNet->getViewNet()->getUndoList()->end();
562  } else {
564  // set child references
565  personParent->addChildElement(personTrip);
566  fromJunction->addChildElement(personTrip);
567  toJunction->addChildElement(personTrip);
568  personTrip->incRef("buildPersonTripFromTo");
569  }
570  }
571  }
572 }
573 
574 
575 void
576 GNERouteHandler::buildWalk(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& fromEdgeID, const std::string& toEdgeID,
577  const std::string& fromJunctionID, const std::string& toJunctionID, const std::string& toBusStopID,
578  const std::vector<std::string>& edgeIDs, const std::string& routeID, double arrivalPos) {
579  // first parse parents
580  GNEDemandElement* personParent = getPersonParent(sumoBaseObject);
581  GNEEdge* fromEdge = fromEdgeID.empty() ? getPreviousPlanEdge(true, sumoBaseObject) : myNet->getAttributeCarriers()->retrieveEdge(fromEdgeID, false);
582  GNEEdge* toEdge = myNet->getAttributeCarriers()->retrieveEdge(toEdgeID, false);
583  GNEJunction* fromJunction = myNet->getAttributeCarriers()->retrieveJunction(fromJunctionID, false);
584  GNEJunction* toJunction = myNet->getAttributeCarriers()->retrieveJunction(toJunctionID, false);
585  GNEAdditional* toBusStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, toBusStopID, false);
587  std::vector<GNEEdge*> edges = parseEdges(SUMO_TAG_WALK, edgeIDs);
588  // check conditions
589  if (personParent) {
590  if (edges.size() > 0) {
591  // create walk edges
592  GNEDemandElement* walk = new GNEWalk(myNet, personParent, edges, arrivalPos);
593  if (myUndoDemandElements) {
594  myNet->getViewNet()->getUndoList()->begin(walk->getTagProperty().getGUIIcon(), "add " + walk->getTagStr());
595  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(walk, true), true);
596  myNet->getViewNet()->getUndoList()->end();
597  } else {
599  // set child references
600  personParent->addChildElement(walk);
601  for (const auto& edge : edges) {
602  edge->addChildElement(walk);
603  }
604  walk->incRef("buildWalkEdges");
605  }
606  } else if (route) {
607  // create walk over route
608  GNEDemandElement* walk = new GNEWalk(myNet, personParent, route, arrivalPos);
609  if (myUndoDemandElements) {
610  myNet->getViewNet()->getUndoList()->begin(walk->getTagProperty().getGUIIcon(), "add " + walk->getTagStr());
611  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(walk, true), true);
612  myNet->getViewNet()->getUndoList()->end();
613  } else {
615  // set child references
616  personParent->addChildElement(walk);
617  route->addChildElement(walk);
618  walk->incRef("buildWalkRoute");
619  }
620  } else if (fromEdge && toEdge) {
621  // create walk from->to (edges)
622  GNEDemandElement* walk = new GNEWalk(myNet, personParent, fromEdge, toEdge, arrivalPos);
623  if (myUndoDemandElements) {
624  myNet->getViewNet()->getUndoList()->begin(walk->getTagProperty().getGUIIcon(), "add " + walk->getTagStr());
625  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(walk, true), true);
626  myNet->getViewNet()->getUndoList()->end();
627  } else {
629  // set child references
630  personParent->addChildElement(walk);
631  fromEdge->addChildElement(walk);
632  toEdge->addChildElement(walk);
633  walk->incRef("buildWalkFromTo");
634  }
635  } else if (fromEdge && toBusStop) {
636  // create walk from->busStop
637  GNEDemandElement* walk = new GNEWalk(myNet, personParent, fromEdge, toBusStop, arrivalPos);
638  if (myUndoDemandElements) {
639  myNet->getViewNet()->getUndoList()->begin(walk->getTagProperty().getGUIIcon(), "add " + walk->getTagStr());
640  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(walk, true), true);
641  myNet->getViewNet()->getUndoList()->end();
642  } else {
644  // set child references
645  personParent->addChildElement(walk);
646  fromEdge->addChildElement(walk);
647  toBusStop->addChildElement(walk);
648  walk->incRef("buildWalkFromBusStop");
649  }
650  } else if (fromJunction && toJunction) {
651  // create walk from->to (junction)
652  GNEDemandElement* walk = new GNEWalk(myNet, personParent, fromJunction, toJunction, arrivalPos);
653  if (myUndoDemandElements) {
654  myNet->getViewNet()->getUndoList()->begin(walk->getTagProperty().getGUIIcon(), "add " + walk->getTagStr());
655  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(walk, true), true);
656  myNet->getViewNet()->getUndoList()->end();
657  } else {
659  // set child references
660  personParent->addChildElement(walk);
661  fromJunction->addChildElement(walk);
662  toJunction->addChildElement(walk);
663  walk->incRef("buildWalkFromTo");
664  }
665  }
666  }
667 }
668 
669 
670 void
671 GNERouteHandler::buildRide(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& fromEdgeID, const std::string& toEdgeID,
672  const std::string& toBusStopID, double arrivalPos, const std::vector<std::string>& lines) {
673  // first parse parents
674  GNEDemandElement* personParent = getPersonParent(sumoBaseObject);
675  GNEEdge* fromEdge = fromEdgeID.empty() ? getPreviousPlanEdge(true, sumoBaseObject) : myNet->getAttributeCarriers()->retrieveEdge(fromEdgeID, false);
676  GNEEdge* toEdge = myNet->getAttributeCarriers()->retrieveEdge(toEdgeID, false);
677  GNEAdditional* toBusStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, toBusStopID, false);
678  // check conditions
679  if (personParent && fromEdge) {
680  if (toEdge) {
681  // create ride from->to
682  GNEDemandElement* ride = new GNERide(myNet, personParent, fromEdge, toEdge, arrivalPos, lines);
683  if (myUndoDemandElements) {
684  myNet->getViewNet()->getUndoList()->begin(ride->getTagProperty().getGUIIcon(), "add " + ride->getTagStr());
685  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(ride, true), true);
686  myNet->getViewNet()->getUndoList()->end();
687  } else {
689  // set child references
690  personParent->addChildElement(ride);
691  fromEdge->addChildElement(ride);
692  toEdge->addChildElement(ride);
693  ride->incRef("buildRideFromTo");
694  }
695  } else if (toBusStop) {
696  // create ride from->busStop
697  GNEDemandElement* ride = new GNERide(myNet, personParent, fromEdge, toBusStop, arrivalPos, lines);
698  if (myUndoDemandElements) {
699  myNet->getViewNet()->getUndoList()->begin(ride->getTagProperty().getGUIIcon(), "add " + ride->getTagStr());
700  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(ride, true), true);
701  myNet->getViewNet()->getUndoList()->end();
702  } else {
704  // set child references
705  personParent->addChildElement(ride);
706  fromEdge->addChildElement(ride);
707  toBusStop->addChildElement(ride);
708  ride->incRef("buildRideFromBusStop");
709  }
710  }
711  }
712 }
713 
714 
715 void
716 GNERouteHandler::buildContainer(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& containerParameters) {
717  // first check if ID is duplicated
718  if (!isContainerIdDuplicated(myNet, containerParameters.id)) {
719  // obtain type
721  if (type == nullptr) {
722  WRITE_ERROR("Invalid container type '" + containerParameters.vtypeid + "' used in " + toString(containerParameters.tag) + " '" + containerParameters.id + "'.");
723  } else {
724  // create container using containerParameters
725  GNEDemandElement* container = new GNEContainer(SUMO_TAG_CONTAINER, myNet, type, containerParameters);
726  if (myUndoDemandElements) {
727  myNet->getViewNet()->getUndoList()->begin(GUIIcon::CONTAINER, "add " + container->getTagStr());
728  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(container, true), true);
729  myNet->getViewNet()->getUndoList()->end();
730  } else {
732  // set container as child of type
733  type->addChildElement(container);
734  container->incRef("buildContainer");
735  }
736  }
737  }
738 }
739 
740 
741 void
742 GNERouteHandler::buildContainerFlow(const CommonXMLStructure::SumoBaseObject* /*sumoBaseObject*/, const SUMOVehicleParameter& containerFlowParameters) {
743  // first check if ID is duplicated
744  if (!isContainerIdDuplicated(myNet, containerFlowParameters.id)) {
745  // obtain type
746  GNEDemandElement* type = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_VTYPE, containerFlowParameters.vtypeid, false);
747  if (type == nullptr) {
748  WRITE_ERROR("Invalid containerFlow type '" + containerFlowParameters.vtypeid + "' used in " + toString(containerFlowParameters.tag) + " '" + containerFlowParameters.id + "'.");
749  } else {
750  // create containerFlow using containerFlowParameters
751  GNEDemandElement* containerFlow = new GNEContainer(SUMO_TAG_CONTAINERFLOW, myNet, type, containerFlowParameters);
752  if (myUndoDemandElements) {
753  myNet->getViewNet()->getUndoList()->begin(GUIIcon::CONTAINERFLOW, "add " + containerFlow->getTagStr());
754  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(containerFlow, true), true);
755  myNet->getViewNet()->getUndoList()->end();
756  } else {
758  // set containerFlow as child of type
759  type->addChildElement(containerFlow);
760  containerFlow->incRef("buildContainerFlow");
761  }
762  }
763  }
764 }
765 
766 
767 void
768 GNERouteHandler::buildTransport(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& fromEdgeID, const std::string& toEdgeID,
769  const std::string& toContainerStopID, const std::vector<std::string>& lines, const double arrivalPos) {
770  // first parse parents
771  GNEDemandElement* containerParent = getContainerParent(sumoBaseObject);
772  GNEEdge* fromEdge = fromEdgeID.empty() ? getPreviousPlanEdge(false, sumoBaseObject) : myNet->getAttributeCarriers()->retrieveEdge(fromEdgeID, false);
773  GNEEdge* toEdge = myNet->getAttributeCarriers()->retrieveEdge(toEdgeID, false);
774  GNEAdditional* toContainerStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_CONTAINER_STOP, toContainerStopID, false);
775  // check conditions
776  if (containerParent && fromEdge) {
777  if (toEdge) {
778  // create transport from->to
779  GNEDemandElement* transport = new GNETransport(myNet, containerParent, fromEdge, toEdge, lines, arrivalPos);
780  if (myUndoDemandElements) {
781  myNet->getViewNet()->getUndoList()->begin(transport->getTagProperty().getGUIIcon(), "add " + transport->getTagStr());
782  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(transport, true), true);
783  myNet->getViewNet()->getUndoList()->end();
784  } else {
786  // set child references
787  containerParent->addChildElement(transport);
788  fromEdge->addChildElement(transport);
789  toEdge->addChildElement(transport);
790  transport->incRef("buildTransportFromTo");
791  }
792  } else if (toContainerStop) {
793  // create transport from->containerStop
794  GNEDemandElement* transport = new GNETransport(myNet, containerParent, fromEdge, toContainerStop, lines, arrivalPos);
795  if (myUndoDemandElements) {
796  myNet->getViewNet()->getUndoList()->begin(transport->getTagProperty().getGUIIcon(), "add " + transport->getTagStr());
797  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(transport, true), true);
798  myNet->getViewNet()->getUndoList()->end();
799  } else {
801  // set child references
802  containerParent->addChildElement(transport);
803  fromEdge->addChildElement(transport);
804  toContainerStop->addChildElement(transport);
805  transport->incRef("buildTransportFromContainerStop");
806  }
807  }
808  }
809 }
810 
811 
812 void
813 GNERouteHandler::buildTranship(const CommonXMLStructure::SumoBaseObject* sumoBaseObject, const std::string& fromEdgeID, const std::string& toEdgeID,
814  const std::string& toContainerStopID, const std::vector<std::string>& edgeIDs, const double speed, const double departPosition, const double arrivalPosition) {
815  // first parse parents
816  GNEDemandElement* containerParent = getContainerParent(sumoBaseObject);
817  GNEEdge* fromEdge = fromEdgeID.empty() ? getPreviousPlanEdge(false, sumoBaseObject) : myNet->getAttributeCarriers()->retrieveEdge(fromEdgeID, false);
818  GNEEdge* toEdge = myNet->getAttributeCarriers()->retrieveEdge(toEdgeID, false);
819  GNEAdditional* toContainerStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_CONTAINER_STOP, toContainerStopID, false);
820  std::vector<GNEEdge*> edges = parseEdges(SUMO_TAG_WALK, edgeIDs);
821  // check conditions
822  if (containerParent && fromEdge) {
823  if (edges.size() > 0) {
824  // create tranship edges
825  GNEDemandElement* tranship = new GNETranship(myNet, containerParent, edges, speed, departPosition, arrivalPosition);
826  if (myUndoDemandElements) {
827  myNet->getViewNet()->getUndoList()->begin(tranship->getTagProperty().getGUIIcon(), "add " + tranship->getTagStr());
828  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(tranship, true), true);
829  myNet->getViewNet()->getUndoList()->end();
830  } else {
832  // set child references
833  containerParent->addChildElement(tranship);
834  for (const auto& edge : edges) {
835  edge->addChildElement(tranship);
836  }
837  tranship->incRef("buildTranshipEdges");
838  }
839  } else if (toEdge) {
840  // create tranship from->to
841  GNEDemandElement* tranship = new GNETranship(myNet, containerParent, fromEdge, toEdge, speed, departPosition, arrivalPosition);
842  if (myUndoDemandElements) {
843  myNet->getViewNet()->getUndoList()->begin(tranship->getTagProperty().getGUIIcon(), "add " + tranship->getTagStr());
844  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(tranship, true), true);
845  myNet->getViewNet()->getUndoList()->end();
846  } else {
848  // set child references
849  containerParent->addChildElement(tranship);
850  fromEdge->addChildElement(tranship);
851  toEdge->addChildElement(tranship);
852  tranship->incRef("buildTranshipFromTo");
853  }
854  } else if (toContainerStop) {
855  // create tranship from->containerStop
856  GNEDemandElement* tranship = new GNETranship(myNet, containerParent, fromEdge, toContainerStop, speed, departPosition, arrivalPosition);
857  if (myUndoDemandElements) {
858  myNet->getViewNet()->getUndoList()->begin(tranship->getTagProperty().getGUIIcon(), "add " + tranship->getTagStr());
859  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(tranship, true), true);
860  myNet->getViewNet()->getUndoList()->end();
861  } else {
863  // set child references
864  containerParent->addChildElement(tranship);
865  fromEdge->addChildElement(tranship);
866  toContainerStop->addChildElement(tranship);
867  tranship->incRef("buildTranshipFromContainerStop");
868  }
869  }
870  }
871 }
872 
873 
874 void
876  // get obj parent
877  const auto objParent = sumoBaseObject->getParentSumoBaseObject();
878  // set tag
879  SumoXMLTag tag = objParent->getTag();
880  if (!objParent->hasStringAttribute(SUMO_ATTR_ROUTE) && !objParent->hasStringAttribute(SUMO_ATTR_FROM) && !objParent->hasStringAttribute(SUMO_ATTR_TO)) {
881  if (tag == SUMO_TAG_VEHICLE) {
883  } else if (tag == SUMO_TAG_FLOW) {
885  }
886  }
887  // get stop parent
888  GNEDemandElement* stopParent = myNet->getAttributeCarriers()->retrieveDemandElement(tag, objParent->getStringAttribute(SUMO_ATTR_ID), false);
889  // check if stopParent exist
890  if (stopParent) {
891  // declare pointers to parent elements
892  GNEAdditional* stoppingPlace = nullptr;
893  GNELane* lane = nullptr;
894  GNEEdge* edge = nullptr;
895  // declare stopTagType
896  SumoXMLTag stopTagType = SUMO_TAG_NOTHING;
897  bool validParentDemandElement = true;
898  // check conditions
899  if (stopParameters.busstop.size() > 0) {
900  stoppingPlace = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, stopParameters.busstop, false);
901  stopTagType = SUMO_TAG_STOP_BUSSTOP;
902  // containers cannot stops in busStops
903  if (stopParent->getTagProperty().isContainer()) {
904  WRITE_ERROR("Containers don't support stops at busStops");
905  validParentDemandElement = false;
906  }
907  } else if (stopParameters.containerstop.size() > 0) {
908  stoppingPlace = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_CONTAINER_STOP, stopParameters.containerstop, false);
909  stopTagType = SUMO_TAG_STOP_CONTAINERSTOP;
910  // persons cannot stops in containerStops
911  if (stopParent->getTagProperty().isPerson()) {
912  WRITE_ERROR("Persons don't support stops at containerStops");
913  validParentDemandElement = false;
914  }
915  } else if (stopParameters.chargingStation.size() > 0) {
916  stoppingPlace = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_CHARGING_STATION, stopParameters.chargingStation, false);
917  stopTagType = SUMO_TAG_STOP_CHARGINGSTATION;
918  // check person and containers
919  if (stopParent->getTagProperty().isPerson()) {
920  WRITE_ERROR("Persons don't support stops at chargingStations");
921  validParentDemandElement = false;
922  } else if (stopParent->getTagProperty().isContainer()) {
923  WRITE_ERROR("Containers don't support stops at chargingStations");
924  validParentDemandElement = false;
925  }
926  } else if (stopParameters.parkingarea.size() > 0) {
927  stoppingPlace = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_PARKING_AREA, stopParameters.parkingarea, false);
928  stopTagType = SUMO_TAG_STOP_PARKINGAREA;
929  // check person and containers
930  if (stopParent->getTagProperty().isPerson()) {
931  WRITE_ERROR("Persons don't support stops at parkingAreas");
932  validParentDemandElement = false;
933  } else if (stopParent->getTagProperty().isContainer()) {
934  WRITE_ERROR("Containers don't support stops at parkingAreas");
935  validParentDemandElement = false;
936  }
937  } else if (stopParameters.lane.size() > 0) {
938  lane = myNet->getAttributeCarriers()->retrieveLane(stopParameters.lane, false);
939  stopTagType = SUMO_TAG_STOP_LANE;
940  } else if (stopParameters.edge.size() > 0) {
941  edge = myNet->getAttributeCarriers()->retrieveEdge(stopParameters.edge, false);
942  // check vehicles
943  if (stopParent->getTagProperty().isVehicle()) {
944  WRITE_ERROR("vehicles don't support stops at edges");
945  validParentDemandElement = false;
946  }
947  }
948  // overwrite lane with edge parent if we're handling a personStop
949  if (lane && (stopParent->getTagProperty().isPerson() || stopParent->getTagProperty().isContainer())) {
950  edge = lane->getParentEdge();
951  lane = nullptr;
952  }
953  // first check that parent is valid
954  if (validParentDemandElement) {
955  // check if values are correct
956  if (stoppingPlace && lane && edge) {
957  WRITE_ERROR("A stop must be defined either over a stoppingPlace, a edge or a lane");
958  } else if (!stoppingPlace && !lane && !edge) {
959  WRITE_ERROR("A stop requires only a stoppingPlace, edge or lane lane");
960  } else if (stoppingPlace) {
961  // create stop using stopParameters and stoppingPlace
962  GNEDemandElement* stop = nullptr;
963  if (stopParent->getTagProperty().isPerson()) {
964  stop = new GNEStop(GNE_TAG_STOPPERSON_BUSSTOP, myNet, stopParent, stoppingPlace, stopParameters);
965  } else if (stopParent->getTagProperty().isContainer()) {
966  stop = new GNEStop(GNE_TAG_TRANSPORT_CONTAINERSTOP, myNet, stopParent, stoppingPlace, stopParameters);
967  } else {
968  stop = new GNEStop(stopTagType, myNet, stopParent, stoppingPlace, stopParameters);
969  }
970  // add it depending of undoDemandElements
971  if (myUndoDemandElements) {
972  myNet->getViewNet()->getUndoList()->begin(stop->getTagProperty().getGUIIcon(), "add " + stop->getTagStr());
973  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(stop, true), true);
974  myNet->getViewNet()->getUndoList()->end();
975  } else {
977  stoppingPlace->addChildElement(stop);
978  stopParent->addChildElement(stop);
979  stop->incRef("buildStoppingPlaceStop");
980  }
981  } else if (lane) {
982  // create stop using stopParameters and lane (only for vehicles)
983  GNEDemandElement* stop = new GNEStop(myNet, stopParent, lane, stopParameters);
984  // add it depending of undoDemandElements
985  if (myUndoDemandElements) {
986  myNet->getViewNet()->getUndoList()->begin(stop->getTagProperty().getGUIIcon(), "add " + stop->getTagStr());
987  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(stop, true), true);
988  myNet->getViewNet()->getUndoList()->end();
989  } else {
991  lane->addChildElement(stop);
992  stopParent->addChildElement(stop);
993  stop->incRef("buildLaneStop");
994  }
995  } else {
996  // create stop using stopParameters and edge
997  GNEDemandElement* stop = nullptr;
998  if (stopParent->getTagProperty().isPerson()) {
999  stop = new GNEStop(GNE_TAG_STOPPERSON_EDGE, myNet, stopParent, edge, stopParameters);
1000  } else {
1001  stop = new GNEStop(GNE_TAG_STOPCONTAINER_EDGE, myNet, stopParent, edge, stopParameters);
1002  }
1003  // add it depending of undoDemandElements
1004  if (myUndoDemandElements) {
1005  myNet->getViewNet()->getUndoList()->begin(stop->getTagProperty().getGUIIcon(), "add " + stop->getTagStr());
1006  myNet->getViewNet()->getUndoList()->add(new GNEChange_DemandElement(stop, true), true);
1007  myNet->getViewNet()->getUndoList()->end();
1008  } else {
1010  edge->addChildElement(stop);
1011  stopParent->addChildElement(stop);
1012  stop->incRef("buildLaneStop");
1013  }
1014  }
1015  }
1016  }
1017 }
1018 
1019 
1020 bool
1022  GNEFrameModules::PathCreator* pathCreator, const bool centerAfterCreation) {
1023  // clear and set person object
1024  myPlanObject->clear();
1025  myPlanObject->setTag(personParent->getTagProperty().getTag());
1027  // declare personPlan object
1029  personPlanObject->setTag(tag);
1030  // get person plan attributes
1031  personPlanAttributes->getAttributesAndValues(personPlanObject, true);
1032  // get attributes
1033  const std::vector<std::string> types = personPlanObject->hasStringListAttribute(SUMO_ATTR_VTYPES) ? personPlanObject->getStringListAttribute(SUMO_ATTR_VTYPES) : std::vector<std::string>();
1034  const std::vector<std::string> modes = personPlanObject->hasStringListAttribute(SUMO_ATTR_MODES) ? personPlanObject->getStringListAttribute(SUMO_ATTR_MODES) : std::vector<std::string>();
1035  const std::vector<std::string> lines = personPlanObject->hasStringListAttribute(SUMO_ATTR_LINES) ? personPlanObject->getStringListAttribute(SUMO_ATTR_LINES) : std::vector<std::string>();
1036  const double arrivalPos = personPlanObject->hasDoubleAttribute(SUMO_ATTR_ARRIVALPOS) ? personPlanObject->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS) : -1;
1037  // get stop parameters
1038  SUMOVehicleParameter::Stop stopParameters;
1039  // fill stops parameters
1040  if ((tag == GNE_TAG_STOPPERSON_BUSSTOP) || (tag == GNE_TAG_STOPPERSON_EDGE)) {
1041  stopParameters.actType = personPlanObject->getStringAttribute(SUMO_ATTR_ACTTYPE);
1042  if (personPlanObject->hasTimeAttribute(SUMO_ATTR_DURATION)) {
1043  stopParameters.duration = personPlanObject->getTimeAttribute(SUMO_ATTR_DURATION);
1044  stopParameters.parametersSet |= STOP_DURATION_SET;
1045  }
1046  if (personPlanObject->hasTimeAttribute(SUMO_ATTR_UNTIL)) {
1047  stopParameters.until = personPlanObject->getTimeAttribute(SUMO_ATTR_UNTIL);
1048  stopParameters.parametersSet |= STOP_UNTIL_SET;
1049  }
1050  }
1051  // get edges
1052  GNEEdge* fromEdge = (pathCreator->getSelectedEdges().size() > 0) ? pathCreator->getSelectedEdges().front() : nullptr;
1053  GNEEdge* toEdge = (pathCreator->getSelectedEdges().size() > 0) ? pathCreator->getSelectedEdges().back() : nullptr;
1054  // get junctions
1055  GNEJunction* fromJunction = (pathCreator->getSelectedJunctions().size() > 0) ? pathCreator->getSelectedJunctions().front() : nullptr;
1056  GNEJunction* toJunction = (pathCreator->getSelectedJunctions().size() > 0) ? pathCreator->getSelectedJunctions().back() : nullptr;
1057  // get busStop
1058  GNEAdditional* toBusStop = pathCreator->getToStoppingPlace(SUMO_TAG_BUS_STOP);
1059  // get path edges
1060  std::vector<std::string> edges;
1061  for (const auto& path : pathCreator->getPath()) {
1062  for (const auto& edge : path.getSubPath()) {
1063  edges.push_back(edge->getID());
1064  }
1065  }
1066  // get route
1067  GNEDemandElement* route = pathCreator->getRoute();
1068  // check what PersonPlan we're creating
1069  switch (tag) {
1070  // Person Trips
1071  case GNE_TAG_PERSONTRIP_EDGE: {
1072  // check if person trip busStop->edge can be created
1073  if (fromEdge && toEdge) {
1074  buildPersonTrip(personPlanObject, fromEdge->getID(), toEdge->getID(), "", "", "", arrivalPos, types, modes);
1075  } else {
1076  myNet->getViewNet()->setStatusBarText("A person trip from edge to edge needs two edges edge");
1077  return false;
1078  }
1079  break;
1080  }
1082  // check if person trip busStop->busStop can be created
1083  if (fromEdge && toBusStop) {
1084  buildPersonTrip(personPlanObject, fromEdge->getID(), "", "", "", toBusStop->getID(), arrivalPos, types, modes);
1085  } else {
1086  myNet->getViewNet()->setStatusBarText("A person trip from edge to busStop needs one edge and one busStop");
1087  return false;
1088  }
1089  break;
1090  }
1092  // check if person trip busStop->junction can be created
1093  if (fromJunction && toJunction) {
1094  buildPersonTrip(personPlanObject, "", "", fromJunction->getID(), toJunction->getID(), "", arrivalPos, types, modes);
1095  } else {
1096  myNet->getViewNet()->setStatusBarText("A person trip from junction to junction needs two junctions junction");
1097  return false;
1098  }
1099  break;
1100  }
1101  // Walks
1102  case GNE_TAG_WALK_EDGE: {
1103  // check if transport busStop->edge can be created
1104  if (fromEdge && toEdge) {
1105  buildWalk(personPlanObject, fromEdge->getID(), toEdge->getID(), "", "", "", {}, "", arrivalPos);
1106  } else {
1107  myNet->getViewNet()->setStatusBarText("A ride from busStop to edge needs a busStop and an edge");
1108  return false;
1109  }
1110  break;
1111  }
1112  case GNE_TAG_WALK_BUSSTOP: {
1113  // check if transport busStop->busStop can be created
1114  if (fromEdge && toBusStop) {
1115  buildWalk(personPlanObject, fromEdge->getID(), "", "", "", toBusStop->getID(), {}, "", arrivalPos);
1116  } else {
1117  myNet->getViewNet()->setStatusBarText("A transport from busStop to busStop needs two busStops");
1118  return false;
1119  }
1120  break;
1121  }
1122  case GNE_TAG_WALK_EDGES: {
1123  // check if transport edges can be created
1124  if (edges.size() > 0) {
1125  buildWalk(personPlanObject, "", "", "", "", "", edges, "", arrivalPos);
1126  } else {
1127  myNet->getViewNet()->setStatusBarText("A transport with edges attribute needs a list of edges");
1128  return false;
1129  }
1130  break;
1131  }
1132  case GNE_TAG_WALK_ROUTE: {
1133  // check if transport edges can be created
1134  if (route) {
1135  buildWalk(personPlanObject, "", "", "", "", "", {}, route->getID(), arrivalPos);
1136  } else {
1137  myNet->getViewNet()->setStatusBarText("A route transport needs a route");
1138  return false;
1139  }
1140  break;
1141  }
1142  case GNE_TAG_WALK_JUNCTIONS: {
1143  // check if transport busStop->junction can be created
1144  if (fromJunction && toJunction) {
1145  buildWalk(personPlanObject, "", "", fromJunction->getID(), toJunction->getID(), "", {}, "", arrivalPos);
1146  } else {
1147  myNet->getViewNet()->setStatusBarText("A ride from busStop to junction needs a busStop and an junction");
1148  return false;
1149  }
1150  break;
1151  }
1152  // Rides
1153  case GNE_TAG_RIDE_EDGE: {
1154  // check if ride busStop->edge can be created
1155  if (fromEdge && toEdge) {
1156  buildRide(personPlanObject, fromEdge->getID(), toEdge->getID(), "", arrivalPos, lines);
1157  } else {
1158  myNet->getViewNet()->setStatusBarText("A ride from edge to edge needs two edges edge");
1159  return false;
1160  }
1161  break;
1162  }
1163  case GNE_TAG_RIDE_BUSSTOP: {
1164  // check if ride busStop->busStop can be created
1165  if (fromEdge && toBusStop) {
1166  buildRide(personPlanObject, fromEdge->getID(), "", toBusStop->getID(), arrivalPos, lines);
1167  } else {
1168  myNet->getViewNet()->setStatusBarText("A ride from edge to busStop needs one edge and one busStop");
1169  return false;
1170  }
1171  break;
1172  }
1173  // stops
1174  case GNE_TAG_STOPPERSON_EDGE: {
1175  // check if ride busStop->busStop can be created
1176  if (fromEdge) {
1177  stopParameters.edge = fromEdge->getID();
1178  stopParameters.endPos = fromEdge->getLanes().front()->getLaneShape().nearest_offset_to_point2D(myNet->getViewNet()->getPositionInformation());
1179  buildStop(personPlanObject, stopParameters);
1180  } else {
1181  myNet->getViewNet()->setStatusBarText("A stop has to be placed over an edge");
1182  return false;
1183  }
1184  break;
1185  }
1187  // check if ride busStop->busStop can be created
1188  if (toBusStop) {
1189  stopParameters.busstop = toBusStop->getID();
1190  buildStop(personPlanObject, stopParameters);
1191  } else {
1192  myNet->getViewNet()->setStatusBarText("A stop has to be placed over a busStop");
1193  return false;
1194  }
1195  break;
1196  }
1197  default:
1198  throw InvalidArgument("Invalid person plan tag");
1199  }
1200  // get person
1201  const auto person = myNet->getAttributeCarriers()->retrieveDemandElement(personPlanObject->getParentSumoBaseObject()->getTag(),
1202  personPlanObject->getParentSumoBaseObject()->getStringAttribute(SUMO_ATTR_ID), false);
1203  if (person) {
1204  // compute person (and all person plans)
1205  person->computePathElement();
1206  // center view after creation
1207  if (centerAfterCreation && !myNet->getViewNet()->getVisibleBoundary().around(person->getPositionInView())) {
1208  myNet->getViewNet()->centerTo(person->getPositionInView(), false);
1209  }
1210  }
1211  return true;
1212 }
1213 
1214 
1215 bool
1217  // clear and set planObject
1218  myPlanObject->clear();
1219  myPlanObject->setTag(containerParent->getTagProperty().getTag());
1220  myPlanObject->addStringAttribute(SUMO_ATTR_ID, containerParent->getID());
1221  // declare containerPlan object
1223  containerPlanObject->setTag(tag);
1224  // get attributes and values
1225  containerPlanAttributes->getAttributesAndValues(containerPlanObject, true);
1226  // get attributes
1227  const std::vector<std::string> lines = containerPlanObject->hasStringListAttribute(SUMO_ATTR_LINES) ? containerPlanObject->getStringListAttribute(SUMO_ATTR_LINES) : std::vector<std::string>();
1228  const double speed = containerPlanObject->hasDoubleAttribute(SUMO_ATTR_SPEED) ? containerPlanObject->getDoubleAttribute(SUMO_ATTR_SPEED) : 1.39;
1229  const double departPos = containerPlanObject->hasDoubleAttribute(SUMO_ATTR_DEPARTPOS) ? containerPlanObject->getDoubleAttribute(SUMO_ATTR_DEPARTPOS) : 0;
1230  const double arrivalPos = containerPlanObject->hasDoubleAttribute(SUMO_ATTR_ARRIVALPOS) ? containerPlanObject->getDoubleAttribute(SUMO_ATTR_ARRIVALPOS) : 0;
1231  // get stop parameters
1232  SUMOVehicleParameter::Stop stopParameters;
1233  // get edges
1234  GNEEdge* fromEdge = (pathCreator->getSelectedEdges().size() > 0) ? pathCreator->getSelectedEdges().front() : nullptr;
1235  GNEEdge* toEdge = (pathCreator->getSelectedEdges().size() > 0) ? pathCreator->getSelectedEdges().back() : nullptr;
1236  // get busStop
1237  GNEAdditional* toBusStop = pathCreator->getToStoppingPlace(SUMO_TAG_CONTAINER_STOP);
1238  // get path edges
1239  std::vector<std::string> edges;
1240  for (const auto& path : pathCreator->getPath()) {
1241  for (const auto& edge : path.getSubPath()) {
1242  edges.push_back(edge->getID());
1243  }
1244  }
1245  // check what ContainerPlan we're creating
1246  switch (tag) {
1247  // Transports
1248  case GNE_TAG_TRANSPORT_EDGE: {
1249  // check if transport busStop->edge can be created
1250  if (fromEdge && toEdge) {
1251  buildTransport(containerPlanObject, fromEdge->getID(), toEdge->getID(), "", lines, arrivalPos);
1252  } else {
1253  myNet->getViewNet()->setStatusBarText("A ride from busStop to edge needs a busStop and an edge");
1254  return false;
1255  }
1256  break;
1257  }
1259  // check if transport busStop->busStop can be created
1260  if (fromEdge && toBusStop) {
1261  buildTransport(containerPlanObject, fromEdge->getID(), "", toBusStop->getID(), lines, arrivalPos);
1262  } else {
1263  myNet->getViewNet()->setStatusBarText("A transport from busStop to busStop needs two busStops");
1264  return false;
1265  }
1266  break;
1267  }
1268  // Tranships
1269  case GNE_TAG_TRANSHIP_EDGE: {
1270  // check if tranship busStop->edge can be created
1271  if (fromEdge && toEdge) {
1272  buildTranship(containerPlanObject, fromEdge->getID(), toEdge->getID(), "", {}, speed, departPos, arrivalPos);
1273  } else {
1274  myNet->getViewNet()->setStatusBarText("A ride from busStop to edge needs a busStop and an edge");
1275  return false;
1276  }
1277  break;
1278  }
1280  // check if tranship busStop->busStop can be created
1281  if (fromEdge && toBusStop) {
1282  buildTranship(containerPlanObject, fromEdge->getID(), "", toBusStop->getID(), {}, speed, departPos, arrivalPos);
1283  } else {
1284  myNet->getViewNet()->setStatusBarText("A tranship from busStop to busStop needs two busStops");
1285  return false;
1286  }
1287  break;
1288  }
1289  case GNE_TAG_TRANSHIP_EDGES: {
1290  // check if tranship edges can be created
1291  if (edges.size() > 0) {
1292  buildTranship(containerPlanObject, "", "", "", edges, speed, departPos, arrivalPos);
1293  } else {
1294  myNet->getViewNet()->setStatusBarText("A tranship with edges attribute needs a list of edges");
1295  return false;
1296  }
1297  break;
1298  }
1299  // stops
1301  // check if ride busStop->busStop can be created
1302  if (fromEdge) {
1303  stopParameters.edge = fromEdge->getID();
1304  buildStop(containerPlanObject, stopParameters);
1305  } else {
1306  myNet->getViewNet()->setStatusBarText("A stop has to be placed over an edge");
1307  return false;
1308  }
1309  break;
1310  }
1312  // check if ride busStop->busStop can be created
1313  if (toBusStop) {
1314  stopParameters.busstop = toBusStop->getID();
1315  buildStop(containerPlanObject, stopParameters);
1316  } else {
1317  myNet->getViewNet()->setStatusBarText("A stop has to be placed over a busStop");
1318  return false;
1319  }
1320  break;
1321  }
1322  default:
1323  throw InvalidArgument("Invalid container plan tag");
1324  }
1325  return true;
1326 }
1327 
1328 
1329 bool
1330 GNERouteHandler::isVehicleIdDuplicated(GNENet* net, const std::string& id) {
1331  // declare vehicle tags vector
1333  for (const auto& vehicleTag : vehicleTags) {
1334  if (net->getAttributeCarriers()->retrieveDemandElement(vehicleTag, id, false) != nullptr) {
1335  WRITE_ERROR("There is another " + toString(vehicleTag) + " with the same ID='" + id + "'.");
1336  return true;
1337  }
1338  }
1339  return false;
1340 }
1341 
1342 
1343 bool
1344 GNERouteHandler::isPersonIdDuplicated(GNENet* net, const std::string& id) {
1345  for (SumoXMLTag personTag : std::vector<SumoXMLTag>({SUMO_TAG_PERSON, SUMO_TAG_PERSONFLOW})) {
1346  if (net->getAttributeCarriers()->retrieveDemandElement(personTag, id, false) != nullptr) {
1347  WRITE_ERROR("There is another " + toString(personTag) + " with the same ID='" + id + "'.");
1348  return true;
1349  }
1350  }
1351  return false;
1352 }
1353 
1354 
1355 bool
1356 GNERouteHandler::isContainerIdDuplicated(GNENet* net, const std::string& id) {
1357  for (SumoXMLTag containerTag : std::vector<SumoXMLTag>({SUMO_TAG_CONTAINER, SUMO_TAG_CONTAINERFLOW})) {
1358  if (net->getAttributeCarriers()->retrieveDemandElement(containerTag, id, false) != nullptr) {
1359  WRITE_ERROR("There is another " + toString(containerTag) + " with the same ID='" + id + "'.");
1360  return true;
1361  }
1362  }
1363  return false;
1364 }
1365 
1366 
1367 void
1368 GNERouteHandler::transformToVehicle(GNEVehicle* originalVehicle, bool createEmbeddedRoute) {
1369  // get original vehicle tag
1370  SumoXMLTag tag = originalVehicle->getTagProperty().getTag();
1371  // get pointer to net
1372  GNENet* net = originalVehicle->getNet();
1373  // declare route handler
1374  GNERouteHandler routeHandler("", net, true);
1375  // obtain vehicle parameters
1376  SUMOVehicleParameter vehicleParameters = *originalVehicle;
1377  // obtain vClass
1378  const auto vClass = originalVehicle->getVClass();
1379  // set "yellow" as original route color
1380  RGBColor routeColor = RGBColor::YELLOW;
1381  // declare edges
1382  std::vector<GNEEdge*> routeEdges;
1383  // obtain edges depending of tag
1384  if ((tag == GNE_TAG_FLOW_ROUTE) || (tag == SUMO_TAG_VEHICLE)) {
1385  // get route edges
1386  routeEdges = originalVehicle->getParentDemandElements().back()->getParentEdges();
1387  // get original route color
1388  routeColor = originalVehicle->getParentDemandElements().back()->getColor();
1389  } else if ((tag == GNE_TAG_VEHICLE_WITHROUTE) || (tag == GNE_TAG_FLOW_WITHROUTE)) {
1390  // get embedded route edges
1391  routeEdges = originalVehicle->getChildDemandElements().front()->getParentEdges();
1392  } else if ((tag == SUMO_TAG_TRIP) || (tag == SUMO_TAG_FLOW)) {
1393  // calculate path using from-via-to edges
1394  routeEdges = originalVehicle->getNet()->getPathManager()->getPathCalculator()->calculateDijkstraPath(originalVehicle->getVClass(), originalVehicle->getParentEdges());
1395  }
1396  // declare edge IDs
1397  std::vector<std::string> edgeIDs;
1398  for (const auto& edge : routeEdges) {
1399  edgeIDs.push_back(edge->getID());
1400  }
1401  // only continue if edges are valid
1402  if (routeEdges.empty()) {
1403  // declare header
1404  const std::string header = "Problem transforming to vehicle";
1405  // declare message
1406  const std::string message = "Vehicle cannot be transformed. Invalid number of edges";
1407  // write warning
1408  WRITE_DEBUG("Opened FXMessageBox " + header);
1409  // open message box
1410  FXMessageBox::warning(originalVehicle->getNet()->getViewNet()->getApp(), MBOX_OK, header.c_str(), "%s", message.c_str());
1411  // write warning if netedit is running in testing mode
1412  WRITE_DEBUG("Closed FXMessageBox " + header);
1413  } else {
1414  // begin undo-redo operation
1415  net->getViewNet()->getUndoList()->begin(originalVehicle->getTagProperty().getGUIIcon(), "transform " + originalVehicle->getTagStr() + " to " + toString(SUMO_TAG_VEHICLE));
1416  // first delete vehicle
1417  net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());
1418  // check if new vehicle must have an embedded route
1419  if (createEmbeddedRoute) {
1420  // change tag in vehicle parameters
1421  vehicleParameters.tag = GNE_TAG_VEHICLE_WITHROUTE;
1422  // create a flow with embebbed routes
1424  CommonXMLStructure::SumoBaseObject* routeBaseOBject = new CommonXMLStructure::SumoBaseObject(vehicleBaseOBject);
1425  // fill parameters
1426  vehicleBaseOBject->setTag(SUMO_TAG_VEHICLE);
1427  vehicleBaseOBject->addStringAttribute(SUMO_ATTR_ID, vehicleParameters.id);
1428  vehicleBaseOBject->setVehicleParameter(&vehicleParameters);
1429  // build embedded route
1430  routeHandler.buildEmbeddedRoute(routeBaseOBject, edgeIDs, "", false, 0, {});
1431  delete vehicleBaseOBject;
1432  } else {
1433  // change tag in vehicle parameters
1434  vehicleParameters.tag = SUMO_TAG_VEHICLE;
1435  // generate route ID
1436  const std::string routeID = net->getAttributeCarriers()->generateDemandElementID(SUMO_TAG_ROUTE);
1437  // build route
1438  routeHandler.buildRoute(nullptr, routeID, vClass, edgeIDs, routeColor, false, 0, {});
1439  // set route ID in vehicle parameters
1440  vehicleParameters.routeid = routeID;
1441  // create vehicle
1442  routeHandler.buildVehicleOverRoute(nullptr, vehicleParameters);
1443  }
1444  // end undo-redo operation
1445  net->getViewNet()->getUndoList()->end();
1446  }
1447 }
1448 
1449 
1450 void
1451 GNERouteHandler::transformToRouteFlow(GNEVehicle* originalVehicle, bool createEmbeddedRoute) {
1452  // get original vehicle tag
1453  SumoXMLTag tag = originalVehicle->getTagProperty().getTag();
1454  // get pointer to net
1455  GNENet* net = originalVehicle->getNet();
1456  // declare route handler
1457  GNERouteHandler routeHandler("", net, true);
1458  // obtain vehicle parameters
1459  SUMOVehicleParameter vehicleParameters = *originalVehicle;
1460  // obtain vClass
1461  const auto vClass = originalVehicle->getVClass();
1462  // set "yellow" as original route color
1463  RGBColor routeColor = RGBColor::YELLOW;
1464  // declare edges
1465  std::vector<GNEEdge*> routeEdges;
1466  // obtain edges depending of tag
1467  if ((tag == GNE_TAG_FLOW_ROUTE) || (tag == SUMO_TAG_VEHICLE)) {
1468  // get route edges
1469  routeEdges = originalVehicle->getParentDemandElements().back()->getParentEdges();
1470  // get original route color
1471  routeColor = originalVehicle->getParentDemandElements().back()->getColor();
1472  } else if ((tag == GNE_TAG_VEHICLE_WITHROUTE) || (tag == GNE_TAG_FLOW_WITHROUTE)) {
1473  // get embedded route edges
1474  routeEdges = originalVehicle->getChildDemandElements().front()->getParentEdges();
1475  } else if ((tag == SUMO_TAG_TRIP) || (tag == SUMO_TAG_FLOW)) {
1476  // calculate path using from-via-to edges
1477  routeEdges = originalVehicle->getNet()->getPathManager()->getPathCalculator()->calculateDijkstraPath(originalVehicle->getVClass(), originalVehicle->getParentEdges());
1478  }
1479  // declare edge IDs
1480  std::vector<std::string> edgeIDs;
1481  for (const auto& edge : routeEdges) {
1482  edgeIDs.push_back(edge->getID());
1483  }
1484  // only continue if edges are valid
1485  if (routeEdges.empty()) {
1486  // declare header
1487  const std::string header = "Problem transforming to vehicle";
1488  // declare message
1489  const std::string message = "Vehicle cannot be transformed. Invalid number of edges";
1490  // write warning
1491  WRITE_DEBUG("Opened FXMessageBox " + header);
1492  // open message box
1493  FXMessageBox::warning(originalVehicle->getNet()->getViewNet()->getApp(), MBOX_OK, header.c_str(), "%s", message.c_str());
1494  // write warning if netedit is running in testing mode
1495  WRITE_DEBUG("Closed FXMessageBox " + header);
1496  } else {
1497  // begin undo-redo operation
1498  net->getViewNet()->getUndoList()->begin(originalVehicle->getTagProperty().getGUIIcon(), "transform " + originalVehicle->getTagStr() + " to " + toString(SUMO_TAG_VEHICLE));
1499  // first delete vehicle
1500  net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());
1501  // change depart
1502  if ((vehicleParameters.tag == SUMO_TAG_TRIP) || (vehicleParameters.tag == SUMO_TAG_VEHICLE) || (vehicleParameters.tag == GNE_TAG_VEHICLE_WITHROUTE)) {
1503  // get template flow
1505  // set flow parameters
1506  vehicleParameters.repetitionEnd = vehicleParameters.depart + string2time("3600");
1507  vehicleParameters.repetitionNumber = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(SUMO_ATTR_NUMBER));
1508  vehicleParameters.repetitionOffset = string2time(templateFlow->getAttribute(SUMO_ATTR_PERIOD));
1509  vehicleParameters.repetitionProbability = GNEAttributeCarrier::parse<double>(templateFlow->getAttribute(SUMO_ATTR_PROB));
1510  // by default, number and end enabled
1511  vehicleParameters.parametersSet = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(GNE_ATTR_FLOWPARAMETERS));
1512  }
1513  // check if new vehicle must have an embedded route
1514  if (createEmbeddedRoute) {
1515  // change tag in vehicle parameters
1516  vehicleParameters.tag = GNE_TAG_FLOW_WITHROUTE;
1517  // create a flow with embebbed routes
1519  CommonXMLStructure::SumoBaseObject* routeBaseOBject = new CommonXMLStructure::SumoBaseObject(vehicleBaseOBject);
1520  // fill parameters
1521  vehicleBaseOBject->setTag(SUMO_TAG_FLOW);
1522  vehicleBaseOBject->addStringAttribute(SUMO_ATTR_ID, vehicleParameters.id);
1523  vehicleBaseOBject->setVehicleParameter(&vehicleParameters);
1524  // build embedded route
1525  routeHandler.buildEmbeddedRoute(routeBaseOBject, edgeIDs, "", false, 0, {});
1526  delete vehicleBaseOBject;
1527  } else {
1528  // change tag in vehicle parameters
1529  vehicleParameters.tag = GNE_TAG_FLOW_ROUTE;
1530  // generate a new route id
1531  const std::string routeID = net->getAttributeCarriers()->generateDemandElementID(SUMO_TAG_ROUTE);
1532  // build route
1533  routeHandler.buildRoute(nullptr, routeID, vClass, edgeIDs, routeColor, false, 0, {});
1534  // set route ID in vehicle parameters
1535  vehicleParameters.routeid = routeID;
1536  // create vehicle
1537  routeHandler.buildFlowOverRoute(nullptr, vehicleParameters);
1538  }
1539  // end undo-redo operation
1540  net->getViewNet()->getUndoList()->end();
1541  }
1542 }
1543 
1544 
1545 void
1547  // get original vehicle tag
1548  SumoXMLTag tag = originalVehicle->getTagProperty().getTag();
1549  // get pointer to net
1550  GNENet* net = originalVehicle->getNet();
1551  // declare route handler
1552  GNERouteHandler routeHandler("", net, true);
1553  // obtain vehicle parameters
1554  SUMOVehicleParameter vehicleParameters = *originalVehicle;
1555  // get route
1556  GNEDemandElement* route = nullptr;
1557  // declare edges
1558  std::vector<GNEEdge*> edges;
1559  // obtain edges depending of tag
1560  if ((tag == SUMO_TAG_VEHICLE) || (tag == GNE_TAG_FLOW_ROUTE)) {
1561  // set route
1562  route = originalVehicle->getParentDemandElements().back();
1563  // get route edges
1564  edges = route->getParentEdges();
1565  } else if ((tag == GNE_TAG_VEHICLE_WITHROUTE) || (tag == GNE_TAG_FLOW_WITHROUTE)) {
1566  // get embedded route edges
1567  edges = originalVehicle->getChildDemandElements().front()->getParentEdges();
1568  } else if ((tag == SUMO_TAG_TRIP) || (tag == SUMO_TAG_FLOW)) {
1569  // just take parent edges (from and to)
1570  edges = originalVehicle->getParentEdges();
1571  }
1572  // only continue if edges are valid
1573  if (edges.size() < 2) {
1574  // declare header
1575  const std::string header = "Problem transforming to vehicle";
1576  // declare message
1577  const std::string message = "Vehicle cannot be transformed. Invalid number of edges";
1578  // write warning
1579  WRITE_DEBUG("Opened FXMessageBox " + header);
1580  // open message box
1581  FXMessageBox::warning(originalVehicle->getNet()->getViewNet()->getApp(), MBOX_OK, header.c_str(), "%s", message.c_str());
1582  // write warning if netedit is running in testing mode
1583  WRITE_DEBUG("Closed FXMessageBox " + header);
1584  } else {
1585  // begin undo-redo operation
1586  net->getViewNet()->getUndoList()->begin(originalVehicle->getTagProperty().getGUIIcon(), "transform " + originalVehicle->getTagStr() + " to " + toString(SUMO_TAG_TRIP));
1587  // first delete vehicle
1588  net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());
1589  // check if route has to be deleted
1590  if (route && route->getChildDemandElements().empty()) {
1591  net->deleteDemandElement(route, net->getViewNet()->getUndoList());
1592  }
1593  // change tag in vehicle parameters
1594  vehicleParameters.tag = SUMO_TAG_TRIP;
1595  // create trip
1596  routeHandler.buildTrip(nullptr, vehicleParameters, edges.front()->getID(), edges.back()->getID(), {});
1597  // end undo-redo operation
1598  net->getViewNet()->getUndoList()->end();
1599  }
1600 }
1601 
1602 
1603 void
1605  // get original vehicle tag
1606  SumoXMLTag tag = originalVehicle->getTagProperty().getTag();
1607  // get pointer to net
1608  GNENet* net = originalVehicle->getNet();
1609  // declare route handler
1610  GNERouteHandler routeHandler("", net, true);
1611  // obtain vehicle parameters
1612  SUMOVehicleParameter vehicleParameters = *originalVehicle;
1613  // declare route
1614  GNEDemandElement* route = nullptr;
1615  // declare edges
1616  std::vector<GNEEdge*> edges;
1617  // obtain edges depending of tag
1618  if ((tag == SUMO_TAG_VEHICLE) || (tag == GNE_TAG_FLOW_ROUTE)) {
1619  // set route
1620  route = originalVehicle->getParentDemandElements().back();
1621  // get route edges
1622  edges = route->getParentEdges();
1623  } else if ((tag == GNE_TAG_VEHICLE_WITHROUTE) || (tag == GNE_TAG_FLOW_WITHROUTE)) {
1624  // get embedded route edges
1625  edges = originalVehicle->getChildDemandElements().front()->getParentEdges();
1626  } else if ((tag == SUMO_TAG_TRIP) || (tag == SUMO_TAG_FLOW)) {
1627  // just take parent edges (from and to)
1628  edges = originalVehicle->getParentEdges();
1629  }
1630  // only continue if edges are valid
1631  if (edges.empty()) {
1632  // declare header
1633  const std::string header = "Problem transforming to vehicle";
1634  // declare message
1635  const std::string message = "Vehicle cannot be transformed. Invalid number of edges";
1636  // write warning
1637  WRITE_DEBUG("Opened FXMessageBox " + header);
1638  // open message box
1639  FXMessageBox::warning(originalVehicle->getNet()->getViewNet()->getApp(), MBOX_OK, header.c_str(), "%s", message.c_str());
1640  // write warning if netedit is running in testing mode
1641  WRITE_DEBUG("Closed FXMessageBox " + header);
1642  } else {
1643  // begin undo-redo operation
1644  net->getViewNet()->getUndoList()->begin(originalVehicle->getTagProperty().getGUIIcon(), "transform " + originalVehicle->getTagStr() + " to " + toString(SUMO_TAG_VEHICLE));
1645  // first delete vehicle
1646  net->deleteDemandElement(originalVehicle, net->getViewNet()->getUndoList());
1647  // check if route has to be deleted
1648  if (route && route->getChildDemandElements().empty()) {
1649  net->deleteDemandElement(route, net->getViewNet()->getUndoList());
1650  }
1651  // change depart
1652  if ((vehicleParameters.tag == SUMO_TAG_TRIP) || (vehicleParameters.tag == SUMO_TAG_VEHICLE) || (vehicleParameters.tag == GNE_TAG_VEHICLE_WITHROUTE)) {
1653  // get template flow
1655  // set flow parameters
1656  vehicleParameters.repetitionEnd = vehicleParameters.depart + string2time("3600");
1657  vehicleParameters.repetitionNumber = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(SUMO_ATTR_NUMBER));
1658  vehicleParameters.repetitionOffset = string2time(templateFlow->getAttribute(SUMO_ATTR_PERIOD));
1659  vehicleParameters.repetitionProbability = GNEAttributeCarrier::parse<double>(templateFlow->getAttribute(SUMO_ATTR_PROB));
1660  // by default, number and end enabled
1661  vehicleParameters.parametersSet = GNEAttributeCarrier::parse<int>(templateFlow->getAttribute(GNE_ATTR_FLOWPARAMETERS));
1662  }
1663  // change tag in vehicle parameters
1664  vehicleParameters.tag = SUMO_TAG_FLOW;
1665  // create flow
1666  routeHandler.buildFlow(nullptr, vehicleParameters, edges.front()->getID(), edges.back()->getID(), {});
1667  // end undo-redo operation
1668  net->getViewNet()->getUndoList()->end();
1669  }
1670 }
1671 
1672 
1673 void
1675  //
1676 }
1677 
1678 
1679 void
1681  //
1682 }
1683 
1684 
1685 void
1687  //
1688 }
1689 
1690 
1691 void
1693  //
1694 }
1695 
1696 
1697 void
1698 GNERouteHandler::setFlowParameters(const SumoXMLAttr attribute, int& parameters) {
1699  // modify parameters depending of given Flow attribute
1700  switch (attribute) {
1701  case SUMO_ATTR_END: {
1702  // give more priority to end
1703  parameters = VEHPARS_END_SET | VEHPARS_NUMBER_SET;
1704  break;
1705  }
1706  case SUMO_ATTR_NUMBER:
1707  parameters ^= VEHPARS_END_SET;
1708  parameters |= VEHPARS_NUMBER_SET;
1709  break;
1710  case SUMO_ATTR_VEHSPERHOUR:
1713  // give more priority to end
1714  if ((parameters & VEHPARS_END_SET) && (parameters & VEHPARS_NUMBER_SET)) {
1715  parameters = VEHPARS_END_SET;
1716  } else if (parameters & VEHPARS_END_SET) {
1717  parameters = VEHPARS_END_SET;
1718  } else if (parameters & VEHPARS_NUMBER_SET) {
1719  parameters = VEHPARS_NUMBER_SET;
1720  }
1721  // set VehsPerHour
1722  parameters |= VEHPARS_VPH_SET;
1723  break;
1724  }
1725  case SUMO_ATTR_PERIOD: {
1726  // give more priority to end
1727  if ((parameters & VEHPARS_END_SET) && (parameters & VEHPARS_NUMBER_SET)) {
1728  parameters = VEHPARS_END_SET;
1729  } else if (parameters & VEHPARS_END_SET) {
1730  parameters = VEHPARS_END_SET;
1731  } else if (parameters & VEHPARS_NUMBER_SET) {
1732  parameters = VEHPARS_NUMBER_SET;
1733  }
1734  // set period
1735  parameters |= VEHPARS_PERIOD_SET;
1736  break;
1737  }
1738  case SUMO_ATTR_PROB: {
1739  // give more priority to end
1740  if ((parameters & VEHPARS_END_SET) && (parameters & VEHPARS_NUMBER_SET)) {
1741  parameters = VEHPARS_END_SET;
1742  } else if (parameters & VEHPARS_END_SET) {
1743  parameters = VEHPARS_END_SET;
1744  } else if (parameters & VEHPARS_NUMBER_SET) {
1745  parameters = VEHPARS_NUMBER_SET;
1746  }
1747  // set probability
1748  parameters |= VEHPARS_PROB_SET;
1749  break;
1750  }
1751  default:
1752  break;
1753  }
1754 }
1755 
1756 // ===========================================================================
1757 // protected
1758 // ===========================================================================
1759 
1760 GNEJunction*
1761 GNERouteHandler::parseJunction(const SumoXMLTag tag, const std::string& junctionID) const {
1762  GNEJunction* junction = myNet->getAttributeCarriers()->retrieveJunction(junctionID, false);
1763  // empty junctions aren't allowed. If junction is empty, write error, clear junctions and stop
1764  if (junction == nullptr) {
1765  WRITE_ERROR("Could not build " + toString(tag) + " in netedit; " + toString(SUMO_TAG_JUNCTION) + " doesn't exist.");
1766  }
1767  return junction;
1768 }
1769 
1770 
1771 GNEEdge*
1772 GNERouteHandler::parseEdge(const SumoXMLTag tag, const std::string& edgeID) const {
1773  GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);
1774  // empty edges aren't allowed. If edge is empty, write error, clear edges and stop
1775  if (edge == nullptr) {
1776  WRITE_ERROR("Could not build " + toString(tag) + " in netedit; " + toString(SUMO_TAG_EDGE) + " doesn't exist.");
1777  }
1778  return edge;
1779 }
1780 
1781 
1782 std::vector<GNEEdge*>
1783 GNERouteHandler::parseEdges(const SumoXMLTag tag, const std::vector<std::string>& edgeIDs) const {
1784  std::vector<GNEEdge*> edges;
1785  for (const auto& edgeID : edgeIDs) {
1786  GNEEdge* edge = myNet->getAttributeCarriers()->retrieveEdge(edgeID, false);
1787  // empty edges aren't allowed. If edge is empty, write error, clear edges and stop
1788  if (edge == nullptr) {
1789  WRITE_ERROR("Could not build " + toString(tag) + " in netedit; " + toString(SUMO_TAG_EDGE) + " doesn't exist.");
1790  edges.clear();
1791  return edges;
1792  } else {
1793  edges.push_back(edge);
1794  }
1795  }
1796  return edges;
1797 }
1798 
1799 
1802  // check that sumoBaseObject has parent
1803  if (sumoBaseObject->getParentSumoBaseObject() == nullptr) {
1804  return nullptr;
1805  }
1806  if ((sumoBaseObject->getParentSumoBaseObject()->getTag() != SUMO_TAG_PERSON) &&
1807  (sumoBaseObject->getParentSumoBaseObject()->getTag() != SUMO_TAG_PERSONFLOW)) {
1808  return nullptr;
1809  }
1810  // try it with person
1812  // if empty, try it with personFlow
1813  if (personParent == nullptr) {
1815  } else {
1816  return personParent;
1817  }
1818 }
1819 
1820 
1823  // check that sumoBaseObject has parent
1824  if (sumoBaseObject->getParentSumoBaseObject() == nullptr) {
1825  return nullptr;
1826  }
1827  if ((sumoBaseObject->getParentSumoBaseObject()->getTag() != SUMO_TAG_CONTAINER) &&
1828  (sumoBaseObject->getParentSumoBaseObject()->getTag() != SUMO_TAG_CONTAINERFLOW)) {
1829  return nullptr;
1830  }
1831  // try it with container
1833  // if empty, try it with containerFlow
1834  if (containerParent == nullptr) {
1836  } else {
1837  return containerParent;
1838  }
1839 }
1840 
1841 
1842 GNEEdge*
1844  if (obj->getParentSumoBaseObject() == nullptr) {
1845  // no parent defined
1846  return nullptr;
1847  }
1848  // get parent object
1849  const CommonXMLStructure::SumoBaseObject* parentObject = obj->getParentSumoBaseObject();
1850  // check person/container conditions
1851  if (person && (parentObject->getTag() != SUMO_TAG_PERSON) && (parentObject->getTag() != SUMO_TAG_PERSONFLOW)) {
1852  // invalid parent
1853  return nullptr;
1854  }
1855  if (!person && (parentObject->getTag() != SUMO_TAG_CONTAINER) && (parentObject->getTag() != SUMO_TAG_CONTAINERFLOW)) {
1856  // invalid parent
1857  return nullptr;
1858  }
1859  // search previous child
1860  const auto it = std::find(parentObject->getSumoBaseObjectChildren().begin(), parentObject->getSumoBaseObjectChildren().end(), obj);
1861  if (it == parentObject->getSumoBaseObjectChildren().begin()) {
1862  return nullptr;
1863  }
1864  // get last children
1865  const CommonXMLStructure::SumoBaseObject* previousPersonPlan = *(it - 1);
1866  // check conditions
1867  if ((previousPersonPlan->getTag() != SUMO_TAG_WALK) && (previousPersonPlan->getTag() != SUMO_TAG_RIDE) &&
1868  (previousPersonPlan->getTag() != SUMO_TAG_PERSONTRIP) && (previousPersonPlan->getTag() != SUMO_TAG_STOP)) {
1869  // invalid last child
1870  return nullptr;
1871  }
1872  // ends in an edge (only for stops)
1873  if (previousPersonPlan->hasStringAttribute(SUMO_ATTR_EDGE)) {
1874  return myNet->getAttributeCarriers()->retrieveEdge(previousPersonPlan->getStringAttribute(SUMO_ATTR_EDGE), false);
1875  }
1876  // ends in a lane (only for stops)
1877  if (previousPersonPlan->hasStringAttribute(SUMO_ATTR_LANE)) {
1878  const auto lane = myNet->getAttributeCarriers()->retrieveLane(previousPersonPlan->getStringAttribute(SUMO_ATTR_LANE), false);
1879  if (lane) {
1880  return lane->getParentEdge();
1881  } else {
1882  return nullptr;
1883  }
1884  }
1885  // ends in a route (walk)
1886  if (previousPersonPlan->hasStringAttribute(SUMO_ATTR_ROUTE) &&
1887  !previousPersonPlan->getStringAttribute(SUMO_ATTR_ROUTE).empty()) {
1888  const auto route = myNet->getAttributeCarriers()->retrieveDemandElement(SUMO_TAG_ROUTE, previousPersonPlan->getStringAttribute(SUMO_ATTR_ROUTE), false);
1889  if (route) {
1890  return route->getParentEdges().back();
1891  } else {
1892  return nullptr;
1893  }
1894  }
1895  // ends in a list of edges (walk)
1896  if (previousPersonPlan->hasStringListAttribute(SUMO_ATTR_EDGES) &&
1897  !previousPersonPlan->getStringListAttribute(SUMO_ATTR_EDGES).empty()) {
1898  return myNet->getAttributeCarriers()->retrieveEdge(previousPersonPlan->getStringListAttribute(SUMO_ATTR_EDGES).back(), false);
1899  }
1900  // ends in a "to" edge
1901  if (previousPersonPlan->hasStringAttribute(SUMO_ATTR_TO) &&
1902  !previousPersonPlan->getStringAttribute(SUMO_ATTR_TO).empty()) {
1903  return myNet->getAttributeCarriers()->retrieveEdge(previousPersonPlan->getStringAttribute(SUMO_ATTR_TO), false);
1904  }
1905  // ends in a "busStop"
1906  if (previousPersonPlan->hasStringAttribute(SUMO_ATTR_BUS_STOP) &&
1907  !previousPersonPlan->getStringAttribute(SUMO_ATTR_BUS_STOP).empty()) {
1908  const auto busStop = myNet->getAttributeCarriers()->retrieveAdditional(SUMO_TAG_BUS_STOP, previousPersonPlan->getStringAttribute(SUMO_ATTR_BUS_STOP), false);
1909  if (busStop) {
1910  return busStop->getParentLanes().front()->getParentEdge();
1911  } else {
1912  return nullptr;
1913  }
1914  }
1915  return nullptr;
1916 }
1917 
1918 /****************************************************************************/
@ CONTAINERFLOW
@ VTYPEDISTRIBUTION
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:290
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
long long int SUMOTime
Definition: SUMOTime.h:32
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
const std::set< std::string > DEFAULT_VTYPES
const int VEHPARS_PROB_SET
const int STOP_DURATION_SET
const int VEHPARS_VPH_SET
const int VEHPARS_END_SET
@ GIVEN
The lane is given.
const int STOP_UNTIL_SET
@ GIVEN
The speed is given.
const int VEHPARS_DEPARTLANE_SET
const int VEHPARS_NUMBER_SET
const int VEHPARS_DEPARTSPEED_SET
const int VEHPARS_PERIOD_SET
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ GNE_TAG_TRIP_JUNCTIONS
a trip between junctions (used in NETEDIT)
@ SUMO_TAG_STOP_CONTAINERSTOP
stop placed over a containerStop (used in netedit)
@ GNE_TAG_PERSONTRIP_JUNCTIONS
@ GNE_TAG_TRANSPORT_CONTAINERSTOP
@ SUMO_TAG_CHARGING_STATION
A Charging Station.
@ SUMO_TAG_VTYPE
description of a vehicle/person/container type
@ SUMO_TAG_WALK
@ GNE_TAG_PERSONTRIP_BUSSTOP
@ SUMO_TAG_NOTHING
invalid tag
@ GNE_TAG_WALK_EDGES
@ SUMO_TAG_CONTAINER_STOP
A container stop.
@ SUMO_TAG_CONTAINERFLOW
@ SUMO_TAG_STOP_CHARGINGSTATION
stop placed over a charging station (used in netedit)
@ SUMO_TAG_STOP_LANE
stop placed over a lane (used in netedit)
@ GNE_TAG_STOPCONTAINER_EDGE
@ SUMO_TAG_BUS_STOP
A bus stop.
@ GNE_TAG_STOPPERSON_BUSSTOP
@ SUMO_TAG_STOP
stop for vehicles
@ SUMO_TAG_VEHICLE
description of a vehicle
@ GNE_TAG_FLOW_ROUTE
a flow definition using a route instead of a from-to edges route (used in NETEDIT)
@ GNE_TAG_FLOW_JUNCTIONS
a flow between junctions (used in NETEDIT)
@ GNE_TAG_TRANSHIP_EDGES
@ GNE_TAG_STOPCONTAINER_CONTAINERSTOP
@ GNE_TAG_FLOW_WITHROUTE
description of a vehicle with an embedded route (used in NETEDIT)
@ SUMO_TAG_FLOW
a flow definitio nusing a from-to edges instead of a route (used by router)
@ SUMO_TAG_PARKING_AREA
A parking area.
@ SUMO_TAG_CONTAINER
@ SUMO_TAG_JUNCTION
begin/end of the description of a junction
@ GNE_TAG_WALK_BUSSTOP
@ SUMO_TAG_ROUTE
begin/end of the description of a route
@ SUMO_TAG_RIDE
@ GNE_TAG_RIDE_EDGE
@ SUMO_TAG_STOP_BUSSTOP
stop placed over a busStop (used in netedit)
@ SUMO_TAG_VTYPE_DISTRIBUTION
distribution of a vehicle type
@ GNE_TAG_TRANSHIP_EDGE
@ GNE_TAG_WALK_JUNCTIONS
@ GNE_TAG_VEHICLE_WITHROUTE
description of a vehicle with an embedded route (used in NETEDIT)
@ SUMO_TAG_PERSON
@ SUMO_TAG_PERSONTRIP
@ SUMO_TAG_STOP_PARKINGAREA
stop placed over a parking area (used in netedit)
@ GNE_TAG_WALK_EDGE
@ GNE_TAG_PERSONTRIP_EDGE
@ GNE_TAG_RIDE_BUSSTOP
@ GNE_TAG_STOPPERSON_EDGE
@ GNE_TAG_WALK_ROUTE
@ SUMO_TAG_PERSONFLOW
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ GNE_TAG_TRANSHIP_CONTAINERSTOP
@ SUMO_TAG_EDGE
begin/end of the description of an edge
@ GNE_TAG_TRANSPORT_EDGE
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_LINES
@ SUMO_ATTR_NUMBER
@ SUMO_ATTR_LANE
@ SUMO_ATTR_VEHSPERHOUR
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_EDGE
@ SUMO_ATTR_BUS_STOP
@ GNE_ATTR_FLOWPARAMETERS
flow parameters (integer for mask end, number, etc...)
@ SUMO_ATTR_ARRIVALPOS
@ SUMO_ATTR_ACTTYPE
@ GNE_ATTR_VTYPE_DISTRIBUTION
vehicle type distribution
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_CONTAINERSPERHOUR
@ SUMO_ATTR_MODES
@ SUMO_ATTR_VTYPES
@ SUMO_ATTR_DEPARTPOS
@ SUMO_ATTR_PERIOD
@ SUMO_ATTR_DEPARTSPEED
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_DEPARTLANE
@ SUMO_ATTR_PROB
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_MAXSPEED
@ SUMO_ATTR_ID
@ SUMO_ATTR_UNTIL
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_PERSONSPERHOUR
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
bool around(const Position &p, double offset=0) const
Returns whether the AbstractPoly the given coordinate.
Definition: Boundary.cpp:171
SUMOTime getTimeAttribute(const SumoXMLAttr attr) const
get time attribute
bool hasStringAttribute(const SumoXMLAttr attr) const
has function
void setTag(const SumoXMLTag tag)
set SumoBaseObject tag
SumoBaseObject * getParentSumoBaseObject() const
get pointer to mySumoBaseObjectParent SumoBaseObject (if is null, then is the root)
bool hasTimeAttribute(const SumoXMLAttr attr) const
check if current SumoBaseObject has the given time attribute
bool hasDoubleAttribute(const SumoXMLAttr attr) const
check if current SumoBaseObject has the given double attribute
void setVehicleParameter(const SUMOVehicleParameter *vehicleParameter)
set vehicle parameters
void addStringAttribute(const SumoXMLAttr attr, const std::string &value)
double getDoubleAttribute(const SumoXMLAttr attr) const
get double attribute
const SUMOVehicleParameter & getVehicleParameter() const
get vehicle parameters
const std::vector< std::string > & getStringListAttribute(const SumoXMLAttr attr) const
get string list attribute
bool hasStringListAttribute(const SumoXMLAttr attr) const
check if current SumoBaseObject has the given string list attribute
void clear()
clear SumoBaseObject
const std::string & getStringAttribute(const SumoXMLAttr attr) const
get string attribute
const std::vector< SumoBaseObject * > & getSumoBaseObjectChildren() const
get SumoBaseObject children
An Element which don't belongs to GNENet but has influency in the simulation.
Definition: GNEAdditional.h:48
const std::string & getID() const
get ID
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
GNENet * getNet() const
get pointer to net
An Element which don't belongs to GNENet but has influency in the simulation.
virtual double getAttributeDouble(SumoXMLAttr key) const =0
virtual void computePathElement()=0
compute pathElement
virtual void setAttribute(SumoXMLAttr key, const std::string &value, GNEUndoList *undoList)=0
method for setting the attribute and letting the object perform demand element changes
const std::string & getID() const
get ID
A road/street connecting two junctions (netedit-version)
Definition: GNEEdge.h:53
const std::vector< GNELane * > & getLanes() const
returns a reference to the lane vector
Definition: GNEEdge.cpp:782
void getAttributesAndValues(CommonXMLStructure::SumoBaseObject *baseObject, bool includeAll) const
get attributes and their values
const std::vector< Path > & getPath() const
get path route
GNEAdditional * getToStoppingPlace(SumoXMLTag expectedTag) const
get to stoppingPlace
GNEDemandElement * getRoute() const
get route
const std::vector< GNEEdge * > & getSelectedEdges() const
get current selected edges
const std::vector< GNEJunction * > & getSelectedJunctions() const
get current selected junctions
GNEAttributeCarrier * getTemplateAC(SumoXMLTag ACTag) const
get templateAC
void addChildElement(T *element)
add child element
const std::vector< GNEDemandElement * > & getChildDemandElements() const
return child demand elements
const std::vector< GNEDemandElement * > & getParentDemandElements() const
get parent demand elements
const std::vector< GNEEdge * > & getParentEdges() const
get parent edges
const std::vector< GNELane * > & getParentLanes() const
get parent lanes
This lane is powered by an underlying GNEEdge and basically knows how to draw itself.
Definition: GNELane.h:46
GNEEdge * getParentEdge() const
get arent edge
Definition: GNELane.cpp:113
GNELane * retrieveLane(const std::string &id, bool hardFail=true, bool checkVolatileChange=false) const
get lane by id
std::string generateDemandElementID(SumoXMLTag tag) const
generate demand element id
GNEAdditional * retrieveAdditional(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named additional.
GNEJunction * retrieveJunction(const std::string &id, bool hardFail=true) const
get junction by id
void insertDemandElement(GNEDemandElement *demandElement)
Insert a demand element element int GNENet container.
GNEEdge * retrieveEdge(const std::string &id, bool hardFail=true) const
get edge by id
GNEDemandElement * retrieveDemandElement(SumoXMLTag type, const std::string &id, bool hardFail=true) const
Returns the named demand element.
A NBNetBuilder extended by visualisation and editing capabilities.
Definition: GNENet.h:42
void deleteDemandElement(GNEDemandElement *demandElement, GNEUndoList *undoList)
remove demand element
Definition: GNENet.cpp:630
GNENetHelper::AttributeCarriers * getAttributeCarriers() const
get all attribute carriers used in this net
Definition: GNENet.cpp:125
GNEPathManager * getPathManager()
get path manager
Definition: GNENet.cpp:131
GNEViewNet * getViewNet() const
get view net
Definition: GNENet.cpp:1964
const std::string & getID() const
get ID
std::vector< GNEEdge * > calculateDijkstraPath(const SUMOVehicleClass vClass, const std::vector< GNEEdge * > &partialEdges) const
calculate Dijkstra path between a list of partial edges
PathCalculator * getPathCalculator()
obtain instance of PathCalculator
void incRef(const std::string &debugMsg="")
Increarse reference.
Builds trigger objects for GNENet (busStops, chargingStations, detectors, etc..)
void buildContainerFlow(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const SUMOVehicleParameter &containerFlowParameters)
build container flow
void buildRouteDistribution(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const std::string &id)
build route distribution
CommonXMLStructure::SumoBaseObject * myPlanObject
pointer for person and container plans
GNEDemandElement * getPersonParent(const CommonXMLStructure::SumoBaseObject *sumoBaseObject) const
get person parent
GNEEdge * getPreviousPlanEdge(const bool person, const CommonXMLStructure::SumoBaseObject *obj) const
get previos person/container plan edge
void buildPerson(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const SUMOVehicleParameter &personParameters)
build person
static void transformToRouteFlow(GNEVehicle *originalVehicle, bool createEmbeddedRoute)
transform routeFlow over an existent route
void buildFlow(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const SUMOVehicleParameter &vehicleParameters, const std::string &fromEdgeID, const std::string &toEdgeID, const std::vector< std::string > &viaIDs)
build flow
GNENet * myNet
pointer to GNENet
void buildPersonTrip(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const std::string &fromEdgeID, const std::string &toEdgeID, const std::string &fromJunctionID, const std::string &toJunctionID, const std::string &toBusStopID, double arrivalPos, const std::vector< std::string > &types, const std::vector< std::string > &modes)
build person trip
static bool isPersonIdDuplicated(GNENet *net, const std::string &id)
check if there is already a person (Person or PersonFlow) with the given ID
void buildWalk(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const std::string &fromEdgeID, const std::string &toEdgeID, const std::string &fromJunctionID, const std::string &toJunctionID, const std::string &toBusStopID, const std::vector< std::string > &edgeIDs, const std::string &routeID, double arrivalPos)
build walk
void buildTrip(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const SUMOVehicleParameter &vehicleParameters, const std::string &fromEdgeID, const std::string &toEdgeID, const std::vector< std::string > &viaIDs)
build trip
static void transformToContainerFlow(GNEContainer *originalContainer)
transform routeFlow over an existent route
void buildVehicleOverRoute(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const SUMOVehicleParameter &vehicleParameters)
build a vehicle over an existent route
bool buildPersonPlan(SumoXMLTag tag, GNEDemandElement *personParent, GNEFrameAttributeModules::AttributesCreator *personPlanAttributes, GNEFrameModules::PathCreator *pathCreator, const bool centerAfterCreation)
build person plan
void buildTransport(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const std::string &fromEdgeID, const std::string &toEdgeID, const std::string &toBusStopID, const std::vector< std::string > &lines, const double arrivalPos)
build transport
static void transformToFlow(GNEVehicle *originalVehicle)
transform to flow
void buildEmbeddedRoute(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const std::vector< std::string > &edgeIDs, const RGBColor &color, const int repeat, const SUMOTime cycleTime, const std::map< std::string, std::string > &routeParameters)
build embedded route
void buildFlowOverRoute(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const SUMOVehicleParameter &vehicleParameters)
build a flow over an existent route
static bool isContainerIdDuplicated(GNENet *net, const std::string &id)
check if there is already a container (Container or ContainerFlow) with the given ID
static void setFlowParameters(const SumoXMLAttr attribute, int &parameters)
set flow parameters
void buildVType(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const SUMOVTypeParameter &vTypeParameter)
build vType
static bool isVehicleIdDuplicated(GNENet *net, const std::string &id)
check if there is already a vehicle (Vehicle, Trip, Flow or Flow) with the given ID
GNERouteHandler(const std::string &file, GNENet *net, bool undoDemandElements=true)
Constructor.
void buildTranship(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const std::string &fromEdgeID, const std::string &toEdgeID, const std::string &toBusStopID, const std::vector< std::string > &edgeIDs, const double speed, const double departPosition, const double arrivalPosition)
build tranship
std::vector< GNEEdge * > parseEdges(const SumoXMLTag tag, const std::vector< std::string > &edgeIDs) const
parse edges
static void transformToTrip(GNEVehicle *originalVehicle)
transform to trip
void buildVTypeDistribution(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const std::string &id, const std::vector< std::string > &vTypes)
build vType distribution
static void transformToPerson(GNEPerson *originalPerson)
transform person functions
bool myUndoDemandElements
flag to check if created demand elements must be undo and redo
~GNERouteHandler()
Destructor.
bool buildContainerPlan(SumoXMLTag tag, GNEDemandElement *containerParent, GNEFrameAttributeModules::AttributesCreator *containerPlanAttributes, GNEFrameModules::PathCreator *pathCreator)
build container plan
void buildRide(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const std::string &fromEdgeID, const std::string &toEdgeID, const std::string &toBusStopID, double arrivalPos, const std::vector< std::string > &lines)
build ride
void buildPersonFlow(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const SUMOVehicleParameter &personFlowParameters)
build person flow
GNEEdge * parseEdge(const SumoXMLTag tag, const std::string &edgeID) const
parse edge
void buildRoute(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const std::string &id, SUMOVehicleClass vClass, const std::vector< std::string > &edgeIDs, const RGBColor &color, const int repeat, const SUMOTime cycleTime, const std::map< std::string, std::string > &routeParameters)
build route
GNEJunction * parseJunction(const SumoXMLTag tag, const std::string &junctionID) const
parse junction
GNEDemandElement * getContainerParent(const CommonXMLStructure::SumoBaseObject *sumoBaseObject) const
get container parent
void buildStop(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const SUMOVehicleParameter::Stop &stopParameters)
build stop
static void transformToContainer(GNEContainer *originalContainer)
transform container functions
void buildContainer(const CommonXMLStructure::SumoBaseObject *sumoBaseObject, const SUMOVehicleParameter &containerParameters)
build container
static void transformToPersonFlow(GNEPerson *originalPerson)
transform routeFlow over an existent route
static void transformToVehicle(GNEVehicle *originalVehicle, bool createEmbeddedRoute)
transform vehicle functions
bool isContainer() const
return true if tag correspond to a container element
bool isVehicle() const
return true if tag correspond to a vehicle element
GUIIcon getGUIIcon() const
get GUI icon associated to this Tag
SumoXMLTag getTag() const
get Tag vinculated with this attribute Property
bool isPerson() const
return true if tag correspond to a person element
void end()
End undo command sub-group. If the sub-group is still empty, it will be deleted; otherwise,...
void begin(GUIIcon icon, const std::string &description)
Begin undo command sub-group with current supermode. This begins a new group of commands that are tre...
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 void overwriteVType(GNEDemandElement *vType, const SUMOVTypeParameter newVTypeParameter, GNEUndoList *undoList)
overwrite all values of GNEVType with a SUMOVTypeParameter
Definition: GNEVType.cpp:935
GNEFrameModules::TagSelector * getVehicleTagSelector() const
get vehicle tag selector (needed for transform vehicles)
SUMOVehicleClass getVClass() const
Definition: GNEVehicle.cpp:558
GNEViewParent * getViewParent() const
get the net object
GNEUndoList * getUndoList() const
get the undoList object
void setStatusBarText(const std::string &text)
set staturBar text
Definition: GNEViewNet.cpp:629
GNEVehicleFrame * getVehicleFrame() const
get frame for DEMAND_VEHICLE
Boundary getVisibleBoundary() const
get visible boundary
virtual void centerTo(GUIGlID id, bool applyZoom, double zoomDist=20)
centers to the chosen artifact
Position getPositionInformation() const
Returns the cursor's x/y position within the network.
static const RGBColor YELLOW
Definition: RGBColor.h:188
Structure representing possible vehicle parameter.
std::string id
The vehicle type's id.
Definition of vehicle stop (position and duration)
std::string edge
The edge to stop at (used only in NETEDIT)
std::string lane
The lane to stop at.
std::string parkingarea
(Optional) parking area if one is assigned to the stop
std::string chargingStation
(Optional) charging station if one is assigned to the stop
int parametersSet
Information for the output which parameter were set.
SUMOTime until
The time at which the vehicle may continue its journey.
std::string actType
act Type (only used by Persons) (used by NETEDIT)
double endPos
The stopping position end.
std::string busstop
(Optional) bus stop if one is assigned to the stop
std::string containerstop
(Optional) container stop if one is assigned to the stop
SUMOTime duration
The stopping duration.
Structure representing possible vehicle parameter.
double repetitionProbability
The probability for emitting a vehicle per second.
int parametersSet
Information for the router which parameter were set, TraCI may modify this (when changing color)
int departLane
(optional) The lane the vehicle shall depart from (index in edge)
double departSpeed
(optional) The initial speed of the vehicle
SumoXMLTag tag
The vehicle tag.
std::string vtypeid
The vehicle's type id.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
std::vector< std::string > via
List of the via-edges the vehicle must visit.
DepartLaneDefinition departLaneProcedure
Information how the vehicle shall choose the lane to depart from.
SUMOTime repetitionEnd
The time at which the flow ends (only needed when using repetitionProbability)
DepartSpeedDefinition departSpeedProcedure
Information how the vehicle's initial speed shall be chosen.
std::string routeid
The vehicle's route id.
std::string id
The vehicle's id.
bool wasSet(int what) const
Returns whether the given parameter was set.