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