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-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#if GDAL_VERSION_MAJOR < 3
151 OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
152#else
153 const OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
154#endif
155 OGRSpatialReference destTransf;
156 // use wgs84 as destination
157 destTransf.SetWellKnownGeogCS("WGS84");
158#if GDAL_VERSION_MAJOR > 2
159 if (oc.getBool("shapefile.traditional-axis-mapping") || origTransf != nullptr) {
160 destTransf.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
161 }
162#endif
163 OGRCoordinateTransformation* poCT = origTransf == nullptr ? nullptr : OGRCreateCoordinateTransformation(origTransf, &destTransf);
164 if (poCT == nullptr) {
165 if (oc.getBool("shapefile.guess-projection")) {
166 OGRSpatialReference origTransf2;
167 origTransf2.SetWellKnownGeogCS("WGS84");
168 poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf);
169 }
170 } else {
172 }
173
174 OGRFeature* poFeature;
175 poLayer->ResetReading();
176 int runningID = 0;
177 while ((poFeature = poLayer->GetNextFeature()) != nullptr) {
178 if (runningID == 0) {
179 std::vector<std::string> fields;
180 for (int i = 0; i < poFeature->GetFieldCount(); i++) {
181 fields.push_back(poFeature->GetFieldDefnRef(i)->GetNameRef());
182 }
183 WRITE_MESSAGE("Available fields: " + toString(fields));
184 }
185 std::vector<Parameterised*> parCont;
186 // read in edge attributes
187 std::string id = useRunningID ? toString(runningID) : poFeature->GetFieldAsString(idField.c_str());
188 ++runningID;
190 if (id == "") {
191 throw ProcessError(TLF("Missing id under '%'", idField));
192 }
193 id = oc.getString("prefix") + id;
194 std::string type;
195 for (const std::string& typeField : oc.getStringVector("shapefile.type-columns")) {
196 if (type != "") {
197 type += ".";
198 }
199 type += poFeature->GetFieldAsString(typeField.c_str());
200 }
201 RGBColor color = RGBColor::parseColor(oc.getString("color"));
202 std::string icon = oc.getString("icon");
203 double layer = oc.getFloat("layer");
204 double angle = Shape::DEFAULT_ANGLE;
205 std::string imgFile = Shape::DEFAULT_IMG_FILE;
206 if (type != "") {
207 if (tm.has(type)) {
208 const PCTypeMap::TypeDef& def = tm.get(type);
209 if (def.discard) {
210 continue;
211 }
212 color = def.color;
213 icon = def.icon;
214 layer = def.layer;
215 angle = def.angle;
216 imgFile = def.imgFile;
217 type = def.id;
218 }
219 } else {
220 type = oc.getString("type");
221 }
222 if (poFeature->GetFieldIndex("angle") >= 0) {
223 angle = poFeature->GetFieldAsDouble("angle");
224 }
225 // read in the geometry
226 OGRGeometry* poGeometry = poFeature->GetGeometryRef();
227 if (poGeometry == 0) {
228 OGRFeature::DestroyFeature(poFeature);
229 continue;
230 }
231 // try transform to wgs84
232 if (poCT != nullptr) {
233 poGeometry->transform(poCT);
234 }
235 OGRwkbGeometryType gtype = poGeometry->getGeometryType();
236 switch (gtype) {
237 case wkbPoint:
238 case wkbPoint25D: {
239 OGRPoint* cgeom = (OGRPoint*) poGeometry;
240 Position pos(cgeom->getX(), cgeom->getY());
241 if (!geoConvHelper.x2cartesian(pos)) {
242 WRITE_ERRORF(TL("Unable to project coordinates for POI '%'."), id);
243 }
244 PointOfInterest* poi = new PointOfInterest(id, type, color, pos, false, "", 0, false, 0, icon, layer, angle, imgFile);
245 if (toFill.add(poi)) {
246 parCont.push_back(poi);
247 }
248 }
249 break;
250 case wkbLineString:
251 case wkbLineString25D: {
252 const PositionVector shape = toShape((OGRLineString*) poGeometry, id);
253 SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, fillType == 1, 1, layer, angle, imgFile);
254 if (toFill.add(poly)) {
255 parCont.push_back(poly);
256 }
257 }
258 break;
259 case wkbPolygon:
260 case wkbPolygon25D: {
261 const bool fill = fillType < 0 || fillType == 1;
262 const PositionVector shape = toShape(((OGRPolygon*) poGeometry)->getExteriorRing(), id);
263 SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, fill, 1, layer, angle, imgFile);
264 if (toFill.add(poly)) {
265 parCont.push_back(poly);
266 }
267 }
268 break;
269 case wkbMultiPoint:
270 case wkbMultiPoint25D: {
271 OGRMultiPoint* cgeom = (OGRMultiPoint*) poGeometry;
272 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
273 OGRPoint* cgeom2 = (OGRPoint*) cgeom->getGeometryRef(i);
274 Position pos(cgeom2->getX(), cgeom2->getY());
275 const std::string tid = id + "#" + toString(i);
276 if (!geoConvHelper.x2cartesian(pos)) {
277 WRITE_ERRORF(TL("Unable to project coordinates for POI '%'."), tid);
278 }
279 PointOfInterest* poi = new PointOfInterest(tid, type, color, pos, false, "", 0, false, 0, icon, layer, angle, imgFile);
280 if (toFill.add(poi)) {
281 parCont.push_back(poi);
282 }
283 }
284 }
285 break;
286 case wkbMultiLineString:
287 case wkbMultiLineString25D: {
288 OGRMultiLineString* cgeom = (OGRMultiLineString*) poGeometry;
289 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
290 const std::string tid = id + "#" + toString(i);
291 const PositionVector shape = toShape((OGRLineString*) cgeom->getGeometryRef(i), tid);
292 SUMOPolygon* poly = new SUMOPolygon(tid, type, color, shape, false, fillType == 1, 1, layer, angle, imgFile);
293 if (toFill.add(poly)) {
294 parCont.push_back(poly);
295 }
296 }
297 }
298 break;
299 case wkbMultiPolygon:
300 case wkbMultiPolygon25D: {
301 const bool fill = fillType < 0 || fillType == 1;
302 OGRMultiPolygon* cgeom = (OGRMultiPolygon*) poGeometry;
303 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
304 const std::string tid = id + "#" + toString(i);
305 const PositionVector shape = toShape(((OGRPolygon*) cgeom->getGeometryRef(i))->getExteriorRing(), tid);
306 SUMOPolygon* poly = new SUMOPolygon(tid, type, color, shape, false, fill, 1, layer, angle, imgFile);
307 if (toFill.add(poly)) {
308 parCont.push_back(poly);
309 }
310 }
311 }
312 break;
313 default:
314 WRITE_WARNINGF(TL("Unsupported shape type occurred (id='%')."), id);
315 break;
316 }
317 if (oc.getBool("shapefile.add-param") || oc.getBool("all-attributes")) {
318 for (std::vector<Parameterised*>::const_iterator it = parCont.begin(); it != parCont.end(); ++it) {
319 OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
320 for (int iField = 0; iField < poFDefn->GetFieldCount(); iField++) {
321 OGRFieldDefn* poFieldDefn = poFDefn->GetFieldDefn(iField);
322 if (poFieldDefn->GetNameRef() != idField) {
323 (*it)->setParameter(poFieldDefn->GetNameRef(), StringUtils::latin1_to_utf8(poFeature->GetFieldAsString(iField)));
324 }
325 }
326 }
327 }
328 OGRFeature::DestroyFeature(poFeature);
329 }
330#if GDAL_VERSION_MAJOR < 2
331 OGRDataSource::DestroyDataSource(poDS);
332#else
333 GDALClose(poDS);
334#endif
336#else
337 UNUSED_PARAMETER(file);
339 UNUSED_PARAMETER(toFill);
341 WRITE_ERROR(TL("SUMO was compiled without GDAL support."));
342#endif
343}
344
345
346/****************************************************************************/
#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: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