SUMO - Simulation of Urban MObility
ShapeHandler.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-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
15 // The XML-Handler for network loading
16 /****************************************************************************/
17 // ===========================================================================
18 // included modules
19 // ===========================================================================
20 #include <config.h>
21 
22 #include <string>
25 #include <utils/xml/XMLSubSys.h>
29 #include <utils/common/RGBColor.h>
35 #include "Shape.h"
36 #include "ShapeContainer.h"
37 #include "ShapeHandler.h"
38 
39 
40 // ===========================================================================
41 // method definitions
42 // ===========================================================================
43 ShapeHandler::ShapeHandler(const std::string& file, ShapeContainer& sc) :
44  SUMOSAXHandler(file), myShapeContainer(sc),
45  myPrefix(""), myDefaultColor(RGBColor::RED), myDefaultLayer(), myDefaultFill(false),
46  myLastParameterised(nullptr) {
47 }
48 
49 
51 
52 
53 void
54 ShapeHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) {
55  try {
56  switch (element) {
57  case SUMO_TAG_POLY:
59  addPoly(attrs, false, false);
60  break;
61  case SUMO_TAG_POI:
63  addPOI(attrs, false, false);
64  break;
65  case SUMO_TAG_PARAM:
66  if (myLastParameterised != nullptr) {
67  bool ok = true;
68  const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
69  // continue if key awas sucesfully loaded
70  if (ok) {
71  // circumventing empty string value
72  const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
73  // show warnings if values are invalid
74  if (key.empty()) {
75  WRITE_WARNING("Error parsing key from shape generic parameter. Key cannot be empty");
77  WRITE_WARNING("Error parsing key from shape generic parameter. Key contains invalid characters");
79  WRITE_WARNING("Error parsing value from shape generic parameter. Value contains invalid characters");
80  } else {
81  WRITE_DEBUG("Inserting generic parameter '" + key + "|" + val + "' into shape.");
83  }
84  }
85  }
86  default:
87  break;
88  }
89  } catch (InvalidArgument& e) {
90  WRITE_ERROR(e.what());
91  }
92 }
93 
94 
95 void
97  if (element != SUMO_TAG_PARAM) {
98  myLastParameterised = nullptr;
99  }
100 }
101 
102 void
103 ShapeHandler::addPOI(const SUMOSAXAttributes& attrs, const bool ignorePruning, const bool useProcessing) {
104  bool ok = true;
105  const double INVALID_POSITION(-1000000);
106  const std::string id = myPrefix + attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
107  double x = attrs.getOpt<double>(SUMO_ATTR_X, id.c_str(), ok, INVALID_POSITION);
108  const double y = attrs.getOpt<double>(SUMO_ATTR_Y, id.c_str(), ok, INVALID_POSITION);
109  double lon = attrs.getOpt<double>(SUMO_ATTR_LON, id.c_str(), ok, INVALID_POSITION);
110  double lat = attrs.getOpt<double>(SUMO_ATTR_LAT, id.c_str(), ok, INVALID_POSITION);
111  const double lanePos = attrs.getOpt<double>(SUMO_ATTR_POSITION, id.c_str(), ok, 0);
112  const double lanePosLat = attrs.getOpt<double>(SUMO_ATTR_POSITION_LAT, id.c_str(), ok, 0);
113  const double layer = attrs.getOpt<double>(SUMO_ATTR_LAYER, id.c_str(), ok, myDefaultLayer);
114  const std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
115  const std::string laneID = attrs.getOpt<std::string>(SUMO_ATTR_LANE, id.c_str(), ok, "");
116  const RGBColor color = attrs.hasAttribute(SUMO_ATTR_COLOR) ? attrs.get<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok) : myDefaultColor;
117  const double angle = attrs.getOpt<double>(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE);
118  std::string imgFile = attrs.getOpt<std::string>(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE);
119  bool relativePath = attrs.getOpt<bool>(SUMO_ATTR_RELATIVEPATH, id.c_str(), ok, Shape::DEFAULT_RELATIVEPATH);
120  if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) {
122  }
123  const double width = attrs.getOpt<double>(SUMO_ATTR_WIDTH, id.c_str(), ok, Shape::DEFAULT_IMG_WIDTH);
124  const double height = attrs.getOpt<double>(SUMO_ATTR_HEIGHT, id.c_str(), ok, Shape::DEFAULT_IMG_HEIGHT);
125  if (!ok) {
126  return;
127  }
128  const GeoConvHelper& gch = useProcessing ? GeoConvHelper::getProcessing() : GeoConvHelper::getFinal();
129  if (useProcessing && gch.usingGeoProjection()) {
130  if (lat == INVALID_POSITION || lon == INVALID_POSITION) {
131  lon = x;
132  lat = y;
133  x = INVALID_POSITION;
134  }
135  }
136  Position pos(x, y);
137  bool useGeo = false;
138  if (x == INVALID_POSITION || y == INVALID_POSITION) {
139  // try computing x,y from lane,pos
140  if (laneID != "") {
141  pos = getLanePos(id, laneID, lanePos, lanePosLat);
142  } else {
143  // try computing x,y from lon,lat
144  if (lat == INVALID_POSITION || lon == INVALID_POSITION) {
145  WRITE_ERROR("Either (x, y), (lon, lat) or (lane, pos) must be specified for PoI '" + id + "'.");
146  return;
147  } else if (!gch.usingGeoProjection()) {
148  WRITE_ERROR("(lon, lat) is specified for PoI '" + id + "' but no geo-conversion is specified for the network.");
149  return;
150  }
151  pos.set(lon, lat);
152  useGeo = true;
153  bool success = true;
154  if (useProcessing) {
155  success = GeoConvHelper::getProcessing().x2cartesian(pos);
156  } else {
158  }
159  if (!success) {
160  WRITE_ERROR("Unable to project coordinates for PoI '" + id + "'.");
161  return;
162  }
163  }
164  }
165  if (!myShapeContainer.addPOI(id, type, color, pos, useGeo, laneID, lanePos, lanePosLat, layer, angle, imgFile, relativePath, width, height, ignorePruning)) {
166  WRITE_ERROR("PoI '" + id + "' already exists.");
167  }
169  if (laneID != "" && addLanePosParams()) {
170  myLastParameterised->setParameter(toString(SUMO_ATTR_LANE), laneID);
171  myLastParameterised->setParameter(toString(SUMO_ATTR_POSITION), toString(lanePos));
172  myLastParameterised->setParameter(toString(SUMO_ATTR_POSITION_LAT), toString(lanePosLat));
173  }
174 }
175 
176 
177 void
178 ShapeHandler::addPoly(const SUMOSAXAttributes& attrs, const bool ignorePruning, const bool useProcessing) {
179  bool ok = true;
180  const std::string id = myPrefix + attrs.get<std::string>(SUMO_ATTR_ID, nullptr, ok);
181  // get the id, report an error if not given or empty...
182  if (!ok) {
183  return;
184  }
185  const double layer = attrs.getOpt<double>(SUMO_ATTR_LAYER, id.c_str(), ok, myDefaultLayer);
186  const bool fill = attrs.getOpt<bool>(SUMO_ATTR_FILL, id.c_str(), ok, myDefaultFill);
187  const double lineWidth = attrs.getOpt<double>(SUMO_ATTR_LINEWIDTH, id.c_str(), ok, Shape::DEFAULT_LINEWIDTH);
188  const std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, Shape::DEFAULT_TYPE);
189  const RGBColor color = attrs.hasAttribute(SUMO_ATTR_COLOR) ? attrs.get<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok) : myDefaultColor;
190  PositionVector shape = attrs.get<PositionVector>(SUMO_ATTR_SHAPE, id.c_str(), ok);
191  bool geo = false;
192  if (attrs.getOpt<bool>(SUMO_ATTR_GEO, id.c_str(), ok, false)) {
193  geo = true;
194  bool success = true;
195  for (int i = 0; i < (int)shape.size(); i++) {
196  if (useProcessing) {
197  success &= GeoConvHelper::getProcessing().x2cartesian(shape[i]);
198  } else {
199  success &= GeoConvHelper::getFinal().x2cartesian_const(shape[i]);
200  }
201  }
202  if (!success) {
203  WRITE_WARNING("Unable to project coordinates for polygon '" + id + "'.");
204  return;
205  }
206  }
207  const double angle = attrs.getOpt<double>(SUMO_ATTR_ANGLE, id.c_str(), ok, Shape::DEFAULT_ANGLE);
208  std::string imgFile = attrs.getOpt<std::string>(SUMO_ATTR_IMGFILE, id.c_str(), ok, Shape::DEFAULT_IMG_FILE);
209  bool relativePath = attrs.getOpt<bool>(SUMO_ATTR_RELATIVEPATH, id.c_str(), ok, Shape::DEFAULT_RELATIVEPATH);
210  if (imgFile != "" && !FileHelpers::isAbsolute(imgFile)) {
212  }
213  // check that shape's size is valid
214  if (shape.size() == 0) {
215  WRITE_ERROR("Polygon's shape cannot be empty.");
216  return;
217  }
218  // check that lineWidth is positive
219  if (lineWidth <= 0) {
220  WRITE_ERROR("Polygon's lineWidth must be greather than 0.");
221  return;
222  }
223  // create polygon, or show an error if polygon already exists
224  if (!myShapeContainer.addPolygon(id, type, color, layer, angle, imgFile, relativePath, shape, geo, fill, lineWidth, ignorePruning)) {
225  WRITE_ERROR("Polygon '" + id + "' already exists.");
226  }
228 }
229 
230 
231 
232 bool
233 ShapeHandler::loadFiles(const std::vector<std::string>& files, ShapeHandler& sh) {
234  for (auto fileIt : files) {
235  if (!XMLSubSys::runParser(sh, fileIt, false)) {
236  WRITE_MESSAGE("Loading of shapes from " + fileIt + " failed.");
237  return false;
238  }
239  }
240  return true;
241 }
242 
243 
244 void
245 ShapeHandler::setDefaults(const std::string& prefix, const RGBColor& color, const double layer, const bool fill) {
246  myPrefix = prefix;
247  myDefaultColor = color;
248  myDefaultLayer = layer;
249  myDefaultFill = fill;
250 }
251 
252 
253 
254 /****************************************************************************/
double myDefaultLayer
The default layer to use.
Definition: ShapeHandler.h:120
static std::string getConfigurationRelative(const std::string &configPath, const std::string &path)
Returns the second path as a relative path to the first file.
Definition: FileHelpers.cpp:75
ShapeHandler(const std::string &file, ShapeContainer &sc)
Constructor.
static const std::string DEFAULT_IMG_FILE
Definition: Shape.h:48
void setDefaults(const std::string &prefix, const RGBColor &color, const double layer, const bool fill=false)
set default values
virtual void myEndElement(int element)
Called when a closing tag occurs.
const Polygons & getPolygons() const
Returns all polygons.
virtual Position getLanePos(const std::string &poiID, const std::string &laneID, double lanePos, double lanePosLat)=0
get position for a given laneID
static const double DEFAULT_LAYER_POI
Definition: Shape.h:46
A layer number.
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:84
static bool loadFiles(const std::vector< std::string > &files, ShapeHandler &sh)
loads all of the given files
const std::string & getFileName() const
returns the current file name
bool x2cartesian(Position &from, bool includeInBoundary=true)
Converts the given coordinate into a cartesian and optionally update myConvBoundary.
T get(const std::string &id) const
Retrieves an item.
virtual void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
static const double DEFAULT_IMG_HEIGHT
Definition: Shape.h:51
Storage for geometrical objects.
begin/end of the description of a Point of interest
RGBColor myDefaultColor
The default color to use.
Definition: ShapeHandler.h:117
Parameterised * myLastParameterised
element to receive parameters
Definition: ShapeHandler.h:126
virtual bool addPolygon(const std::string &id, const std::string &type, const RGBColor &color, double layer, double angle, const std::string &imgFile, bool relativePath, const PositionVector &shape, bool geo, bool fill, double lineWidth, bool ignorePruning=false)
Builds a polygon using the given values and adds it to the container.
void set(double x, double y)
set positions x and y
Definition: Position.h:87
SAX-handler base for SUMO-files.
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything&#39;s ok.
Definition: XMLSubSys.cpp:113
static const std::string DEFAULT_TYPE
Definition: Shape.h:43
std::string myPrefix
The prefix to use.
Definition: ShapeHandler.h:114
static bool isValidGenericParameterKey(const std::string &value)
whether the given string is a valid key for a generic parameter
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list...
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
virtual std::string getString(int id) const =0
Returns the string-value of the named (by its enum-value) attribute.
The XML-Handler for network loading.
Definition: ShapeHandler.h:49
static bool isValidGenericParameterValue(const std::string &value)
whether the given string is a valid value for a generic parameter
static methods for processing the coordinates conversion for the current net
Definition: GeoConvHelper.h:53
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
Encapsulated SAX-Attributes.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool addLanePosParams()
Whether some input attributes shall be automatically added as params.
Definition: ShapeHandler.h:95
static bool isAbsolute(const std::string &path)
Returns the information whether the given path is absolute.
Definition: FileHelpers.cpp:90
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
parameter associated to a certain key
A list of positions.
void addPOI(const SUMOSAXAttributes &attrs, const bool ignorePruning, const bool useProcessing)
adds a POI
static const bool DEFAULT_RELATIVEPATH
Definition: Shape.h:49
virtual bool addPOI(const std::string &id, const std::string &type, const RGBColor &color, const Position &pos, bool geo, const std::string &lane, double posOverLane, double posLat, double layer, double angle, const std::string &imgFile, bool relativePath, double width, double height, bool ignorePruning=false)
Builds a POI using the given values and adds it to the container.
static const double DEFAULT_LINEWIDTH
Definition: Shape.h:45
bool myDefaultFill
Information whether polygons should be filled.
Definition: ShapeHandler.h:123
void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
edge: the shape in xml-definition
#define WRITE_DEBUG(msg)
Definition: MsgHandler.h:248
void addPoly(const SUMOSAXAttributes &attrs, const bool ignorePruning, const bool useProcessing)
adds a polygon
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:247
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual ~ShapeHandler()
Destructor.
ShapeContainer & myShapeContainer
Definition: ShapeHandler.h:110
static const GeoConvHelper & getFinal()
the coordinate transformation for writing the location element and for tracking the original coordina...
#define INVALID_POSITION
static const double DEFAULT_IMG_WIDTH
Definition: Shape.h:50
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation. ...
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:242
A color information.
Fill the polygon.
static const double DEFAULT_ANGLE
Definition: Shape.h:47
begin/end of the description of a polygon
static const double DEFAULT_LAYER
Definition: Shape.h:44
const POIs & getPOIs() const
Returns all pois.