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