Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: Implements OGRGeoconceptLayer class.
5 : * Author: Didier Richard, didier.richard@ign.fr
6 : * Language: C++
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2007, Geoconcept and IGN
10 : * Copyright (c) 2008, Even Rouault <even dot rouault at spatialys.com>
11 : *
12 : * SPDX-License-Identifier: MIT
13 : ****************************************************************************/
14 :
15 : #include "cpl_conv.h"
16 : #include "cpl_string.h"
17 : #include "ogrgeoconceptlayer.h"
18 :
19 : /************************************************************************/
20 : /* OGRGeoconceptLayer() */
21 : /************************************************************************/
22 :
23 9 : OGRGeoconceptLayer::OGRGeoconceptLayer()
24 9 : : _poFeatureDefn(nullptr), _gcFeature(nullptr)
25 : {
26 9 : }
27 :
28 : /************************************************************************/
29 : /* ~OGRGeoconceptLayer() */
30 : /************************************************************************/
31 :
32 36 : OGRGeoconceptLayer::~OGRGeoconceptLayer()
33 :
34 : {
35 9 : if (_poFeatureDefn)
36 : {
37 18 : CPLDebug("GEOCONCEPT", "%ld features on layer %s.",
38 9 : GetSubTypeNbFeatures_GCIO(_gcFeature),
39 9 : _poFeatureDefn->GetName());
40 :
41 9 : _poFeatureDefn->Release();
42 : }
43 :
44 9 : _gcFeature = nullptr; /* deleted when OGCGeoconceptDatasource destroyed */
45 18 : }
46 :
47 : /************************************************************************/
48 : /* Open() */
49 : /************************************************************************/
50 :
51 9 : OGRErr OGRGeoconceptLayer::Open(GCSubType *Subclass)
52 :
53 : {
54 9 : _gcFeature = Subclass;
55 9 : if (GetSubTypeFeatureDefn_GCIO(_gcFeature))
56 : {
57 8 : _poFeatureDefn = reinterpret_cast<OGRFeatureDefn *>(
58 8 : GetSubTypeFeatureDefn_GCIO(_gcFeature));
59 8 : SetDescription(_poFeatureDefn->GetName());
60 8 : _poFeatureDefn->Reference();
61 : }
62 : else
63 : {
64 : char pszln[512];
65 1 : snprintf(pszln, 511, "%s.%s", GetSubTypeName_GCIO(_gcFeature),
66 1 : GetTypeName_GCIO(GetSubTypeType_GCIO(_gcFeature)));
67 1 : pszln[511] = '\0';
68 :
69 1 : _poFeatureDefn = new OGRFeatureDefn(pszln);
70 1 : SetDescription(_poFeatureDefn->GetName());
71 1 : _poFeatureDefn->Reference();
72 1 : _poFeatureDefn->SetGeomType(wkbUnknown);
73 :
74 1 : const int n = CountSubTypeFields_GCIO(_gcFeature);
75 1 : if (n > 0)
76 : {
77 : OGRFieldType oft;
78 8 : for (int i = 0; i < n; i++)
79 : {
80 7 : GCField *aField = GetSubTypeField_GCIO(_gcFeature, i);
81 7 : if (aField)
82 : {
83 7 : if (IsPrivateField_GCIO(aField))
84 7 : continue;
85 0 : switch (GetFieldKind_GCIO(aField))
86 : {
87 0 : case vIntFld_GCIO:
88 : case vPositionFld_GCIO:
89 0 : oft = OFTInteger;
90 0 : break;
91 0 : case vRealFld_GCIO:
92 : case vLengthFld_GCIO:
93 : case vAreaFld_GCIO:
94 0 : oft = OFTReal;
95 0 : break;
96 0 : case vDateFld_GCIO:
97 0 : oft = OFTDate;
98 0 : break;
99 0 : case vTimeFld_GCIO:
100 0 : oft = OFTTime;
101 0 : break;
102 0 : case vMemoFld_GCIO:
103 : case vChoiceFld_GCIO:
104 : case vInterFld_GCIO:
105 : default:
106 0 : oft = OFTString;
107 0 : break;
108 : }
109 0 : OGRFieldDefn ofd(GetFieldName_GCIO(aField), oft);
110 0 : _poFeatureDefn->AddFieldDefn(&ofd);
111 : }
112 : }
113 : }
114 1 : SetSubTypeFeatureDefn_GCIO(_gcFeature, (OGRFeatureDefnH)_poFeatureDefn);
115 1 : _poFeatureDefn->Reference();
116 : }
117 :
118 9 : if (_poFeatureDefn->GetGeomFieldCount() > 0)
119 9 : _poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(GetSpatialRef());
120 :
121 9 : return OGRERR_NONE;
122 : }
123 :
124 : /************************************************************************/
125 : /* ResetReading() */
126 : /************************************************************************/
127 :
128 6 : void OGRGeoconceptLayer::ResetReading()
129 :
130 : {
131 6 : Rewind_GCIO(GetSubTypeGCHandle_GCIO(_gcFeature), _gcFeature);
132 6 : }
133 :
134 : /************************************************************************/
135 : /* GetNextFeature() */
136 : /************************************************************************/
137 :
138 37 : OGRFeature *OGRGeoconceptLayer::GetNextFeature()
139 :
140 : {
141 37 : OGRFeature *poFeature = nullptr;
142 :
143 : for (;;)
144 : {
145 37 : if (!(poFeature = (OGRFeature *)ReadNextFeature_GCIO(_gcFeature)))
146 : {
147 : /*
148 : * As several features are embed in the Geoconcept file,
149 : * when reaching the end of the feature type, resetting
150 : * the reader would allow reading other features :
151 : * ogrinfo -ro export.gxt FT1 FT2 ...
152 : * will be all features for all features types !
153 : */
154 6 : Rewind_GCIO(GetSubTypeGCHandle_GCIO(_gcFeature), nullptr);
155 6 : break;
156 : }
157 62 : if ((m_poFilterGeom == nullptr ||
158 62 : FilterGeometry(poFeature->GetGeometryRef())) &&
159 31 : (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
160 : {
161 31 : break;
162 : }
163 0 : delete poFeature;
164 : }
165 :
166 130 : CPLDebug("GEOCONCEPT",
167 : "FID : " CPL_FRMT_GIB "\n"
168 : "%s : %s",
169 31 : poFeature ? poFeature->GetFID() : -1L,
170 31 : poFeature && poFeature->GetFieldCount() > 0
171 31 : ? poFeature->GetFieldDefnRef(0)->GetNameRef()
172 : : "-",
173 31 : poFeature && poFeature->GetFieldCount() > 0
174 31 : ? poFeature->GetFieldAsString(0)
175 : : "");
176 :
177 37 : return poFeature;
178 : }
179 :
180 : /************************************************************************/
181 : /* OGRGeoconceptLayer_GetCompatibleFieldName() */
182 : /************************************************************************/
183 :
184 15 : static char *OGRGeoconceptLayer_GetCompatibleFieldName(const char *pszName)
185 : {
186 15 : char *pszCompatibleName = CPLStrdup(pszName);
187 169 : for (int i = 0; pszCompatibleName[i] != 0; i++)
188 : {
189 154 : if (pszCompatibleName[i] == ' ')
190 0 : pszCompatibleName[i] = '_';
191 : }
192 15 : return pszCompatibleName;
193 : }
194 :
195 : /************************************************************************/
196 : /* ICreateFeature() */
197 : /************************************************************************/
198 :
199 2 : OGRErr OGRGeoconceptLayer::ICreateFeature(OGRFeature *poFeature)
200 :
201 : {
202 2 : OGRGeometry *poGeom = poFeature->GetGeometryRef();
203 :
204 2 : if (poGeom == nullptr)
205 : {
206 0 : CPLError(
207 : CE_Warning, CPLE_NotSupported,
208 : "NULL geometry not supported in Geoconcept, feature skipped.\n");
209 0 : return OGRERR_NONE;
210 : }
211 :
212 2 : OGRwkbGeometryType eGt = poGeom->getGeometryType();
213 2 : switch (wkbFlatten(eGt))
214 : {
215 2 : case wkbPoint:
216 : case wkbMultiPoint:
217 2 : if (GetSubTypeKind_GCIO(_gcFeature) == vUnknownItemType_GCIO)
218 : {
219 0 : SetSubTypeKind_GCIO(_gcFeature, vPoint_GCIO);
220 : }
221 2 : else if (GetSubTypeKind_GCIO(_gcFeature) != vPoint_GCIO)
222 : {
223 0 : CPLError(CE_Failure, CPLE_NotSupported,
224 : "Can't write non ponctual feature in a ponctual "
225 : "Geoconcept layer %s.\n",
226 0 : _poFeatureDefn->GetName());
227 0 : return OGRERR_FAILURE;
228 : }
229 2 : break;
230 0 : case wkbLineString:
231 : case wkbMultiLineString:
232 0 : if (GetSubTypeKind_GCIO(_gcFeature) == vUnknownItemType_GCIO)
233 : {
234 0 : SetSubTypeKind_GCIO(_gcFeature, vLine_GCIO);
235 : }
236 0 : else if (GetSubTypeKind_GCIO(_gcFeature) != vLine_GCIO)
237 : {
238 0 : CPLError(
239 : CE_Failure, CPLE_NotSupported,
240 : "Can't write non linear feature in a linear Geoconcept "
241 : "layer %s.\n",
242 0 : _poFeatureDefn->GetName());
243 0 : return OGRERR_FAILURE;
244 : }
245 0 : break;
246 0 : case wkbPolygon:
247 : case wkbMultiPolygon:
248 0 : if (GetSubTypeKind_GCIO(_gcFeature) == vUnknownItemType_GCIO)
249 : {
250 0 : SetSubTypeKind_GCIO(_gcFeature, vPoly_GCIO);
251 : }
252 0 : else if (GetSubTypeKind_GCIO(_gcFeature) != vPoly_GCIO)
253 : {
254 0 : CPLError(CE_Failure, CPLE_NotSupported,
255 : "Can't write non polygonal feature in a polygonal "
256 : "Geoconcept layer %s.\n",
257 0 : _poFeatureDefn->GetName());
258 0 : return OGRERR_FAILURE;
259 : }
260 0 : break;
261 0 : default:
262 0 : CPLError(CE_Warning, CPLE_AppDefined,
263 : "Geometry type %s not supported in Geoconcept, "
264 : "feature skipped.\n",
265 : OGRGeometryTypeToName(eGt));
266 0 : return OGRERR_NONE;
267 : }
268 2 : if (GetSubTypeDim_GCIO(_gcFeature) == vUnknown3D_GCIO)
269 : {
270 0 : if (poGeom->getCoordinateDimension() == 3)
271 : {
272 0 : SetSubTypeDim_GCIO(_gcFeature, v3D_GCIO);
273 : }
274 : else
275 : {
276 0 : SetSubTypeDim_GCIO(_gcFeature, v2D_GCIO);
277 : }
278 : }
279 :
280 2 : int nbGeom = 0;
281 2 : bool isSingle = false;
282 :
283 2 : switch (wkbFlatten(eGt))
284 : {
285 2 : case wkbPoint:
286 : case wkbLineString:
287 : case wkbPolygon:
288 2 : nbGeom = 1;
289 2 : isSingle = true;
290 2 : break;
291 0 : case wkbMultiPoint:
292 : case wkbMultiLineString:
293 : case wkbMultiPolygon:
294 0 : nbGeom = poGeom->toGeometryCollection()->getNumGeometries();
295 0 : isSingle = false;
296 0 : break;
297 0 : default:
298 0 : nbGeom = 0;
299 0 : isSingle = false;
300 0 : break;
301 : }
302 :
303 : /* 1st feature, let's write header : */
304 4 : if (GetGCMode_GCIO(GetSubTypeGCHandle_GCIO(_gcFeature)) ==
305 4 : vWriteAccess_GCIO &&
306 2 : GetFeatureCount(TRUE) == 0)
307 1 : if (WriteHeader_GCIO(GetSubTypeGCHandle_GCIO(_gcFeature)) == nullptr)
308 : {
309 0 : return OGRERR_FAILURE;
310 : }
311 :
312 2 : if (nbGeom > 0)
313 : {
314 4 : for (int iGeom = 0; iGeom < nbGeom; iGeom++)
315 : {
316 4 : int nextField = StartWritingFeature_GCIO(
317 : _gcFeature,
318 2 : isSingle ? static_cast<int>(poFeature->GetFID()) : OGRNullFID);
319 10 : while (nextField != WRITECOMPLETED_GCIO)
320 : {
321 8 : if (nextField == WRITEERROR_GCIO)
322 : {
323 0 : return OGRERR_FAILURE;
324 : }
325 8 : if (nextField == GEOMETRYEXPECTED_GCIO)
326 : {
327 : OGRGeometry *poGeomPart =
328 : isSingle
329 2 : ? poGeom
330 0 : : poGeom->toGeometryCollection()->getGeometryRef(
331 2 : iGeom);
332 2 : nextField = WriteFeatureGeometry_GCIO(
333 : _gcFeature, (OGRGeometryH)poGeomPart);
334 : }
335 : else
336 : {
337 : GCField *theField =
338 6 : GetSubTypeField_GCIO(_gcFeature, nextField);
339 : /* for each field, find out its mapping ... */
340 6 : int nF = poFeature->GetFieldCount();
341 6 : if (nF > 0)
342 : {
343 6 : int iF = 0;
344 12 : for (; iF < nF; iF++)
345 : {
346 : OGRFieldDefn *poField =
347 12 : poFeature->GetFieldDefnRef(iF);
348 : char *pszName =
349 12 : OGRGeoconceptLayer_GetCompatibleFieldName(
350 : poField->GetNameRef());
351 12 : if (EQUAL(pszName, GetFieldName_GCIO(theField)))
352 : {
353 6 : CPLFree(pszName);
354 6 : nextField = WriteFeatureFieldAsString_GCIO(
355 : _gcFeature, nextField,
356 6 : poFeature->IsFieldSetAndNotNull(iF)
357 5 : ? poFeature->GetFieldAsString(iF)
358 : : nullptr);
359 6 : break;
360 : }
361 6 : CPLFree(pszName);
362 : }
363 6 : if (iF == nF)
364 : {
365 0 : CPLError(CE_Failure, CPLE_AppDefined,
366 : "Can't find a field attached to %s on "
367 : "Geoconcept layer %s.\n",
368 : GetFieldName_GCIO(theField),
369 0 : _poFeatureDefn->GetName());
370 0 : return OGRERR_FAILURE;
371 : }
372 : }
373 : else
374 : {
375 0 : nextField = WRITECOMPLETED_GCIO;
376 : }
377 : }
378 : }
379 2 : StopWritingFeature_GCIO(_gcFeature);
380 : }
381 : }
382 :
383 2 : return OGRERR_NONE;
384 : }
385 :
386 : /************************************************************************/
387 : /* GetSpatialRef() */
388 : /************************************************************************/
389 :
390 12 : OGRSpatialReference *OGRGeoconceptLayer::GetSpatialRef()
391 :
392 : {
393 12 : GCExportFileH *hGXT = GetSubTypeGCHandle_GCIO(_gcFeature);
394 12 : if (!hGXT)
395 0 : return nullptr;
396 12 : GCExportFileMetadata *Meta = GetGCMeta_GCIO(hGXT);
397 12 : if (!Meta)
398 0 : return nullptr;
399 12 : return (OGRSpatialReference *)GetMetaSRS_GCIO(Meta);
400 : }
401 :
402 : /************************************************************************/
403 : /* GetFeatureCount() */
404 : /* */
405 : /* If a spatial filter is in effect, we turn control over to */
406 : /* the generic counter. Otherwise we return the total count. */
407 : /************************************************************************/
408 :
409 7 : GIntBig OGRGeoconceptLayer::GetFeatureCount(int bForce)
410 :
411 : {
412 7 : if (m_poFilterGeom != nullptr || m_poAttrQuery != nullptr)
413 0 : return OGRLayer::GetFeatureCount(bForce);
414 :
415 7 : return GetSubTypeNbFeatures_GCIO(_gcFeature);
416 : }
417 :
418 : /************************************************************************/
419 : /* GetExtent() */
420 : /************************************************************************/
421 :
422 0 : OGRErr OGRGeoconceptLayer::GetExtent(OGREnvelope *psExtent,
423 : CPL_UNUSED int bForce)
424 : {
425 0 : GCExtent *theExtent = GetSubTypeExtent_GCIO(_gcFeature);
426 0 : if (!theExtent)
427 0 : return OGRERR_FAILURE;
428 0 : psExtent->MinX = GetExtentULAbscissa_GCIO(theExtent);
429 0 : psExtent->MinY = GetExtentLROrdinate_GCIO(theExtent);
430 0 : psExtent->MaxX = GetExtentLRAbscissa_GCIO(theExtent);
431 0 : psExtent->MaxY = GetExtentULOrdinate_GCIO(theExtent);
432 :
433 0 : return OGRERR_NONE;
434 : }
435 :
436 : /************************************************************************/
437 : /* TestCapability() */
438 : /************************************************************************/
439 :
440 2 : int OGRGeoconceptLayer::TestCapability(const char *pszCap)
441 :
442 : {
443 2 : if (EQUAL(pszCap, OLCRandomRead))
444 0 : return FALSE; // the GetFeature() method does not work for this layer.
445 : // TODO
446 :
447 2 : else if (EQUAL(pszCap, OLCSequentialWrite))
448 0 : return TRUE; // the CreateFeature() method works for this layer.
449 :
450 2 : else if (EQUAL(pszCap, OLCRandomWrite))
451 0 : return FALSE; // the SetFeature() method is not operational on this
452 : // layer.
453 :
454 2 : else if (EQUAL(pszCap, OLCFastSpatialFilter))
455 0 : return FALSE; // this layer does not implement spatial filtering
456 : // efficiently.
457 :
458 2 : else if (EQUAL(pszCap, OLCFastFeatureCount))
459 0 : return FALSE; // this layer can not return a feature count efficiently.
460 : // FIXME
461 :
462 2 : else if (EQUAL(pszCap, OLCFastGetExtent))
463 0 : return FALSE; // this layer can not return its data extent efficiently.
464 : // FIXME
465 :
466 2 : else if (EQUAL(pszCap, OLCFastSetNextByIndex))
467 0 : return FALSE; // this layer can not perform the SetNextByIndex() call
468 : // efficiently.
469 :
470 2 : else if (EQUAL(pszCap, OLCDeleteFeature))
471 0 : return FALSE;
472 :
473 2 : else if (EQUAL(pszCap, OLCCreateField))
474 0 : return TRUE;
475 :
476 2 : else if (EQUAL(pszCap, OLCZGeometries))
477 0 : return TRUE;
478 :
479 2 : return FALSE;
480 : }
481 :
482 : /************************************************************************/
483 : /* CreateField() */
484 : /************************************************************************/
485 :
486 3 : OGRErr OGRGeoconceptLayer::CreateField(const OGRFieldDefn *poField,
487 : CPL_UNUSED int bApproxOK)
488 : {
489 3 : if (GetGCMode_GCIO(GetSubTypeGCHandle_GCIO(_gcFeature)) == vReadAccess_GCIO)
490 : {
491 0 : CPLError(CE_Failure, CPLE_NotSupported,
492 : "Can't create fields on a read-only Geoconcept layer.\n");
493 0 : return OGRERR_FAILURE;
494 : }
495 :
496 : /* -------------------------------------------------------------------- */
497 : /* Add field to layer */
498 : /* -------------------------------------------------------------------- */
499 :
500 : {
501 : /* check whether field exists ... */
502 : char *pszName =
503 3 : OGRGeoconceptLayer_GetCompatibleFieldName(poField->GetNameRef());
504 :
505 3 : GCField *theField = FindFeatureField_GCIO(_gcFeature, pszName);
506 3 : if (!theField)
507 : {
508 3 : if (GetFeatureCount(TRUE) > 0)
509 : {
510 0 : CPLError(CE_Failure, CPLE_NotSupported,
511 : "Can't create field '%s' on existing Geoconcept layer "
512 : "'%s.%s'.\n",
513 0 : pszName, GetSubTypeName_GCIO(_gcFeature),
514 0 : GetTypeName_GCIO(GetSubTypeType_GCIO(_gcFeature)));
515 0 : CPLFree(pszName);
516 0 : return OGRERR_FAILURE;
517 : }
518 3 : if (GetSubTypeNbFields_GCIO(_gcFeature) == -1)
519 1 : SetSubTypeNbFields_GCIO(_gcFeature, 0L);
520 3 : if (!(theField = AddSubTypeField_GCIO(
521 3 : GetSubTypeGCHandle_GCIO(_gcFeature),
522 3 : GetTypeName_GCIO(GetSubTypeType_GCIO(_gcFeature)),
523 3 : GetSubTypeName_GCIO(_gcFeature),
524 6 : FindFeatureFieldIndex_GCIO(_gcFeature, kNbFields_GCIO) +
525 3 : GetSubTypeNbFields_GCIO(_gcFeature) + 1,
526 3 : pszName, GetSubTypeNbFields_GCIO(_gcFeature) - 999L,
527 : vUnknownItemType_GCIO, nullptr, nullptr)))
528 : {
529 0 : CPLError(CE_Failure, CPLE_AppDefined,
530 : "Field '%s' could not be created for Feature %s.%s.\n",
531 0 : pszName, GetSubTypeName_GCIO(_gcFeature),
532 0 : GetTypeName_GCIO(GetSubTypeType_GCIO(_gcFeature)));
533 0 : CPLFree(pszName);
534 0 : return OGRERR_FAILURE;
535 : }
536 3 : SetSubTypeNbFields_GCIO(_gcFeature,
537 : GetSubTypeNbFields_GCIO(_gcFeature) + 1);
538 3 : _poFeatureDefn->AddFieldDefn(poField);
539 : }
540 : else
541 : {
542 0 : if (_poFeatureDefn->GetFieldIndex(GetFieldName_GCIO(theField)) ==
543 : -1)
544 : {
545 0 : CPLError(CE_Failure, CPLE_AppDefined,
546 : "Field %s not found for Feature %s.%s.\n",
547 : GetFieldName_GCIO(theField),
548 0 : GetSubTypeName_GCIO(_gcFeature),
549 0 : GetTypeName_GCIO(GetSubTypeType_GCIO(_gcFeature)));
550 0 : CPLFree(pszName);
551 0 : return OGRERR_FAILURE;
552 : }
553 : }
554 :
555 3 : CPLFree(pszName);
556 3 : pszName = nullptr;
557 :
558 : /* check/update type ? */
559 3 : if (GetFieldKind_GCIO(theField) == vUnknownItemType_GCIO)
560 : {
561 3 : switch (poField->GetType())
562 : {
563 0 : case OFTInteger:
564 0 : SetFieldKind_GCIO(theField, vIntFld_GCIO);
565 0 : break;
566 0 : case OFTReal:
567 0 : SetFieldKind_GCIO(theField, vRealFld_GCIO);
568 0 : break;
569 0 : case OFTDate:
570 0 : SetFieldKind_GCIO(theField, vDateFld_GCIO);
571 0 : break;
572 0 : case OFTTime:
573 : case OFTDateTime:
574 0 : SetFieldKind_GCIO(theField, vTimeFld_GCIO);
575 0 : break;
576 3 : case OFTString:
577 3 : SetFieldKind_GCIO(theField, vMemoFld_GCIO);
578 3 : break;
579 0 : case OFTIntegerList:
580 : case OFTRealList:
581 : case OFTStringList:
582 : case OFTBinary:
583 : default:
584 0 : CPLError(CE_Failure, CPLE_NotSupported,
585 : "Can't create fields of type %s on Geoconcept "
586 : "feature %s.\n",
587 : OGRFieldDefn::GetFieldTypeName(poField->GetType()),
588 0 : _poFeatureDefn->GetName());
589 0 : return OGRERR_FAILURE;
590 : }
591 : }
592 : }
593 :
594 3 : return OGRERR_NONE;
595 : }
596 :
597 : /************************************************************************/
598 : /* SyncToDisk() */
599 : /************************************************************************/
600 :
601 0 : OGRErr OGRGeoconceptLayer::SyncToDisk()
602 :
603 : {
604 0 : FFlush_GCIO(GetSubTypeGCHandle_GCIO(_gcFeature));
605 0 : return OGRERR_NONE;
606 : }
607 :
608 : /************************************************************************/
609 : /* SetSpatialRef() */
610 : /************************************************************************/
611 :
612 1 : void OGRGeoconceptLayer::SetSpatialRef(OGRSpatialReference *poSpatialRef)
613 :
614 : {
615 1 : OGRSpatialReference *poSRS = GetSpatialRef();
616 : /*-----------------------------------------------------------------
617 : * Keep a copy of the OGRSpatialReference...
618 : * Note: we have to take the reference count into account...
619 : *----------------------------------------------------------------*/
620 1 : if (poSRS && poSRS->Dereference() == 0)
621 0 : delete poSRS;
622 :
623 1 : if (!poSpatialRef)
624 0 : return;
625 :
626 1 : poSRS = poSpatialRef->Clone();
627 1 : poSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
628 1 : GCExportFileH *hGXT = GetSubTypeGCHandle_GCIO(_gcFeature);
629 1 : if (!hGXT)
630 : {
631 0 : delete poSRS;
632 0 : return;
633 : }
634 1 : GCExportFileMetadata *Meta = GetGCMeta_GCIO(hGXT);
635 1 : if (!Meta)
636 : {
637 0 : delete poSRS;
638 0 : return;
639 : }
640 1 : GCSysCoord *os = GetMetaSysCoord_GCIO(Meta);
641 1 : GCSysCoord *ns = OGRSpatialReference2SysCoord_GCSRS(
642 1 : reinterpret_cast<OGRSpatialReferenceH>(poSRS));
643 :
644 1 : if (os && ns && GetSysCoordSystemID_GCSRS(os) != -1 &&
645 0 : (GetSysCoordSystemID_GCSRS(os) != GetSysCoordSystemID_GCSRS(ns) ||
646 0 : GetSysCoordTimeZone_GCSRS(os) != GetSysCoordTimeZone_GCSRS(ns)))
647 : {
648 0 : CPLError(CE_Warning, CPLE_AppDefined,
649 : "Can't change SRS on Geoconcept layers.\n");
650 0 : DestroySysCoord_GCSRS(&ns);
651 0 : delete poSRS;
652 0 : return;
653 : }
654 :
655 1 : if (os)
656 0 : DestroySysCoord_GCSRS(&os);
657 1 : SetMetaSysCoord_GCIO(Meta, ns);
658 1 : SetMetaSRS_GCIO(Meta, (OGRSpatialReferenceH)poSRS);
659 1 : return;
660 : }
|