Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/polyconvert/PCLoaderArcView.cpp
193678 views
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
/****************************************************************************/
14
/// @file PCLoaderArcView.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Michael Behrisch
18
/// @date Sept 2002
19
///
20
// A reader of pois and polygons from shape files
21
/****************************************************************************/
22
#include <config.h>
23
24
#include <string>
25
#include <utils/common/MsgHandler.h>
26
#include <utils/common/ToString.h>
27
#include <utils/common/StringUtils.h>
28
#include <utils/options/OptionsCont.h>
29
#include <utils/geom/GeomHelper.h>
30
#include <utils/geom/GeoConvHelper.h>
31
#include <utils/common/RGBColor.h>
32
#include <polyconvert/PCPolyContainer.h>
33
#include <polyconvert/PCTypeMap.h>
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
// ===========================================================================
58
bool PCLoaderArcView::myWarnMissingProjection = true;
59
60
61
// ===========================================================================
62
// method definitions
63
// ===========================================================================
64
void
65
PCLoaderArcView::loadIfSet(OptionsCont& oc, PCPolyContainer& toFill, PCTypeMap& tm) {
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);
74
PROGRESS_DONE_MESSAGE();
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);
79
PROGRESS_DONE_MESSAGE();
80
}
81
}
82
83
84
#ifdef HAVE_GDAL
85
const PositionVector
86
PCLoaderArcView::toShape(OGRLineString* geom, const std::string& tid) {
87
if (myWarnMissingProjection) {
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
}
100
myWarnMissingProjection = false;
101
}
102
GeoConvHelper& geoConvHelper = GeoConvHelper::getProcessing();
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
121
void
122
PCLoaderArcView::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill, PCTypeMap& tm) {
123
#ifdef HAVE_GDAL
124
GeoConvHelper& geoConvHelper = GeoConvHelper::getProcessing();
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 {
171
myWarnMissingProjection = false;
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;
189
id = StringUtils::latin1_to_utf8(StringUtils::prune(id));
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
335
PROGRESS_DONE_MESSAGE();
336
#else
337
UNUSED_PARAMETER(file);
338
UNUSED_PARAMETER(oc);
339
UNUSED_PARAMETER(toFill);
340
UNUSED_PARAMETER(tm);
341
WRITE_ERROR(TL("SUMO was compiled without GDAL support."));
342
#endif
343
}
344
345
346
/****************************************************************************/
347
348