LCOV - code coverage report
Current view: top level - src/polyconvert - PCLoaderArcView.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 56.4 % 163 92
Test Date: 2024-12-21 15:45:41 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-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           41 : PCLoaderArcView::loadIfSet(OptionsCont& oc, PCPolyContainer& toFill, PCTypeMap& tm) {
      66           82 :     if (!oc.isSet("shapefile-prefixes")) {
      67           38 :         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            9 :         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        74774 :         Position pos(p.getX(), p.getY(), p.Is3D() ? p.getZ() : 0.0);
     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            3 :     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         1195 :         id = StringUtils::latin1_to_utf8(StringUtils::prune(id));
     183         1195 :         if (id == "") {
     184            0 :             throw ProcessError(TLF("Missing id under '%'", idField));
     185              :         }
     186         3585 :         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         1195 :         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              :             case wkbPoint25D: {
     232              :                 OGRPoint* cgeom = (OGRPoint*) poGeometry;
     233              :                 Position pos(cgeom->getX(), cgeom->getY());
     234            0 :                 if (!geoConvHelper.x2cartesian(pos)) {
     235            0 :                     WRITE_ERRORF(TL("Unable to project coordinates for POI '%'."), id);
     236              :                 }
     237            0 :                 PointOfInterest* poi = new PointOfInterest(id, type, color, pos, false, "", 0, false, 0, icon, layer, angle, imgFile);
     238            0 :                 if (toFill.add(poi)) {
     239            0 :                     parCont.push_back(poi);
     240              :                 }
     241              :             }
     242            0 :             break;
     243            0 :             case wkbLineString:
     244              :             case wkbLineString25D: {
     245            0 :                 const PositionVector shape = toShape((OGRLineString*) poGeometry, id);
     246            0 :                 SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, fillType == 1, 1, layer, angle, imgFile);
     247            0 :                 if (toFill.add(poly)) {
     248            0 :                     parCont.push_back(poly);
     249              :                 }
     250            0 :             }
     251            0 :             break;
     252         1194 :             case wkbPolygon:
     253              :             case wkbPolygon25D: {
     254         1194 :                 const bool fill = fillType < 0 || fillType == 1;
     255         1194 :                 const PositionVector shape = toShape(((OGRPolygon*) poGeometry)->getExteriorRing(), id);
     256         1194 :                 SUMOPolygon* poly = new SUMOPolygon(id, type, color, shape, false, fill, 1, layer, angle, imgFile);
     257         1194 :                 if (toFill.add(poly)) {
     258         1194 :                     parCont.push_back(poly);
     259              :                 }
     260         1194 :             }
     261         1194 :             break;
     262            0 :             case wkbMultiPoint:
     263              :             case wkbMultiPoint25D: {
     264              :                 OGRMultiPoint* cgeom = (OGRMultiPoint*) poGeometry;
     265            0 :                 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
     266              :                     OGRPoint* cgeom2 = (OGRPoint*) cgeom->getGeometryRef(i);
     267              :                     Position pos(cgeom2->getX(), cgeom2->getY());
     268            0 :                     const std::string tid = id + "#" + toString(i);
     269            0 :                     if (!geoConvHelper.x2cartesian(pos)) {
     270            0 :                         WRITE_ERRORF(TL("Unable to project coordinates for POI '%'."), tid);
     271              :                     }
     272            0 :                     PointOfInterest* poi = new PointOfInterest(tid, type, color, pos, false, "", 0, false, 0, icon, layer, angle, imgFile);
     273            0 :                     if (toFill.add(poi)) {
     274            0 :                         parCont.push_back(poi);
     275              :                     }
     276              :                 }
     277              :             }
     278            0 :             break;
     279            0 :             case wkbMultiLineString:
     280              :             case wkbMultiLineString25D: {
     281              :                 OGRMultiLineString* cgeom = (OGRMultiLineString*) poGeometry;
     282            0 :                 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
     283            0 :                     const std::string tid = id + "#" + toString(i);
     284            0 :                     const PositionVector shape = toShape((OGRLineString*) cgeom->getGeometryRef(i), tid);
     285            0 :                     SUMOPolygon* poly = new SUMOPolygon(tid, type, color, shape, false, fillType == 1, 1, layer, angle, imgFile);
     286            0 :                     if (toFill.add(poly)) {
     287            0 :                         parCont.push_back(poly);
     288              :                     }
     289            0 :                 }
     290              :             }
     291            0 :             break;
     292            1 :             case wkbMultiPolygon:
     293              :             case wkbMultiPolygon25D: {
     294            1 :                 const bool fill = fillType < 0 || fillType == 1;
     295              :                 OGRMultiPolygon* cgeom = (OGRMultiPolygon*) poGeometry;
     296            3 :                 for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
     297            4 :                     const std::string tid = id + "#" + toString(i);
     298            2 :                     const PositionVector shape = toShape(((OGRPolygon*) cgeom->getGeometryRef(i))->getExteriorRing(), tid);
     299            2 :                     SUMOPolygon* poly = new SUMOPolygon(tid, type, color, shape, false, fill, 1, layer, angle, imgFile);
     300            2 :                     if (toFill.add(poly)) {
     301            2 :                         parCont.push_back(poly);
     302              :                     }
     303            2 :                 }
     304              :             }
     305            1 :             break;
     306            0 :             default:
     307            0 :                 WRITE_WARNINGF(TL("Unsupported shape type occurred (id='%')."), id);
     308            0 :                 break;
     309              :         }
     310         2390 :         if (oc.getBool("shapefile.add-param")) {
     311            0 :             for (std::vector<Parameterised*>::const_iterator it = parCont.begin(); it != parCont.end(); ++it) {
     312            0 :                 OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
     313            0 :                 for (int iField = 0; iField < poFDefn->GetFieldCount(); iField++) {
     314            0 :                     OGRFieldDefn* poFieldDefn = poFDefn->GetFieldDefn(iField);
     315            0 :                     if (poFieldDefn->GetNameRef() != idField) {
     316            0 :                         if (poFieldDefn->GetType() == OFTReal) {
     317            0 :                             (*it)->setParameter(poFieldDefn->GetNameRef(), toString(poFeature->GetFieldAsDouble(iField)));
     318              :                         } else {
     319            0 :                             (*it)->setParameter(poFieldDefn->GetNameRef(), StringUtils::latin1_to_utf8(poFeature->GetFieldAsString(iField)));
     320              :                         }
     321              :                     }
     322              :                 }
     323              :             }
     324              :         }
     325         1195 :         OGRFeature::DestroyFeature(poFeature);
     326         1195 :     }
     327              : #if GDAL_VERSION_MAJOR < 2
     328              :     OGRDataSource::DestroyDataSource(poDS);
     329              : #else
     330            3 :     GDALClose(poDS);
     331              : #endif
     332            3 :     PROGRESS_DONE_MESSAGE();
     333              : #else
     334              :     UNUSED_PARAMETER(file);
     335              :     UNUSED_PARAMETER(oc);
     336              :     UNUSED_PARAMETER(toFill);
     337              :     UNUSED_PARAMETER(tm);
     338              :     WRITE_ERROR(TL("SUMO was compiled without GDAL support."));
     339              : #endif
     340            6 : }
     341              : 
     342              : 
     343              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1