Eclipse SUMO - Simulation of Urban MObility
PCLoaderArcView.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 /****************************************************************************/
20 // A reader of pois and polygons from shape files
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <string>
26 #include <utils/common/ToString.h>
29 #include <utils/geom/GeomHelper.h>
31 #include <utils/common/RGBColor.h>
33 #include <polyconvert/PCTypeMap.h>
34 #include "PCLoaderArcView.h"
35 
36 #ifdef HAVE_GDAL
37 #if __GNUC__ > 3
38 #pragma GCC diagnostic push
39 #pragma GCC diagnostic ignored "-Wpedantic"
40 #endif
41 #include <ogrsf_frmts.h>
42 #if __GNUC__ > 3
43 #pragma GCC diagnostic pop
44 #endif
45 #endif
46 
47 
48 // ===========================================================================
49 // method definitions
50 // ===========================================================================
51 void
53  PCTypeMap& tm) {
54  if (!oc.isSet("shapefile-prefixes")) {
55  return;
56  }
57  // parse file(s)
58  std::vector<std::string> files = oc.getStringVector("shapefile-prefixes");
59  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
60  PROGRESS_BEGIN_MESSAGE("Parsing from shape-file '" + *file + "'");
61  load(*file, oc, toFill, tm);
63  }
64 }
65 
66 
67 
68 void
69 PCLoaderArcView::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill,
70  PCTypeMap& tm) {
71 #ifdef HAVE_GDAL
73  // get defaults
74  const std::string idField = oc.getString("shapefile.id-column");
75  const bool useRunningID = oc.getBool("shapefile.use-running-id") || idField == "";
76  // start parsing
77  std::string shpName = file + ".shp";
78  int fillType = -1;
79  if (oc.getString("shapefile.fill") == "true") {
80  fillType = 1;
81  } else if (oc.getString("shapefile.fill") == "false") {
82  fillType = 0;
83  }
84 #if GDAL_VERSION_MAJOR < 2
85  OGRRegisterAll();
86  OGRDataSource* poDS = OGRSFDriverRegistrar::Open(shpName.c_str(), FALSE);
87 #else
88  GDALAllRegister();
89  GDALDataset* poDS = (GDALDataset*) GDALOpenEx(shpName.c_str(), GDAL_OF_VECTOR | GA_ReadOnly, NULL, NULL, NULL);
90 #endif
91  if (poDS == NULL) {
92  throw ProcessError("Could not open shape description '" + shpName + "'.");
93  }
94 
95  // begin file parsing
96  OGRLayer* poLayer = poDS->GetLayer(0);
97  poLayer->ResetReading();
98 
99  // build coordinate transformation
100  OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
101  OGRSpatialReference destTransf;
102  // use wgs84 as destination
103  destTransf.SetWellKnownGeogCS("WGS84");
104 #if GDAL_VERSION_MAJOR > 2
105  if (oc.getBool("shapefile.traditional-axis-mapping")) {
106  destTransf.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
107  }
108 #endif
109  OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(origTransf, &destTransf);
110  if (poCT == nullptr) {
111  if (oc.getBool("shapefile.guess-projection")) {
112  OGRSpatialReference origTransf2;
113  origTransf2.SetWellKnownGeogCS("WGS84");
114  poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf);
115  }
116  if (poCT == nullptr) {
117  WRITE_WARNING("Could not create geocoordinates converter; check whether proj.4 is installed.");
118  }
119  }
120 
121  OGRFeature* poFeature;
122  poLayer->ResetReading();
123  int runningID = 0;
124  while ((poFeature = poLayer->GetNextFeature()) != nullptr) {
125  std::vector<Parameterised*> parCont;
126  // read in edge attributes
127  std::string id = useRunningID ? toString(runningID) : poFeature->GetFieldAsString(idField.c_str());
128  ++runningID;
130  if (id == "") {
131  throw ProcessError("Missing id under '" + idField + "'");
132  }
133  id = oc.getString("prefix") + id;
134  std::string type;
135  for (const std::string& typeField : oc.getStringVector("shapefile.type-columns")) {
136  if (type != "") {
137  type += ".";
138  }
139  type += poFeature->GetFieldAsString(typeField.c_str());
140  }
141  RGBColor color = RGBColor::parseColor(oc.getString("color"));
142  double layer = oc.getFloat("layer");
143  double angle = Shape::DEFAULT_ANGLE;
144  std::string imgFile = Shape::DEFAULT_IMG_FILE;
145  if (type != "" && tm.has(type)) {
146  const PCTypeMap::TypeDef& def = tm.get(type);
147  if (def.discard) {
148  continue;
149  }
150  color = def.color;
151  layer = def.layer;
152  angle = def.angle;
153  imgFile = def.imgFile;
154  type = def.id;
155  } else {
156  type = oc.getString("type");
157  }
158  if (poFeature->GetFieldIndex("angle") >= 0) {
159  angle = poFeature->GetFieldAsDouble("angle");
160  }
161  // read in the geometry
162  OGRGeometry* poGeometry = poFeature->GetGeometryRef();
163  if (poGeometry == 0) {
164  OGRFeature::DestroyFeature(poFeature);
165  continue;
166  }
167  // try transform to wgs84
168  if (poCT != nullptr) {
169  poGeometry->transform(poCT);
170  }
171  OGRwkbGeometryType gtype = poGeometry->getGeometryType();
172  switch (gtype) {
173  case wkbPoint: {
174  OGRPoint* cgeom = (OGRPoint*) poGeometry;
175  Position pos(cgeom->getX(), cgeom->getY());
176  if (!geoConvHelper.x2cartesian(pos)) {
177  WRITE_ERROR("Unable to project coordinates for POI '" + id + "'.");
178  }
179  PointOfInterest* poi = new PointOfInterest(id, type, color, pos, false, "", 0, false, 0, layer, angle, imgFile);
180  if (toFill.add(poi)) {
181  parCont.push_back(poi);
182  }
183  }
184  break;
185  case wkbLineString: {
186  OGRLineString* cgeom = (OGRLineString*) poGeometry;
187  PositionVector shape;
188  for (int j = 0; j < cgeom->getNumPoints(); j++) {
189  Position pos(cgeom->getX(j), cgeom->getY(j));
190  if (!geoConvHelper.x2cartesian(pos)) {
191  WRITE_ERROR("Unable to project coordinates for polygon '" + id + "'.");
192  }
193  shape.push_back_noDoublePos(pos);
194  }
195  SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, fillType == 1, 1, layer, angle, imgFile);
196  if (toFill.add(poly)) {
197  parCont.push_back(poly);
198  }
199  }
200  break;
201  case wkbPolygon: {
202  const bool fill = fillType < 0 || fillType == 1;
203  OGRLinearRing* cgeom = ((OGRPolygon*) poGeometry)->getExteriorRing();
204  PositionVector shape;
205  for (int j = 0; j < cgeom->getNumPoints(); j++) {
206  Position pos((double) cgeom->getX(j), (double) cgeom->getY(j));
207  if (!geoConvHelper.x2cartesian(pos)) {
208  WRITE_ERROR("Unable to project coordinates for polygon '" + id + "'.");
209  }
210  shape.push_back_noDoublePos(pos);
211  }
212  SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, fill, 1, layer, angle, imgFile);
213  if (toFill.add(poly)) {
214  parCont.push_back(poly);
215  }
216  }
217  break;
218  case wkbMultiPoint: {
219  OGRMultiPoint* cgeom = (OGRMultiPoint*) poGeometry;
220  for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
221  OGRPoint* cgeom2 = (OGRPoint*) cgeom->getGeometryRef(i);
222  Position pos(cgeom2->getX(), cgeom2->getY());
223  std::string tid = id + "#" + toString(i);
224  if (!geoConvHelper.x2cartesian(pos)) {
225  WRITE_ERROR("Unable to project coordinates for POI '" + tid + "'.");
226  }
227  PointOfInterest* poi = new PointOfInterest(tid, type, color, pos, false, "", 0, false, 0, layer, angle, imgFile);
228  if (toFill.add(poi)) {
229  parCont.push_back(poi);
230  }
231  }
232  }
233  break;
234  case wkbMultiLineString: {
235  OGRMultiLineString* cgeom = (OGRMultiLineString*) poGeometry;
236  for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
237  OGRLineString* cgeom2 = (OGRLineString*) cgeom->getGeometryRef(i);
238  PositionVector shape;
239  std::string tid = id + "#" + toString(i);
240  for (int j = 0; j < cgeom2->getNumPoints(); j++) {
241  Position pos(cgeom2->getX(j), cgeom2->getY(j));
242  if (!geoConvHelper.x2cartesian(pos)) {
243  WRITE_ERROR("Unable to project coordinates for polygon '" + tid + "'.");
244  }
245  shape.push_back_noDoublePos(pos);
246  }
247  SUMOPolygon* poly = new SUMOPolygon(tid, type, color, shape, false, fillType == 1, 1, layer, angle, imgFile);
248  if (toFill.add(poly)) {
249  parCont.push_back(poly);
250  }
251  }
252  }
253  break;
254  case wkbMultiPolygon: {
255  const bool fill = fillType < 0 || fillType == 1;
256  OGRMultiPolygon* cgeom = (OGRMultiPolygon*) poGeometry;
257  for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
258  OGRLinearRing* cgeom2 = ((OGRPolygon*) cgeom->getGeometryRef(i))->getExteriorRing();
259  PositionVector shape;
260  std::string tid = id + "#" + toString(i);
261  for (int j = 0; j < cgeom2->getNumPoints(); j++) {
262  Position pos(cgeom2->getX(j), cgeom2->getY(j));
263  if (!geoConvHelper.x2cartesian(pos)) {
264  WRITE_ERROR("Unable to project coordinates for polygon '" + tid + "'.");
265  }
266  shape.push_back_noDoublePos(pos);
267  }
268  SUMOPolygon* poly = new SUMOPolygon(tid, type, color, shape, false, fill, 1, layer, angle, imgFile);
269  if (toFill.add(poly)) {
270  parCont.push_back(poly);
271  }
272  }
273  }
274  break;
275  default:
276  WRITE_WARNING("Unsupported shape type occurred (id='" + id + "').");
277  break;
278  }
279  if (oc.getBool("shapefile.add-param")) {
280  for (std::vector<Parameterised*>::const_iterator it = parCont.begin(); it != parCont.end(); ++it) {
281  OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
282  for (int iField = 0; iField < poFDefn->GetFieldCount(); iField++) {
283  OGRFieldDefn* poFieldDefn = poFDefn->GetFieldDefn(iField);
284  if (poFieldDefn->GetNameRef() != idField) {
285  if (poFieldDefn->GetType() == OFTReal) {
286  (*it)->setParameter(poFieldDefn->GetNameRef(), toString(poFeature->GetFieldAsDouble(iField)));
287  } else {
288  (*it)->setParameter(poFieldDefn->GetNameRef(), StringUtils::latin1_to_utf8(poFeature->GetFieldAsString(iField)));
289  }
290  }
291  }
292  }
293  }
294  OGRFeature::DestroyFeature(poFeature);
295  }
296 #if GDAL_VERSION_MAJOR < 2
297  OGRDataSource::DestroyDataSource(poDS);
298 #else
299  GDALClose(poDS);
300 #endif
302 #else
303  UNUSED_PARAMETER(file);
304  UNUSED_PARAMETER(oc);
305  UNUSED_PARAMETER(toFill);
306  UNUSED_PARAMETER(tm);
307  WRITE_ERROR("SUMO was compiled without GDAL support.");
308 #endif
309 }
310 
311 
312 /****************************************************************************/
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:288
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:280
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:284
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:283
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static methods for processing the coordinates conversion for the current net
Definition: GeoConvHelper.h:53
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:84
bool x2cartesian(Position &from, bool includeInBoundary=true)
Converts the given coordinate into a cartesian and optionally update myConvBoundary.
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static void load(const std::string &file, OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Parses pois/polys stored within the given file.
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored as shape files-files.
A storage for loaded polygons and pois.
bool add(SUMOPolygon *poly, bool ignorePruning=false)
Adds a polygon to the storage.
A storage for type mappings.
Definition: PCTypeMap.h:42
const TypeDef & get(const std::string &id)
Returns a type definition.
Definition: PCTypeMap.cpp:69
bool has(const std::string &id)
Returns the information whether the named type is known.
Definition: PCTypeMap.cpp:75
A point-of-interest.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
A list of positions.
void push_back_noDoublePos(const Position &p)
insert in back a non double position
static RGBColor parseColor(std::string coldef)
Parses a color information.
Definition: RGBColor.cpp:236
static const std::string DEFAULT_IMG_FILE
Definition: Shape.h:46
static const double DEFAULT_ANGLE
Definition: Shape.h:45
static std::string latin1_to_utf8(std::string str)
Transfers from Latin 1 (ISO-8859-1) to UTF-8.
Definition: StringUtils.cpp:70
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
Definition: StringUtils.cpp:48
A single definition of values that shall be used for a given type.
Definition: PCTypeMap.h:56
bool discard
Information whether polygons of this type shall be discarded.
Definition: PCTypeMap.h:70
double layer
The layer to use.
Definition: PCTypeMap.h:64
double angle
The angle to use.
Definition: PCTypeMap.h:66
std::string imgFile
The image file to use.
Definition: PCTypeMap.h:68
std::string id
The new type id to use.
Definition: PCTypeMap.h:58
RGBColor color
The color to use.
Definition: PCTypeMap.h:60