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 : }
|