Coverage Report

Created: 2025-06-09 07:42

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