Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
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-2026 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 <gdal_version.h>
46#include <ogrsf_frmts.h>
47#if __GNUC__ > 3
48#pragma GCC diagnostic pop
49#endif
50#ifdef _MSC_VER
51#pragma warning(pop)
52#endif
53#endif
54
55
56// ===========================================================================
57// static member variables
58// ===========================================================================
60
61
62// ===========================================================================
63// method definitions
64// ===========================================================================
65void
67 if (!oc.isSet("shapefile-prefixes") && !oc.isSet("geojson-files")) {
68 return;
69 }
70 // parse file(s)
71 for (std::string file : oc.getStringVector("shapefile-prefixes")) {
72 file += ".shp";
73 PROGRESS_BEGIN_MESSAGE("Parsing from shape-file '" + file + "'");
74 load(file, oc, toFill, tm);
76 }
77 for (const std::string& file : oc.getStringVector("geojson-files")) {
78 PROGRESS_BEGIN_MESSAGE("Parsing from geojson-file '" + file + "'");
79 load(file, oc, toFill, tm);
81 }
82}
83
84
85#ifdef HAVE_GDAL
87PCLoaderArcView::toShape(OGRLineString* geom, const std::string& tid) {
89 int outOfRange = 0;
90 for (int j = 0; j < geom->getNumPoints(); j++) {
91 if (fabs(geom->getX(j)) > 180 || fabs(geom->getY(j)) > 90) {
92 outOfRange++;
93 }
94 }
95 if (2 * outOfRange > geom->getNumPoints()) {
96 WRITE_WARNING(TL("No coordinate system found and coordinates look already projected."));
97 GeoConvHelper::init("!", GeoConvHelper::getProcessing().getOffset(), GeoConvHelper::getProcessing().getOrigBoundary(), GeoConvHelper::getProcessing().getConvBoundary());
98 } else {
99 WRITE_WARNING(TL("Could not find geo coordinate system, assuming WGS84."));
100 }
102 }
104 PositionVector shape;
105#if GDAL_VERSION_MAJOR < 3
106 for (int j = 0; j < geom->getNumPoints(); j++) {
107 Position pos(geom->getX(j), geom->getY(j));
108#else
109 for (const OGRPoint& p : *geom) {
110 Position pos(p.getX(), p.getY(), p.Is3D() ? p.getZ() : 0.0);
111#endif
112 if (!geoConvHelper.x2cartesian(pos)) {
113 WRITE_ERRORF(TL("Unable to project coordinates for polygon '%'."), tid);
114 }
115 shape.push_back_noDoublePos(pos);
116 }
117 return shape;
118}
119#endif
120
121
122void
123PCLoaderArcView::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill, PCTypeMap& tm) {
124#ifdef HAVE_GDAL
126 // get defaults
127 const std::string idField = oc.getString("shapefile.id-column");
128 const bool useRunningID = oc.getBool("shapefile.use-running-id") || idField == "";
129 int fillType = -1;
130 if (oc.getString("shapefile.fill") == "true") {
131 fillType = 1;
132 } else if (oc.getString("shapefile.fill") == "false") {
133 fillType = 0;
134 }
135#if GDAL_VERSION_MAJOR < 2
136 OGRRegisterAll();
137 OGRDataSource* poDS = OGRSFDriverRegistrar::Open(file.c_str(), FALSE);
138#else
139 GDALAllRegister();
140 GDALDataset* poDS = (GDALDataset*) GDALOpenEx(file.c_str(), GDAL_OF_VECTOR | GA_ReadOnly, NULL, NULL, NULL);
141#endif
142 if (poDS == NULL) {
143 throw ProcessError(TLF("Could not open shape description '%'.", file));
144 }
145
146 // begin file parsing
147 OGRLayer* poLayer = poDS->GetLayer(0);
148 poLayer->ResetReading();
149
150 // build coordinate transformation
151#if GDAL_VERSION_MAJOR < 3
152 OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
153#else
154 const OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
155#endif
156 OGRSpatialReference destTransf;
157 // use wgs84 as destination
158 destTransf.SetWellKnownGeogCS("WGS84");
159#if GDAL_VERSION_MAJOR > 2
160 if (oc.getBool("shapefile.traditional-axis-mapping") || origTransf != nullptr) {
161 destTransf.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
162 }
163#endif
164 OGRCoordinateTransformation* poCT = origTransf == nullptr ? nullptr : OGRCreateCoordinateTransformation(origTransf, &destTransf);
165 if (poCT == nullptr) {
166 if (oc.getBool("shapefile.guess-projection")) {
167 OGRSpatialReference origTransf2;
168 origTransf2.SetWellKnownGeogCS("WGS84");
169 poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf);
170 }
171 } else {
173 }
174
175 OGRFeature* poFeature;
176 poLayer->ResetReading();
177 int runningID = 0;
178 while ((poFeature = poLayer->GetNextFeature()) != nullptr) {
179 if (runningID == 0) {
180 std::vector<std::string> fields;
181 for (int i = 0; i < poFeature->GetFieldCount(); i++) {
182 fields.push_back(poFeature->GetFieldDefnRef(i)->GetNameRef());
183 }
184 WRITE_MESSAGE("Available fields: " + toString(fields));
185 }
186 std::vector<Parameterised*> parCont;
187 // read in edge attributes
188 std::string id = useRunningID ? toString(runningID) : poFeature->GetFieldAsString(idField.c_str());
189 ++runningID;
191 if (id == "") {
192 throw ProcessError(TLF("Missing id under '%'", idField));
193 }
194 id = oc.getString("prefix") + id;
195 std::string type;
196 for (const std::string& typeField : oc.getStringVector("shapefile.type-columns")) {
197 if (type != "") {
198 type += ".";
199 }
200 type += poFeature->GetFieldAsString(typeField.c_str());
201 }
202 RGBColor color = RGBColor::parseColor(oc.getString("color"));
203 std::string icon = oc.getString("icon");
204 double layer = oc.getFloat("layer");
205 double angle = Shape::DEFAULT_ANGLE;
206 std::string imgFile = Shape::DEFAULT_IMG_FILE;
207 if (type != "") {
208 if (tm.has(type)) {
209 const PCTypeMap::TypeDef& def = tm.get(type);
210 if (def.discard) {
211 continue;
212 }
213 color = def.color;
214 icon = def.icon;
215 layer = def.layer;
216 angle = def.angle;
217 imgFile = def.imgFile;
218 type = def.id;
219 }
220 } else {
221 type = oc.getString("type");
222 }
223 if (poFeature->GetFieldIndex("angle") >= 0) {
224 angle = poFeature->GetFieldAsDouble("angle");
225 }
226 // read in the geometry
227 OGRGeometry* poGeometry = poFeature->GetGeometryRef();
228 if (poGeometry == 0) {
229 OGRFeature::DestroyFeature(poFeature);
230 continue;
231 }
232 // try transform to wgs84
233 if (poCT != nullptr) {
234 poGeometry->transform(poCT);
235 }
236 OGRwkbGeometryType gtype = poGeometry->getGeometryType();
237 switch (gtype) {
238 case wkbPoint:
239 case wkbPoint25D: {
240 OGRPoint* cgeom = (OGRPoint*) poGeometry;
241 Position pos(cgeom->getX(), cgeom->getY());
242 if (!geoConvHelper.x2cartesian(pos)) {
243 WRITE_ERRORF(TL("Unable to project coordinates for POI '%'."), id);
244 }
245 PointOfInterest* poi = new PointOfInterest(id, type, color, pos, false, "", 0, false, 0, icon, layer, angle, imgFile);
246 if (toFill.add(poi)) {
247 parCont.push_back(poi);
248 }
249 }
250 break;
251 case wkbLineString:
252 case wkbLineString25D: {
253 const PositionVector shape = toShape((OGRLineString*) poGeometry, id);
254 SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, fillType == 1, 1, layer, angle, imgFile);
255 if (toFill.add(poly)) {
256 parCont.push_back(poly);
257 }
258 }
259 break;
260 case wkbPolygon:
261 case wkbPolygon25D: {
262 const bool fill = fillType < 0 || fillType == 1;
263 const PositionVector shape = toShape(((OGRPolygon*) poGeometry)->getExteriorRing(), id);
264 SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, fill, 1, layer, angle, imgFile);
265 if (toFill.add(poly)) {
266 parCont.push_back(poly);
267 }
268 }
269 break;
270 case wkbMultiPoint:
271 case wkbMultiPoint25D: {
272 OGRMultiPoint* cgeom = (OGRMultiPoint*) poGeometry;
273 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
274 OGRPoint* cgeom2 = (OGRPoint*) cgeom->getGeometryRef(i);
275 Position pos(cgeom2->getX(), cgeom2->getY());
276 const std::string tid = id + "#" + toString(i);
277 if (!geoConvHelper.x2cartesian(pos)) {
278 WRITE_ERRORF(TL("Unable to project coordinates for POI '%'."), tid);
279 }
280 PointOfInterest* poi = new PointOfInterest(tid, type, color, pos, false, "", 0, false, 0, icon, layer, angle, imgFile);
281 if (toFill.add(poi)) {
282 parCont.push_back(poi);
283 }
284 }
285 }
286 break;
287 case wkbMultiLineString:
288 case wkbMultiLineString25D: {
289 OGRMultiLineString* cgeom = (OGRMultiLineString*) poGeometry;
290 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
291 const std::string tid = id + "#" + toString(i);
292 const PositionVector shape = toShape((OGRLineString*) cgeom->getGeometryRef(i), tid);
293 SUMOPolygon* poly = new SUMOPolygon(tid, type, color, shape, false, fillType == 1, 1, layer, angle, imgFile);
294 if (toFill.add(poly)) {
295 parCont.push_back(poly);
296 }
297 }
298 }
299 break;
300 case wkbMultiPolygon:
301 case wkbMultiPolygon25D: {
302 const bool fill = fillType < 0 || fillType == 1;
303 OGRMultiPolygon* cgeom = (OGRMultiPolygon*) poGeometry;
304 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
305 const std::string tid = id + "#" + toString(i);
306 const PositionVector shape = toShape(((OGRPolygon*) cgeom->getGeometryRef(i))->getExteriorRing(), tid);
307 SUMOPolygon* poly = new SUMOPolygon(tid, type, color, shape, false, fill, 1, layer, angle, imgFile);
308 if (toFill.add(poly)) {
309 parCont.push_back(poly);
310 }
311 }
312 }
313 break;
314 default:
315 WRITE_WARNINGF(TL("Unsupported shape type occurred (id='%')."), id);
316 break;
317 }
318 if (oc.getBool("shapefile.add-param") || oc.getBool("all-attributes")) {
319 for (std::vector<Parameterised*>::const_iterator it = parCont.begin(); it != parCont.end(); ++it) {
320 OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
321 for (int iField = 0; iField < poFDefn->GetFieldCount(); iField++) {
322 OGRFieldDefn* poFieldDefn = poFDefn->GetFieldDefn(iField);
323 if (poFieldDefn->GetNameRef() != idField) {
324 (*it)->setParameter(poFieldDefn->GetNameRef(), StringUtils::latin1_to_utf8(poFeature->GetFieldAsString(iField)));
325 }
326 }
327 }
328 }
329 OGRFeature::DestroyFeature(poFeature);
330 }
331#if GDAL_VERSION_MAJOR < 2
332 OGRDataSource::DestroyDataSource(poDS);
333#else
334 GDALClose(poDS);
335#endif
337#else
338 UNUSED_PARAMETER(file);
340 UNUSED_PARAMETER(toFill);
342 WRITE_ERROR(TL("SUMO was compiled without GDAL support."));
343#endif
344}
345
346
347/****************************************************************************/
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:288
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define PROGRESS_DONE_MESSAGE()
Definition MsgHandler.h:291
#define TLF(string,...)
Definition MsgHandler.h:306
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition MsgHandler.h:290
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
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:249
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