Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OpenGIS Simple Features Reference Implementation
4 : * Purpose: C API Functions that don't correspond one-to-one with C++
5 : * methods, such as the "simplified" geometry access functions.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2002, Frank Warmerdam
10 : * Copyright (c) 2009-2011, Even Rouault <even dot rouault at spatialys.com>
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "cpl_port.h"
32 : #include "ogr_api.h"
33 :
34 : #include <cstddef>
35 :
36 : #include "cpl_error.h"
37 : #include "ogr_geometry.h"
38 : #include "ogr_geos.h"
39 :
40 : static bool bNonLinearGeometriesEnabled = true;
41 :
42 : /************************************************************************/
43 : /* OGRGetGEOSVersion() */
44 : /************************************************************************/
45 :
46 : /** \brief Get the GEOS version
47 : *
48 : * @param pnMajor Pointer to major version number, or NULL
49 : * @param pnMinor Pointer to minor version number, or NULL
50 : * @param pnPatch Pointer to patch version number, or NULL
51 : * @return TRUE if GDAL is built against GEOS
52 : * @since GDAL 3.4.0
53 : */
54 : #ifdef HAVE_GEOS
55 4226 : bool OGRGetGEOSVersion(int *pnMajor, int *pnMinor, int *pnPatch)
56 : {
57 4226 : CPLStringList aosTokens(CSLTokenizeString2(GEOSversion(), ".", 0));
58 :
59 4226 : if (pnMajor && aosTokens.size() > 0)
60 3820 : *pnMajor = std::stoi(aosTokens[0]);
61 4226 : if (pnMinor && aosTokens.size() > 1)
62 203 : *pnMinor = std::stoi(aosTokens[1]);
63 4226 : if (pnPatch && aosTokens.size() > 2)
64 203 : *pnPatch = std::stoi(aosTokens[2]);
65 8452 : return TRUE;
66 : }
67 : #else
68 : bool OGRGetGEOSVersion(int *pnMajor, int *pnMinor, int *pnPatch)
69 : {
70 : if (pnMajor)
71 : *pnMajor = 0;
72 : if (pnMinor)
73 : *pnMinor = 0;
74 : if (pnPatch)
75 : *pnPatch = 0;
76 : return FALSE;
77 : }
78 : #endif
79 :
80 : /************************************************************************/
81 : /* ToPointer() */
82 : /************************************************************************/
83 :
84 936768 : static inline OGRGeometry *ToPointer(OGRGeometryH hGeom)
85 : {
86 936768 : return OGRGeometry::FromHandle(hGeom);
87 : }
88 :
89 : /************************************************************************/
90 : /* ToHandle() */
91 : /************************************************************************/
92 :
93 9109 : static inline OGRGeometryH ToHandle(OGRGeometry *poGeom)
94 : {
95 9109 : return OGRGeometry::ToHandle(poGeom);
96 : }
97 :
98 : /************************************************************************/
99 : /* OGR_G_GetPointCount() */
100 : /************************************************************************/
101 : /**
102 : * \brief Fetch number of points from a Point or a LineString/LinearRing
103 : * geometry.
104 : *
105 : * Only wkbPoint[25D] or wkbLineString[25D] may return a valid value.
106 : * Other geometry types will silently return 0.
107 : *
108 : * @param hGeom handle to the geometry from which to get the number of points.
109 : * @return the number of points.
110 : */
111 :
112 11715 : int OGR_G_GetPointCount(OGRGeometryH hGeom)
113 :
114 : {
115 11715 : VALIDATE_POINTER1(hGeom, "OGR_G_GetPointCount", 0);
116 :
117 : const OGRwkbGeometryType eGType =
118 11715 : wkbFlatten(ToPointer(hGeom)->getGeometryType());
119 11715 : if (eGType == wkbPoint)
120 : {
121 1538 : return 1;
122 : }
123 10177 : else if (OGR_GT_IsCurve(eGType))
124 : {
125 6767 : return ToPointer(hGeom)->toCurve()->getNumPoints();
126 : }
127 : else
128 : {
129 : // autotest/pymod/ogrtest.py calls this method on any geometry. So keep
130 : // silent.
131 : // CPLError(CE_Failure, CPLE_NotSupported,
132 : // "Incompatible geometry for operation");
133 3410 : return 0;
134 : }
135 : }
136 :
137 : /************************************************************************/
138 : /* OGR_G_SetPointCount() */
139 : /************************************************************************/
140 : /**
141 : * \brief Set number of points in a geometry.
142 : *
143 : * This method primary exists to preset the number of points in a linestring
144 : * geometry before setPoint() is used to assign them to avoid reallocating
145 : * the array larger with each call to addPoint().
146 : *
147 : * @param hGeom handle to the geometry.
148 : * @param nNewPointCount the new number of points for geometry.
149 : */
150 :
151 0 : void OGR_G_SetPointCount(OGRGeometryH hGeom, int nNewPointCount)
152 :
153 : {
154 0 : VALIDATE_POINTER0(hGeom, "OGR_G_SetPointCount");
155 :
156 0 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
157 : {
158 0 : case wkbLineString:
159 : case wkbCircularString:
160 : {
161 0 : OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
162 0 : poSC->setNumPoints(nNewPointCount);
163 0 : break;
164 : }
165 0 : default:
166 0 : CPLError(CE_Failure, CPLE_NotSupported,
167 : "Incompatible geometry for operation");
168 0 : break;
169 : }
170 : }
171 :
172 : /************************************************************************/
173 : /* OGR_G_Get_Component() */
174 : /************************************************************************/
175 : template <typename Getter>
176 86275 : static double OGR_G_Get_Component(OGRGeometryH hGeom, int i)
177 : {
178 86275 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
179 : {
180 3998 : case wkbPoint:
181 : {
182 3998 : if (i == 0)
183 : {
184 3995 : return Getter::get(ToPointer(hGeom)->toPoint());
185 : }
186 : else
187 : {
188 3 : CPLError(CE_Failure, CPLE_NotSupported,
189 : "Only i == 0 is supported");
190 3 : return 0.0;
191 : }
192 : }
193 :
194 82274 : case wkbLineString:
195 : case wkbCircularString:
196 : {
197 82274 : OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
198 82274 : if (i < 0 || i >= poSC->getNumPoints())
199 : {
200 3 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
201 3 : return 0.0;
202 : }
203 82271 : return Getter::get(poSC, i);
204 : }
205 :
206 3 : default:
207 3 : CPLError(CE_Failure, CPLE_NotSupported,
208 : "Incompatible geometry for operation");
209 3 : return 0.0;
210 : }
211 : }
212 :
213 : /************************************************************************/
214 : /* OGR_G_GetX() */
215 : /************************************************************************/
216 : /**
217 : * \brief Fetch the x coordinate of a point from a Point or a
218 : * LineString/LinearRing geometry.
219 : *
220 : * @param hGeom handle to the geometry from which to get the x coordinate.
221 : * @param i point to get the x coordinate.
222 : * @return the X coordinate of this point.
223 : */
224 :
225 35948 : double OGR_G_GetX(OGRGeometryH hGeom, int i)
226 :
227 : {
228 35948 : VALIDATE_POINTER1(hGeom, "OGR_G_GetX", 0);
229 :
230 : struct Getter
231 : {
232 2197 : static double get(const OGRPoint *poPoint)
233 : {
234 2197 : return poPoint->getX();
235 : }
236 :
237 33748 : static double get(const OGRSimpleCurve *poSC, int l_i)
238 : {
239 33748 : return poSC->getX(l_i);
240 : }
241 : };
242 :
243 35948 : return OGR_G_Get_Component<Getter>(hGeom, i);
244 : }
245 :
246 : /************************************************************************/
247 : /* OGR_G_GetY() */
248 : /************************************************************************/
249 : /**
250 : * \brief Fetch the x coordinate of a point from a Point or a
251 : * LineString/LinearRing geometry.
252 : *
253 : * @param hGeom handle to the geometry from which to get the y coordinate.
254 : * @param i point to get the Y coordinate.
255 : * @return the Y coordinate of this point.
256 : */
257 :
258 34738 : double OGR_G_GetY(OGRGeometryH hGeom, int i)
259 :
260 : {
261 34738 : VALIDATE_POINTER1(hGeom, "OGR_G_GetY", 0);
262 :
263 : struct Getter
264 : {
265 987 : static double get(const OGRPoint *poPoint)
266 : {
267 987 : return poPoint->getY();
268 : }
269 :
270 33748 : static double get(const OGRSimpleCurve *poSC, int l_i)
271 : {
272 33748 : return poSC->getY(l_i);
273 : }
274 : };
275 :
276 34738 : return OGR_G_Get_Component<Getter>(hGeom, i);
277 : }
278 :
279 : /************************************************************************/
280 : /* OGR_G_GetZ() */
281 : /************************************************************************/
282 : /**
283 : * \brief Fetch the z coordinate of a point from a Point or a
284 : * LineString/LinearRing geometry.
285 : *
286 : * @param hGeom handle to the geometry from which to get the Z coordinate.
287 : * @param i point to get the Z coordinate.
288 : * @return the Z coordinate of this point.
289 : */
290 :
291 13335 : double OGR_G_GetZ(OGRGeometryH hGeom, int i)
292 :
293 : {
294 13335 : VALIDATE_POINTER1(hGeom, "OGR_G_GetZ", 0);
295 :
296 : struct Getter
297 : {
298 705 : static double get(const OGRPoint *poPoint)
299 : {
300 705 : return poPoint->getZ();
301 : }
302 :
303 12627 : static double get(const OGRSimpleCurve *poSC, int l_i)
304 : {
305 12627 : return poSC->getZ(l_i);
306 : }
307 : };
308 :
309 13335 : return OGR_G_Get_Component<Getter>(hGeom, i);
310 : }
311 :
312 : /************************************************************************/
313 : /* OGR_G_GetM() */
314 : /************************************************************************/
315 : /**
316 : * \brief Fetch the m coordinate of a point from a geometry.
317 : *
318 : * @param hGeom handle to the geometry from which to get the M coordinate.
319 : * @param i point to get the M coordinate.
320 : * @return the M coordinate of this point.
321 : */
322 :
323 2254 : double OGR_G_GetM(OGRGeometryH hGeom, int i)
324 :
325 : {
326 2254 : VALIDATE_POINTER1(hGeom, "OGR_G_GetM", 0);
327 :
328 : struct Getter
329 : {
330 106 : static double get(const OGRPoint *poPoint)
331 : {
332 106 : return poPoint->getM();
333 : }
334 :
335 2148 : static double get(const OGRSimpleCurve *poSC, int l_i)
336 : {
337 2148 : return poSC->getM(l_i);
338 : }
339 : };
340 :
341 2254 : return OGR_G_Get_Component<Getter>(hGeom, i);
342 : }
343 :
344 : /************************************************************************/
345 : /* OGR_G_GetPoints() */
346 : /************************************************************************/
347 :
348 : /**
349 : * \brief Returns all points of line string.
350 : *
351 : * This method copies all points into user arrays. The user provides the
352 : * stride between 2 consecutive elements of the array.
353 : *
354 : * On some CPU architectures, care must be taken so that the arrays are properly
355 : * aligned.
356 : *
357 : * @param hGeom handle to the geometry from which to get the coordinates.
358 : * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount)
359 : * bytes, may be NULL.
360 : * @param nXStride the number of bytes between 2 elements of pabyX.
361 : * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount)
362 : * bytes, may be NULL.
363 : * @param nYStride the number of bytes between 2 elements of pabyY.
364 : * @param pabyZ a buffer of at last size (sizeof(double) * nZStride *
365 : * nPointCount) bytes, may be NULL.
366 : * @param nZStride the number of bytes between 2 elements of pabyZ.
367 : *
368 : * @return the number of points
369 : *
370 : * @since OGR 1.9.0
371 : */
372 :
373 15 : int OGR_G_GetPoints(OGRGeometryH hGeom, void *pabyX, int nXStride, void *pabyY,
374 : int nYStride, void *pabyZ, int nZStride)
375 : {
376 15 : VALIDATE_POINTER1(hGeom, "OGR_G_GetPoints", 0);
377 :
378 15 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
379 : {
380 4 : case wkbPoint:
381 : {
382 4 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
383 4 : if (pabyX)
384 4 : *(static_cast<double *>(pabyX)) = poPoint->getX();
385 4 : if (pabyY)
386 4 : *(static_cast<double *>(pabyY)) = poPoint->getY();
387 4 : if (pabyZ)
388 2 : *(static_cast<double *>(pabyZ)) = poPoint->getZ();
389 4 : return 1;
390 : }
391 : break;
392 :
393 10 : case wkbLineString:
394 : case wkbCircularString:
395 : {
396 10 : OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
397 10 : poSC->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride);
398 10 : return poSC->getNumPoints();
399 : }
400 : break;
401 :
402 1 : default:
403 1 : CPLError(CE_Failure, CPLE_NotSupported,
404 : "Incompatible geometry for operation");
405 1 : return 0;
406 : break;
407 : }
408 : }
409 :
410 : /************************************************************************/
411 : /* OGR_G_GetPointsZM() */
412 : /************************************************************************/
413 :
414 : /**
415 : * \brief Returns all points of line string.
416 : *
417 : * This method copies all points into user arrays. The user provides the
418 : * stride between 2 consecutive elements of the array.
419 : *
420 : * On some CPU architectures, care must be taken so that the arrays are properly
421 : * aligned.
422 : *
423 : * @param hGeom handle to the geometry from which to get the coordinates.
424 : * @param pabyX a buffer of at least (nXStride * nPointCount)
425 : * bytes, may be NULL.
426 : * @param nXStride the number of bytes between 2 elements of pabyX.
427 : * @param pabyY a buffer of at least (nYStride * nPointCount)
428 : * bytes, may be NULL.
429 : * @param nYStride the number of bytes between 2 elements of pabyY.
430 : * @param pabyZ a buffer of at last size (nZStride *
431 : * nPointCount) bytes, may be NULL.
432 : * @param nZStride the number of bytes between 2 elements of pabyZ.
433 : * @param pabyM a buffer of at last size (nMStride *
434 : * nPointCount) bytes, may be NULL.
435 : * @param nMStride the number of bytes between 2 elements of pabyM.
436 : *
437 : * @return the number of points
438 : *
439 : * @since OGR 1.9.0
440 : */
441 :
442 0 : int OGR_G_GetPointsZM(OGRGeometryH hGeom, void *pabyX, int nXStride,
443 : void *pabyY, int nYStride, void *pabyZ, int nZStride,
444 : void *pabyM, int nMStride)
445 : {
446 0 : VALIDATE_POINTER1(hGeom, "OGR_G_GetPointsZM", 0);
447 :
448 0 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
449 : {
450 0 : case wkbPoint:
451 : {
452 0 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
453 0 : if (pabyX)
454 0 : *static_cast<double *>(pabyX) = poPoint->getX();
455 0 : if (pabyY)
456 0 : *static_cast<double *>(pabyY) = poPoint->getY();
457 0 : if (pabyZ)
458 0 : *static_cast<double *>(pabyZ) = poPoint->getZ();
459 0 : if (pabyM)
460 0 : *static_cast<double *>(pabyM) = poPoint->getM();
461 0 : return 1;
462 : }
463 : break;
464 :
465 0 : case wkbLineString:
466 : case wkbCircularString:
467 : {
468 0 : OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
469 0 : poSC->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride,
470 : pabyM, nMStride);
471 0 : return poSC->getNumPoints();
472 : }
473 : break;
474 :
475 0 : default:
476 0 : CPLError(CE_Failure, CPLE_NotSupported,
477 : "Incompatible geometry for operation");
478 0 : return 0;
479 : break;
480 : }
481 : }
482 :
483 : /************************************************************************/
484 : /* OGR_G_GetPoint() */
485 : /************************************************************************/
486 :
487 : /**
488 : * \brief Fetch a point in line string or a point geometry.
489 : *
490 : * @param hGeom handle to the geometry from which to get the coordinates.
491 : * @param i the vertex to fetch, from 0 to getNumPoints()-1, zero for a point.
492 : * @param pdfX value of x coordinate.
493 : * @param pdfY value of y coordinate.
494 : * @param pdfZ value of z coordinate.
495 : */
496 :
497 756 : void OGR_G_GetPoint(OGRGeometryH hGeom, int i, double *pdfX, double *pdfY,
498 : double *pdfZ)
499 :
500 : {
501 756 : VALIDATE_POINTER0(hGeom, "OGR_G_GetPoint");
502 :
503 756 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
504 : {
505 21 : case wkbPoint:
506 : {
507 21 : if (i == 0)
508 : {
509 20 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
510 20 : *pdfX = poPoint->getX();
511 20 : *pdfY = poPoint->getY();
512 20 : if (pdfZ != nullptr)
513 20 : *pdfZ = poPoint->getZ();
514 : }
515 : else
516 : {
517 1 : CPLError(CE_Failure, CPLE_NotSupported,
518 : "Only i == 0 is supported");
519 : }
520 : }
521 21 : break;
522 :
523 734 : case wkbLineString:
524 : case wkbCircularString:
525 : {
526 734 : OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
527 734 : if (i < 0 || i >= poSC->getNumPoints())
528 : {
529 5 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
530 5 : *pdfX = 0.0;
531 5 : *pdfY = 0.0;
532 5 : if (pdfZ != nullptr)
533 3 : *pdfZ = 0.0;
534 : }
535 : else
536 : {
537 729 : *pdfX = poSC->getX(i);
538 729 : *pdfY = poSC->getY(i);
539 729 : if (pdfZ != nullptr)
540 728 : *pdfZ = poSC->getZ(i);
541 : }
542 : }
543 734 : break;
544 :
545 1 : default:
546 1 : CPLError(CE_Failure, CPLE_NotSupported,
547 : "Incompatible geometry for operation");
548 1 : break;
549 : }
550 : }
551 :
552 : /************************************************************************/
553 : /* OGR_G_GetPointZM() */
554 : /************************************************************************/
555 :
556 : /**
557 : * \brief Fetch a point in line string or a point geometry.
558 : *
559 : * @param hGeom handle to the geometry from which to get the coordinates.
560 : * @param i the vertex to fetch, from 0 to getNumPoints()-1, zero for a point.
561 : * @param pdfX value of x coordinate.
562 : * @param pdfY value of y coordinate.
563 : * @param pdfZ value of z coordinate.
564 : * @param pdfM value of m coordinate.
565 : */
566 :
567 1 : void OGR_G_GetPointZM(OGRGeometryH hGeom, int i, double *pdfX, double *pdfY,
568 : double *pdfZ, double *pdfM)
569 :
570 : {
571 1 : VALIDATE_POINTER0(hGeom, "OGR_G_GetPointZM");
572 :
573 1 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
574 : {
575 1 : case wkbPoint:
576 : {
577 1 : if (i == 0)
578 : {
579 1 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
580 1 : *pdfX = poPoint->getX();
581 1 : *pdfY = poPoint->getY();
582 1 : if (pdfZ != nullptr)
583 1 : *pdfZ = poPoint->getZ();
584 1 : if (pdfM != nullptr)
585 1 : *pdfM = poPoint->getM();
586 : }
587 : else
588 : {
589 0 : CPLError(CE_Failure, CPLE_NotSupported,
590 : "Only i == 0 is supported");
591 : }
592 : }
593 1 : break;
594 :
595 0 : case wkbLineString:
596 : case wkbCircularString:
597 : {
598 0 : OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
599 0 : if (i < 0 || i >= poSC->getNumPoints())
600 : {
601 0 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
602 0 : *pdfX = 0.0;
603 0 : *pdfY = 0.0;
604 0 : if (pdfZ != nullptr)
605 0 : *pdfZ = 0.0;
606 0 : if (pdfM != nullptr)
607 0 : *pdfM = 0.0;
608 : }
609 : else
610 : {
611 0 : *pdfX = poSC->getX(i);
612 0 : *pdfY = poSC->getY(i);
613 0 : if (pdfZ != nullptr)
614 0 : *pdfZ = poSC->getZ(i);
615 0 : if (pdfM != nullptr)
616 0 : *pdfM = poSC->getM(i);
617 : }
618 : }
619 0 : break;
620 :
621 0 : default:
622 0 : CPLError(CE_Failure, CPLE_NotSupported,
623 : "Incompatible geometry for operation");
624 0 : break;
625 : }
626 : }
627 :
628 : /************************************************************************/
629 : /* OGR_G_SetPoints() */
630 : /************************************************************************/
631 : /**
632 : * \brief Assign all points in a point or a line string geometry.
633 : *
634 : * This method clear any existing points assigned to this geometry,
635 : * and assigns a whole new set.
636 : *
637 : * @param hGeom handle to the geometry to set the coordinates.
638 : * @param nPointsIn number of points being passed in padfX and padfY.
639 : * @param pabyX list of X coordinates (double values) of points being assigned.
640 : * @param nXStride the number of bytes between 2 elements of pabyX.
641 : * @param pabyY list of Y coordinates (double values) of points being assigned.
642 : * @param nYStride the number of bytes between 2 elements of pabyY.
643 : * @param pabyZ list of Z coordinates (double values) of points being assigned
644 : * (defaults to NULL for 2D objects).
645 : * @param nZStride the number of bytes between 2 elements of pabyZ.
646 : */
647 :
648 9 : void CPL_DLL OGR_G_SetPoints(OGRGeometryH hGeom, int nPointsIn,
649 : const void *pabyX, int nXStride, const void *pabyY,
650 : int nYStride, const void *pabyZ, int nZStride)
651 :
652 : {
653 9 : VALIDATE_POINTER0(hGeom, "OGR_G_SetPoints");
654 :
655 9 : if (pabyX == nullptr || pabyY == nullptr)
656 : {
657 2 : CPLError(CE_Failure, CPLE_NotSupported,
658 : "pabyX == NULL || pabyY == NULL");
659 2 : return;
660 : }
661 :
662 7 : const double *const padfX = static_cast<const double *>(pabyX);
663 7 : const double *const padfY = static_cast<const double *>(pabyY);
664 7 : const double *const padfZ = static_cast<const double *>(pabyZ);
665 :
666 7 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
667 : {
668 2 : case wkbPoint:
669 : {
670 2 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
671 2 : poPoint->setX(*padfX);
672 2 : poPoint->setY(*padfY);
673 2 : if (pabyZ != nullptr)
674 1 : poPoint->setZ(*(padfZ));
675 2 : break;
676 : }
677 5 : case wkbLineString:
678 : case wkbCircularString:
679 : {
680 5 : OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
681 :
682 5 : const int nSizeDouble = static_cast<int>(sizeof(double));
683 5 : if (nXStride == nSizeDouble && nYStride == nSizeDouble &&
684 2 : ((nZStride == 0 && pabyZ == nullptr) ||
685 1 : (nZStride == nSizeDouble && pabyZ != nullptr)))
686 : {
687 2 : poSC->setPoints(nPointsIn, padfX, padfY, padfZ);
688 : }
689 : else
690 : {
691 3 : poSC->setNumPoints(nPointsIn);
692 :
693 : // TODO(schwehr): Create pasX and pasY.
694 6 : for (int i = 0; i < nPointsIn; ++i)
695 : {
696 3 : const double x = *reinterpret_cast<const double *>(
697 3 : static_cast<const char *>(pabyX) + i * nXStride);
698 3 : const double y = *reinterpret_cast<const double *>(
699 3 : static_cast<const char *>(pabyY) + i * nYStride);
700 3 : if (pabyZ)
701 : {
702 1 : const double z = *reinterpret_cast<const double *>(
703 1 : static_cast<const char *>(pabyZ) + i * nZStride);
704 1 : poSC->setPoint(i, x, y, z);
705 : }
706 : else
707 : {
708 2 : poSC->setPoint(i, x, y);
709 : }
710 : }
711 : }
712 5 : break;
713 : }
714 0 : default:
715 0 : CPLError(CE_Failure, CPLE_NotSupported,
716 : "Incompatible geometry for operation");
717 0 : break;
718 : }
719 : }
720 :
721 : /************************************************************************/
722 : /* OGR_G_SetPointsZM() */
723 : /************************************************************************/
724 : /**
725 : * \brief Assign all points in a point or a line string geometry.
726 : *
727 : * This method clear any existing points assigned to this geometry,
728 : * and assigns a whole new set.
729 : *
730 : * @param hGeom handle to the geometry to set the coordinates.
731 : * @param nPointsIn number of points being passed in padfX and padfY.
732 : * @param pX list of X coordinates (double values) of points being assigned.
733 : * @param nXStride the number of bytes between 2 elements of pX.
734 : * @param pY list of Y coordinates (double values) of points being assigned.
735 : * @param nYStride the number of bytes between 2 elements of pY.
736 : * @param pZ list of Z coordinates (double values) of points being assigned
737 : * (if not NULL, upgrades the geometry to have Z coordinate).
738 : * @param nZStride the number of bytes between 2 elements of pZ.
739 : * @param pM list of M coordinates (double values) of points being assigned
740 : * (if not NULL, upgrades the geometry to have M coordinate).
741 : * @param nMStride the number of bytes between 2 elements of pM.
742 : */
743 :
744 0 : void CPL_DLL OGR_G_SetPointsZM(OGRGeometryH hGeom, int nPointsIn,
745 : const void *pX, int nXStride, const void *pY,
746 : int nYStride, const void *pZ, int nZStride,
747 : const void *pM, int nMStride)
748 :
749 : {
750 0 : VALIDATE_POINTER0(hGeom, "OGR_G_SetPointsZM");
751 :
752 0 : if (pX == nullptr || pY == nullptr)
753 : {
754 0 : CPLError(CE_Failure, CPLE_NotSupported,
755 : "pabyX == NULL || pabyY == NULL");
756 0 : return;
757 : }
758 :
759 0 : const double *const padfX = static_cast<const double *>(pX);
760 0 : const double *const padfY = static_cast<const double *>(pY);
761 0 : const double *const padfZ = static_cast<const double *>(pZ);
762 0 : const double *const padfM = static_cast<const double *>(pM);
763 0 : const char *const pabyX = static_cast<const char *>(pX);
764 0 : const char *const pabyY = static_cast<const char *>(pY);
765 0 : const char *const pabyZ = static_cast<const char *>(pZ);
766 0 : const char *const pabyM = static_cast<const char *>(pM);
767 :
768 0 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
769 : {
770 0 : case wkbPoint:
771 : {
772 0 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
773 0 : poPoint->setX(*padfX);
774 0 : poPoint->setY(*padfY);
775 0 : if (pabyZ)
776 0 : poPoint->setZ(*padfZ);
777 0 : if (pabyM)
778 0 : poPoint->setM(*padfM);
779 0 : break;
780 : }
781 0 : case wkbLineString:
782 : case wkbCircularString:
783 : {
784 0 : OGRSimpleCurve *poSC = ToPointer(hGeom)->toSimpleCurve();
785 :
786 0 : const int nSizeDouble = static_cast<int>(sizeof(double));
787 0 : if (nXStride == nSizeDouble && nYStride == nSizeDouble &&
788 0 : ((nZStride == 0 && padfZ == nullptr) ||
789 0 : (nZStride == nSizeDouble && padfZ != nullptr)) &&
790 0 : ((nMStride == 0 && padfM == nullptr) ||
791 0 : (nMStride == nSizeDouble && padfM != nullptr)))
792 : {
793 0 : if (!padfZ && !padfM)
794 0 : poSC->setPoints(nPointsIn, padfX, padfY);
795 0 : else if (pabyZ && !pabyM)
796 0 : poSC->setPoints(nPointsIn, padfX, padfY, padfZ);
797 0 : else if (!pabyZ && pabyM)
798 0 : poSC->setPointsM(nPointsIn, padfX, padfY, padfM);
799 : else
800 0 : poSC->setPoints(nPointsIn, padfX, padfY, padfZ, padfM);
801 : }
802 : else
803 : {
804 0 : poSC->setNumPoints(nPointsIn);
805 :
806 0 : if (!pabyM)
807 : {
808 0 : if (!pabyZ)
809 : {
810 0 : for (int i = 0; i < nPointsIn; ++i)
811 : {
812 0 : const double x = *reinterpret_cast<const double *>(
813 0 : pabyX + i * nXStride);
814 0 : const double y = *reinterpret_cast<const double *>(
815 0 : pabyY + i * nYStride);
816 0 : poSC->setPoint(i, x, y);
817 : }
818 : }
819 : else
820 : {
821 0 : for (int i = 0; i < nPointsIn; ++i)
822 : {
823 0 : const double x = *reinterpret_cast<const double *>(
824 0 : pabyX + i * nXStride);
825 0 : const double y = *reinterpret_cast<const double *>(
826 0 : pabyY + i * nYStride);
827 0 : const double z = *reinterpret_cast<const double *>(
828 0 : pabyZ + i * nZStride);
829 0 : poSC->setPoint(i, x, y, z);
830 : }
831 : }
832 : }
833 : else
834 : {
835 0 : if (!pabyZ)
836 : {
837 0 : for (int i = 0; i < nPointsIn; ++i)
838 : {
839 0 : const double x = *reinterpret_cast<const double *>(
840 0 : pabyX + i * nXStride);
841 0 : const double y = *reinterpret_cast<const double *>(
842 0 : pabyY + i * nYStride);
843 0 : const double m = *reinterpret_cast<const double *>(
844 0 : pabyM + i * nMStride);
845 0 : poSC->setPointM(i, x, y, m);
846 : }
847 : }
848 : else
849 : {
850 0 : for (int i = 0; i < nPointsIn; ++i)
851 : {
852 0 : const double x = *reinterpret_cast<const double *>(
853 0 : pabyX + i * nXStride);
854 0 : const double y = *reinterpret_cast<const double *>(
855 0 : pabyY + i * nYStride);
856 0 : const double z = *reinterpret_cast<const double *>(
857 0 : pabyZ + i * nZStride);
858 0 : const double m = *reinterpret_cast<const double *>(
859 0 : pabyM + i * nMStride);
860 0 : poSC->setPoint(i, x, y, z, m);
861 : }
862 : }
863 : }
864 : }
865 0 : break;
866 : }
867 0 : default:
868 0 : CPLError(CE_Failure, CPLE_NotSupported,
869 : "Incompatible geometry for operation");
870 0 : break;
871 : }
872 : }
873 :
874 : /************************************************************************/
875 : /* OGR_G_SetPoint() */
876 : /************************************************************************/
877 : /**
878 : * \brief Set the location of a vertex in a point or linestring geometry.
879 : *
880 : * If iPoint is larger than the number of existing
881 : * points in the linestring, the point count will be increased to
882 : * accommodate the request.
883 : *
884 : * @param hGeom handle to the geometry to add a vertex to.
885 : * @param i the index of the vertex to assign (zero based) or
886 : * zero for a point.
887 : * @param dfX input X coordinate to assign.
888 : * @param dfY input Y coordinate to assign.
889 : * @param dfZ input Z coordinate to assign (defaults to zero).
890 : */
891 :
892 49903 : void OGR_G_SetPoint(OGRGeometryH hGeom, int i, double dfX, double dfY,
893 : double dfZ)
894 :
895 : {
896 49903 : VALIDATE_POINTER0(hGeom, "OGR_G_SetPoint");
897 :
898 49903 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
899 : {
900 164 : case wkbPoint:
901 : {
902 164 : if (i == 0)
903 : {
904 163 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
905 163 : poPoint->setX(dfX);
906 163 : poPoint->setY(dfY);
907 163 : poPoint->setZ(dfZ);
908 : }
909 : else
910 : {
911 1 : CPLError(CE_Failure, CPLE_NotSupported,
912 : "Only i == 0 is supported");
913 : }
914 : }
915 164 : break;
916 :
917 49738 : case wkbLineString:
918 : case wkbCircularString:
919 : {
920 49738 : if (i < 0)
921 : {
922 2 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
923 2 : return;
924 : }
925 49736 : ToPointer(hGeom)->toSimpleCurve()->setPoint(i, dfX, dfY, dfZ);
926 49736 : break;
927 : }
928 :
929 1 : default:
930 1 : CPLError(CE_Failure, CPLE_NotSupported,
931 : "Incompatible geometry for operation");
932 1 : break;
933 : }
934 : }
935 :
936 : /************************************************************************/
937 : /* OGR_G_SetPoint_2D() */
938 : /************************************************************************/
939 : /**
940 : * \brief Set the location of a vertex in a point or linestring geometry.
941 : *
942 : * If iPoint is larger than the number of existing
943 : * points in the linestring, the point count will be increased to
944 : * accommodate the request.
945 : *
946 : * @param hGeom handle to the geometry to add a vertex to.
947 : * @param i the index of the vertex to assign (zero based) or
948 : * zero for a point.
949 : * @param dfX input X coordinate to assign.
950 : * @param dfY input Y coordinate to assign.
951 : */
952 :
953 229247 : void OGR_G_SetPoint_2D(OGRGeometryH hGeom, int i, double dfX, double dfY)
954 :
955 : {
956 229247 : VALIDATE_POINTER0(hGeom, "OGR_G_SetPoint_2D");
957 :
958 229247 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
959 : {
960 160001 : case wkbPoint:
961 : {
962 160001 : if (i == 0)
963 : {
964 160000 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
965 160000 : poPoint->setX(dfX);
966 160000 : poPoint->setY(dfY);
967 : }
968 : else
969 : {
970 1 : CPLError(CE_Failure, CPLE_NotSupported,
971 : "Only i == 0 is supported");
972 : }
973 : }
974 160001 : break;
975 :
976 69245 : case wkbLineString:
977 : case wkbCircularString:
978 : {
979 69245 : if (i < 0)
980 : {
981 2 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
982 2 : return;
983 : }
984 69243 : ToPointer(hGeom)->toSimpleCurve()->setPoint(i, dfX, dfY);
985 69243 : break;
986 : }
987 :
988 1 : default:
989 1 : CPLError(CE_Failure, CPLE_NotSupported,
990 : "Incompatible geometry for operation");
991 1 : break;
992 : }
993 : }
994 :
995 : /************************************************************************/
996 : /* OGR_G_SetPointM() */
997 : /************************************************************************/
998 : /**
999 : * \brief Set the location of a vertex in a point or linestring geometry.
1000 : *
1001 : * If iPoint is larger than the number of existing
1002 : * points in the linestring, the point count will be increased to
1003 : * accommodate the request.
1004 : *
1005 : * @param hGeom handle to the geometry to add a vertex to.
1006 : * @param i the index of the vertex to assign (zero based) or
1007 : * zero for a point.
1008 : * @param dfX input X coordinate to assign.
1009 : * @param dfY input Y coordinate to assign.
1010 : * @param dfM input M coordinate to assign.
1011 : */
1012 :
1013 0 : void OGR_G_SetPointM(OGRGeometryH hGeom, int i, double dfX, double dfY,
1014 : double dfM)
1015 :
1016 : {
1017 0 : VALIDATE_POINTER0(hGeom, "OGR_G_SetPointM");
1018 :
1019 0 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
1020 : {
1021 0 : case wkbPoint:
1022 : {
1023 0 : if (i == 0)
1024 : {
1025 0 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
1026 0 : poPoint->setX(dfX);
1027 0 : poPoint->setY(dfY);
1028 0 : poPoint->setM(dfM);
1029 : }
1030 : else
1031 : {
1032 0 : CPLError(CE_Failure, CPLE_NotSupported,
1033 : "Only i == 0 is supported");
1034 : }
1035 : }
1036 0 : break;
1037 :
1038 0 : case wkbLineString:
1039 : case wkbCircularString:
1040 : {
1041 0 : if (i < 0)
1042 : {
1043 0 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
1044 0 : return;
1045 : }
1046 0 : ToPointer(hGeom)->toSimpleCurve()->setPointM(i, dfX, dfY, dfM);
1047 0 : break;
1048 : }
1049 :
1050 0 : default:
1051 0 : CPLError(CE_Failure, CPLE_NotSupported,
1052 : "Incompatible geometry for operation");
1053 0 : break;
1054 : }
1055 : }
1056 :
1057 : /************************************************************************/
1058 : /* OGR_G_SetPointZM() */
1059 : /************************************************************************/
1060 : /**
1061 : * \brief Set the location of a vertex in a point or linestring geometry.
1062 : *
1063 : * If iPoint is larger than the number of existing
1064 : * points in the linestring, the point count will be increased to
1065 : * accommodate the request.
1066 : *
1067 : * @param hGeom handle to the geometry to add a vertex to.
1068 : * @param i the index of the vertex to assign (zero based) or
1069 : * zero for a point.
1070 : * @param dfX input X coordinate to assign.
1071 : * @param dfY input Y coordinate to assign.
1072 : * @param dfZ input Z coordinate to assign.
1073 : * @param dfM input M coordinate to assign.
1074 : */
1075 :
1076 0 : void OGR_G_SetPointZM(OGRGeometryH hGeom, int i, double dfX, double dfY,
1077 : double dfZ, double dfM)
1078 :
1079 : {
1080 0 : VALIDATE_POINTER0(hGeom, "OGR_G_SetPointZM");
1081 :
1082 0 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
1083 : {
1084 0 : case wkbPoint:
1085 : {
1086 0 : if (i == 0)
1087 : {
1088 0 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
1089 0 : poPoint->setX(dfX);
1090 0 : poPoint->setY(dfY);
1091 0 : poPoint->setZ(dfZ);
1092 0 : poPoint->setM(dfM);
1093 : }
1094 : else
1095 : {
1096 0 : CPLError(CE_Failure, CPLE_NotSupported,
1097 : "Only i == 0 is supported");
1098 : }
1099 : }
1100 0 : break;
1101 :
1102 0 : case wkbLineString:
1103 : case wkbCircularString:
1104 : {
1105 0 : if (i < 0)
1106 : {
1107 0 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
1108 0 : return;
1109 : }
1110 0 : ToPointer(hGeom)->toSimpleCurve()->setPoint(i, dfX, dfY, dfZ, dfM);
1111 0 : break;
1112 : }
1113 :
1114 0 : default:
1115 0 : CPLError(CE_Failure, CPLE_NotSupported,
1116 : "Incompatible geometry for operation");
1117 0 : break;
1118 : }
1119 : }
1120 :
1121 : /************************************************************************/
1122 : /* OGR_G_AddPoint() */
1123 : /************************************************************************/
1124 : /**
1125 : * \brief Add a point to a geometry (line string or point).
1126 : *
1127 : * The vertex count of the line string is increased by one, and assigned from
1128 : * the passed location value.
1129 : *
1130 : * @param hGeom handle to the geometry to add a point to.
1131 : * @param dfX x coordinate of point to add.
1132 : * @param dfY y coordinate of point to add.
1133 : * @param dfZ z coordinate of point to add.
1134 : */
1135 :
1136 254 : void OGR_G_AddPoint(OGRGeometryH hGeom, double dfX, double dfY, double dfZ)
1137 :
1138 : {
1139 254 : VALIDATE_POINTER0(hGeom, "OGR_G_AddPoint");
1140 :
1141 254 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
1142 : {
1143 4 : case wkbPoint:
1144 : {
1145 4 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
1146 4 : poPoint->setX(dfX);
1147 4 : poPoint->setY(dfY);
1148 4 : poPoint->setZ(dfZ);
1149 : }
1150 4 : break;
1151 :
1152 249 : case wkbLineString:
1153 : case wkbCircularString:
1154 249 : ToPointer(hGeom)->toSimpleCurve()->addPoint(dfX, dfY, dfZ);
1155 249 : break;
1156 :
1157 1 : default:
1158 1 : CPLError(CE_Failure, CPLE_NotSupported,
1159 : "Incompatible geometry for operation");
1160 1 : break;
1161 : }
1162 : }
1163 :
1164 : /************************************************************************/
1165 : /* OGR_G_AddPoint_2D() */
1166 : /************************************************************************/
1167 : /**
1168 : * \brief Add a point to a geometry (line string or point).
1169 : *
1170 : * The vertex count of the line string is increased by one, and assigned from
1171 : * the passed location value.
1172 : *
1173 : * @param hGeom handle to the geometry to add a point to.
1174 : * @param dfX x coordinate of point to add.
1175 : * @param dfY y coordinate of point to add.
1176 : */
1177 :
1178 78120 : void OGR_G_AddPoint_2D(OGRGeometryH hGeom, double dfX, double dfY)
1179 :
1180 : {
1181 78120 : VALIDATE_POINTER0(hGeom, "OGR_G_AddPoint_2D");
1182 :
1183 78120 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
1184 : {
1185 74 : case wkbPoint:
1186 : {
1187 74 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
1188 74 : poPoint->setX(dfX);
1189 74 : poPoint->setY(dfY);
1190 : }
1191 74 : break;
1192 :
1193 78045 : case wkbLineString:
1194 : case wkbCircularString:
1195 78045 : ToPointer(hGeom)->toSimpleCurve()->addPoint(dfX, dfY);
1196 78045 : break;
1197 :
1198 1 : default:
1199 1 : CPLError(CE_Failure, CPLE_NotSupported,
1200 : "Incompatible geometry for operation");
1201 1 : break;
1202 : }
1203 : }
1204 :
1205 : /************************************************************************/
1206 : /* OGR_G_AddPointM() */
1207 : /************************************************************************/
1208 : /**
1209 : * \brief Add a point to a geometry (line string or point).
1210 : *
1211 : * The vertex count of the line string is increased by one, and assigned from
1212 : * the passed location value.
1213 : *
1214 : * @param hGeom handle to the geometry to add a point to.
1215 : * @param dfX x coordinate of point to add.
1216 : * @param dfY y coordinate of point to add.
1217 : * @param dfM m coordinate of point to add.
1218 : */
1219 :
1220 0 : void OGR_G_AddPointM(OGRGeometryH hGeom, double dfX, double dfY, double dfM)
1221 :
1222 : {
1223 0 : VALIDATE_POINTER0(hGeom, "OGR_G_AddPointM");
1224 :
1225 0 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
1226 : {
1227 0 : case wkbPoint:
1228 : {
1229 0 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
1230 0 : poPoint->setX(dfX);
1231 0 : poPoint->setY(dfY);
1232 0 : poPoint->setM(dfM);
1233 : }
1234 0 : break;
1235 :
1236 0 : case wkbLineString:
1237 : case wkbCircularString:
1238 0 : ToPointer(hGeom)->toSimpleCurve()->addPointM(dfX, dfY, dfM);
1239 0 : break;
1240 :
1241 0 : default:
1242 0 : CPLError(CE_Failure, CPLE_NotSupported,
1243 : "Incompatible geometry for operation");
1244 0 : break;
1245 : }
1246 : }
1247 :
1248 : /************************************************************************/
1249 : /* OGR_G_AddPointZM() */
1250 : /************************************************************************/
1251 : /**
1252 : * \brief Add a point to a geometry (line string or point).
1253 : *
1254 : * The vertex count of the line string is increased by one, and assigned from
1255 : * the passed location value.
1256 : *
1257 : * @param hGeom handle to the geometry to add a point to.
1258 : * @param dfX x coordinate of point to add.
1259 : * @param dfY y coordinate of point to add.
1260 : * @param dfZ z coordinate of point to add.
1261 : * @param dfM m coordinate of point to add.
1262 : */
1263 :
1264 0 : void OGR_G_AddPointZM(OGRGeometryH hGeom, double dfX, double dfY, double dfZ,
1265 : double dfM)
1266 :
1267 : {
1268 0 : VALIDATE_POINTER0(hGeom, "OGR_G_AddPointZM");
1269 :
1270 0 : switch (wkbFlatten(ToPointer(hGeom)->getGeometryType()))
1271 : {
1272 0 : case wkbPoint:
1273 : {
1274 0 : OGRPoint *poPoint = ToPointer(hGeom)->toPoint();
1275 0 : poPoint->setX(dfX);
1276 0 : poPoint->setY(dfY);
1277 0 : poPoint->setZ(dfZ);
1278 0 : poPoint->setM(dfM);
1279 : }
1280 0 : break;
1281 :
1282 0 : case wkbLineString:
1283 : case wkbCircularString:
1284 0 : ToPointer(hGeom)->toSimpleCurve()->addPoint(dfX, dfY, dfZ, dfM);
1285 0 : break;
1286 :
1287 0 : default:
1288 0 : CPLError(CE_Failure, CPLE_NotSupported,
1289 : "Incompatible geometry for operation");
1290 0 : break;
1291 : }
1292 : }
1293 :
1294 : /************************************************************************/
1295 : /* OGR_G_GetGeometryCount() */
1296 : /************************************************************************/
1297 : /**
1298 : * \brief Fetch the number of elements in a geometry or number of geometries in
1299 : * container.
1300 : *
1301 : * Only geometries of type wkbPolygon[25D], wkbMultiPoint[25D],
1302 : * wkbMultiLineString[25D], wkbMultiPolygon[25D] or wkbGeometryCollection[25D]
1303 : * may return a valid value. Other geometry types will silently return 0.
1304 : *
1305 : * For a polygon, the returned number is the number of rings (exterior ring +
1306 : * interior rings).
1307 : *
1308 : * @param hGeom single geometry or geometry container from which to get
1309 : * the number of elements.
1310 : * @return the number of elements.
1311 : */
1312 :
1313 10790 : int OGR_G_GetGeometryCount(OGRGeometryH hGeom)
1314 :
1315 : {
1316 10790 : VALIDATE_POINTER1(hGeom, "OGR_G_GetGeometryCount", 0);
1317 :
1318 10790 : const auto poGeom = ToPointer(hGeom);
1319 10790 : const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
1320 10790 : if (OGR_GT_IsSubClassOf(eType, wkbCurvePolygon))
1321 : {
1322 2720 : if (poGeom->toCurvePolygon()->getExteriorRingCurve() == nullptr)
1323 111 : return 0;
1324 : else
1325 2609 : return poGeom->toCurvePolygon()->getNumInteriorRings() + 1;
1326 : }
1327 8070 : else if (OGR_GT_IsSubClassOf(eType, wkbCompoundCurve))
1328 : {
1329 231 : return poGeom->toCompoundCurve()->getNumCurves();
1330 : }
1331 7839 : else if (OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
1332 : {
1333 2706 : return poGeom->toGeometryCollection()->getNumGeometries();
1334 : }
1335 5133 : else if (OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface))
1336 : {
1337 86 : return poGeom->toPolyhedralSurface()->getNumGeometries();
1338 : }
1339 : else
1340 : {
1341 : // autotest/pymod/ogrtest.py calls this method on any geometry. So keep
1342 : // silent.
1343 : // CPLError(CE_Failure, CPLE_NotSupported,
1344 : // "Incompatible geometry for operation");
1345 5047 : return 0;
1346 : }
1347 : }
1348 :
1349 : /************************************************************************/
1350 : /* OGR_G_GetGeometryRef() */
1351 : /************************************************************************/
1352 :
1353 : /**
1354 : * \brief Fetch geometry from a geometry container.
1355 : *
1356 : * This function returns a handle to a geometry within the container.
1357 : * The returned geometry remains owned by the container, and should not be
1358 : * modified. The handle is only valid until the next change to the
1359 : * geometry container. Use OGR_G_Clone() to make a copy.
1360 : *
1361 : * This function relates to the SFCOM
1362 : * IGeometryCollection::get_Geometry() method.
1363 : *
1364 : * This function is the same as the CPP method
1365 : * OGRGeometryCollection::getGeometryRef().
1366 : *
1367 : * For a polygon, OGR_G_GetGeometryRef(iSubGeom) returns the exterior ring
1368 : * if iSubGeom == 0, and the interior rings for iSubGeom > 0.
1369 : *
1370 : * @param hGeom handle to the geometry container from which to get a
1371 : * geometry from.
1372 : * @param iSubGeom the index of the geometry to fetch, between 0 and
1373 : * getNumGeometries() - 1.
1374 : * @return handle to the requested geometry.
1375 : */
1376 :
1377 2949 : OGRGeometryH OGR_G_GetGeometryRef(OGRGeometryH hGeom, int iSubGeom)
1378 :
1379 : {
1380 2949 : VALIDATE_POINTER1(hGeom, "OGR_G_GetGeometryRef", nullptr);
1381 :
1382 2949 : const auto poGeom = ToPointer(hGeom);
1383 2949 : const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
1384 2949 : if (OGR_GT_IsSubClassOf(eType, wkbCurvePolygon))
1385 : {
1386 1122 : if (iSubGeom == 0)
1387 1044 : return ToHandle(poGeom->toCurvePolygon()->getExteriorRingCurve());
1388 : else
1389 78 : return ToHandle(
1390 78 : poGeom->toCurvePolygon()->getInteriorRingCurve(iSubGeom - 1));
1391 : }
1392 1827 : else if (OGR_GT_IsSubClassOf(eType, wkbCompoundCurve))
1393 : {
1394 232 : return ToHandle(poGeom->toCompoundCurve()->getCurve(iSubGeom));
1395 : }
1396 1595 : else if (OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
1397 : {
1398 1463 : return ToHandle(
1399 1463 : poGeom->toGeometryCollection()->getGeometryRef(iSubGeom));
1400 : }
1401 132 : else if (OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface))
1402 : {
1403 131 : return ToHandle(
1404 131 : poGeom->toPolyhedralSurface()->getGeometryRef(iSubGeom));
1405 : }
1406 : else
1407 : {
1408 1 : CPLError(CE_Failure, CPLE_NotSupported,
1409 : "Incompatible geometry for operation");
1410 1 : return nullptr;
1411 : }
1412 : }
1413 :
1414 : /************************************************************************/
1415 : /* OGR_G_AddGeometry() */
1416 : /************************************************************************/
1417 :
1418 : /**
1419 : * \brief Add a geometry to a geometry container.
1420 : *
1421 : * Some subclasses of OGRGeometryCollection restrict the types of geometry
1422 : * that can be added, and may return an error. The passed geometry is cloned
1423 : * to make an internal copy.
1424 : *
1425 : * There is no SFCOM analog to this method.
1426 : *
1427 : * This function is the same as the CPP method
1428 : * OGRGeometryCollection::addGeometry.
1429 : *
1430 : * For a polygon, hNewSubGeom must be a linearring. If the polygon is empty,
1431 : * the first added subgeometry will be the exterior ring. The next ones will be
1432 : * the interior rings.
1433 : *
1434 : * @param hGeom existing geometry container.
1435 : * @param hNewSubGeom geometry to add to the container.
1436 : *
1437 : * @return OGRERR_NONE if successful, or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if
1438 : * the geometry type is illegal for the type of existing geometry.
1439 : */
1440 :
1441 106 : OGRErr OGR_G_AddGeometry(OGRGeometryH hGeom, OGRGeometryH hNewSubGeom)
1442 :
1443 : {
1444 106 : VALIDATE_POINTER1(hGeom, "OGR_G_AddGeometry", OGRERR_UNSUPPORTED_OPERATION);
1445 106 : VALIDATE_POINTER1(hNewSubGeom, "OGR_G_AddGeometry",
1446 : OGRERR_UNSUPPORTED_OPERATION);
1447 :
1448 106 : OGRErr eErr = OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
1449 :
1450 106 : auto poGeom = ToPointer(hGeom);
1451 106 : auto poNewSubGeom = ToPointer(hNewSubGeom);
1452 106 : const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
1453 106 : if (OGR_GT_IsSubClassOf(eType, wkbCurvePolygon))
1454 : {
1455 57 : if (OGR_GT_IsCurve(wkbFlatten(poNewSubGeom->getGeometryType())))
1456 57 : eErr = poGeom->toCurvePolygon()->addRing(poNewSubGeom->toCurve());
1457 : }
1458 49 : else if (OGR_GT_IsSubClassOf(eType, wkbCompoundCurve))
1459 : {
1460 2 : if (OGR_GT_IsCurve(wkbFlatten(poNewSubGeom->getGeometryType())))
1461 2 : eErr = poGeom->toCompoundCurve()->addCurve(poNewSubGeom->toCurve());
1462 : }
1463 47 : else if (OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
1464 : {
1465 41 : eErr = poGeom->toGeometryCollection()->addGeometry(poNewSubGeom);
1466 : }
1467 6 : else if (OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface))
1468 : {
1469 5 : eErr = poGeom->toPolyhedralSurface()->addGeometry(poNewSubGeom);
1470 : }
1471 :
1472 106 : return eErr;
1473 : }
1474 :
1475 : /************************************************************************/
1476 : /* OGR_G_AddGeometryDirectly() */
1477 : /************************************************************************/
1478 : /**
1479 : * \brief Add a geometry directly to an existing geometry container.
1480 : *
1481 : * Some subclasses of OGRGeometryCollection restrict the types of geometry
1482 : * that can be added, and may return an error. Ownership of the passed
1483 : * geometry is taken by the container rather than cloning as addGeometry()
1484 : * does.
1485 : *
1486 : * This function is the same as the CPP method
1487 : * OGRGeometryCollection::addGeometryDirectly.
1488 : *
1489 : * There is no SFCOM analog to this method.
1490 : *
1491 : * For a polygon, hNewSubGeom must be a linearring. If the polygon is empty,
1492 : * the first added subgeometry will be the exterior ring. The next ones will be
1493 : * the interior rings.
1494 : *
1495 : * @param hGeom existing geometry.
1496 : * @param hNewSubGeom geometry to add to the existing geometry.
1497 : *
1498 : * @return OGRERR_NONE if successful, or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if
1499 : * the geometry type is illegal for the type of geometry container.
1500 : */
1501 :
1502 3709 : OGRErr OGR_G_AddGeometryDirectly(OGRGeometryH hGeom, OGRGeometryH hNewSubGeom)
1503 :
1504 : {
1505 3709 : VALIDATE_POINTER1(hGeom, "OGR_G_AddGeometryDirectly",
1506 : OGRERR_UNSUPPORTED_OPERATION);
1507 3709 : VALIDATE_POINTER1(hNewSubGeom, "OGR_G_AddGeometryDirectly",
1508 : OGRERR_UNSUPPORTED_OPERATION);
1509 :
1510 3709 : OGRErr eErr = OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
1511 :
1512 3709 : auto poGeom = ToPointer(hGeom);
1513 3709 : auto poNewSubGeom = ToPointer(hNewSubGeom);
1514 3709 : const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
1515 :
1516 3709 : if (OGR_GT_IsSubClassOf(eType, wkbCurvePolygon))
1517 : {
1518 3651 : if (OGR_GT_IsCurve(wkbFlatten(poNewSubGeom->getGeometryType())))
1519 7302 : eErr = poGeom->toCurvePolygon()->addRingDirectly(
1520 3651 : poNewSubGeom->toCurve());
1521 : }
1522 58 : else if (OGR_GT_IsSubClassOf(eType, wkbCompoundCurve))
1523 : {
1524 3 : if (OGR_GT_IsCurve(wkbFlatten(poNewSubGeom->getGeometryType())))
1525 3 : eErr = poGeom->toCompoundCurve()->addCurveDirectly(
1526 : poNewSubGeom->toCurve());
1527 : }
1528 55 : else if (OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
1529 : {
1530 : eErr =
1531 51 : poGeom->toGeometryCollection()->addGeometryDirectly(poNewSubGeom);
1532 : }
1533 4 : else if (OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface))
1534 : {
1535 3 : eErr = poGeom->toPolyhedralSurface()->addGeometryDirectly(poNewSubGeom);
1536 : }
1537 :
1538 3709 : if (eErr != OGRERR_NONE)
1539 3 : delete poNewSubGeom;
1540 :
1541 3709 : return eErr;
1542 : }
1543 :
1544 : /************************************************************************/
1545 : /* OGR_G_RemoveGeometry() */
1546 : /************************************************************************/
1547 :
1548 : /**
1549 : * \brief Remove a geometry from an exiting geometry container.
1550 : *
1551 : * Removing a geometry will cause the geometry count to drop by one, and all
1552 : * "higher" geometries will shuffle down one in index.
1553 : *
1554 : * There is no SFCOM analog to this method.
1555 : *
1556 : * This function is the same as the CPP method
1557 : * OGRGeometryCollection::removeGeometry() for geometry collections,
1558 : * OGRCurvePolygon::removeRing() for polygons / curve polygons and
1559 : * OGRPolyhedralSurface::removeGeometry() for polyhedral surfaces and TINs.
1560 : *
1561 : * @param hGeom the existing geometry to delete from.
1562 : * @param iGeom the index of the geometry to delete. A value of -1 is a
1563 : * special flag meaning that all geometries should be removed.
1564 : *
1565 : * @param bDelete if TRUE the geometry will be destroyed, otherwise it will
1566 : * not. The default is TRUE as the existing geometry is considered to own the
1567 : * geometries in it.
1568 : *
1569 : * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is
1570 : * out of range.
1571 : */
1572 :
1573 63 : OGRErr OGR_G_RemoveGeometry(OGRGeometryH hGeom, int iGeom, int bDelete)
1574 :
1575 : {
1576 63 : VALIDATE_POINTER1(hGeom, "OGR_G_RemoveGeometry", OGRERR_FAILURE);
1577 :
1578 63 : const auto poGeom = ToPointer(hGeom);
1579 63 : const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
1580 63 : if (OGR_GT_IsSubClassOf(eType, wkbCurvePolygon))
1581 : {
1582 30 : return poGeom->toCurvePolygon()->removeRing(iGeom,
1583 30 : CPL_TO_BOOL(bDelete));
1584 : }
1585 48 : else if (OGR_GT_IsSubClassOf(eType, wkbGeometryCollection))
1586 : {
1587 42 : return poGeom->toGeometryCollection()->removeGeometry(iGeom, bDelete);
1588 : }
1589 6 : else if (OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface))
1590 : {
1591 5 : return poGeom->toPolyhedralSurface()->removeGeometry(iGeom, bDelete);
1592 : }
1593 : else
1594 : {
1595 1 : return OGRERR_UNSUPPORTED_OPERATION;
1596 : }
1597 : }
1598 :
1599 : /************************************************************************/
1600 : /* OGR_G_Length() */
1601 : /************************************************************************/
1602 :
1603 : /**
1604 : * \brief Compute length of a geometry.
1605 : *
1606 : * Computes the length for OGRCurve or MultiCurve objects.
1607 : * Undefined for all other geometry types (returns zero).
1608 : *
1609 : * This function utilizes the C++ get_Length() method.
1610 : *
1611 : * @param hGeom the geometry to operate on.
1612 : * @return the length or 0.0 for unsupported geometry types.
1613 : *
1614 : * @since OGR 1.8.0
1615 : */
1616 :
1617 27 : double OGR_G_Length(OGRGeometryH hGeom)
1618 :
1619 : {
1620 27 : VALIDATE_POINTER1(hGeom, "OGR_G_GetLength", 0);
1621 :
1622 27 : double dfLength = 0.0;
1623 :
1624 27 : const auto poGeom = ToPointer(hGeom);
1625 : const OGRwkbGeometryType eType =
1626 27 : wkbFlatten(ToPointer(hGeom)->getGeometryType());
1627 27 : if (OGR_GT_IsCurve(eType))
1628 : {
1629 21 : dfLength = poGeom->toCurve()->get_Length();
1630 : }
1631 6 : else if (OGR_GT_IsSubClassOf(eType, wkbMultiCurve) ||
1632 : eType == wkbGeometryCollection)
1633 : {
1634 5 : dfLength = poGeom->toGeometryCollection()->get_Length();
1635 : }
1636 : else
1637 : {
1638 1 : CPLError(CE_Warning, CPLE_AppDefined,
1639 : "OGR_G_Length() called against a non-curve geometry type.");
1640 1 : dfLength = 0.0;
1641 : }
1642 :
1643 27 : return dfLength;
1644 : }
1645 :
1646 : /************************************************************************/
1647 : /* OGR_G_Area() */
1648 : /************************************************************************/
1649 :
1650 : /**
1651 : * \brief Compute geometry area.
1652 : *
1653 : * The returned area is a 2D Cartesian (planar) area in square units of the
1654 : * spatial reference system in use, so potentially "square degrees" for a
1655 : * geometry expressed in a geographic SRS.
1656 : *
1657 : * Computes the area for surfaces or closed curves.
1658 : * Undefined for all other geometry types (returns 0.0).
1659 : *
1660 : * This function utilizes the C++ OGRSurface::get_Area() method.
1661 : *
1662 : * @param hGeom the geometry to operate on.
1663 : * @return the area of the geometry in square units of the spatial reference
1664 : * system in use, or 0.0 for unsupported geometry types.
1665 :
1666 : * @see OGR_G_GeodesicArea() for an alternative function returning areas
1667 : * computed on the ellipsoid, an in square meters.
1668 : *
1669 : * @since OGR 1.8.0
1670 : */
1671 :
1672 1444 : double OGR_G_Area(OGRGeometryH hGeom)
1673 :
1674 : {
1675 1444 : VALIDATE_POINTER1(hGeom, "OGR_G_Area", 0);
1676 :
1677 1444 : double dfArea = 0.0;
1678 :
1679 1444 : const auto poGeom = ToPointer(hGeom);
1680 1444 : const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
1681 1444 : if (OGR_GT_IsSurface(eType))
1682 : {
1683 1435 : dfArea = poGeom->toSurface()->get_Area();
1684 : }
1685 9 : else if (OGR_GT_IsCurve(eType))
1686 : {
1687 3 : dfArea = poGeom->toCurve()->get_Area();
1688 : }
1689 6 : else if (OGR_GT_IsSubClassOf(eType, wkbMultiSurface) ||
1690 : eType == wkbGeometryCollection)
1691 : {
1692 5 : dfArea = poGeom->toGeometryCollection()->get_Area();
1693 : }
1694 : else
1695 : {
1696 1 : CPLError(CE_Warning, CPLE_AppDefined,
1697 : "OGR_G_Area() called against non-surface geometry type.");
1698 :
1699 1 : dfArea = 0.0;
1700 : }
1701 :
1702 1444 : return dfArea;
1703 : }
1704 :
1705 : /**
1706 : * \brief Compute geometry area (deprecated)
1707 : *
1708 : * @deprecated
1709 : * @see OGR_G_Area()
1710 : */
1711 0 : double OGR_G_GetArea(OGRGeometryH hGeom)
1712 :
1713 : {
1714 0 : return OGR_G_Area(hGeom);
1715 : }
1716 :
1717 : /************************************************************************/
1718 : /* OGR_G_GeodesicArea() */
1719 : /************************************************************************/
1720 :
1721 : /**
1722 : * \brief Compute geometry area, considered as a surface on the underlying
1723 : * ellipsoid of the SRS attached to the geometry.
1724 : *
1725 : * The returned area will always be in square meters, and assumes that
1726 : * polygon edges describe geodesic lines on the ellipsoid.
1727 : *
1728 : * If the geometry' SRS is not a geographic one, geometries are reprojected to
1729 : * the underlying geographic SRS of the geometry' SRS.
1730 : * OGRSpatialReference::GetDataAxisToSRSAxisMapping() is honored.
1731 : *
1732 : * Computes the area for surfaces or closed curves.
1733 : * Undefined for all other geometry types (returns a negative value).
1734 : *
1735 : * Note that geometries with circular arcs will be linearized in their original
1736 : * coordinate space first, so the resulting geodesic area will be an
1737 : * approximation.
1738 : *
1739 : * This function utilizes the C++ OGRSurface::get_GeodesicArea() method.
1740 : *
1741 : * @param hGeom the geometry to operate on.
1742 : * @return the area, or a negative value in case of error (unsupported geometry
1743 : * type, no SRS attached, etc.)
1744 : *
1745 : * @see OGR_G_Area() for an alternative method returning areas computed in
1746 : * 2D Cartesian space.
1747 : *
1748 : * @since OGR 3.9.0
1749 : */
1750 :
1751 29 : double OGR_G_GeodesicArea(OGRGeometryH hGeom)
1752 :
1753 : {
1754 29 : VALIDATE_POINTER1(hGeom, "OGR_G_GeodesicArea", -1);
1755 :
1756 29 : double dfArea = -1;
1757 :
1758 29 : const auto poGeom = ToPointer(hGeom);
1759 29 : const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
1760 29 : if (OGR_GT_IsSurface(eType))
1761 : {
1762 16 : dfArea = poGeom->toSurface()->get_GeodesicArea();
1763 : }
1764 13 : else if (OGR_GT_IsCurve(eType))
1765 : {
1766 8 : dfArea = poGeom->toCurve()->get_GeodesicArea();
1767 : }
1768 5 : else if (OGR_GT_IsSubClassOf(eType, wkbMultiSurface) ||
1769 : eType == wkbGeometryCollection)
1770 : {
1771 4 : dfArea = poGeom->toGeometryCollection()->get_GeodesicArea();
1772 : }
1773 : else
1774 : {
1775 1 : CPLError(CE_Failure, CPLE_AppDefined,
1776 : "OGR_G_GeodesicArea() called against non-surface geometry "
1777 : "type.");
1778 : }
1779 :
1780 29 : return dfArea;
1781 : }
1782 :
1783 : /************************************************************************/
1784 : /* OGR_G_IsClockwise() */
1785 : /************************************************************************/
1786 : /**
1787 : * \brief Returns true if the ring has clockwise winding (or less than 2 points)
1788 : *
1789 : * Assumes that the ring is closed.
1790 : *
1791 : * @param hGeom handle to a curve geometry
1792 : * @since GDAL 3.8
1793 : */
1794 :
1795 33 : bool OGR_G_IsClockwise(OGRGeometryH hGeom)
1796 :
1797 : {
1798 33 : VALIDATE_POINTER1(hGeom, "OGR_G_IsClockwise", false);
1799 :
1800 33 : auto poGeom = OGRGeometry::FromHandle(hGeom);
1801 33 : const OGRwkbGeometryType eGType = wkbFlatten(poGeom->getGeometryType());
1802 33 : if (OGR_GT_IsCurve(eGType))
1803 : {
1804 32 : return poGeom->toCurve()->isClockwise();
1805 : }
1806 : else
1807 : {
1808 1 : CPLError(CE_Failure, CPLE_NotSupported,
1809 : "Incompatible geometry for operation");
1810 1 : return false;
1811 : }
1812 : }
1813 :
1814 : /************************************************************************/
1815 : /* OGR_G_HasCurveGeometry() */
1816 : /************************************************************************/
1817 :
1818 : /**
1819 : * \brief Returns if this geometry is or has curve geometry.
1820 : *
1821 : * Returns if a geometry is or has CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
1822 : * MULTICURVE or MULTISURFACE in it.
1823 : *
1824 : * If bLookForNonLinear is set to TRUE, it will be actually looked if the
1825 : * geometry or its subgeometries are or contain a non-linear geometry in
1826 : * them. In which case, if the method returns TRUE, it means that
1827 : * OGR_G_GetLinearGeometry() would return an approximate version of the
1828 : * geometry. Otherwise, OGR_G_GetLinearGeometry() would do a conversion, but
1829 : * with just converting container type, like COMPOUNDCURVE -> LINESTRING,
1830 : * MULTICURVE -> MULTILINESTRING or MULTISURFACE -> MULTIPOLYGON, resulting in a
1831 : * "loss-less" conversion.
1832 : *
1833 : * This function is the same as C++ method OGRGeometry::hasCurveGeometry().
1834 : *
1835 : * @param hGeom the geometry to operate on.
1836 : * @param bLookForNonLinear set it to TRUE to check if the geometry is or
1837 : * contains a CIRCULARSTRING.
1838 : * @return TRUE if this geometry is or has curve geometry.
1839 : *
1840 : * @since GDAL 2.0
1841 : */
1842 :
1843 29 : int OGR_G_HasCurveGeometry(OGRGeometryH hGeom, int bLookForNonLinear)
1844 : {
1845 29 : VALIDATE_POINTER1(hGeom, "OGR_G_HasCurveGeometry", FALSE);
1846 29 : return ToPointer(hGeom)->hasCurveGeometry(bLookForNonLinear);
1847 : }
1848 :
1849 : /************************************************************************/
1850 : /* OGR_G_GetLinearGeometry() */
1851 : /************************************************************************/
1852 :
1853 : /**
1854 : * \brief Return, possibly approximate, linear version of this geometry.
1855 : *
1856 : * Returns a geometry that has no CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
1857 : * MULTICURVE or MULTISURFACE in it, by approximating curve geometries.
1858 : *
1859 : * The ownership of the returned geometry belongs to the caller.
1860 : *
1861 : * The reverse function is OGR_G_GetCurveGeometry().
1862 : *
1863 : * This method relates to the ISO SQL/MM Part 3 ICurve::CurveToLine() and
1864 : * CurvePolygon::CurvePolyToPoly() methods.
1865 : *
1866 : * This function is the same as C++ method OGRGeometry::getLinearGeometry().
1867 : *
1868 : * @param hGeom the geometry to operate on.
1869 : * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
1870 : * arc, zero to use the default setting.
1871 : * @param papszOptions options as a null-terminated list of strings or NULL.
1872 : * See OGRGeometryFactory::curveToLineString() for valid options.
1873 : *
1874 : * @return a new geometry.
1875 : *
1876 : * @since GDAL 2.0
1877 : */
1878 :
1879 3083 : OGRGeometryH CPL_DLL OGR_G_GetLinearGeometry(OGRGeometryH hGeom,
1880 : double dfMaxAngleStepSizeDegrees,
1881 : char **papszOptions)
1882 : {
1883 3083 : VALIDATE_POINTER1(hGeom, "OGR_G_GetLinearGeometry", nullptr);
1884 6166 : return ToHandle(ToPointer(hGeom)->getLinearGeometry(
1885 6166 : dfMaxAngleStepSizeDegrees, papszOptions));
1886 : }
1887 :
1888 : /************************************************************************/
1889 : /* OGR_G_GetCurveGeometry() */
1890 : /************************************************************************/
1891 :
1892 : /**
1893 : * \brief Return curve version of this geometry.
1894 : *
1895 : * Returns a geometry that has possibly CIRCULARSTRING, COMPOUNDCURVE,
1896 : * CURVEPOLYGON, MULTICURVE or MULTISURFACE in it, by de-approximating linear
1897 : * into curve geometries.
1898 : *
1899 : * If the geometry has no curve portion, the returned geometry will be a clone
1900 : * of it.
1901 : *
1902 : * The ownership of the returned geometry belongs to the caller.
1903 : *
1904 : * The reverse function is OGR_G_GetLinearGeometry().
1905 : *
1906 : * This function is the same as C++ method OGRGeometry::getCurveGeometry().
1907 : *
1908 : * @param hGeom the geometry to operate on.
1909 : * @param papszOptions options as a null-terminated list of strings.
1910 : * Unused for now. Must be set to NULL.
1911 : *
1912 : * @return a new geometry.
1913 : *
1914 : * @since GDAL 2.0
1915 : */
1916 :
1917 3056 : OGRGeometryH CPL_DLL OGR_G_GetCurveGeometry(OGRGeometryH hGeom,
1918 : char **papszOptions)
1919 : {
1920 3056 : VALIDATE_POINTER1(hGeom, "OGR_G_GetCurveGeometry", nullptr);
1921 :
1922 3056 : return ToHandle(ToPointer(hGeom)->getCurveGeometry(papszOptions));
1923 : }
1924 :
1925 : /************************************************************************/
1926 : /* OGR_G_Value() */
1927 : /************************************************************************/
1928 : /**
1929 : * \brief Fetch point at given distance along curve.
1930 : *
1931 : * This function relates to the SF COM ICurve::get_Value() method.
1932 : *
1933 : * This function is the same as the C++ method OGRCurve::Value().
1934 : *
1935 : * @param hGeom curve geometry.
1936 : * @param dfDistance distance along the curve at which to sample position.
1937 : * This distance should be between zero and get_Length()
1938 : * for this curve.
1939 : * @return a point or NULL.
1940 : *
1941 : * @since GDAL 2.0
1942 : */
1943 :
1944 22 : OGRGeometryH OGR_G_Value(OGRGeometryH hGeom, double dfDistance)
1945 : {
1946 22 : VALIDATE_POINTER1(hGeom, "OGR_G_Value", nullptr);
1947 :
1948 22 : const auto poGeom = ToPointer(hGeom);
1949 22 : if (OGR_GT_IsCurve(poGeom->getGeometryType()))
1950 : {
1951 22 : OGRPoint *p = new OGRPoint();
1952 22 : poGeom->toCurve()->Value(dfDistance, p);
1953 22 : return ToHandle(p);
1954 : }
1955 :
1956 0 : return nullptr;
1957 : }
1958 :
1959 : /************************************************************************/
1960 : /* OGRSetNonLinearGeometriesEnabledFlag() */
1961 : /************************************************************************/
1962 :
1963 : /**
1964 : * \brief Set flag to enable/disable returning non-linear geometries in the C
1965 : * API.
1966 : *
1967 : * This flag has only an effect on the OGR_F_GetGeometryRef(),
1968 : * OGR_F_GetGeomFieldRef(), OGR_L_GetGeomType(), OGR_GFld_GetType() and
1969 : * OGR_FD_GetGeomType() C API, and corresponding methods in the SWIG
1970 : * bindings. It is meant as making it simple for applications using the OGR C
1971 : * API not to have to deal with non-linear geometries, even if such geometries
1972 : * might be returned by drivers. In which case, they will be transformed into
1973 : * their closest linear geometry, by doing linear approximation, with
1974 : * OGR_G_ForceTo().
1975 : *
1976 : * Libraries should generally *not* use that method, since that could interfere
1977 : * with other libraries or applications.
1978 : *
1979 : * Note that it *does* not affect the behavior of the C++ API.
1980 : *
1981 : * @param bFlag TRUE if non-linear geometries might be returned (default value).
1982 : * FALSE to ask for non-linear geometries to be approximated as
1983 : * linear geometries.
1984 : *
1985 : * @since GDAL 2.0
1986 : */
1987 :
1988 2 : void OGRSetNonLinearGeometriesEnabledFlag(int bFlag)
1989 : {
1990 2 : bNonLinearGeometriesEnabled = bFlag != FALSE;
1991 2 : }
1992 :
1993 : /************************************************************************/
1994 : /* OGRGetNonLinearGeometriesEnabledFlag() */
1995 : /************************************************************************/
1996 :
1997 : /**
1998 : * \brief Get flag to enable/disable returning non-linear geometries in the C
1999 : * API.
2000 : *
2001 : * return TRUE if non-linear geometries might be returned (default value is
2002 : * TRUE).
2003 : *
2004 : * @since GDAL 2.0
2005 : * @see OGRSetNonLinearGeometriesEnabledFlag()
2006 : */
2007 :
2008 38253 : int OGRGetNonLinearGeometriesEnabledFlag(void)
2009 : {
2010 38253 : return bNonLinearGeometriesEnabled;
2011 : }
|