Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
PCLoaderArcView.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
20// A reader of pois and polygons from shape files
21/****************************************************************************/
22#include <config.h>
23
24#include <string>
34#include "PCLoaderArcView.h"
35
36#ifdef HAVE_GDAL
37#ifdef _MSC_VER
38#pragma warning(push)
39#pragma warning(disable: 4435 5219 5220)
40#endif
41#if __GNUC__ > 3
42#pragma GCC diagnostic push
43#pragma GCC diagnostic ignored "-Wpedantic"
44#endif
45#include <ogrsf_frmts.h>
46#if __GNUC__ > 3
47#pragma GCC diagnostic pop
48#endif
49#ifdef _MSC_VER
50#pragma warning(pop)
51#endif
52#endif
53
54
55// ===========================================================================
56// static member variables
57// ===========================================================================
59
60
61// ===========================================================================
62// method definitions
63// ===========================================================================
64void
66 if (!oc.isSet("shapefile-prefixes") && !oc.isSet("geojson-files")) {
67 return;
68 }
69 // parse file(s)
70 for (std::string file : oc.getStringVector("shapefile-prefixes")) {
71 file += ".shp";
72 PROGRESS_BEGIN_MESSAGE("Parsing from shape-file '" + file + "'");
73 load(file, oc, toFill, tm);
75 }
76 for (const std::string& file : oc.getStringVector("geojson-files")) {
77 PROGRESS_BEGIN_MESSAGE("Parsing from geojson-file '" + file + "'");
78 load(file, oc, toFill, tm);
80 }
81}
82
83
84#ifdef HAVE_GDAL
86PCLoaderArcView::toShape(OGRLineString* geom, const std::string& tid) {
88 int outOfRange = 0;
89 for (int j = 0; j < geom->getNumPoints(); j++) {
90 if (fabs(geom->getX(j)) > 180 || fabs(geom->getY(j)) > 90) {
91 outOfRange++;
92 }
93 }
94 if (2 * outOfRange > geom->getNumPoints()) {
95 WRITE_WARNING(TL("No coordinate system found and coordinates look already projected."));
96 GeoConvHelper::init("!", GeoConvHelper::getProcessing().getOffset(), GeoConvHelper::getProcessing().getOrigBoundary(), GeoConvHelper::getProcessing().getConvBoundary());
97 } else {
98 WRITE_WARNING(TL("Could not find geo coordinate system, assuming WGS84."));
99 }
101 }
103 PositionVector shape;
104#if GDAL_VERSION_MAJOR < 3
105 for (int j = 0; j < geom->getNumPoints(); j++) {
106 Position pos(geom->getX(j), geom->getY(j));
107#else
108 for (const OGRPoint& p : *geom) {
109 Position pos(p.getX(), p.getY(), p.Is3D() ? p.getZ() : 0.0);
110#endif
111 if (!geoConvHelper.x2cartesian(pos)) {
112 WRITE_ERRORF(TL("Unable to project coordinates for polygon '%'."), tid);
113 }
114 shape.push_back_noDoublePos(pos);
115 }
116 return shape;
117}
118#endif
119
120
121void
122PCLoaderArcView::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill, PCTypeMap& tm) {
123#ifdef HAVE_GDAL
125 // get defaults
126 const std::string idField = oc.getString("shapefile.id-column");
127 const bool useRunningID = oc.getBool("shapefile.use-running-id") || idField == "";
128 int fillType = -1;
129 if (oc.getString("shapefile.fill") == "true") {
130 fillType = 1;
131 } else if (oc.getString("shapefile.fill") == "false") {
132 fillType = 0;
133 }
134#if GDAL_VERSION_MAJOR < 2
135 OGRRegisterAll();
136 OGRDataSource* poDS = OGRSFDriverRegistrar::Open(file.c_str(), FALSE);
137#else
138 GDALAllRegister();
139 GDALDataset* poDS = (GDALDataset*) GDALOpenEx(file.c_str(), GDAL_OF_VECTOR | GA_ReadOnly, NULL, NULL, NULL);
140#endif
141 if (poDS == NULL) {
142 throw ProcessError(TLF("Could not open shape description '%'.", file));
143 }
144
145 // begin file parsing
146 OGRLayer* poLayer = poDS->GetLayer(0);
147 poLayer->ResetReading();
148
149 // build coordinate transformation
150 OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
151 OGRSpatialReference destTransf;
152 // use wgs84 as destination
153 destTransf.SetWellKnownGeogCS("WGS84");
154#if GDAL_VERSION_MAJOR > 2
155 if (oc.getBool("shapefile.traditional-axis-mapping") || origTransf != nullptr) {
156 destTransf.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
157 }
158#endif
159 OGRCoordinateTransformation* poCT = origTransf == nullptr ? nullptr : OGRCreateCoordinateTransformation(origTransf, &destTransf);
160 if (poCT == nullptr) {
161 if (oc.getBool("shapefile.guess-projection")) {
162 OGRSpatialReference origTransf2;
163 origTransf2.SetWellKnownGeogCS("WGS84");
164 poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf);
165 }
166 } else {
168 }
169
170 OGRFeature* poFeature;
171 poLayer->ResetReading();
172 int runningID = 0;
173 while ((poFeature = poLayer->GetNextFeature()) != nullptr) {
174 if (runningID == 0) {
175 std::vector<std::string> fields;
176 for (int i = 0; i < poFeature->GetFieldCount(); i++) {
177 fields.push_back(poFeature->GetFieldDefnRef(i)->GetNameRef());
178 }
179 WRITE_MESSAGE("Available fields: " + toString(fields));
180 }
181 std::vector<Parameterised*> parCont;
182 // read in edge attributes
183 std::string id = useRunningID ? toString(runningID) : poFeature->GetFieldAsString(idField.c_str());
184 ++runningID;
186 if (id == "") {
187 throw ProcessError(TLF("Missing id under '%'", idField));
188 }
189 id = oc.getString("prefix") + id;
190 std::string type;
191 for (const std::string& typeField : oc.getStringVector("shapefile.type-columns")) {
192 if (type != "") {
193 type += ".";
194 }
195 type += poFeature->GetFieldAsString(typeField.c_str());
196 }
197 RGBColor color = RGBColor::parseColor(oc.getString("color"));
198 std::string icon = oc.getString("icon");
199 double layer = oc.getFloat("layer");
200 double angle = Shape::DEFAULT_ANGLE;
201 std::string imgFile = Shape::DEFAULT_IMG_FILE;
202 if (type != "") {
203 if (tm.has(type)) {
204 const PCTypeMap::TypeDef& def = tm.get(type);
205 if (def.discard) {
206 continue;
207 }
208 color = def.color;
209 icon = def.icon;
210 layer = def.layer;
211 angle = def.angle;
212 imgFile = def.imgFile;
213 type = def.id;
214 }
215 } else {
216 type = oc.getString("type");
217 }
218 if (poFeature->GetFieldIndex("angle") >= 0) {
219 angle = poFeature->GetFieldAsDouble("angle");
220 }
221 // read in the geometry
222 OGRGeometry* poGeometry = poFeature->GetGeometryRef();
223 if (poGeometry == 0) {
224 OGRFeature::DestroyFeature(poFeature);
225 continue;
226 }
227 // try transform to wgs84
228 if (poCT != nullptr) {
229 poGeometry->transform(poCT);
230 }
231 OGRwkbGeometryType gtype = poGeometry->getGeometryType();
232 switch (gtype) {
233 case wkbPoint:
234 case wkbPoint25D: {
235 OGRPoint* cgeom = (OGRPoint*) poGeometry;
236 Position pos(cgeom->getX(), cgeom->getY());
237 if (!geoConvHelper.x2cartesian(pos)) {
238 WRITE_ERRORF(TL("Unable to project coordinates for POI '%'."), id);
239 }
240 PointOfInterest* poi = new PointOfInterest(id, type, color, pos, false, "", 0, false, 0, icon, layer, angle, imgFile);
241 if (toFill.add(poi)) {
242 parCont.push_back(poi);
243 }
244 }
245 break;
246 case wkbLineString:
247 case wkbLineString25D: {
248 const PositionVector shape = toShape((OGRLineString*) poGeometry, id);
249 SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, fillType == 1, 1, layer, angle, imgFile);
250 if (toFill.add(poly)) {
251 parCont.push_back(poly);
252 }
253 }
254 break;
255 case wkbPolygon:
256 case wkbPolygon25D: {
257 const bool fill = fillType < 0 || fillType == 1;
258 const PositionVector shape = toShape(((OGRPolygon*) poGeometry)->getExteriorRing(), id);
259 SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, fill, 1, layer, angle, imgFile);
260 if (toFill.add(poly)) {
261 parCont.push_back(poly);
262 }
263 }
264 break;
265 case wkbMultiPoint:
266 case wkbMultiPoint25D: {
267 OGRMultiPoint* cgeom = (OGRMultiPoint*) poGeometry;
268 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
269 OGRPoint* cgeom2 = (OGRPoint*) cgeom->getGeometryRef(i);
270 Position pos(cgeom2->getX(), cgeom2->getY());
271 const std::string tid = id + "#" + toString(i);
272 if (!geoConvHelper.x2cartesian(pos)) {
273 WRITE_ERRORF(TL("Unable to project coordinates for POI '%'."), tid);
274 }
275 PointOfInterest* poi = new PointOfInterest(tid, type, color, pos, false, "", 0, false, 0, icon, layer, angle, imgFile);
276 if (toFill.add(poi)) {
277 parCont.push_back(poi);
278 }
279 }
280 }
281 break;
282 case wkbMultiLineString:
283 case wkbMultiLineString25D: {
284 OGRMultiLineString* cgeom = (OGRMultiLineString*) poGeometry;
285 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
286 const std::string tid = id + "#" + toString(i);
287 const PositionVector shape = toShape((OGRLineString*) cgeom->getGeometryRef(i), tid);
288 SUMOPolygon* poly = new SUMOPolygon(tid, type, color, shape, false, fillType == 1, 1, layer, angle, imgFile);
289 if (toFill.add(poly)) {
290 parCont.push_back(poly);
291 }
292 }
293 }
294 break;
295 case wkbMultiPolygon:
296 case wkbMultiPolygon25D: {
297 const bool fill = fillType < 0 || fillType == 1;
298 OGRMultiPolygon* cgeom = (OGRMultiPolygon*) poGeometry;
299 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
300 const std::string tid = id + "#" + toString(i);
301 const PositionVector shape = toShape(((OGRPolygon*) cgeom->getGeometryRef(i))->getExteriorRing(), tid);
302 SUMOPolygon* poly = new SUMOPolygon(tid, type, color, shape, false, fill, 1, layer, angle, imgFile);
303 if (toFill.add(poly)) {
304 parCont.push_back(poly);
305 }
306 }
307 }
308 break;
309 default:
310 WRITE_WARNINGF(TL("Unsupported shape type occurred (id='%')."), id);
311 break;
312 }
313 if (oc.getBool("shapefile.add-param") || oc.getBool("all-attributes")) {
314 for (std::vector<Parameterised*>::const_iterator it = parCont.begin(); it != parCont.end(); ++it) {
315 OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
316 for (int iField = 0; iField < poFDefn->GetFieldCount(); iField++) {
317 OGRFieldDefn* poFieldDefn = poFDefn->GetFieldDefn(iField);
318 if (poFieldDefn->GetNameRef() != idField) {
319 (*it)->setParameter(poFieldDefn->GetNameRef(), StringUtils::latin1_to_utf8(poFeature->GetFieldAsString(iField)));
320 }
321 }
322 }
323 }
324 OGRFeature::DestroyFeature(poFeature);
325 }
326#if GDAL_VERSION_MAJOR < 2
327 OGRDataSource::DestroyDataSource(poDS);
328#else
329 GDALClose(poDS);
330#endif
332#else
333 UNUSED_PARAMETER(file);
335 UNUSED_PARAMETER(toFill);
337 WRITE_ERROR(TL("SUMO was compiled without GDAL support."));
338#endif
339}
340
341
342/****************************************************************************/
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:288
#define WRITE_ERRORF(...)
Definition MsgHandler.h:297
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:289
#define WRITE_ERROR(msg)
Definition MsgHandler.h:296
#define WRITE_WARNING(msg)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:305
#define PROGRESS_DONE_MESSAGE()
Definition MsgHandler.h:292
#define TLF(string,...)
Definition MsgHandler.h:307
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition MsgHandler.h:291
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
bool x2cartesian(Position &from, bool includeInBoundary=true)
Converts the given coordinate into a cartesian and optionally update myConvBoundary.
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
static bool init(OptionsCont &oc)
Initialises the processing and the final instance using the given options.
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 bool myWarnMissingProjection
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:70
bool has(const std::string &id)
Returns the information whether the named type is known.
Definition PCTypeMap.cpp:76
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:239
static const std::string DEFAULT_IMG_FILE
Definition Shape.h:47
static const double DEFAULT_ANGLE
Definition Shape.h:46
static std::string latin1_to_utf8(std::string str)
Transfers from Latin 1 (ISO-8859-1) to UTF-8.
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
#define UNUSED_PARAMETER(x)
A single definition of values that shall be used for a given type.
Definition PCTypeMap.h:61
std::string icon
the icon to use
Definition PCTypeMap.h:69
bool discard
Information whether polygons of this type shall be discarded.
Definition PCTypeMap.h:77
double layer
The layer to use.
Definition PCTypeMap.h:71
double angle
The angle to use.
Definition PCTypeMap.h:73
std::string imgFile
The image file to use.
Definition PCTypeMap.h:75
std::string id
The new type id to use.
Definition PCTypeMap.h:63
RGBColor color
The color to use.
Definition PCTypeMap.h:65