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

Generated by: LCOV version 1.14