1 /******************************************************************************
2  *
3  * Project:  OpenGIS Simple Features Reference Implementation
4  * Purpose:  The OGRGeomFieldDefn class implementation.
5  * Author:   Even Rouault, <even dot rouault at spatialys.com>
6  *
7  ******************************************************************************
8  * Copyright (c) 2013, Even Rouault <even dot rouault at spatialys.com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #include "cpl_port.h"
30 #include "ogr_api.h"
31 
32 #include <cstring>
33 
34 #include "cpl_conv.h"
35 #include "cpl_error.h"
36 #include "ogr_core.h"
37 #include "ogr_feature.h"
38 #include "ogr_p.h"
39 #include "ogr_spatialref.h"
40 #include "ogr_srs_api.h"
41 #include "ograpispy.h"
42 
43 CPL_CVSID("$Id: ogrgeomfielddefn.cpp b55a33407a80673ec314b165c82f47dd02e9dc9c 2020-04-27 20:37:55 +0200 Even Rouault $")
44 
45 /************************************************************************/
46 /*                         OGRGeomFieldDefn()                           */
47 /************************************************************************/
48 
49 /**
50  * \brief Constructor.
51  *
52  * @param pszNameIn the name of the new field.
53  * @param eGeomTypeIn the type of the new field.
54  *
55  * @since GDAL 1.11
56  */
57 
OGRGeomFieldDefn(const char * pszNameIn,OGRwkbGeometryType eGeomTypeIn)58 OGRGeomFieldDefn::OGRGeomFieldDefn( const char * pszNameIn,
59                                     OGRwkbGeometryType eGeomTypeIn )
60 
61 {
62     Initialize( pszNameIn, eGeomTypeIn );
63 }
64 
65 /************************************************************************/
66 /*                          OGRGeomFieldDefn()                          */
67 /************************************************************************/
68 
69 /**
70  * \brief Constructor.
71  *
72  * Create by cloning an existing geometry field definition.
73  *
74  * @param poPrototype the geometry field definition to clone.
75  *
76  * @since GDAL 1.11
77  */
78 
OGRGeomFieldDefn(const OGRGeomFieldDefn * poPrototype)79 OGRGeomFieldDefn::OGRGeomFieldDefn( const OGRGeomFieldDefn *poPrototype )
80 
81 {
82     Initialize( poPrototype->GetNameRef(), poPrototype->GetType() );
83     auto l_poSRS = poPrototype->GetSpatialRef();
84     if( l_poSRS )
85     {
86         l_poSRS = l_poSRS->Clone();
87         SetSpatialRef( l_poSRS );
88         l_poSRS->Release();
89     }
90     SetNullable( poPrototype->IsNullable() );
91 }
92 
93 /************************************************************************/
94 /*                           OGR_GFld_Create()                          */
95 /************************************************************************/
96 /**
97  * \brief Create a new field geometry definition.
98  *
99  * This function is the same as the CPP method
100  * OGRGeomFieldDefn::OGRGeomFieldDefn().
101  *
102  * @param pszName the name of the new field definition.
103  * @param eType the type of the new field definition.
104  * @return handle to the new field definition.
105  *
106  * @since GDAL 1.11
107  */
108 
OGR_GFld_Create(const char * pszName,OGRwkbGeometryType eType)109 OGRGeomFieldDefnH OGR_GFld_Create( const char *pszName,
110                                    OGRwkbGeometryType eType )
111 
112 {
113   return
114       OGRGeomFieldDefn::ToHandle(new OGRGeomFieldDefn(pszName, eType));
115 }
116 
117 /************************************************************************/
118 /*                             Initialize()                             */
119 /************************************************************************/
120 
121 //! @cond Doxygen_Suppress
Initialize(const char * pszNameIn,OGRwkbGeometryType eTypeIn)122 void OGRGeomFieldDefn::Initialize( const char * pszNameIn,
123                                    OGRwkbGeometryType eTypeIn )
124 
125 {
126     pszName = CPLStrdup( pszNameIn );
127     eGeomType = eTypeIn;
128 }
129 //! @endcond
130 
131 /************************************************************************/
132 /*                         ~OGRGeomFieldDefn()                          */
133 /************************************************************************/
134 
~OGRGeomFieldDefn()135 OGRGeomFieldDefn::~OGRGeomFieldDefn()
136 
137 {
138     CPLFree( pszName );
139 
140     if( nullptr != poSRS )
141         poSRS->Release();
142 }
143 
144 /************************************************************************/
145 /*                         OGR_GFld_Destroy()                           */
146 /************************************************************************/
147 /**
148  * \brief Destroy a geometry field definition.
149  *
150  * @param hDefn handle to the geometry field definition to destroy.
151  *
152  * @since GDAL 1.11
153  */
154 
OGR_GFld_Destroy(OGRGeomFieldDefnH hDefn)155 void OGR_GFld_Destroy( OGRGeomFieldDefnH hDefn )
156 
157 {
158     VALIDATE_POINTER0( hDefn, "OGR_GFld_Destroy" );
159 
160     delete OGRGeomFieldDefn::FromHandle(hDefn);
161 }
162 
163 /************************************************************************/
164 /*                              SetName()                               */
165 /************************************************************************/
166 
167 /**
168  * \brief Reset the name of this field.
169  *
170  * This method is the same as the C function OGR_GFld_SetName().
171  *
172  * @param pszNameIn the new name to apply.
173  *
174  * @since GDAL 1.11
175  */
176 
SetName(const char * pszNameIn)177 void OGRGeomFieldDefn::SetName( const char * pszNameIn )
178 
179 {
180     if( pszName != pszNameIn )
181     {
182         CPLFree( pszName );
183         pszName = CPLStrdup( pszNameIn );
184     }
185 }
186 
187 /************************************************************************/
188 /*                         OGR_GFld_SetName()                           */
189 /************************************************************************/
190 /**
191  * \brief Reset the name of this field.
192  *
193  * This function is the same as the CPP method OGRGeomFieldDefn::SetName().
194  *
195  * @param hDefn handle to the geometry field definition to apply the
196  * new name to.
197  * @param pszName the new name to apply.
198  *
199  * @since GDAL 1.11
200  */
201 
OGR_GFld_SetName(OGRGeomFieldDefnH hDefn,const char * pszName)202 void OGR_GFld_SetName( OGRGeomFieldDefnH hDefn, const char *pszName )
203 
204 {
205     VALIDATE_POINTER0( hDefn, "OGR_GFld_SetName" );
206 
207     OGRGeomFieldDefn::FromHandle(hDefn)->SetName(pszName);
208 }
209 
210 /************************************************************************/
211 /*                             GetNameRef()                             */
212 /************************************************************************/
213 
214 /**
215  * \fn const char *OGRGeomFieldDefn::GetNameRef();
216  *
217  * \brief Fetch name of this field.
218  *
219  * This method is the same as the C function OGR_GFld_GetNameRef().
220  *
221  * @return pointer to an internal name string that should not be freed or
222  * modified.
223  *
224  * @since GDAL 1.11
225  */
226 
227 /************************************************************************/
228 /*                        OGR_GFld_GetNameRef()                         */
229 /************************************************************************/
230 /**
231  * \brief Fetch name of this field.
232  *
233  * This function is the same as the CPP method OGRGeomFieldDefn::GetNameRef().
234  *
235  * @param hDefn handle to the geometry field definition.
236  * @return the name of the geometry field definition.
237  *
238  * @since GDAL 1.11
239  */
240 
OGR_GFld_GetNameRef(OGRGeomFieldDefnH hDefn)241 const char *OGR_GFld_GetNameRef( OGRGeomFieldDefnH hDefn )
242 
243 {
244     VALIDATE_POINTER1( hDefn, "OGR_GFld_GetNameRef", "" );
245 
246 #ifdef OGRAPISPY_ENABLED
247     if( bOGRAPISpyEnabled )
248         OGRAPISpy_GFld_GetXXXX(hDefn, "GetNameRef");
249 #endif
250 
251     return OGRGeomFieldDefn::FromHandle(hDefn)->GetNameRef();
252 }
253 
254 /************************************************************************/
255 /*                              GetType()                               */
256 /************************************************************************/
257 
258 /**
259  * \fn OGRwkbGeometryType OGRGeomFieldDefn::GetType() const;
260  *
261  * \brief Fetch geometry type of this field.
262  *
263  * This method is the same as the C function OGR_GFld_GetType().
264  *
265  * @return field geometry type.
266  *
267  * @since GDAL 1.11
268  */
269 
270 /************************************************************************/
271 /*                          OGR_GFld_GetType()                          */
272 /************************************************************************/
273 /**
274  * \brief Fetch geometry type of this field.
275  *
276  * This function is the same as the CPP method OGRGeomFieldDefn::GetType().
277  *
278  * @param hDefn handle to the geometry field definition to get type from.
279  * @return field geometry type.
280  *
281  * @since GDAL 1.11
282  */
283 
OGR_GFld_GetType(OGRGeomFieldDefnH hDefn)284 OGRwkbGeometryType OGR_GFld_GetType( OGRGeomFieldDefnH hDefn )
285 
286 {
287     VALIDATE_POINTER1( hDefn, "OGR_GFld_GetType", wkbUnknown );
288 
289 #ifdef OGRAPISPY_ENABLED
290     if( bOGRAPISpyEnabled )
291         OGRAPISpy_GFld_GetXXXX(hDefn, "GetType");
292 #endif
293 
294     OGRwkbGeometryType eType =
295         OGRGeomFieldDefn::FromHandle(hDefn)->GetType();
296     if( OGR_GT_IsNonLinear(eType) && !OGRGetNonLinearGeometriesEnabledFlag() )
297     {
298         eType = OGR_GT_GetLinear(eType);
299     }
300     return eType;
301 }
302 
303 /************************************************************************/
304 /*                              SetType()                               */
305 /************************************************************************/
306 
307 /**
308  * \brief Set the geometry type of this field.
309  * This should never be done to an OGRGeomFieldDefn
310  * that is already part of an OGRFeatureDefn.
311  *
312  * This method is the same as the C function OGR_GFld_SetType().
313  *
314  * @param eTypeIn the new field geometry type.
315  *
316  * @since GDAL 1.11
317  */
318 
SetType(OGRwkbGeometryType eTypeIn)319 void OGRGeomFieldDefn::SetType( OGRwkbGeometryType eTypeIn )
320 
321 {
322     eGeomType = eTypeIn;
323 }
324 
325 /************************************************************************/
326 /*                          OGR_GFld_SetType()                          */
327 /************************************************************************/
328 /**
329  * \brief Set the geometry type of this field.
330  * This should never be done to an OGRGeomFieldDefn
331  * that is already part of an OGRFeatureDefn.
332  *
333  * This function is the same as the CPP method OGRGeomFieldDefn::SetType().
334  *
335  * @param hDefn handle to the geometry field definition to set type to.
336  * @param eType the new field geometry type.
337  *
338  * @since GDAL 1.11
339  */
340 
OGR_GFld_SetType(OGRGeomFieldDefnH hDefn,OGRwkbGeometryType eType)341 void OGR_GFld_SetType( OGRGeomFieldDefnH hDefn, OGRwkbGeometryType eType )
342 
343 {
344     VALIDATE_POINTER0( hDefn, "OGR_GFld_SetType" );
345 
346     OGRGeomFieldDefn::FromHandle(hDefn)->SetType(eType);
347 }
348 
349 /************************************************************************/
350 /*                             IsIgnored()                              */
351 /************************************************************************/
352 
353 /**
354  * \fn int OGRGeomFieldDefn::IsIgnored() const;
355  *
356  * \brief Return whether this field should be omitted when fetching features
357  *
358  * This method is the same as the C function OGR_GFld_IsIgnored().
359  *
360  * @return ignore state
361  *
362  * @since GDAL 1.11
363  */
364 
365 /************************************************************************/
366 /*                         OGR_GFld_IsIgnored()                         */
367 /************************************************************************/
368 
369 /**
370  * \brief Return whether this field should be omitted when fetching features
371  *
372  * This method is the same as the C++ method OGRGeomFieldDefn::IsIgnored().
373  *
374  * @param hDefn handle to the geometry field definition
375  * @return ignore state
376  *
377  * @since GDAL 1.11
378  */
379 
OGR_GFld_IsIgnored(OGRGeomFieldDefnH hDefn)380 int OGR_GFld_IsIgnored( OGRGeomFieldDefnH hDefn )
381 {
382     VALIDATE_POINTER1( hDefn, "OGR_GFld_IsIgnored", FALSE );
383 
384     return OGRGeomFieldDefn::FromHandle(hDefn)->IsIgnored();
385 }
386 
387 /************************************************************************/
388 /*                            SetIgnored()                              */
389 /************************************************************************/
390 
391 /**
392  * \fn void OGRGeomFieldDefn::SetIgnored( int ignore );
393  *
394  * \brief Set whether this field should be omitted when fetching features
395  *
396  * This method is the same as the C function OGR_GFld_SetIgnored().
397  *
398  * @param ignore ignore state
399  *
400  * @since GDAL 1.11
401  */
402 
403 /************************************************************************/
404 /*                        OGR_GFld_SetIgnored()                         */
405 /************************************************************************/
406 
407 /**
408  * \brief Set whether this field should be omitted when fetching features
409  *
410  * This method is the same as the C++ method OGRGeomFieldDefn::SetIgnored().
411  *
412  * @param hDefn handle to the geometry field definition
413  * @param ignore ignore state
414  *
415  * @since GDAL 1.11
416  */
417 
OGR_GFld_SetIgnored(OGRGeomFieldDefnH hDefn,int ignore)418 void OGR_GFld_SetIgnored( OGRGeomFieldDefnH hDefn, int ignore )
419 {
420     VALIDATE_POINTER0( hDefn, "OGR_GFld_SetIgnored" );
421 
422     OGRGeomFieldDefn::FromHandle(hDefn)->SetIgnored(ignore);
423 }
424 
425 /************************************************************************/
426 /*                           GetSpatialRef()                            */
427 /************************************************************************/
428 /**
429  * \brief Fetch spatial reference system of this field.
430  *
431  * This method is the same as the C function OGR_GFld_GetSpatialRef().
432  *
433  * @return field spatial reference system.
434  *
435  * @since GDAL 1.11
436  */
437 
GetSpatialRef() const438 OGRSpatialReference* OGRGeomFieldDefn::GetSpatialRef() const
439 {
440     return poSRS;
441 }
442 
443 /************************************************************************/
444 /*                       OGR_GFld_GetSpatialRef()                       */
445 /************************************************************************/
446 
447 /**
448  * \brief Fetch spatial reference system of this field.
449  *
450  * This function is the same as the C++ method
451  * OGRGeomFieldDefn::GetSpatialRef().
452  *
453  * @param hDefn handle to the geometry field definition
454  *
455  * @return field spatial reference system.
456  *
457  * @since GDAL 1.11
458  */
459 
OGR_GFld_GetSpatialRef(OGRGeomFieldDefnH hDefn)460 OGRSpatialReferenceH OGR_GFld_GetSpatialRef( OGRGeomFieldDefnH hDefn )
461 {
462     VALIDATE_POINTER1( hDefn, "OGR_GFld_GetSpatialRef", nullptr );
463 
464 #ifdef OGRAPISPY_ENABLED
465     if( bOGRAPISpyEnabled )
466         OGRAPISpy_GFld_GetXXXX(hDefn, "GetSpatialRef");
467 #endif
468 
469     return reinterpret_cast<OGRSpatialReferenceH>(
470         OGRGeomFieldDefn::FromHandle(hDefn)->GetSpatialRef());
471 }
472 
473 /************************************************************************/
474 /*                           SetSpatialRef()                            */
475 /************************************************************************/
476 
477 /**
478  * \brief Set the spatial reference of this field.
479  *
480  * This method is the same as the C function OGR_GFld_SetSpatialRef().
481  *
482  * This method drops the reference of the previously set SRS object and
483  * acquires a new reference on the passed object (if non-NULL).
484  *
485  * @param poSRSIn the new SRS to apply.
486  *
487  * @since GDAL 1.11
488  */
SetSpatialRef(OGRSpatialReference * poSRSIn)489 void OGRGeomFieldDefn::SetSpatialRef(OGRSpatialReference* poSRSIn)
490 {
491     if( poSRS != nullptr )
492         poSRS->Release();
493     poSRS = poSRSIn;
494     if( poSRS != nullptr )
495         poSRS->Reference();
496 }
497 
498 /************************************************************************/
499 /*                       OGR_GFld_SetSpatialRef()                       */
500 /************************************************************************/
501 
502 /**
503  * \brief Set the spatial reference of this field.
504  *
505  * This function is the same as the C++ method
506  * OGRGeomFieldDefn::SetSpatialRef().
507  *
508  * This function drops the reference of the previously set SRS object and
509  * acquires a new reference on the passed object (if non-NULL).
510  *
511  * @param hDefn handle to the geometry field definition
512  * @param hSRS the new SRS to apply.
513  *
514  * @since GDAL 1.11
515  */
516 
OGR_GFld_SetSpatialRef(OGRGeomFieldDefnH hDefn,OGRSpatialReferenceH hSRS)517 void OGR_GFld_SetSpatialRef( OGRGeomFieldDefnH hDefn,
518                              OGRSpatialReferenceH hSRS )
519 {
520     VALIDATE_POINTER0( hDefn, "OGR_GFld_SetSpatialRef" );
521 
522     OGRGeomFieldDefn::FromHandle(hDefn)->
523         SetSpatialRef(reinterpret_cast<OGRSpatialReference *>(hSRS));
524 }
525 
526 /************************************************************************/
527 /*                             IsSame()                                 */
528 /************************************************************************/
529 
530 /**
531  * \brief Test if the geometry field definition is identical to the other one.
532  *
533  * @param poOtherFieldDefn the other field definition to compare to.
534  * @return TRUE if the geometry field definition is identical to the other one.
535  *
536  * @since GDAL 1.11
537  */
538 
IsSame(const OGRGeomFieldDefn * poOtherFieldDefn) const539 int OGRGeomFieldDefn::IsSame( const OGRGeomFieldDefn * poOtherFieldDefn ) const
540 {
541     if( !(strcmp(GetNameRef(), poOtherFieldDefn->GetNameRef()) == 0 &&
542                  GetType() == poOtherFieldDefn->GetType() &&
543                  IsNullable() == poOtherFieldDefn->IsNullable()) )
544         return FALSE;
545     OGRSpatialReference* poMySRS = GetSpatialRef();
546     OGRSpatialReference* poOtherSRS = poOtherFieldDefn->GetSpatialRef();
547     return ((poMySRS == poOtherSRS) ||
548             (poMySRS != nullptr && poOtherSRS != nullptr &&
549              poMySRS->IsSame(poOtherSRS)));
550 }
551 
552 /************************************************************************/
553 /*                             IsNullable()                             */
554 /************************************************************************/
555 
556 /**
557  * \fn int OGRGeomFieldDefn::IsNullable() const
558  *
559  * \brief Return whether this geometry field can receive null values.
560  *
561  * By default, fields are nullable.
562  *
563  * Even if this method returns FALSE (i.e not-nullable field), it doesn't mean
564  * that OGRFeature::IsFieldSet() will necessary return TRUE, as fields can be
565  * temporary unset and null/not-null validation is usually done when
566  * OGRLayer::CreateFeature()/SetFeature() is called.
567  *
568  * Note that not-nullable geometry fields might also contain 'empty' geometries.
569  *
570  * This method is the same as the C function OGR_GFld_IsNullable().
571  *
572  * @return TRUE if the field is authorized to be null.
573  * @since GDAL 2.0
574  */
575 
576 /************************************************************************/
577 /*                         OGR_GFld_IsNullable()                        */
578 /************************************************************************/
579 
580 /**
581  * \brief Return whether this geometry field can receive null values.
582  *
583  * By default, fields are nullable.
584  *
585  * Even if this method returns FALSE (i.e not-nullable field), it doesn't mean
586  * that OGRFeature::IsFieldSet() will necessary return TRUE, as fields can be
587  * temporary unset and null/not-null validation is usually done when
588  * OGRLayer::CreateFeature()/SetFeature() is called.
589  *
590  * Note that not-nullable geometry fields might also contain 'empty' geometries.
591  *
592  * This method is the same as the C++ method OGRGeomFieldDefn::IsNullable().
593  *
594  * @param hDefn handle to the field definition
595  * @return TRUE if the field is authorized to be null.
596  * @since GDAL 2.0
597  */
598 
OGR_GFld_IsNullable(OGRGeomFieldDefnH hDefn)599 int OGR_GFld_IsNullable( OGRGeomFieldDefnH hDefn )
600 {
601     return OGRGeomFieldDefn::FromHandle(hDefn)->IsNullable();
602 }
603 
604 /************************************************************************/
605 /*                            SetNullable()                             */
606 /************************************************************************/
607 
608 /**
609  * \fn void OGRGeomFieldDefn::SetNullable( int bNullableIn );
610  *
611  * \brief Set whether this geometry field can receive null values.
612  *
613  * By default, fields are nullable, so this method is generally called with
614  * FALSE to set a not-null constraint.
615  *
616  * Drivers that support writing not-null constraint will advertise the
617  * GDAL_DCAP_NOTNULL_GEOMFIELDS driver metadata item.
618  *
619  * This method is the same as the C function OGR_GFld_SetNullable().
620  *
621  * @param bNullableIn FALSE if the field must have a not-null constraint.
622  * @since GDAL 2.0
623  */
624 
625 /************************************************************************/
626 /*                        OGR_GFld_SetNullable()                        */
627 /************************************************************************/
628 
629 /**
630  * \brief Set whether this geometry field can receive null values.
631  *
632  * By default, fields are nullable, so this method is generally called with
633  * FALSE to set a not-null constraint.
634  *
635  * Drivers that support writing not-null constraint will advertise the
636  * GDAL_DCAP_NOTNULL_GEOMFIELDS driver metadata item.
637  *
638  * This method is the same as the C++ method OGRGeomFieldDefn::SetNullable().
639  *
640  * @param hDefn handle to the field definition
641  * @param bNullableIn FALSE if the field must have a not-null constraint.
642  * @since GDAL 2.0
643  */
644 
OGR_GFld_SetNullable(OGRGeomFieldDefnH hDefn,int bNullableIn)645 void OGR_GFld_SetNullable( OGRGeomFieldDefnH hDefn, int bNullableIn )
646 {
647     OGRGeomFieldDefn::FromHandle(hDefn)->SetNullable(bNullableIn);
648 }
649