Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/polyconvert/PCLoaderArcView.cpp
169665 views
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
/****************************************************************************/
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
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 {
167
myWarnMissingProjection = false;
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;
185
id = StringUtils::latin1_to_utf8(StringUtils::prune(id));
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
331
PROGRESS_DONE_MESSAGE();
332
#else
333
UNUSED_PARAMETER(file);
334
UNUSED_PARAMETER(oc);
335
UNUSED_PARAMETER(toFill);
336
UNUSED_PARAMETER(tm);
337
WRITE_ERROR(TL("SUMO was compiled without GDAL support."));
338
#endif
339
}
340
341
342
/****************************************************************************/
343
344