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

Generated by: LCOV version 2.0-1