LCOV - code coverage report
Current view: top level - src/polyconvert - PCLoaderArcView.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 90 161 55.9 %
Date: 2024-04-28 15:39:05 Functions: 3 3 100.0 %

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

Generated by: LCOV version 1.14