PostGIS  2.3.8dev-r@@SVN_REVISION@@
lwpoly.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * PostGIS is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * PostGIS is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
18  *
19  **********************************************************************
20  *
21  * Copyright (C) 2012 Sandro Santilli <strk@kbt.io>
22  * Copyright (C) 2001-2006 Refractions Research Inc.
23  *
24  **********************************************************************/
25 
26 
27 /* basic LWPOLY manipulation */
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <math.h>
33 #include "liblwgeom_internal.h"
34 #include "lwgeom_log.h"
35 
36 
37 #define CHECK_POLY_RINGS_ZM 1
38 
39 /* construct a new LWPOLY. arrays (points/points per ring) will NOT be copied
40  * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0)
41  */
42 LWPOLY*
43 lwpoly_construct(int srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
44 {
45  LWPOLY *result;
46  int hasz, hasm;
47 #ifdef CHECK_POLY_RINGS_ZM
48  char zm;
49  uint32_t i;
50 #endif
51 
52  if ( nrings < 1 ) lwerror("lwpoly_construct: need at least 1 ring");
53 
54  hasz = FLAGS_GET_Z(points[0]->flags);
55  hasm = FLAGS_GET_M(points[0]->flags);
56 
57 #ifdef CHECK_POLY_RINGS_ZM
58  zm = FLAGS_GET_ZM(points[0]->flags);
59  for (i=1; i<nrings; i++)
60  {
61  if ( zm != FLAGS_GET_ZM(points[i]->flags) )
62  lwerror("lwpoly_construct: mixed dimensioned rings");
63  }
64 #endif
65 
66  result = (LWPOLY*) lwalloc(sizeof(LWPOLY));
67  result->type = POLYGONTYPE;
68  result->flags = gflags(hasz, hasm, 0);
69  FLAGS_SET_BBOX(result->flags, bbox?1:0);
70  result->srid = srid;
71  result->nrings = nrings;
72  result->maxrings = nrings;
73  result->rings = points;
74  result->bbox = bbox;
75 
76  return result;
77 }
78 
79 LWPOLY*
80 lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2,
81  POINT4D *p3, POINT4D *p4)
82 {
83  POINTARRAY *pa = ptarray_construct_empty(hasz, hasm, 5);
84  LWPOLY *lwpoly = lwpoly_construct_empty(SRID_UNKNOWN, hasz, hasm);
85 
91 
92  lwpoly_add_ring(lwpoly, pa);
93 
94  return lwpoly;
95 }
96 
97 LWPOLY*
98 lwpoly_construct_circle(int srid, double x, double y, double radius, uint32_t segments_per_quarter, char exterior)
99 {
100  const int segments = 4*segments_per_quarter;
101  double theta;
102  LWPOLY *lwpoly;
103  POINTARRAY *pa;
104  POINT4D pt;
105  uint32_t i;
106 
107  if (segments_per_quarter == 0)
108  {
109  lwerror("Need at least one segment per quarter-circle.");
110  return NULL;
111  }
112 
113  if (radius < 0)
114  {
115  lwerror("Radius must be positive.");
116  return NULL;
117  }
118 
119  theta = 2*M_PI / segments;
120 
121  lwpoly = lwpoly_construct_empty(srid, LW_FALSE, LW_FALSE);
122  pa = ptarray_construct_empty(LW_FALSE, LW_FALSE, segments + 1);
123 
124  if (exterior)
125  radius *= sqrt(1 + pow(tan(theta/2), 2));
126 
127  for (i = 0; i <= segments; i++)
128  {
129  pt.x = x + radius*sin(i * theta);
130  pt.y = y + radius*cos(i * theta);
131  ptarray_append_point(pa, &pt, LW_TRUE);
132  }
133 
134  lwpoly_add_ring(lwpoly, pa);
135  return lwpoly;
136 }
137 
138 LWPOLY*
139 lwpoly_construct_empty(int srid, char hasz, char hasm)
140 {
141  LWPOLY *result = lwalloc(sizeof(LWPOLY));
142  result->type = POLYGONTYPE;
143  result->flags = gflags(hasz,hasm,0);
144  result->srid = srid;
145  result->nrings = 0;
146  result->maxrings = 1; /* Allocate room for ring, just in case. */
147  result->rings = lwalloc(result->maxrings * sizeof(POINTARRAY*));
148  result->bbox = NULL;
149  return result;
150 }
151 
152 void lwpoly_free(LWPOLY *poly)
153 {
154  int t;
155 
156  if( ! poly ) return;
157 
158  if ( poly->bbox )
159  lwfree(poly->bbox);
160 
161  for (t=0; t<poly->nrings; t++)
162  {
163  if ( poly->rings[t] )
164  ptarray_free(poly->rings[t]);
165  }
166 
167  if ( poly->rings )
168  lwfree(poly->rings);
169 
170  lwfree(poly);
171 }
172 
173 void printLWPOLY(LWPOLY *poly)
174 {
175  int t;
176  lwnotice("LWPOLY {");
177  lwnotice(" ndims = %i", (int)FLAGS_NDIMS(poly->flags));
178  lwnotice(" SRID = %i", (int)poly->srid);
179  lwnotice(" nrings = %i", (int)poly->nrings);
180  for (t=0; t<poly->nrings; t++)
181  {
182  lwnotice(" RING # %i :",t);
183  printPA(poly->rings[t]);
184  }
185  lwnotice("}");
186 }
187 
188 /* @brief Clone LWLINE object. Serialized point lists are not copied.
189  *
190  * @see ptarray_clone
191  */
192 LWPOLY *
194 {
195  int i;
196  LWPOLY *ret = lwalloc(sizeof(LWPOLY));
197  memcpy(ret, g, sizeof(LWPOLY));
198  ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
199  for ( i = 0; i < g->nrings; i++ ) {
200  ret->rings[i] = ptarray_clone(g->rings[i]);
201  }
202  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
203  return ret;
204 }
205 
206 /* Deep clone LWPOLY object. POINTARRAY are copied, as is ring array */
207 LWPOLY *
209 {
210  int i;
211  LWPOLY *ret = lwalloc(sizeof(LWPOLY));
212  memcpy(ret, g, sizeof(LWPOLY));
213  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
214  ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
215  for ( i = 0; i < ret->nrings; i++ )
216  {
217  ret->rings[i] = ptarray_clone_deep(g->rings[i]);
218  }
219  FLAGS_SET_READONLY(ret->flags,0);
220  return ret;
221 }
222 
226 int
228 {
229  if( ! poly || ! pa )
230  return LW_FAILURE;
231 
232  /* We have used up our storage, add some more. */
233  if( poly->nrings >= poly->maxrings )
234  {
235  int new_maxrings = 2 * (poly->nrings + 1);
236  poly->rings = lwrealloc(poly->rings, new_maxrings * sizeof(POINTARRAY*));
237  poly->maxrings = new_maxrings;
238  }
239 
240  /* Add the new ring entry. */
241  poly->rings[poly->nrings] = pa;
242  poly->nrings++;
243 
244  return LW_SUCCESS;
245 }
246 
247 void
249 {
250  int i;
251 
252  /* No-op empties */
253  if ( lwpoly_is_empty(poly) )
254  return;
255 
256  /* External ring */
257  if ( ptarray_isccw(poly->rings[0]) )
258  ptarray_reverse(poly->rings[0]);
259 
260  /* Internal rings */
261  for (i=1; i<poly->nrings; i++)
262  if ( ! ptarray_isccw(poly->rings[i]) )
263  ptarray_reverse(poly->rings[i]);
264 
265 }
266 
267 void
269 {
271 }
272 
273 void
275 {
276  int i;
277  if ( lwpoly_is_empty(poly) ) return;
278  for (i=0; i<poly->nrings; i++)
279  ptarray_reverse(poly->rings[i]);
280 }
281 
282 LWPOLY *
283 lwpoly_segmentize2d(LWPOLY *poly, double dist)
284 {
285  POINTARRAY **newrings;
286  uint32_t i;
287 
288  newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
289  for (i=0; i<poly->nrings; i++)
290  {
291  newrings[i] = ptarray_segmentize2d(poly->rings[i], dist);
292  if ( ! newrings[i] ) {
293  while (i--) ptarray_free(newrings[i]);
294  lwfree(newrings);
295  return NULL;
296  }
297  }
298  return lwpoly_construct(poly->srid, NULL,
299  poly->nrings, newrings);
300 }
301 
302 /*
303  * check coordinate equality
304  * ring and coordinate order is considered
305  */
306 char
307 lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
308 {
309  uint32_t i;
310 
311  if ( p1->nrings != p2->nrings ) return 0;
312  for (i=0; i<p1->nrings; i++)
313  {
314  if ( ! ptarray_same(p1->rings[i], p2->rings[i]) )
315  return 0;
316  }
317  return 1;
318 }
319 
320 /*
321  * Construct a polygon from a LWLINE being
322  * the shell and an array of LWLINE (possibly NULL) being holes.
323  * Pointarrays from intput geoms are cloned.
324  * SRID must be the same for each input line.
325  * Input lines must have at least 4 points, and be closed.
326  */
327 LWPOLY *
329  uint32_t nholes, const LWLINE **holes)
330 {
331  uint32_t nrings;
332  POINTARRAY **rings = lwalloc((nholes+1)*sizeof(POINTARRAY *));
333  int srid = shell->srid;
334  LWPOLY *ret;
335 
336  if ( shell->points->npoints < 4 )
337  lwerror("lwpoly_from_lwlines: shell must have at least 4 points");
338  if ( ! ptarray_is_closed_2d(shell->points) )
339  lwerror("lwpoly_from_lwlines: shell must be closed");
340  rings[0] = ptarray_clone_deep(shell->points);
341 
342  for (nrings=1; nrings<=nholes; nrings++)
343  {
344  const LWLINE *hole = holes[nrings-1];
345 
346  if ( hole->srid != srid )
347  lwerror("lwpoly_from_lwlines: mixed SRIDs in input lines");
348 
349  if ( hole->points->npoints < 4 )
350  lwerror("lwpoly_from_lwlines: holes must have at least 4 points");
351  if ( ! ptarray_is_closed_2d(hole->points) )
352  lwerror("lwpoly_from_lwlines: holes must be closed");
353 
354  rings[nrings] = ptarray_clone_deep(hole->points);
355  }
356 
357  ret = lwpoly_construct(srid, NULL, nrings, rings);
358  return ret;
359 }
360 
361 LWGEOM*
362 lwpoly_remove_repeated_points(const LWPOLY *poly, double tolerance)
363 {
364  uint32_t i;
365  POINTARRAY **newrings;
366 
367  newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
368  for (i=0; i<poly->nrings; i++)
369  {
370  newrings[i] = ptarray_remove_repeated_points_minpoints(poly->rings[i], tolerance, 4);
371  }
372 
373  return (LWGEOM*)lwpoly_construct(poly->srid,
374  poly->bbox ? gbox_copy(poly->bbox) : NULL,
375  poly->nrings, newrings);
376 
377 }
378 
379 
380 LWPOLY*
381 lwpoly_force_dims(const LWPOLY *poly, int hasz, int hasm)
382 {
383  LWPOLY *polyout;
384 
385  /* Return 2D empty */
386  if( lwpoly_is_empty(poly) )
387  {
388  polyout = lwpoly_construct_empty(poly->srid, hasz, hasm);
389  }
390  else
391  {
392  POINTARRAY **rings = NULL;
393  int i;
394  rings = lwalloc(sizeof(POINTARRAY*) * poly->nrings);
395  for( i = 0; i < poly->nrings; i++ )
396  {
397  rings[i] = ptarray_force_dims(poly->rings[i], hasz, hasm);
398  }
399  polyout = lwpoly_construct(poly->srid, NULL, poly->nrings, rings);
400  }
401  polyout->type = poly->type;
402  return polyout;
403 }
404 
405 int lwpoly_is_empty(const LWPOLY *poly)
406 {
407  if ( (poly->nrings < 1) || (!poly->rings) || (!poly->rings[0]) || (poly->rings[0]->npoints < 1) )
408  return LW_TRUE;
409  return LW_FALSE;
410 }
411 
413 {
414  int i = 0;
415  int v = 0; /* vertices */
416  assert(poly);
417  for ( i = 0; i < poly->nrings; i ++ )
418  {
419  v += poly->rings[i]->npoints;
420  }
421  return v;
422 }
423 
424 LWPOLY* lwpoly_simplify(const LWPOLY *ipoly, double dist, int preserve_collapsed)
425 {
426  int i;
427  LWPOLY *opoly = lwpoly_construct_empty(ipoly->srid, FLAGS_GET_Z(ipoly->flags), FLAGS_GET_M(ipoly->flags));
428 
429  LWDEBUGF(2, "%s: simplifying polygon with %d rings", __func__, ipoly->nrings);
430 
431  if ( lwpoly_is_empty(ipoly) )
432  {
433  lwpoly_free(opoly);
434  return NULL;
435  }
436 
437  for ( i = 0; i < ipoly->nrings; i++ )
438  {
439  POINTARRAY *opts;
440  int minvertices = 0;
441 
442  /* We'll still let holes collapse, but if we're preserving */
443  /* and this is a shell, we ensure it is kept */
444  if ( preserve_collapsed && i == 0 )
445  minvertices = 4;
446 
447  opts = ptarray_simplify(ipoly->rings[i], dist, minvertices);
448 
449  LWDEBUGF(3, "ring%d simplified from %d to %d points", i, ipoly->rings[i]->npoints, opts->npoints);
450 
451  /* Less points than are needed to form a closed ring, we can't use this */
452  if ( opts->npoints < 4 )
453  {
454  LWDEBUGF(3, "ring%d skipped (% pts)", i, opts->npoints);
455  ptarray_free(opts);
456  if ( i ) continue;
457  else break; /* Don't scan holes if shell is collapsed */
458  }
459 
460  /* Add ring to simplified polygon */
461  if( lwpoly_add_ring(opoly, opts) == LW_FAILURE )
462  {
463  lwpoly_free(opoly);
464  return NULL;
465  }
466  }
467 
468  LWDEBUGF(3, "simplified polygon with %d rings", ipoly->nrings);
469  opoly->type = ipoly->type;
470 
471  if( lwpoly_is_empty(opoly) )
472  {
473  lwpoly_free(opoly);
474  return NULL;
475  }
476 
477  return opoly;
478 }
479 
483 double
484 lwpoly_area(const LWPOLY *poly)
485 {
486  double poly_area = 0.0;
487  int i;
488 
489  if ( ! poly )
490  lwerror("lwpoly_area called with null polygon pointer!");
491 
492  for ( i=0; i < poly->nrings; i++ )
493  {
494  POINTARRAY *ring = poly->rings[i];
495  double ringarea = 0.0;
496 
497  /* Empty or messed-up ring. */
498  if ( ring->npoints < 3 )
499  continue;
500 
501  ringarea = fabs(ptarray_signed_area(ring));
502  if ( i == 0 ) /* Outer ring, positive area! */
503  poly_area += ringarea;
504  else /* Inner ring, negative area! */
505  poly_area -= ringarea;
506  }
507 
508  return poly_area;
509 }
510 
511 
516 double
518 {
519  double result=0.0;
520  int i;
521 
522  LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
523 
524  for (i=0; i<poly->nrings; i++)
525  result += ptarray_length(poly->rings[i]);
526 
527  return result;
528 }
529 
534 double
536 {
537  double result=0.0;
538  int i;
539 
540  LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
541 
542  for (i=0; i<poly->nrings; i++)
543  result += ptarray_length_2d(poly->rings[i]);
544 
545  return result;
546 }
547 
548 int
550 {
551  int i = 0;
552 
553  if ( poly->nrings == 0 )
554  return LW_TRUE;
555 
556  for ( i = 0; i < poly->nrings; i++ )
557  {
558  if (FLAGS_GET_Z(poly->flags))
559  {
560  if ( ! ptarray_is_closed_3d(poly->rings[i]) )
561  return LW_FALSE;
562  }
563  else
564  {
565  if ( ! ptarray_is_closed_2d(poly->rings[i]) )
566  return LW_FALSE;
567  }
568  }
569 
570  return LW_TRUE;
571 }
572 
573 int
575 {
576  if ( poly->nrings < 1 )
577  return LW_FAILURE;
578  return ptarray_startpoint(poly->rings[0], pt);
579 }
580 
581 int
582 lwpoly_contains_point(const LWPOLY *poly, const POINT2D *pt)
583 {
584  int i;
585 
586  if ( lwpoly_is_empty(poly) )
587  return LW_FALSE;
588 
589  if ( ptarray_contains_point(poly->rings[0], pt) == LW_OUTSIDE )
590  return LW_FALSE;
591 
592  for ( i = 1; i < poly->nrings; i++ )
593  {
594  if ( ptarray_contains_point(poly->rings[i], pt) == LW_INSIDE )
595  return LW_FALSE;
596  }
597  return LW_TRUE;
598 }
599 
600 
601 
602 LWPOLY* lwpoly_grid(const LWPOLY *poly, const gridspec *grid)
603 {
604  LWPOLY *opoly;
605  int ri;
606 
607 #if 0
608  /*
609  * TODO: control this assertion
610  * it is assumed that, since the grid size will be a pixel,
611  * a visible ring should show at least a white pixel inside,
612  * thus, for a square, that would be grid_xsize*grid_ysize
613  */
614  double minvisiblearea = grid->xsize * grid->ysize;
615 #endif
616 
617  LWDEBUGF(3, "lwpoly_grid: applying grid to polygon with %d rings", poly->nrings);
618 
619  opoly = lwpoly_construct_empty(poly->srid, lwgeom_has_z((LWGEOM*)poly), lwgeom_has_m((LWGEOM*)poly));
620 
621  for (ri=0; ri<poly->nrings; ri++)
622  {
623  POINTARRAY *ring = poly->rings[ri];
624  POINTARRAY *newring;
625 
626  newring = ptarray_grid(ring, grid);
627 
628  /* Skip ring if not composed by at least 4 pts (3 segments) */
629  if ( newring->npoints < 4 )
630  {
631  ptarray_free(newring);
632 
633  LWDEBUGF(3, "grid_polygon3d: ring%d skipped ( <4 pts )", ri);
634 
635  if ( ri ) continue;
636  else break; /* this is the external ring, no need to work on holes */
637  }
638 
639  if ( ! lwpoly_add_ring(opoly, newring) )
640  {
641  lwerror("lwpoly_grid, memory error");
642  return NULL;
643  }
644  }
645 
646  LWDEBUGF(3, "lwpoly_grid: simplified polygon with %d rings", opoly->nrings);
647 
648  if ( ! opoly->nrings )
649  {
650  lwpoly_free(opoly);
651  return NULL;
652  }
653 
654  return opoly;
655 }
double x
Definition: liblwgeom.h:351
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition: g_box.c:438
LWPOLY * lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D *p4)
Definition: lwpoly.c:80
LWPOLY * lwpoly_grid(const LWPOLY *poly, const gridspec *grid)
Definition: lwpoly.c:602
POINTARRAY * ptarray_clone(const POINTARRAY *ptarray)
Clone a POINTARRAY object.
Definition: ptarray.c:658
double lwpoly_area(const LWPOLY *poly)
Find the area of the outer ring - sum (area of inner rings).
Definition: lwpoly.c:484
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:89
void lwfree(void *mem)
Definition: lwutil.c:242
void lwpoly_release(LWPOLY *lwpoly)
Definition: lwpoly.c:268
int npoints
Definition: liblwgeom.h:370
int ptarray_is_closed_3d(const POINTARRAY *pa)
Definition: ptarray.c:707
#define POLYGONTYPE
Definition: liblwgeom.h:86
LWGEOM * lwpoly_remove_repeated_points(const LWPOLY *poly, double tolerance)
Definition: lwpoly.c:362
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:330
double lwpoly_perimeter(const LWPOLY *poly)
Compute the sum of polygon rings length.
Definition: lwpoly.c:517
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it&#39;s 3d)
Definition: ptarray.c:1645
#define LW_SUCCESS
Definition: liblwgeom.h:79
POINTARRAY * ptarray_segmentize2d(const POINTARRAY *ipa, double dist)
Returns a modified POINTARRAY so that no segment is longer than the given distance (computed using 2d...
Definition: ptarray.c:420
void printLWPOLY(LWPOLY *poly)
Definition: lwpoly.c:173
#define FLAGS_GET_ZM(flags)
Definition: liblwgeom.h:152
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring to a polygon.
Definition: lwpoly.c:227
GBOX * bbox
Definition: liblwgeom.h:452
int32_t srid
Definition: liblwgeom.h:420
double lwpoly_perimeter_2d(const LWPOLY *poly)
Compute the sum of polygon rings length (forcing 2d computation).
Definition: lwpoly.c:535
LWPOLY * lwpoly_clone(const LWPOLY *g)
Definition: lwpoly.c:193
double ptarray_signed_area(const POINTARRAY *pa)
Returns the area in cartesian units.
Definition: ptarray.c:995
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:694
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:849
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:252
#define LW_FAILURE
Definition: liblwgeom.h:78
int lwpoly_is_closed(const LWPOLY *poly)
Definition: lwpoly.c:549
char lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
Definition: lwpoly.c:307
LWPOLY * lwpoly_construct(int srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
Definition: lwpoly.c:43
int ptarray_isccw(const POINTARRAY *pa)
Definition: ptarray.c:1026
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE, then a duplicate point will not be added.
Definition: ptarray.c:156
#define LW_FALSE
Definition: liblwgeom.h:76
uint8_t type
Definition: liblwgeom.h:450
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:75
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:187
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:139
POINTARRAY ** rings
Definition: liblwgeom.h:456
LWPOLY * lwpoly_simplify(const LWPOLY *ipoly, double dist, int preserve_collapsed)
Definition: lwpoly.c:424
POINTARRAY * ptarray_clone_deep(const POINTARRAY *ptarray)
Deep clone a pointarray (also clones serialized pointlist)
Definition: ptarray.c:634
#define LW_INSIDE
Constants for point-in-polygon return values.
POINTARRAY * ptarray_force_dims(const POINTARRAY *pa, int hasz, int hasm)
Definition: ptarray.c:1035
int nrings
Definition: liblwgeom.h:454
int lwpoly_contains_point(const LWPOLY *poly, const POINT2D *pt)
Definition: lwpoly.c:582
LWPOLY * lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes)
Definition: lwpoly.c:328
LWPOLY * lwpoly_clone_deep(const LWPOLY *g)
Definition: lwpoly.c:208
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:139
void lwpoly_reverse(LWPOLY *poly)
Definition: lwpoly.c:274
LWPOLY * lwpoly_force_dims(const LWPOLY *poly, int hasz, int hasm)
Definition: lwpoly.c:381
uint8_t gflags(int hasz, int hasm, int geodetic)
Construct a new flags char.
Definition: g_util.c:145
int lwpoly_startpoint(const LWPOLY *poly, POINT4D *pt)
Definition: lwpoly.c:574
LWPOLY * lwpoly_segmentize2d(LWPOLY *poly, double dist)
Definition: lwpoly.c:283
int ptarray_startpoint(const POINTARRAY *pa, POINT4D *pt)
Definition: ptarray.c:1826
double ptarray_length(const POINTARRAY *pts)
Find the 3d/2d length of the given POINTARRAY (depending on its dimensionality)
Definition: ptarray.c:1673
POINTARRAY * ptarray_simplify(POINTARRAY *inpts, double epsilon, unsigned int minpts)
Definition: ptarray.c:1554
#define FLAGS_SET_BBOX(flags, value)
Definition: liblwgeom.h:147
int maxrings
Definition: liblwgeom.h:455
LWPOLY * lwpoly_construct_circle(int srid, double x, double y, double radius, uint32_t segments_per_quarter, char exterior)
Definition: lwpoly.c:98
void printPA(POINTARRAY *pa)
Definition: lwgeom_api.c:611
int32_t srid
Definition: liblwgeom.h:453
int lwpoly_count_vertices(LWPOLY *poly)
Definition: lwpoly.c:412
char ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2)
Definition: ptarray.c:484
POINTARRAY * ptarray_remove_repeated_points_minpoints(const POINTARRAY *in, double tolerance, int minpoints)
Definition: ptarray.c:1437
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:152
POINTARRAY * ptarray_grid(const POINTARRAY *pa, const gridspec *grid)
Definition: ptarray.c:1843
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:235
void ptarray_reverse(POINTARRAY *pa)
Definition: ptarray.c:343
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:140
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
Definition: lwgeom.c:385
int ptarray_contains_point(const POINTARRAY *pa, const POINT2D *pt)
Return 1 if the point is inside the POINTARRAY, -1 if it is outside, and 0 if it is on the boundary...
Definition: ptarray.c:733
void lwpoly_force_clockwise(LWPOLY *poly)
Definition: lwpoly.c:248
uint8_t flags
Definition: liblwgeom.h:451
#define LW_OUTSIDE
void * lwalloc(size_t size)
Definition: lwutil.c:227
double y
Definition: liblwgeom.h:351
opts
Definition: ovdump.py:44
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:151
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:856
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:102
int lwpoly_is_empty(const LWPOLY *poly)
Definition: lwpoly.c:405
#define FLAGS_SET_READONLY(flags, value)
Definition: liblwgeom.h:149
POINTARRAY * points
Definition: liblwgeom.h:421
Snap to grid.