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