LCOV - code coverage report
Current view: top level - src/polyconvert - PCLoaderArcView.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 73.6 % 163 120
Test Date: 2026-08-23 15:49:09 Functions: 100.0 % 3 3

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

Generated by: LCOV version 2.0-1