1 : /******************************************************************************
2 : * $Id: ogr_api.cpp 22416 2011-05-22 20:19:45Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: C API Functions that don't correspond one-to-one with C++
6 : * methods, such as the "simplified" geometry access functions.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2002, Frank Warmerdam
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 "ogr_geometry.h"
32 : #include "ogr_api.h"
33 : #include "cpl_error.h"
34 :
35 : /************************************************************************/
36 : /* OGR_G_GetPointCount() */
37 : /************************************************************************/
38 : /**
39 : * \brief Fetch number of points from a geometry.
40 : *
41 : * Only wkbPoint[25D] or wkbLineString[25D] may return a valid value.
42 : * Other geometry types will silently return 0.
43 : *
44 : * @param hGeom handle to the geometry from which to get the number of points.
45 : * @return the number of points.
46 : */
47 :
48 3927 : int OGR_G_GetPointCount( OGRGeometryH hGeom )
49 :
50 : {
51 3927 : VALIDATE_POINTER1( hGeom, "OGR_G_GetPointCount", 0 );
52 :
53 3927 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
54 : {
55 : case wkbPoint:
56 844 : return 1;
57 :
58 : case wkbLineString:
59 : {
60 2069 : OGRLineString *poLine = (OGRLineString *) hGeom;
61 2069 : return poLine->getNumPoints();
62 : }
63 :
64 : default:
65 : // autotest/pymod/ogrtest.py calls this method on any geometry. So keep silent
66 : //CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
67 1014 : return 0;
68 : }
69 : }
70 :
71 : /************************************************************************/
72 : /* OGR_G_GetX() */
73 : /************************************************************************/
74 : /**
75 : * \brief Fetch the x coordinate of a point from a geometry.
76 : *
77 : * @param hGeom handle to the geometry from which to get the x coordinate.
78 : * @param i point to get the x coordinate.
79 : * @return the X coordinate of this point.
80 : */
81 :
82 17958 : double OGR_G_GetX( OGRGeometryH hGeom, int i )
83 :
84 : {
85 17958 : VALIDATE_POINTER1( hGeom, "OGR_G_GetX", 0 );
86 :
87 17958 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
88 : {
89 : case wkbPoint:
90 : {
91 597 : if( i == 0 )
92 597 : return ((OGRPoint *) hGeom)->getX();
93 : else
94 : {
95 0 : CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
96 0 : return 0.0;
97 : }
98 : }
99 :
100 : case wkbLineString:
101 : {
102 17361 : OGRLineString* poLS = (OGRLineString *) hGeom;
103 17361 : if (i < 0 || i >= poLS->getNumPoints())
104 : {
105 0 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
106 0 : return 0.0;
107 : }
108 17361 : return poLS->getX( i );
109 : }
110 :
111 : default:
112 0 : CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
113 0 : return 0.0;
114 : }
115 : }
116 :
117 : /************************************************************************/
118 : /* OGR_G_GetY() */
119 : /************************************************************************/
120 : /**
121 : * \brief Fetch the x coordinate of a point from a geometry.
122 : *
123 : * @param hGeom handle to the geometry from which to get the y coordinate.
124 : * @param i point to get the Y coordinate.
125 : * @return the Y coordinate of this point.
126 : */
127 :
128 17958 : double OGR_G_GetY( OGRGeometryH hGeom, int i )
129 :
130 : {
131 17958 : VALIDATE_POINTER1( hGeom, "OGR_G_GetY", 0 );
132 :
133 17958 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
134 : {
135 : case wkbPoint:
136 : {
137 597 : if( i == 0 )
138 597 : return ((OGRPoint *) hGeom)->getY();
139 : else
140 : {
141 0 : CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
142 0 : return 0.0;
143 : }
144 : }
145 :
146 : case wkbLineString:
147 : {
148 17361 : OGRLineString* poLS = (OGRLineString *) hGeom;
149 17361 : if (i < 0 || i >= poLS->getNumPoints())
150 : {
151 0 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
152 0 : return 0.0;
153 : }
154 17361 : return poLS->getY( i );
155 : }
156 :
157 : default:
158 0 : CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
159 0 : return 0.0;
160 : }
161 : }
162 :
163 : /************************************************************************/
164 : /* OGR_G_GetZ() */
165 : /************************************************************************/
166 : /**
167 : * \brief Fetch the z coordinate of a point from a geometry.
168 : *
169 : * @param hGeom handle to the geometry from which to get the Z coordinate.
170 : * @param i point to get the Z coordinate.
171 : * @return the Z coordinate of this point.
172 : */
173 :
174 17618 : double OGR_G_GetZ( OGRGeometryH hGeom, int i )
175 :
176 : {
177 17618 : VALIDATE_POINTER1( hGeom, "OGR_G_GetZ", 0 );
178 :
179 17618 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
180 : {
181 : case wkbPoint:
182 : {
183 562 : if( i == 0 )
184 562 : return ((OGRPoint *) hGeom)->getZ();
185 : else
186 : {
187 0 : CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
188 0 : return 0.0;
189 : }
190 : }
191 :
192 : case wkbLineString:
193 : {
194 17056 : OGRLineString* poLS = (OGRLineString *) hGeom;
195 17056 : if (i < 0 || i >= poLS->getNumPoints())
196 : {
197 0 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
198 0 : return 0.0;
199 : }
200 17056 : return poLS->getZ( i );
201 : }
202 :
203 : default:
204 0 : CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
205 0 : return 0.0;
206 : }
207 : }
208 :
209 : /************************************************************************/
210 : /* OGR_G_GetPoints() */
211 : /************************************************************************/
212 :
213 : /**
214 : * \brief Returns all points of line string.
215 : *
216 : * This method copies all points into user arrays. The user provides the
217 : * stride between 2 consecutives elements of the array.
218 : *
219 : * On some CPU architectures, care must be taken so that the arrays are properly aligned.
220 : *
221 : * @param hGeom handle to the geometry from which to get the coordinates.
222 : * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount) bytes, may be NULL.
223 : * @param nXStride the number of bytes between 2 elements of pabyX.
224 : * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount) bytes, may be NULL.
225 : * @param nYStride the number of bytes between 2 elements of pabyY.
226 : * @param pabyZ a buffer of at last size (sizeof(double) * nZStride * nPointCount) bytes, may be NULL.
227 : * @param nZStride the number of bytes between 2 elements of pabyZ.
228 : *
229 : * @return the number of points
230 : *
231 : * @since OGR 1.9.0
232 : */
233 :
234 13 : int OGR_G_GetPoints( OGRGeometryH hGeom,
235 : void* pabyX, int nXStride,
236 : void* pabyY, int nYStride,
237 : void* pabyZ, int nZStride)
238 : {
239 13 : VALIDATE_POINTER1( hGeom, "OGR_G_GetPoints", 0 );
240 :
241 13 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
242 : {
243 : case wkbPoint:
244 : {
245 4 : if (pabyX) *((double*)pabyX) = ((OGRPoint *)hGeom)->getX();
246 4 : if (pabyY) *((double*)pabyY) = ((OGRPoint *)hGeom)->getY();
247 4 : if (pabyZ) *((double*)pabyZ) = ((OGRPoint *)hGeom)->getZ();
248 4 : return 1;
249 : }
250 : break;
251 :
252 : case wkbLineString:
253 : {
254 9 : OGRLineString* poLS = (OGRLineString *) hGeom;
255 9 : poLS->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride);
256 9 : return poLS->getNumPoints();
257 : }
258 : break;
259 :
260 : default:
261 0 : CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
262 0 : return 0;
263 : break;
264 : }
265 : }
266 :
267 :
268 : /************************************************************************/
269 : /* OGR_G_GetPoint() */
270 : /************************************************************************/
271 :
272 : /**
273 : * \brief Fetch a point in line string or a point geometry.
274 : *
275 : * @param hGeom handle to the geometry from which to get the coordinates.
276 : * @param i the vertex to fetch, from 0 to getNumPoints()-1, zero for a point.
277 : * @param pdfX value of x coordinate.
278 : * @param pdfY value of y coordinate.
279 : * @param pdfZ value of z coordinate.
280 : */
281 :
282 6 : void OGR_G_GetPoint( OGRGeometryH hGeom, int i,
283 : double *pdfX, double *pdfY, double *pdfZ )
284 :
285 : {
286 6 : VALIDATE_POINTER0( hGeom, "OGR_G_GetPoint" );
287 :
288 6 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
289 : {
290 : case wkbPoint:
291 : {
292 2 : if( i == 0 )
293 : {
294 2 : *pdfX = ((OGRPoint *)hGeom)->getX();
295 2 : *pdfY = ((OGRPoint *)hGeom)->getY();
296 2 : if( pdfZ != NULL )
297 2 : *pdfZ = ((OGRPoint *)hGeom)->getZ();
298 : }
299 : else
300 : {
301 0 : CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
302 : }
303 : }
304 2 : break;
305 :
306 : case wkbLineString:
307 : {
308 4 : OGRLineString* poLS = (OGRLineString *) hGeom;
309 4 : if (i < 0 || i >= poLS->getNumPoints())
310 : {
311 4 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
312 4 : *pdfX = *pdfY = 0;
313 4 : if( pdfZ != NULL )
314 2 : *pdfZ = 0;
315 : }
316 : else
317 : {
318 0 : *pdfX = poLS->getX( i );
319 0 : *pdfY = poLS->getY( i );
320 0 : if( pdfZ != NULL )
321 0 : *pdfZ = poLS->getZ( i );
322 : }
323 : }
324 4 : break;
325 :
326 : default:
327 0 : CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
328 : break;
329 : }
330 : }
331 :
332 : /************************************************************************/
333 : /* OGR_G_SetPoint() */
334 : /************************************************************************/
335 : /**
336 : * \brief Set the location of a vertex in a point or linestring geometry.
337 : *
338 : * If iPoint is larger than the number of existing
339 : * points in the linestring, the point count will be increased to
340 : * accomodate the request.
341 : *
342 : * @param hGeom handle to the geometry to add a vertex to.
343 : * @param i the index of the vertex to assign (zero based) or
344 : * zero for a point.
345 : * @param dfX input X coordinate to assign.
346 : * @param dfY input Y coordinate to assign.
347 : * @param dfZ input Z coordinate to assign (defaults to zero).
348 : */
349 :
350 21765 : void OGR_G_SetPoint( OGRGeometryH hGeom, int i,
351 : double dfX, double dfY, double dfZ )
352 :
353 : {
354 21765 : VALIDATE_POINTER0( hGeom, "OGR_G_SetPoint" );
355 :
356 21765 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
357 : {
358 : case wkbPoint:
359 : {
360 4 : if( i == 0 )
361 : {
362 4 : ((OGRPoint *) hGeom)->setX( dfX );
363 4 : ((OGRPoint *) hGeom)->setY( dfY );
364 4 : ((OGRPoint *) hGeom)->setZ( dfZ );
365 : }
366 : else
367 : {
368 0 : CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
369 : }
370 : }
371 4 : break;
372 :
373 : case wkbLineString:
374 : {
375 21761 : if (i < 0)
376 : {
377 1 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
378 1 : return;
379 : }
380 21760 : ((OGRLineString *) hGeom)->setPoint( i, dfX, dfY, dfZ );
381 21760 : break;
382 : }
383 :
384 : default:
385 0 : CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
386 : break;
387 : }
388 : }
389 :
390 : /************************************************************************/
391 : /* OGR_G_SetPoint_2D() */
392 : /************************************************************************/
393 : /**
394 : * \brief Set the location of a vertex in a point or linestring geometry.
395 : *
396 : * If iPoint is larger than the number of existing
397 : * points in the linestring, the point count will be increased to
398 : * accomodate the request.
399 : *
400 : * @param hGeom handle to the geometry to add a vertex to.
401 : * @param i the index of the vertex to assign (zero based) or
402 : * zero for a point.
403 : * @param dfX input X coordinate to assign.
404 : * @param dfY input Y coordinate to assign.
405 : */
406 :
407 1262 : void OGR_G_SetPoint_2D( OGRGeometryH hGeom, int i,
408 : double dfX, double dfY )
409 :
410 : {
411 1262 : VALIDATE_POINTER0( hGeom, "OGR_G_SetPoint_2D" );
412 :
413 1262 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
414 : {
415 : case wkbPoint:
416 : {
417 0 : if( i == 0 )
418 : {
419 0 : ((OGRPoint *) hGeom)->setX( dfX );
420 0 : ((OGRPoint *) hGeom)->setY( dfY );
421 : }
422 : else
423 : {
424 0 : CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
425 : }
426 : }
427 0 : break;
428 :
429 : case wkbLineString:
430 : {
431 1262 : if (i < 0)
432 : {
433 1 : CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
434 1 : return;
435 : }
436 1261 : ((OGRLineString *) hGeom)->setPoint( i, dfX, dfY );
437 1261 : break;
438 : }
439 :
440 : default:
441 0 : CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
442 : break;
443 : }
444 : }
445 :
446 : /************************************************************************/
447 : /* OGR_G_AddPoint() */
448 : /************************************************************************/
449 : /**
450 : * \brief Add a point to a geometry (line string or point).
451 : *
452 : * The vertex count of the line string is increased by one, and assigned from
453 : * the passed location value.
454 : *
455 : * @param hGeom handle to the geometry to add a point to.
456 : * @param dfX x coordinate of point to add.
457 : * @param dfY y coordinate of point to add.
458 : * @param dfZ z coordinate of point to add.
459 : */
460 :
461 10 : void OGR_G_AddPoint( OGRGeometryH hGeom,
462 : double dfX, double dfY, double dfZ )
463 :
464 : {
465 10 : VALIDATE_POINTER0( hGeom, "OGR_G_AddPoint" );
466 :
467 10 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
468 : {
469 : case wkbPoint:
470 : {
471 0 : ((OGRPoint *) hGeom)->setX( dfX );
472 0 : ((OGRPoint *) hGeom)->setY( dfY );
473 0 : ((OGRPoint *) hGeom)->setZ( dfZ );
474 : }
475 0 : break;
476 :
477 : case wkbLineString:
478 10 : ((OGRLineString *) hGeom)->addPoint( dfX, dfY, dfZ );
479 10 : break;
480 :
481 : default:
482 0 : CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
483 : break;
484 : }
485 : }
486 :
487 : /************************************************************************/
488 : /* OGR_G_AddPoint() */
489 : /************************************************************************/
490 : /**
491 : * \brief Add a point to a geometry (line string or point).
492 : *
493 : * The vertex count of the line string is increased by one, and assigned from
494 : * the passed location value.
495 : *
496 : * @param hGeom handle to the geometry to add a point to.
497 : * @param dfX x coordinate of point to add.
498 : * @param dfY y coordinate of point to add.
499 : */
500 :
501 245 : void OGR_G_AddPoint_2D( OGRGeometryH hGeom,
502 : double dfX, double dfY )
503 :
504 : {
505 245 : VALIDATE_POINTER0( hGeom, "OGR_G_AddPoint_2D" );
506 :
507 245 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
508 : {
509 : case wkbPoint:
510 : {
511 10 : ((OGRPoint *) hGeom)->setX( dfX );
512 10 : ((OGRPoint *) hGeom)->setY( dfY );
513 : }
514 10 : break;
515 :
516 : case wkbLineString:
517 235 : ((OGRLineString *) hGeom)->addPoint( dfX, dfY );
518 235 : break;
519 :
520 : default:
521 0 : CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
522 : break;
523 : }
524 : }
525 :
526 : /************************************************************************/
527 : /* OGR_G_GetGeometryCount() */
528 : /************************************************************************/
529 : /**
530 : * \brief Fetch the number of elements in a geometry or number of geometries in container.
531 : *
532 : * Only geometries of type wkbPolygon[25D], wkbMultiPoint[25D], wkbMultiLineString[25D],
533 : * wkbMultiPolygon[25D] or wkbGeometryCollection[25D] may return a valid value.
534 : * Other geometry types will silently return 0.
535 : *
536 : * For a polygon, the returned number is the number of rings (exterior ring + interior rings).
537 : *
538 : * @param hGeom single geometry or geometry container from which to get
539 : * the number of elements.
540 : * @return the number of elements.
541 : */
542 :
543 4939 : int OGR_G_GetGeometryCount( OGRGeometryH hGeom )
544 :
545 : {
546 4939 : VALIDATE_POINTER1( hGeom, "OGR_G_GetGeometryCount", 0 );
547 :
548 4939 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
549 : {
550 : case wkbPolygon:
551 1486 : if( ((OGRPolygon *)hGeom)->getExteriorRing() == NULL )
552 6 : return 0;
553 : else
554 1480 : return ((OGRPolygon *)hGeom)->getNumInteriorRings() + 1;
555 :
556 : case wkbMultiPoint:
557 : case wkbMultiLineString:
558 : case wkbMultiPolygon:
559 : case wkbGeometryCollection:
560 597 : return ((OGRGeometryCollection *)hGeom)->getNumGeometries();
561 :
562 : default:
563 : // autotest/pymod/ogrtest.py calls this method on any geometry. So keep silent
564 : //CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
565 2856 : return 0;
566 : }
567 : }
568 :
569 : /************************************************************************/
570 : /* OGR_G_GetGeometryRef() */
571 : /************************************************************************/
572 :
573 : /**
574 : * \brief Fetch geometry from a geometry container.
575 : *
576 : * This function returns an handle to a geometry within the container.
577 : * The returned geometry remains owned by the container, and should not be
578 : * modified. The handle is only valid untill the next change to the
579 : * geometry container. Use OGR_G_Clone() to make a copy.
580 : *
581 : * This function relates to the SFCOM
582 : * IGeometryCollection::get_Geometry() method.
583 : *
584 : * This function is the same as the CPP method
585 : * OGRGeometryCollection::getGeometryRef().
586 : *
587 : * For a polygon, OGR_G_GetGeometryRef(iSubGeom) returns the exterior ring
588 : * if iSubGeom == 0, and the interior rings for iSubGeom > 0.
589 : *
590 : * @param hGeom handle to the geometry container from which to get a
591 : * geometry from.
592 : * @param iSubGeom the index of the geometry to fetch, between 0 and
593 : * getNumGeometries() - 1.
594 : * @return handle to the requested geometry.
595 : */
596 :
597 1592 : OGRGeometryH OGR_G_GetGeometryRef( OGRGeometryH hGeom, int iSubGeom )
598 :
599 : {
600 1592 : VALIDATE_POINTER1( hGeom, "OGR_G_GetGeometryRef", NULL );
601 :
602 1592 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
603 : {
604 : case wkbPolygon:
605 888 : if( iSubGeom == 0 )
606 : return (OGRGeometryH)
607 752 : ((OGRPolygon *)hGeom)->getExteriorRing();
608 : else
609 : return (OGRGeometryH)
610 136 : ((OGRPolygon *)hGeom)->getInteriorRing(iSubGeom-1);
611 :
612 : case wkbMultiPoint:
613 : case wkbMultiLineString:
614 : case wkbMultiPolygon:
615 : case wkbGeometryCollection:
616 : return (OGRGeometryH)
617 704 : ((OGRGeometryCollection *)hGeom)->getGeometryRef( iSubGeom );
618 :
619 : default:
620 0 : CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
621 0 : return 0;
622 : }
623 : }
624 :
625 : /************************************************************************/
626 : /* OGR_G_AddGeometry() */
627 : /************************************************************************/
628 :
629 : /**
630 : * \brief Add a geometry to a geometry container.
631 : *
632 : * Some subclasses of OGRGeometryCollection restrict the types of geometry
633 : * that can be added, and may return an error. The passed geometry is cloned
634 : * to make an internal copy.
635 : *
636 : * There is no SFCOM analog to this method.
637 : *
638 : * This function is the same as the CPP method
639 : * OGRGeometryCollection::addGeometry.
640 : *
641 : * For a polygon, hNewSubGeom must be a linearring. If the polygon is empty,
642 : * the first added subgeometry will be the exterior ring. The next ones will be
643 : * the interior rings.
644 : *
645 : * @param hGeom existing geometry container.
646 : * @param hNewSubGeom geometry to add to the container.
647 : *
648 : * @return OGRERR_NONE if successful, or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if
649 : * the geometry type is illegal for the type of existing geometry.
650 : */
651 :
652 52 : OGRErr OGR_G_AddGeometry( OGRGeometryH hGeom, OGRGeometryH hNewSubGeom )
653 :
654 : {
655 52 : VALIDATE_POINTER1( hGeom, "OGR_G_AddGeometry", OGRERR_UNSUPPORTED_OPERATION );
656 52 : VALIDATE_POINTER1( hNewSubGeom, "OGR_G_AddGeometry", OGRERR_UNSUPPORTED_OPERATION );
657 :
658 52 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
659 : {
660 : case wkbPolygon:
661 : {
662 12 : if( !EQUAL( ((OGRGeometry*) hNewSubGeom)->getGeometryName(), "LINEARRING" ) )
663 : {
664 0 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
665 : }
666 : else
667 : {
668 12 : ((OGRPolygon *)hGeom)->addRing( (OGRLinearRing *) hNewSubGeom );
669 12 : return OGRERR_NONE;
670 : }
671 : }
672 :
673 : case wkbMultiPoint:
674 : case wkbMultiLineString:
675 : case wkbMultiPolygon:
676 : case wkbGeometryCollection:
677 : return ((OGRGeometryCollection *)hGeom)->addGeometry(
678 40 : (OGRGeometry *) hNewSubGeom );
679 :
680 : default:
681 0 : return OGRERR_UNSUPPORTED_OPERATION;
682 : }
683 : }
684 :
685 : /************************************************************************/
686 : /* OGR_G_AddGeometryDirectly() */
687 : /************************************************************************/
688 : /**
689 : * \brief Add a geometry directly to an existing geometry container.
690 : *
691 : * Some subclasses of OGRGeometryCollection restrict the types of geometry
692 : * that can be added, and may return an error. Ownership of the passed
693 : * geometry is taken by the container rather than cloning as addGeometry()
694 : * does.
695 : *
696 : * This function is the same as the CPP method
697 : * OGRGeometryCollection::addGeometryDirectly.
698 : *
699 : * There is no SFCOM analog to this method.
700 : *
701 : * For a polygon, hNewSubGeom must be a linearring. If the polygon is empty,
702 : * the first added subgeometry will be the exterior ring. The next ones will be
703 : * the interior rings.
704 : *
705 : * @param hGeom existing geometry.
706 : * @param hNewSubGeom geometry to add to the existing geometry.
707 : *
708 : * @return OGRERR_NONE if successful, or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if
709 : * the geometry type is illegal for the type of geometry container.
710 : */
711 :
712 276 : OGRErr OGR_G_AddGeometryDirectly( OGRGeometryH hGeom,
713 : OGRGeometryH hNewSubGeom )
714 :
715 : {
716 276 : VALIDATE_POINTER1( hGeom, "OGR_G_AddGeometryDirectly", OGRERR_UNSUPPORTED_OPERATION );
717 276 : VALIDATE_POINTER1( hNewSubGeom, "OGR_G_AddGeometryDirectly", OGRERR_UNSUPPORTED_OPERATION );
718 :
719 276 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
720 : {
721 : case wkbPolygon:
722 : {
723 259 : if( !EQUAL( ((OGRGeometry*) hNewSubGeom)->getGeometryName(), "LINEARRING" ) )
724 : {
725 0 : return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
726 : }
727 : else
728 : {
729 259 : ((OGRPolygon *)hGeom)->addRingDirectly( (OGRLinearRing *) hNewSubGeom );
730 259 : return OGRERR_NONE;
731 : }
732 : }
733 :
734 : case wkbMultiPoint:
735 : case wkbMultiLineString:
736 : case wkbMultiPolygon:
737 : case wkbGeometryCollection:
738 : return ((OGRGeometryCollection *)hGeom)->addGeometryDirectly(
739 17 : (OGRGeometry *) hNewSubGeom );
740 :
741 : default:
742 0 : return OGRERR_UNSUPPORTED_OPERATION;
743 : }
744 : }
745 :
746 : /************************************************************************/
747 : /* OGR_G_RemoveGeometry() */
748 : /************************************************************************/
749 :
750 : /**
751 : * \brief Remove a geometry from an exiting geometry container.
752 : *
753 : * Removing a geometry will cause the geometry count to drop by one, and all
754 : * "higher" geometries will shuffle down one in index.
755 : *
756 : * There is no SFCOM analog to this method.
757 : *
758 : * This function is the same as the CPP method
759 : * OGRGeometryCollection::removeGeometry().
760 : *
761 : * @param hGeom the existing geometry to delete from.
762 : * @param iGeom the index of the geometry to delete. A value of -1 is a
763 : * special flag meaning that all geometries should be removed.
764 : *
765 : * @param bDelete if TRUE the geometry will be destroyed, otherwise it will
766 : * not. The default is TRUE as the existing geometry is considered to own the
767 : * geometries in it.
768 : *
769 : * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is
770 : * out of range.
771 : */
772 :
773 :
774 :
775 0 : OGRErr OGR_G_RemoveGeometry( OGRGeometryH hGeom, int iGeom, int bDelete )
776 :
777 : {
778 0 : VALIDATE_POINTER1( hGeom, "OGR_G_RemoveGeometry", 0 );
779 :
780 0 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
781 : {
782 : case wkbPolygon:
783 : {
784 : CPLError( CE_Failure, CPLE_AppDefined,
785 0 : "OGR_G_RemoveGeometry() not supported on polygons yet." );
786 0 : return OGRERR_UNSUPPORTED_OPERATION;
787 : }
788 :
789 : case wkbMultiPoint:
790 : case wkbMultiLineString:
791 : case wkbMultiPolygon:
792 : case wkbGeometryCollection:
793 0 : return ((OGRGeometryCollection *)hGeom)->removeGeometry( iGeom,bDelete);
794 :
795 : default:
796 0 : return OGRERR_UNSUPPORTED_OPERATION;
797 : }
798 : }
799 :
800 : /************************************************************************/
801 : /* OGR_G_Length() */
802 : /************************************************************************/
803 :
804 : /**
805 : * \brief Compute length of a geometry.
806 : *
807 : * Computes the area for OGRCurve or MultiCurve objects.
808 : * Undefined for all other geometry types (returns zero).
809 : *
810 : * This function utilizes the C++ get_Length() method.
811 : *
812 : * @param hGeom the geometry to operate on.
813 : * @return the lenght or 0.0 for unsupported geometry types.
814 : *
815 : * @since OGR 1.8.0
816 : */
817 :
818 12 : double OGR_G_Length( OGRGeometryH hGeom )
819 :
820 : {
821 12 : VALIDATE_POINTER1( hGeom, "OGR_G_GetLength", 0 );
822 :
823 12 : double fLength = 0.0;
824 :
825 12 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
826 : {
827 : case wkbLinearRing:
828 : case wkbLineString:
829 6 : fLength = ((OGRCurve *) hGeom)->get_Length();
830 6 : break;
831 :
832 : case wkbMultiLineString:
833 : case wkbGeometryCollection:
834 5 : fLength = ((OGRGeometryCollection *) hGeom)->get_Length();
835 5 : break;
836 :
837 : default:
838 : CPLError( CE_Warning, CPLE_AppDefined,
839 1 : "OGR_G_Length() called against a non-curve geometry type." );
840 :
841 1 : fLength = 0.0;
842 : }
843 :
844 12 : return fLength;
845 : }
846 :
847 : /************************************************************************/
848 : /* OGR_G_Area() */
849 : /************************************************************************/
850 :
851 : /**
852 : * \brief Compute geometry area.
853 : *
854 : * Computes the area for an OGRLinearRing, OGRPolygon or OGRMultiPolygon.
855 : * Undefined for all other geometry types (returns zero).
856 : *
857 : * This function utilizes the C++ get_Area() methods such as
858 : * OGRPolygon::get_Area().
859 : *
860 : * @param hGeom the geometry to operate on.
861 : * @return the area or 0.0 for unsupported geometry types.
862 : *
863 : * @since OGR 1.8.0
864 : */
865 :
866 34 : double OGR_G_Area( OGRGeometryH hGeom )
867 :
868 : {
869 34 : VALIDATE_POINTER1( hGeom, "OGR_G_Area", 0 );
870 :
871 34 : double fArea = 0.0;
872 :
873 34 : switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
874 : {
875 : case wkbPolygon:
876 27 : fArea = ((OGRPolygon *) hGeom)->get_Area();
877 27 : break;
878 :
879 : case wkbMultiPolygon:
880 2 : fArea = ((OGRMultiPolygon *) hGeom)->get_Area();
881 2 : break;
882 :
883 : case wkbLinearRing:
884 : case wkbLineString:
885 : /* This test below is required to filter out wkbLineString geometries
886 : * not being of type of wkbLinearRing.
887 : */
888 3 : if( EQUAL( ((OGRGeometry*) hGeom)->getGeometryName(), "LINEARRING" ) )
889 : {
890 3 : fArea = ((OGRLinearRing *) hGeom)->get_Area();
891 : }
892 3 : break;
893 :
894 : case wkbGeometryCollection:
895 1 : fArea = ((OGRGeometryCollection *) hGeom)->get_Area();
896 1 : break;
897 :
898 : default:
899 : CPLError( CE_Warning, CPLE_AppDefined,
900 1 : "OGR_G_Area() called against non-surface geometry type." );
901 :
902 1 : fArea = 0.0;
903 : }
904 :
905 34 : return fArea;
906 : }
907 :
908 : /**
909 : * \brief Compute geometry area (deprecated)
910 : *
911 : * @deprecated
912 : * @see OGR_G_Area()
913 : */
914 27 : double OGR_G_GetArea( OGRGeometryH hGeom )
915 :
916 : {
917 27 : return OGR_G_Area( hGeom );
918 : }
|