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