LCOV - code coverage report
Current view: top level - frmts/pcidsk - ogrpcidsklayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 260 348 74.7 %
Date: 2024-11-21 22:18:42 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  PCIDSK Translator
       4             :  * Purpose:  Implements OGRPCIDSKLayer class.
       5             :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
       9             :  * Copyright (c) 2011-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "pcidskdataset2.h"
      15             : 
      16             : #include <algorithm>
      17             : 
      18             : /************************************************************************/
      19             : /*                           OGRPCIDSKLayer()                           */
      20             : /************************************************************************/
      21             : 
      22        1183 : OGRPCIDSKLayer::OGRPCIDSKLayer(GDALDataset *poDS,
      23             :                                PCIDSK::PCIDSKSegment *poSegIn,
      24             :                                PCIDSK::PCIDSKVectorSegment *poVecSegIn,
      25        1183 :                                bool bUpdate)
      26        1183 :     : m_poDS(poDS)
      27             : 
      28             : {
      29        1183 :     poSRS = nullptr;
      30        1183 :     bUpdateAccess = bUpdate;
      31        1183 :     poSeg = poSegIn;
      32        1183 :     poVecSeg = poVecSegIn;
      33             : 
      34        1183 :     poFeatureDefn = new OGRFeatureDefn(poSeg->GetName().c_str());
      35        1183 :     SetDescription(poFeatureDefn->GetName());
      36        1183 :     poFeatureDefn->Reference();
      37             : 
      38        1183 :     hLastShapeId = PCIDSK::NullShapeId;
      39             : 
      40             :     /* -------------------------------------------------------------------- */
      41             :     /*      Attempt to assign a geometry type.                              */
      42             :     /* -------------------------------------------------------------------- */
      43             :     try
      44             :     {
      45        3549 :         std::string osLayerType = poSeg->GetMetadataValue("LAYER_TYPE");
      46             : 
      47        1183 :         if (osLayerType == "WHOLE_POLYGONS")
      48          16 :             poFeatureDefn->SetGeomType(wkbPolygon25D);
      49        1167 :         else if (osLayerType == "ARCS" || osLayerType == "TOPO_ARCS")
      50          28 :             poFeatureDefn->SetGeomType(wkbLineString25D);
      51        1139 :         else if (osLayerType == "POINTS" || osLayerType == "TOPO_NODES")
      52          28 :             poFeatureDefn->SetGeomType(wkbPoint25D);
      53        1111 :         else if (osLayerType == "TABLE")
      54          20 :             poFeatureDefn->SetGeomType(wkbNone);
      55             :     }
      56           0 :     catch (...)
      57             :     {
      58             :     }
      59             : 
      60             :     /* -------------------------------------------------------------------- */
      61             :     /*      Build field definitions.                                        */
      62             :     /* -------------------------------------------------------------------- */
      63             :     try
      64             :     {
      65        1183 :         iRingStartField = -1;
      66             : 
      67        1333 :         for (int iField = 0; iField < poVecSeg->GetFieldCount(); iField++)
      68             :         {
      69         150 :             OGRFieldDefn oField(poVecSeg->GetFieldName(iField).c_str(),
      70         300 :                                 OFTString);
      71             : 
      72         150 :             switch (poVecSeg->GetFieldType(iField))
      73             :             {
      74          27 :                 case PCIDSK::FieldTypeFloat:
      75             :                 case PCIDSK::FieldTypeDouble:
      76          27 :                     oField.SetType(OFTReal);
      77          27 :                     break;
      78             : 
      79          27 :                 case PCIDSK::FieldTypeInteger:
      80          27 :                     oField.SetType(OFTInteger);
      81          27 :                     break;
      82             : 
      83          96 :                 case PCIDSK::FieldTypeString:
      84          96 :                     oField.SetType(OFTString);
      85          96 :                     break;
      86             : 
      87           0 :                 case PCIDSK::FieldTypeCountedInt:
      88           0 :                     oField.SetType(OFTIntegerList);
      89           0 :                     break;
      90             : 
      91           0 :                 default:
      92           0 :                     CPLAssert(false);
      93             :                     break;
      94             :             }
      95             : 
      96             :             // we ought to try and extract some width/precision information
      97             :             // from the format string at some point.
      98             : 
      99             :             // If the last field is named RingStart we treat it specially.
     100         150 :             if (EQUAL(oField.GetNameRef(), "RingStart") &&
     101         150 :                 oField.GetType() == OFTIntegerList &&
     102           0 :                 iField == poVecSeg->GetFieldCount() - 1)
     103           0 :                 iRingStartField = iField;
     104             :             else
     105             :             {
     106         150 :                 poFeatureDefn->AddFieldDefn(&oField);
     107         150 :                 m_oMapFieldNameToIdx[oField.GetNameRef()] =
     108         150 :                     poFeatureDefn->GetFieldCount() - 1;
     109             :             }
     110             :         }
     111             : 
     112             :         /* --------------------------------------------------------------------
     113             :          */
     114             :         /*      Look for a coordinate system. */
     115             :         /* --------------------------------------------------------------------
     116             :          */
     117        2366 :         CPLString osGeosys;
     118        1183 :         const char *pszUnits = nullptr;
     119        2366 :         std::vector<double> adfParameters;
     120             : 
     121        1183 :         adfParameters = poVecSeg->GetProjection(osGeosys);
     122             : 
     123        1183 :         if (static_cast<PCIDSK::UnitCode>(
     124        1183 :                 static_cast<int>(adfParameters[16])) == PCIDSK::UNIT_DEGREE)
     125           0 :             pszUnits = "DEGREE";
     126        1183 :         else if (static_cast<PCIDSK::UnitCode>(
     127        1183 :                      static_cast<int>(adfParameters[16])) == PCIDSK::UNIT_METER)
     128           0 :             pszUnits = "METER";
     129        1183 :         else if (static_cast<PCIDSK::UnitCode>(static_cast<int>(
     130        1183 :                      adfParameters[16])) == PCIDSK::UNIT_US_FOOT)
     131           0 :             pszUnits = "FOOT";
     132        1183 :         else if (static_cast<PCIDSK::UnitCode>(static_cast<int>(
     133        1183 :                      adfParameters[16])) == PCIDSK::UNIT_INTL_FOOT)
     134           0 :             pszUnits = "INTL FOOT";
     135             : 
     136        1183 :         poSRS = new OGRSpatialReference();
     137             : 
     138        1183 :         if (poSRS->importFromPCI(osGeosys, pszUnits, &(adfParameters[0])) !=
     139             :             OGRERR_NONE)
     140             :         {
     141           0 :             delete poSRS;
     142           0 :             poSRS = nullptr;
     143             :         }
     144             :     }
     145             : 
     146             :     /* -------------------------------------------------------------------- */
     147             :     /*      Trap pcidsk exceptions.                                         */
     148             :     /* -------------------------------------------------------------------- */
     149           0 :     catch (const PCIDSK::PCIDSKException &ex)
     150             :     {
     151           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     152             :                  "PCIDSK Exception while initializing layer, operation likely "
     153             :                  "impaired.\n%s",
     154           0 :                  ex.what());
     155             :     }
     156           0 :     catch (...)
     157             :     {
     158           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     159             :                  "Non-PCIDSK exception trapped while initializing layer, "
     160             :                  "operation likely impaired.");
     161             :     }
     162             : 
     163        1183 :     if (poFeatureDefn->GetGeomFieldCount() > 0)
     164        1163 :         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
     165        1183 : }
     166             : 
     167             : /************************************************************************/
     168             : /*                          ~OGRPCIDSKLayer()                           */
     169             : /************************************************************************/
     170             : 
     171        2366 : OGRPCIDSKLayer::~OGRPCIDSKLayer()
     172             : 
     173             : {
     174        1183 :     if (m_nFeaturesRead > 0)
     175             :     {
     176          80 :         CPLDebug("PCIDSK", "%d features read on layer '%s'.",
     177          40 :                  static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName());
     178             :     }
     179             : 
     180        1183 :     poFeatureDefn->Release();
     181             : 
     182        1183 :     if (poSRS)
     183        1183 :         poSRS->Release();
     184        2366 : }
     185             : 
     186             : /************************************************************************/
     187             : /*                            ResetReading()                            */
     188             : /************************************************************************/
     189             : 
     190         380 : void OGRPCIDSKLayer::ResetReading()
     191             : 
     192             : {
     193         380 :     hLastShapeId = PCIDSK::NullShapeId;
     194         380 :     m_bEOF = false;
     195         380 : }
     196             : 
     197             : /************************************************************************/
     198             : /*                         GetNextRawFeature()                          */
     199             : /************************************************************************/
     200             : 
     201         263 : OGRFeature *OGRPCIDSKLayer::GetNextRawFeature()
     202             : 
     203             : {
     204         263 :     if (m_bEOF)
     205           6 :         return nullptr;
     206             : 
     207             :     try
     208             :     {
     209             :         /* --------------------------------------------------------------------
     210             :          */
     211             :         /*      Get the next shapeid. */
     212             :         /* --------------------------------------------------------------------
     213             :          */
     214         257 :         if (hLastShapeId == PCIDSK::NullShapeId)
     215         187 :             hLastShapeId = poVecSeg->FindFirst();
     216             :         else
     217          70 :             hLastShapeId = poVecSeg->FindNext(hLastShapeId);
     218             : 
     219         257 :         if (hLastShapeId == PCIDSK::NullShapeId)
     220             :         {
     221         124 :             m_bEOF = true;
     222         124 :             return nullptr;
     223             :         }
     224             : 
     225         133 :         return GetFeature(hLastShapeId);
     226             :     }
     227           0 :     catch (const PCIDSK::PCIDSKException &ex)
     228             :     {
     229           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     230           0 :                  "PCIDSK Exception while iterating features.\n%s", ex.what());
     231           0 :         return nullptr;
     232             :     }
     233             : }
     234             : 
     235             : /************************************************************************/
     236             : /*                             GetFeature()                             */
     237             : /************************************************************************/
     238             : 
     239         168 : OGRFeature *OGRPCIDSKLayer::GetFeature(GIntBig nFID)
     240             : 
     241             : {
     242             :     /* -------------------------------------------------------------------- */
     243             :     /*      Create the OGR feature.                                         */
     244             :     /* -------------------------------------------------------------------- */
     245         168 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     246         168 :     poFeature->SetFID(static_cast<int>(nFID));
     247             : 
     248             :     /* -------------------------------------------------------------------- */
     249             :     /*      Set attributes for any indicated attribute records.             */
     250             :     /* -------------------------------------------------------------------- */
     251             :     try
     252             :     {
     253         336 :         std::vector<PCIDSK::ShapeField> aoFields;
     254             : 
     255         168 :         poVecSeg->GetFields(static_cast<int>(nFID), aoFields);
     256         293 :         for (unsigned int i = 0; i < aoFields.size(); i++)
     257             :         {
     258         143 :             if (static_cast<int>(i) == iRingStartField)
     259           0 :                 continue;
     260             : 
     261         143 :             switch (aoFields[i].GetType())
     262             :             {
     263           0 :                 case PCIDSK::FieldTypeNone:
     264             :                     // null field value.
     265           0 :                     break;
     266             : 
     267          37 :                 case PCIDSK::FieldTypeInteger:
     268          37 :                     poFeature->SetField(i, aoFields[i].GetValueInteger());
     269          37 :                     break;
     270             : 
     271           0 :                 case PCIDSK::FieldTypeFloat:
     272           0 :                     poFeature->SetField(i, aoFields[i].GetValueFloat());
     273           0 :                     break;
     274             : 
     275          37 :                 case PCIDSK::FieldTypeDouble:
     276          37 :                     poFeature->SetField(i, aoFields[i].GetValueDouble());
     277          37 :                     break;
     278             : 
     279          69 :                 case PCIDSK::FieldTypeString:
     280          69 :                     poFeature->SetField(i,
     281         138 :                                         aoFields[i].GetValueString().c_str());
     282          69 :                     break;
     283             : 
     284           0 :                 case PCIDSK::FieldTypeCountedInt:
     285             :                     std::vector<PCIDSK::int32> list =
     286           0 :                         aoFields[i].GetValueCountedInt();
     287             : 
     288           0 :                     poFeature->SetField(i, static_cast<int>(list.size()),
     289           0 :                                         &(list[0]));
     290           0 :                     break;
     291             :             }
     292             :         }
     293             : 
     294             :         /* --------------------------------------------------------------------
     295             :          */
     296             :         /*      Translate the geometry. */
     297             :         /* --------------------------------------------------------------------
     298             :          */
     299         300 :         std::vector<PCIDSK::ShapeVertex> aoVertices;
     300             : 
     301         150 :         poVecSeg->GetVertices(static_cast<int>(nFID), aoVertices);
     302             : 
     303             :         /* --------------------------------------------------------------------
     304             :          */
     305             :         /*      Point */
     306             :         /* --------------------------------------------------------------------
     307             :          */
     308         248 :         if (poFeatureDefn->GetGeomType() == wkbPoint25D ||
     309         107 :             (wkbFlatten(poFeatureDefn->GetGeomType()) == wkbUnknown &&
     310           9 :              aoVertices.size() == 1))
     311             :         {
     312          52 :             if (aoVertices.size() == 1)
     313             :             {
     314             :                 OGRPoint *poPoint = new OGRPoint(
     315          50 :                     aoVertices[0].x, aoVertices[0].y, aoVertices[0].z);
     316          50 :                 if (poSRS)
     317          50 :                     poPoint->assignSpatialReference(poSRS);
     318          50 :                 poFeature->SetGeometryDirectly(poPoint);
     319             :             }
     320             :             else
     321             :             {
     322             :                 // report issue?
     323             :             }
     324             :         }
     325             : 
     326             :         /* --------------------------------------------------------------------
     327             :          */
     328             :         /*      LineString */
     329             :         /* --------------------------------------------------------------------
     330             :          */
     331         144 :         else if (poFeatureDefn->GetGeomType() == wkbLineString25D ||
     332          55 :                  (wkbFlatten(poFeatureDefn->GetGeomType()) == wkbUnknown &&
     333           9 :                   aoVertices.size() > 1))
     334             :         {
     335             :             // We should likely be applying ringstart to break things into
     336             :             // a multilinestring in some cases.
     337          52 :             if (aoVertices.size() > 1)
     338             :             {
     339          50 :                 OGRLineString *poLS = new OGRLineString();
     340             : 
     341          50 :                 poLS->setNumPoints(static_cast<int>(aoVertices.size()));
     342             : 
     343         150 :                 for (unsigned int i = 0; i < aoVertices.size(); i++)
     344         100 :                     poLS->setPoint(i, aoVertices[i].x, aoVertices[i].y,
     345         100 :                                    aoVertices[i].z);
     346          50 :                 if (poSRS)
     347          50 :                     poLS->assignSpatialReference(poSRS);
     348             : 
     349          50 :                 poFeature->SetGeometryDirectly(poLS);
     350             :             }
     351             :             else
     352             :             {
     353             :                 // report issue?
     354             :             }
     355             :         }
     356             : 
     357             :         /* --------------------------------------------------------------------
     358             :          */
     359             :         /*      Polygon - Currently we have no way to recognise if we are */
     360             :         /*      dealing with a multipolygon when we have more than one */
     361             :         /*      ring.  Also, PCIDSK allows the rings to be in arbitrary */
     362             :         /*      order, not necessarily outside first which we are not yet */
     363             :         /*      ready to address in the following code. */
     364             :         /* --------------------------------------------------------------------
     365             :          */
     366          46 :         else if (poFeatureDefn->GetGeomType() == wkbPolygon25D)
     367             :         {
     368           4 :             std::vector<PCIDSK::int32> anRingStart;
     369           2 :             OGRPolygon *poPoly = new OGRPolygon();
     370             : 
     371           2 :             if (iRingStartField != -1)
     372           0 :                 anRingStart = aoFields[iRingStartField].GetValueCountedInt();
     373             : 
     374           4 :             for (unsigned int iRing = 0; iRing < anRingStart.size() + 1;
     375             :                  iRing++)
     376             :             {
     377             :                 int iStartVertex;
     378           2 :                 if (iRing == 0)
     379           2 :                     iStartVertex = 0;
     380             :                 else
     381           0 :                     iStartVertex = anRingStart[iRing - 1];
     382             : 
     383             :                 int iEndVertex;
     384           2 :                 if (iRing == anRingStart.size())
     385           2 :                     iEndVertex = static_cast<int>(aoVertices.size()) - 1;
     386             :                 else
     387           0 :                     iEndVertex = anRingStart[iRing] - 1;
     388             : 
     389             :                 int iVertex;
     390           2 :                 OGRLinearRing *poRing = new OGRLinearRing();
     391           2 :                 poRing->setNumPoints(iEndVertex - iStartVertex + 1);
     392           2 :                 for (iVertex = iStartVertex; iVertex <= iEndVertex; iVertex++)
     393             :                 {
     394           0 :                     poRing->setPoint(
     395           0 :                         iVertex - iStartVertex, aoVertices[iVertex].x,
     396           0 :                         aoVertices[iVertex].y, aoVertices[iVertex].z);
     397             :                 }
     398             : 
     399           2 :                 poPoly->addRingDirectly(poRing);
     400             :             }
     401             : 
     402           2 :             if (poSRS)
     403           2 :                 poPoly->assignSpatialReference(poSRS);
     404             : 
     405           2 :             poFeature->SetGeometryDirectly(poPoly);
     406             :         }
     407             :     }
     408             : 
     409             :     /* -------------------------------------------------------------------- */
     410             :     /*      Trap exceptions and report as CPL errors.                       */
     411             :     /* -------------------------------------------------------------------- */
     412          18 :     catch (const PCIDSK::PCIDSKException &ex)
     413             :     {
     414          18 :         delete poFeature;
     415          18 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", ex.what());
     416          18 :         return nullptr;
     417             :     }
     418           0 :     catch (...)
     419             :     {
     420           0 :         delete poFeature;
     421           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Non-PCIDSK exception trapped.");
     422           0 :         return nullptr;
     423             :     }
     424             : 
     425         150 :     m_nFeaturesRead++;
     426             : 
     427         150 :     return poFeature;
     428             : }
     429             : 
     430             : /************************************************************************/
     431             : /*                           TestCapability()                           */
     432             : /************************************************************************/
     433             : 
     434         318 : int OGRPCIDSKLayer::TestCapability(const char *pszCap)
     435             : 
     436             : {
     437         318 :     if (EQUAL(pszCap, OLCRandomRead))
     438           6 :         return TRUE;
     439             : 
     440         312 :     else if (EQUAL(pszCap, OLCFastFeatureCount))
     441           0 :         return m_poFilterGeom == nullptr && m_poAttrQuery == nullptr;
     442             : 
     443         312 :     else if (EQUAL(pszCap, OLCSequentialWrite) || EQUAL(pszCap, OLCRandomWrite))
     444          28 :         return bUpdateAccess;
     445             : 
     446         284 :     else if (EQUAL(pszCap, OLCDeleteFeature))
     447           6 :         return bUpdateAccess;
     448             : 
     449         278 :     else if (EQUAL(pszCap, OLCCreateField))
     450          28 :         return bUpdateAccess;
     451             : 
     452         250 :     else if (EQUAL(pszCap, OLCZGeometries))
     453          18 :         return TRUE;
     454             : 
     455         232 :     return FALSE;
     456             : }
     457             : 
     458             : /************************************************************************/
     459             : /*                         GetFeatureCount()                          */
     460             : /************************************************************************/
     461             : 
     462         102 : GIntBig OGRPCIDSKLayer::GetFeatureCount(int bForce)
     463             : 
     464             : {
     465         102 :     if (m_poFilterGeom != nullptr || m_poAttrQuery != nullptr)
     466          18 :         return OGRLayer::GetFeatureCount(bForce);
     467             : 
     468             :     try
     469             :     {
     470          84 :         return poVecSeg->GetShapeCount();
     471             :     }
     472           0 :     catch (...)
     473             :     {
     474           0 :         return 0;
     475             :     }
     476             : }
     477             : 
     478             : /************************************************************************/
     479             : /*                             GetExtent()                              */
     480             : /************************************************************************/
     481             : 
     482          10 : OGRErr OGRPCIDSKLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     483             : 
     484             : {
     485          10 :     if (!bForce)
     486           0 :         return OGRERR_FAILURE;
     487             : 
     488             :     /* -------------------------------------------------------------------- */
     489             :     /*      Loop over all features, but just read the geometry.  This is    */
     490             :     /*      a fair amount quicker than actually processing all the          */
     491             :     /*      attributes, forming features and then examining the             */
     492             :     /*      geometries as the default implementation would do.              */
     493             :     /* -------------------------------------------------------------------- */
     494             :     try
     495             :     {
     496          10 :         bool bHaveExtent = false;
     497             : 
     498          20 :         std::vector<PCIDSK::ShapeVertex> asVertices;
     499             : 
     500          20 :         for (PCIDSK::ShapeIterator oIt = poVecSeg->begin();
     501          30 :              oIt != poVecSeg->end(); oIt++)
     502             :         {
     503          10 :             poVecSeg->GetVertices(*oIt, asVertices);
     504             : 
     505          22 :             for (unsigned int i = 0; i < asVertices.size(); i++)
     506             :             {
     507          12 :                 if (!bHaveExtent)
     508             :                 {
     509           8 :                     psExtent->MinX = asVertices[i].x;
     510           8 :                     psExtent->MaxX = asVertices[i].x;
     511           8 :                     psExtent->MinY = asVertices[i].y;
     512           8 :                     psExtent->MaxY = asVertices[i].y;
     513           8 :                     bHaveExtent = true;
     514             :                 }
     515             :                 else
     516             :                 {
     517           4 :                     psExtent->MinX = std::min(psExtent->MinX, asVertices[i].x);
     518           4 :                     psExtent->MaxX = std::max(psExtent->MaxX, asVertices[i].x);
     519           4 :                     psExtent->MinY = std::min(psExtent->MinY, asVertices[i].y);
     520           4 :                     psExtent->MaxY = std::max(psExtent->MaxY, asVertices[i].y);
     521             :                 }
     522             :             }
     523             :         }
     524             : 
     525          10 :         if (bHaveExtent)
     526           8 :             return OGRERR_NONE;
     527             : 
     528           2 :         return OGRERR_FAILURE;
     529             :     }
     530             : 
     531             :     /* -------------------------------------------------------------------- */
     532             :     /*      Trap pcidsk exceptions.                                         */
     533             :     /* -------------------------------------------------------------------- */
     534           0 :     catch (const PCIDSK::PCIDSKException &ex)
     535             :     {
     536           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     537             :                  "PCIDSK Exception while initializing layer, operation likely "
     538             :                  "impaired.\n%s",
     539           0 :                  ex.what());
     540           0 :         return OGRERR_FAILURE;
     541             :     }
     542           0 :     catch (...)
     543             :     {
     544           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     545             :                  "Non-PCIDSK exception trapped while initializing layer, "
     546             :                  "operation likely impaired.");
     547           0 :         return OGRERR_FAILURE;
     548             :     }
     549             : }
     550             : 
     551             : /************************************************************************/
     552             : /*                           DeleteFeature()                            */
     553             : /************************************************************************/
     554             : 
     555          20 : OGRErr OGRPCIDSKLayer::DeleteFeature(GIntBig nFID)
     556             : 
     557             : {
     558             :     try
     559             :     {
     560          20 :         poVecSeg->DeleteShape((PCIDSK::ShapeId)nFID);
     561             : 
     562           8 :         return OGRERR_NONE;
     563             :     }
     564             : 
     565             :     /* -------------------------------------------------------------------- */
     566             :     /*      Trap exceptions and report as CPL errors.                       */
     567             :     /* -------------------------------------------------------------------- */
     568          12 :     catch (const PCIDSK::PCIDSKException &ex)
     569             :     {
     570          12 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", ex.what());
     571          12 :         return OGRERR_FAILURE;
     572             :     }
     573           0 :     catch (...)
     574             :     {
     575           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Non-PCIDSK exception trapped.");
     576           0 :         return OGRERR_FAILURE;
     577             :     }
     578             : }
     579             : 
     580             : /************************************************************************/
     581             : /*                          ICreateFeature()                            */
     582             : /************************************************************************/
     583             : 
     584         102 : OGRErr OGRPCIDSKLayer::ICreateFeature(OGRFeature *poFeature)
     585             : 
     586             : {
     587             :     try
     588             :     {
     589             :         PCIDSK::ShapeId id =
     590         102 :             poVecSeg->CreateShape((PCIDSK::ShapeId)poFeature->GetFID());
     591             : 
     592          96 :         poFeature->SetFID((long)id);
     593             : 
     594          96 :         return SetFeature(poFeature);
     595             :     }
     596             :     /* -------------------------------------------------------------------- */
     597             :     /*      Trap exceptions and report as CPL errors.                       */
     598             :     /* -------------------------------------------------------------------- */
     599           6 :     catch (const PCIDSK::PCIDSKException &ex)
     600             :     {
     601           6 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", ex.what());
     602           6 :         return OGRERR_FAILURE;
     603             :     }
     604           0 :     catch (...)
     605             :     {
     606           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Non-PCIDSK exception trapped.");
     607           0 :         return OGRERR_FAILURE;
     608             :     }
     609             : }
     610             : 
     611             : /************************************************************************/
     612             : /*                            ISetFeature()                             */
     613             : /************************************************************************/
     614             : 
     615          98 : OGRErr OGRPCIDSKLayer::ISetFeature(OGRFeature *poFeature)
     616             : 
     617             : {
     618          98 :     PCIDSK::ShapeId id = (PCIDSK::ShapeId)poFeature->GetFID();
     619             : 
     620             :     /* -------------------------------------------------------------------- */
     621             :     /*      Translate attribute fields.                                     */
     622             :     /* -------------------------------------------------------------------- */
     623             :     try
     624             :     {
     625         196 :         std::vector<PCIDSK::ShapeField> aoPCIFields;
     626             : 
     627          98 :         aoPCIFields.resize(poVecSeg->GetFieldCount());
     628             : 
     629         454 :         for (int iPCI = 0; iPCI < poVecSeg->GetFieldCount(); iPCI++)
     630             :         {
     631         356 :             int iOGR = -1;
     632         356 :             const auto osFieldName(poVecSeg->GetFieldName(iPCI));
     633         356 :             auto oIter = m_oMapFieldNameToIdx.find(osFieldName);
     634         356 :             if (oIter != m_oMapFieldNameToIdx.end())
     635             :             {
     636         356 :                 iOGR = oIter->second;
     637             :             }
     638             : 
     639         356 :             if (iOGR == -1)
     640           0 :                 continue;
     641             : 
     642         356 :             switch (poVecSeg->GetFieldType(iPCI))
     643             :             {
     644          70 :                 case PCIDSK::FieldTypeInteger:
     645          70 :                     aoPCIFields[iPCI].SetValue(
     646             :                         poFeature->GetFieldAsInteger(iOGR));
     647          70 :                     break;
     648             : 
     649           0 :                 case PCIDSK::FieldTypeFloat:
     650           0 :                     aoPCIFields[iPCI].SetValue(
     651           0 :                         static_cast<float>(poFeature->GetFieldAsDouble(iOGR)));
     652           0 :                     break;
     653             : 
     654          70 :                 case PCIDSK::FieldTypeDouble:
     655          70 :                     aoPCIFields[iPCI].SetValue(
     656             :                         static_cast<double>(poFeature->GetFieldAsDouble(iOGR)));
     657          70 :                     break;
     658             : 
     659         216 :                 case PCIDSK::FieldTypeString:
     660         216 :                     aoPCIFields[iPCI].SetValue(
     661             :                         poFeature->GetFieldAsString(iOGR));
     662         216 :                     break;
     663             : 
     664           0 :                 case PCIDSK::FieldTypeCountedInt:
     665             :                 {
     666             :                     int nCount;
     667             :                     const int *panList =
     668           0 :                         poFeature->GetFieldAsIntegerList(iOGR, &nCount);
     669           0 :                     std::vector<PCIDSK::int32> anList;
     670             : 
     671           0 :                     anList.resize(nCount);
     672           0 :                     memcpy(&(anList[0]), panList, 4 * anList.size());
     673           0 :                     aoPCIFields[iPCI].SetValue(anList);
     674             :                 }
     675           0 :                 break;
     676             : 
     677           0 :                 default:
     678           0 :                     CPLAssert(false);
     679             :                     break;
     680             :             }
     681             :         }
     682             : 
     683          98 :         if (poVecSeg->GetFieldCount() > 0)
     684          88 :             poVecSeg->SetFields(id, aoPCIFields);
     685             : 
     686             :         /* --------------------------------------------------------------------
     687             :          */
     688             :         /*      Translate the geometry. */
     689             :         /* --------------------------------------------------------------------
     690             :          */
     691         196 :         std::vector<PCIDSK::ShapeVertex> aoVertices;
     692          98 :         OGRGeometry *poGeometry = poFeature->GetGeometryRef();
     693             : 
     694          98 :         if (poGeometry == nullptr)
     695             :         {
     696             :             // TODO: What?  Is this really a NOP?
     697             :         }
     698             : 
     699          53 :         else if (wkbFlatten(poGeometry->getGeometryType()) == wkbPoint)
     700             :         {
     701          12 :             OGRPoint *poPoint = poGeometry->toPoint();
     702             : 
     703          12 :             aoVertices.resize(1);
     704          12 :             aoVertices[0].x = poPoint->getX();
     705          12 :             aoVertices[0].y = poPoint->getY();
     706          12 :             aoVertices[0].z = poPoint->getZ();
     707             :         }
     708             : 
     709          41 :         else if (wkbFlatten(poGeometry->getGeometryType()) == wkbLineString)
     710             :         {
     711          11 :             OGRLineString *poLS = poGeometry->toLineString();
     712             :             unsigned int i;
     713             : 
     714          11 :             aoVertices.resize(poLS->getNumPoints());
     715             : 
     716          33 :             for (i = 0; i < aoVertices.size(); i++)
     717             :             {
     718          22 :                 aoVertices[i].x = poLS->getX(i);
     719          22 :                 aoVertices[i].y = poLS->getY(i);
     720          22 :                 aoVertices[i].z = poLS->getZ(i);
     721             :             }
     722             :         }
     723             : 
     724             :         else
     725             :         {
     726          30 :             CPLDebug("PCIDSK", "Unsupported geometry type in SetFeature(): %s",
     727          30 :                      poGeometry->getGeometryName());
     728             :         }
     729             : 
     730          98 :         poVecSeg->SetVertices(id, aoVertices);
     731             :     } /* try */
     732             : 
     733             :     /* -------------------------------------------------------------------- */
     734             :     /*      Trap exceptions and report as CPL errors.                       */
     735             :     /* -------------------------------------------------------------------- */
     736           0 :     catch (const PCIDSK::PCIDSKException &ex)
     737             :     {
     738           0 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", ex.what());
     739           0 :         return OGRERR_FAILURE;
     740             :     }
     741           0 :     catch (...)
     742             :     {
     743           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Non-PCIDSK exception trapped.");
     744           0 :         return OGRERR_FAILURE;
     745             :     }
     746             : 
     747          98 :     return OGRERR_NONE;
     748             : }
     749             : 
     750             : /************************************************************************/
     751             : /*                            CreateField()                             */
     752             : /************************************************************************/
     753             : 
     754         104 : OGRErr OGRPCIDSKLayer::CreateField(const OGRFieldDefn *poFieldDefn,
     755             :                                    int bApproxOK)
     756             : 
     757             : {
     758             :     try
     759             :     {
     760         104 :         if (poFieldDefn->GetType() == OFTInteger)
     761             :         {
     762          18 :             poVecSeg->AddField(poFieldDefn->GetNameRef(),
     763          18 :                                PCIDSK::FieldTypeInteger, "", "");
     764          18 :             poFeatureDefn->AddFieldDefn(poFieldDefn);
     765             :         }
     766          86 :         else if (poFieldDefn->GetType() == OFTReal)
     767             :         {
     768          18 :             poVecSeg->AddField(poFieldDefn->GetNameRef(),
     769          18 :                                PCIDSK::FieldTypeDouble, "", "");
     770          18 :             poFeatureDefn->AddFieldDefn(poFieldDefn);
     771             :         }
     772          68 :         else if (poFieldDefn->GetType() == OFTString)
     773             :         {
     774          42 :             poVecSeg->AddField(poFieldDefn->GetNameRef(),
     775          36 :                                PCIDSK::FieldTypeString, "", "");
     776          35 :             poFeatureDefn->AddFieldDefn(poFieldDefn);
     777             :         }
     778          32 :         else if (poFieldDefn->GetType() == OFTIntegerList)
     779             :         {
     780           0 :             poVecSeg->AddField(poFieldDefn->GetNameRef(),
     781           0 :                                PCIDSK::FieldTypeCountedInt, "", "");
     782           0 :             poFeatureDefn->AddFieldDefn(poFieldDefn);
     783             :         }
     784          32 :         else if (bApproxOK)
     785             :         {
     786             :             // Fallback to treating everything else as a string field.
     787          64 :             OGRFieldDefn oModFieldDefn(poFieldDefn);
     788          32 :             oModFieldDefn.SetType(OFTString);
     789          32 :             poVecSeg->AddField(poFieldDefn->GetNameRef(),
     790          32 :                                PCIDSK::FieldTypeString, "", "");
     791          32 :             poFeatureDefn->AddFieldDefn(&oModFieldDefn);
     792             :         }
     793             :         else
     794             :         {
     795           0 :             CPLError(CE_Failure, CPLE_AppDefined,
     796             :                      "Attempt to create field '%s' of unsupported data type.",
     797             :                      poFieldDefn->GetNameRef());
     798             :         }
     799             :     }
     800             : 
     801             :     /* -------------------------------------------------------------------- */
     802             :     /*      Trap exceptions and report as CPL errors.                       */
     803             :     /* -------------------------------------------------------------------- */
     804           1 :     catch (const PCIDSK::PCIDSKException &ex)
     805             :     {
     806           1 :         CPLError(CE_Failure, CPLE_AppDefined, "%s", ex.what());
     807           1 :         return OGRERR_FAILURE;
     808             :     }
     809           0 :     catch (...)
     810             :     {
     811           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Non-PCIDSK exception trapped.");
     812           0 :         return OGRERR_FAILURE;
     813             :     }
     814             : 
     815         103 :     m_oMapFieldNameToIdx[poFieldDefn->GetNameRef()] =
     816         103 :         poFeatureDefn->GetFieldCount() - 1;
     817             : 
     818         103 :     return OGRERR_NONE;
     819             : }

Generated by: LCOV version 1.14