PostGIS  2.4.9dev-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_envelope(int srid, double x1, double y1, double x2, double y2)
99 {
100  POINT4D p1, p2, p3, p4;
101  LWPOLY *poly;
102 
103  p1.x = x1;
104  p1.y = y1;
105  p2.x = x1;
106  p2.y = y2;
107  p3.x = x2;
108  p3.y = y2;
109  p4.x = x2;
110  p4.y = y1;
111 
112  poly = lwpoly_construct_rectangle(0, 0, &p1, &p2, &p3, &p4);
113  lwgeom_set_srid(lwpoly_as_lwgeom(poly), srid);
115 
116  return poly;
117 }
118 
119 LWPOLY*
120 lwpoly_construct_circle(int srid, double x, double y, double radius, uint32_t segments_per_quarter, char exterior)
121 {
122  const int segments = 4*segments_per_quarter;
123  double theta;
124  LWPOLY *lwpoly;
125  POINTARRAY *pa;
126  POINT4D pt;
127  uint32_t i;
128 
129  if (segments_per_quarter == 0)
130  {
131  lwerror("Need at least one segment per quarter-circle.");
132  return NULL;
133  }
134 
135  if (radius < 0)
136  {
137  lwerror("Radius must be positive.");
138  return NULL;
139  }
140 
141  theta = 2*M_PI / segments;
142 
143  lwpoly = lwpoly_construct_empty(srid, LW_FALSE, LW_FALSE);
144  pa = ptarray_construct_empty(LW_FALSE, LW_FALSE, segments + 1);
145 
146  if (exterior)
147  radius *= sqrt(1 + pow(tan(theta/2), 2));
148 
149  for (i = 0; i <= segments; i++)
150  {
151  pt.x = x + radius*sin(i * theta);
152  pt.y = y + radius*cos(i * theta);
153  ptarray_append_point(pa, &pt, LW_TRUE);
154  }
155 
156  lwpoly_add_ring(lwpoly, pa);
157  return lwpoly;
158 }
159 
160 LWPOLY*
161 lwpoly_construct_empty(int srid, char hasz, char hasm)
162 {
163  LWPOLY *result = lwalloc(sizeof(LWPOLY));
164  result->type = POLYGONTYPE;
165  result->flags = gflags(hasz,hasm,0);
166  result->srid = srid;
167  result->nrings = 0;
168  result->maxrings = 1; /* Allocate room for ring, just in case. */
169  result->rings = lwalloc(result->maxrings * sizeof(POINTARRAY*));
170  result->bbox = NULL;
171  return result;
172 }
173 
174 void lwpoly_free(LWPOLY *poly)
175 {
176  int t;
177 
178  if( ! poly ) return;
179 
180  if ( poly->bbox )
181  lwfree(poly->bbox);
182 
183  for (t=0; t<poly->nrings; t++)
184  {
185  if ( poly->rings[t] )
186  ptarray_free(poly->rings[t]);
187  }
188 
189  if ( poly->rings )
190  lwfree(poly->rings);
191 
192  lwfree(poly);
193 }
194 
195 void printLWPOLY(LWPOLY *poly)
196 {
197  int t;
198  lwnotice("LWPOLY {");
199  lwnotice(" ndims = %i", (int)FLAGS_NDIMS(poly->flags));
200  lwnotice(" SRID = %i", (int)poly->srid);
201  lwnotice(" nrings = %i", (int)poly->nrings);
202  for (t=0; t<poly->nrings; t++)
203  {
204  lwnotice(" RING # %i :",t);
205  printPA(poly->rings[t]);
206  }
207  lwnotice("}");
208 }
209 
210 /* @brief Clone LWLINE object. Serialized point lists are not copied.
211  *
212  * @see ptarray_clone
213  */
214 LWPOLY *
216 {
217  int i;
218  LWPOLY *ret = lwalloc(sizeof(LWPOLY));
219  memcpy(ret, g, sizeof(LWPOLY));
220  ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
221  for ( i = 0; i < g->nrings; i++ ) {
222  ret->rings[i] = ptarray_clone(g->rings[i]);
223  }
224  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
225  return ret;
226 }
227 
228 /* Deep clone LWPOLY object. POINTARRAY are copied, as is ring array */
229 LWPOLY *
231 {
232  int i;
233  LWPOLY *ret = lwalloc(sizeof(LWPOLY));
234  memcpy(ret, g, sizeof(LWPOLY));
235  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
236  ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
237  for ( i = 0; i < ret->nrings; i++ )
238  {
239  ret->rings[i] = ptarray_clone_deep(g->rings[i]);
240  }
241  FLAGS_SET_READONLY(ret->flags,0);
242  return ret;
243 }
244 
248 int
250 {
251  if( ! poly || ! pa )
252  return LW_FAILURE;
253 
254  /* We have used up our storage, add some more. */
255  if( poly->nrings >= poly->maxrings )
256  {
257  int new_maxrings = 2 * (poly->nrings + 1);
258  poly->rings = lwrealloc(poly->rings, new_maxrings * sizeof(POINTARRAY*));
259  poly->maxrings = new_maxrings;
260  }
261 
262  /* Add the new ring entry. */
263  poly->rings[poly->nrings] = pa;
264  poly->nrings++;
265 
266  return LW_SUCCESS;
267 }
268 
269 void
271 {
272  int i;
273 
274  /* No-op empties */
275  if ( lwpoly_is_empty(poly) )
276  return;
277 
278  /* External ring */
279  if ( ptarray_isccw(poly->rings[0]) )
280  ptarray_reverse(poly->rings[0]);
281 
282  /* Internal rings */
283  for (i=1; i<poly->nrings; i++)
284  if ( ! ptarray_isccw(poly->rings[i]) )
285  ptarray_reverse(poly->rings[i]);
286 
287 }
288 
289 int
291 {
292  int i;
293 
294  if ( lwpoly_is_empty(poly) )
295  return LW_TRUE;
296 
297  if ( ptarray_isccw(poly->rings[0]) )
298  return LW_FALSE;
299 
300  for ( i = 1; i < poly->nrings; i++)
301  if ( !ptarray_isccw(poly->rings[i]) )
302  return LW_FALSE;
303 
304  return LW_TRUE;
305 }
306 
307 void
309 {
311 }
312 
313 void
315 {
316  int i;
317  if ( lwpoly_is_empty(poly) ) return;
318  for (i=0; i<poly->nrings; i++)
319  ptarray_reverse(poly->rings[i]);
320 }
321 
322 LWPOLY *
323 lwpoly_segmentize2d(LWPOLY *poly, double dist)
324 {
325  POINTARRAY **newrings;
326  uint32_t i;
327 
328  newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
329  for (i=0; i<poly->nrings; i++)
330  {
331  newrings[i] = ptarray_segmentize2d(poly->rings[i], dist);
332  if ( ! newrings[i] ) {
333  while (i--) ptarray_free(newrings[i]);
334  lwfree(newrings);
335  return NULL;
336  }
337  }
338  return lwpoly_construct(poly->srid, NULL,
339  poly->nrings, newrings);
340 }
341 
342 /*
343  * check coordinate equality
344  * ring and coordinate order is considered
345  */
346 char
347 lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
348 {
349  uint32_t i;
350 
351  if ( p1->nrings != p2->nrings ) return 0;
352  for (i=0; i<p1->nrings; i++)
353  {
354  if ( ! ptarray_same(p1->rings[i], p2->rings[i]) )
355  return 0;
356  }
357  return 1;
358 }
359 
360 /*
361  * Construct a polygon from a LWLINE being
362  * the shell and an array of LWLINE (possibly NULL) being holes.
363  * Pointarrays from intput geoms are cloned.
364  * SRID must be the same for each input line.
365  * Input lines must have at least 4 points, and be closed.
366  */
367 LWPOLY *
369  uint32_t nholes, const LWLINE **holes)
370 {
371  uint32_t nrings;
372  POINTARRAY **rings = lwalloc((nholes+1)*sizeof(POINTARRAY *));
373  int srid = shell->srid;
374  LWPOLY *ret;
375 
376  if ( shell->points->npoints < 4 )
377  lwerror("lwpoly_from_lwlines: shell must have at least 4 points");
378  if ( ! ptarray_is_closed_2d(shell->points) )
379  lwerror("lwpoly_from_lwlines: shell must be closed");
380  rings[0] = ptarray_clone_deep(shell->points);
381 
382  for (nrings=1; nrings<=nholes; nrings++)
383  {
384  const LWLINE *hole = holes[nrings-1];
385 
386  if ( hole->srid != srid )
387  lwerror("lwpoly_from_lwlines: mixed SRIDs in input lines");
388 
389  if ( hole->points->npoints < 4 )
390  lwerror("lwpoly_from_lwlines: holes must have at least 4 points");
391  if ( ! ptarray_is_closed_2d(hole->points) )
392  lwerror("lwpoly_from_lwlines: holes must be closed");
393 
394  rings[nrings] = ptarray_clone_deep(hole->points);
395  }
396 
397  ret = lwpoly_construct(srid, NULL, nrings, rings);
398  return ret;
399 }
400 
401 LWGEOM*
402 lwpoly_remove_repeated_points(const LWPOLY *poly, double tolerance)
403 {
404  uint32_t i;
405  POINTARRAY **newrings;
406 
407  newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
408  for (i=0; i<poly->nrings; i++)
409  {
410  newrings[i] = ptarray_remove_repeated_points_minpoints(poly->rings[i], tolerance, 4);
411  }
412 
413  return (LWGEOM*)lwpoly_construct(poly->srid,
414  poly->bbox ? gbox_copy(poly->bbox) : NULL,
415  poly->nrings, newrings);
416 
417 }
418 
419 
420 LWPOLY*
421 lwpoly_force_dims(const LWPOLY *poly, int hasz, int hasm)
422 {
423  LWPOLY *polyout;
424 
425  /* Return 2D empty */
426  if( lwpoly_is_empty(poly) )
427  {
428  polyout = lwpoly_construct_empty(poly->srid, hasz, hasm);
429  }
430  else
431  {
432  POINTARRAY **rings = NULL;
433  int i;
434  rings = lwalloc(sizeof(POINTARRAY*) * poly->nrings);
435  for( i = 0; i < poly->nrings; i++ )
436  {
437  rings[i] = ptarray_force_dims(poly->rings[i], hasz, hasm);
438  }
439  polyout = lwpoly_construct(poly->srid, NULL, poly->nrings, rings);
440  }
441  polyout->type = poly->type;
442  return polyout;
443 }
444 
445 int lwpoly_is_empty(const LWPOLY *poly)
446 {
447  if ( (poly->nrings < 1) || (!poly->rings) || (!poly->rings[0]) || (poly->rings[0]->npoints < 1) )
448  return LW_TRUE;
449  return LW_FALSE;
450 }
451 
453 {
454  int i = 0;
455  int v = 0; /* vertices */
456  assert(poly);
457  for ( i = 0; i < poly->nrings; i ++ )
458  {
459  v += poly->rings[i]->npoints;
460  }
461  return v;
462 }
463 
464 LWPOLY* lwpoly_simplify(const LWPOLY *ipoly, double dist, int preserve_collapsed)
465 {
466  int i;
467  LWPOLY *opoly = lwpoly_construct_empty(ipoly->srid, FLAGS_GET_Z(ipoly->flags), FLAGS_GET_M(ipoly->flags));
468 
469  LWDEBUGF(2, "%s: simplifying polygon with %d rings", __func__, ipoly->nrings);
470 
471  if ( lwpoly_is_empty(ipoly) )
472  {
473  lwpoly_free(opoly);
474  return NULL;
475  }
476 
477  for ( i = 0; i < ipoly->nrings; i++ )
478  {
479  POINTARRAY *opts;
480  int minvertices = 0;
481 
482  /* We'll still let holes collapse, but if we're preserving */
483  /* and this is a shell, we ensure it is kept */
484  if ( preserve_collapsed && i == 0 )
485  minvertices = 4;
486 
487  opts = ptarray_simplify(ipoly->rings[i], dist, minvertices);
488 
489  LWDEBUGF(3, "ring%d simplified from %d to %d points", i, ipoly->rings[i]->npoints, opts->npoints);
490 
491  /* Less points than are needed to form a closed ring, we can't use this */
492  if ( opts->npoints < 4 )
493  {
494  LWDEBUGF(3, "ring%d skipped (% pts)", i, opts->npoints);
495  ptarray_free(opts);
496  if ( i ) continue;
497  else break; /* Don't scan holes if shell is collapsed */
498  }
499 
500  /* Add ring to simplified polygon */
501  if( lwpoly_add_ring(opoly, opts) == LW_FAILURE )
502  {
503  lwpoly_free(opoly);
504  return NULL;
505  }
506  }
507 
508  LWDEBUGF(3, "simplified polygon with %d rings", ipoly->nrings);
509  opoly->type = ipoly->type;
510 
511  if( lwpoly_is_empty(opoly) )
512  {
513  lwpoly_free(opoly);
514  return NULL;
515  }
516 
517  return opoly;
518 }
519 
523 double
524 lwpoly_area(const LWPOLY *poly)
525 {
526  double poly_area = 0.0;
527  int i;
528 
529  if ( ! poly )
530  lwerror("lwpoly_area called with null polygon pointer!");
531 
532  for ( i=0; i < poly->nrings; i++ )
533  {
534  POINTARRAY *ring = poly->rings[i];
535  double ringarea = 0.0;
536 
537  /* Empty or messed-up ring. */
538  if ( ring->npoints < 3 )
539  continue;
540 
541  ringarea = fabs(ptarray_signed_area(ring));
542  if ( i == 0 ) /* Outer ring, positive area! */
543  poly_area += ringarea;
544  else /* Inner ring, negative area! */
545  poly_area -= ringarea;
546  }
547 
548  return poly_area;
549 }
550 
551 
556 double
558 {
559  double result=0.0;
560  int i;
561 
562  LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
563 
564  for (i=0; i<poly->nrings; i++)
565  result += ptarray_length(poly->rings[i]);
566 
567  return result;
568 }
569 
574 double
576 {
577  double result=0.0;
578  int i;
579 
580  LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
581 
582  for (i=0; i<poly->nrings; i++)
583  result += ptarray_length_2d(poly->rings[i]);
584 
585  return result;
586 }
587 
588 int
590 {
591  int i = 0;
592 
593  if ( poly->nrings == 0 )
594  return LW_TRUE;
595 
596  for ( i = 0; i < poly->nrings; i++ )
597  {
598  if (FLAGS_GET_Z(poly->flags))
599  {
600  if ( ! ptarray_is_closed_3d(poly->rings[i]) )
601  return LW_FALSE;
602  }
603  else
604  {
605  if ( ! ptarray_is_closed_2d(poly->rings[i]) )
606  return LW_FALSE;
607  }
608  }
609 
610  return LW_TRUE;
611 }
612 
613 int
615 {
616  if ( poly->nrings < 1 )
617  return LW_FAILURE;
618  return ptarray_startpoint(poly->rings[0], pt);
619 }
620 
621 int
622 lwpoly_contains_point(const LWPOLY *poly, const POINT2D *pt)
623 {
624  int i;
625 
626  if ( lwpoly_is_empty(poly) )
627  return LW_FALSE;
628 
629  if ( ptarray_contains_point(poly->rings[0], pt) == LW_OUTSIDE )
630  return LW_FALSE;
631 
632  for ( i = 1; i < poly->nrings; i++ )
633  {
634  if ( ptarray_contains_point(poly->rings[i], pt) == LW_INSIDE )
635  return LW_FALSE;
636  }
637  return LW_TRUE;
638 }
639 
640 
641 
642 LWPOLY* lwpoly_grid(const LWPOLY *poly, const gridspec *grid)
643 {
644  LWPOLY *opoly;
645  int ri;
646 
647 #if 0
648  /*
649  * TODO: control this assertion
650  * it is assumed that, since the grid size will be a pixel,
651  * a visible ring should show at least a white pixel inside,
652  * thus, for a square, that would be grid_xsize*grid_ysize
653  */
654  double minvisiblearea = grid->xsize * grid->ysize;
655 #endif
656 
657  LWDEBUGF(3, "lwpoly_grid: applying grid to polygon with %d rings", poly->nrings);
658 
659  opoly = lwpoly_construct_empty(poly->srid, lwgeom_has_z((LWGEOM*)poly), lwgeom_has_m((LWGEOM*)poly));
660 
661  for (ri=0; ri<poly->nrings; ri++)
662  {
663  POINTARRAY *ring = poly->rings[ri];
664  POINTARRAY *newring;
665 
666  newring = ptarray_grid(ring, grid);
667 
668  /* Skip ring if not composed by at least 4 pts (3 segments) */
669  if ( newring->npoints < 4 )
670  {
671  ptarray_free(newring);
672 
673  LWDEBUGF(3, "grid_polygon3d: ring%d skipped ( <4 pts )", ri);
674 
675  if ( ri ) continue;
676  else break; /* this is the external ring, no need to work on holes */
677  }
678 
679  if ( ! lwpoly_add_ring(opoly, newring) )
680  {
681  lwerror("lwpoly_grid, memory error");
682  return NULL;
683  }
684  }
685 
686  LWDEBUGF(3, "lwpoly_grid: simplified polygon with %d rings", opoly->nrings);
687 
688  if ( ! opoly->nrings )
689  {
690  lwpoly_free(opoly);
691  return NULL;
692  }
693 
694  return opoly;
695 }
double x
Definition: liblwgeom.h:352
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:642
POINTARRAY * ptarray_clone(const POINTARRAY *ptarray)
Clone a POINTARRAY object.
Definition: ptarray.c:661
double lwpoly_area(const LWPOLY *poly)
Find the area of the outer ring - sum (area of inner rings).
Definition: lwpoly.c:524
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
void lwfree(void *mem)
Definition: lwutil.c:244
void lwpoly_release(LWPOLY *lwpoly)
Definition: lwpoly.c:308
int npoints
Definition: liblwgeom.h:371
int ptarray_is_closed_3d(const POINTARRAY *pa)
Definition: ptarray.c:710
#define POLYGONTYPE
Definition: liblwgeom.h:87
LWGEOM * lwpoly_remove_repeated_points(const LWPOLY *poly, double tolerance)
Definition: lwpoly.c:402
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:557
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it&#39;s 3d)
Definition: ptarray.c:1692
#define LW_SUCCESS
Definition: liblwgeom.h:80
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:415
void printLWPOLY(LWPOLY *poly)
Definition: lwpoly.c:195
#define FLAGS_GET_ZM(flags)
Definition: liblwgeom.h:153
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring to a polygon.
Definition: lwpoly.c:249
GBOX * bbox
Definition: liblwgeom.h:453
int32_t srid
Definition: liblwgeom.h:421
double lwpoly_perimeter_2d(const LWPOLY *poly)
Compute the sum of polygon rings length (forcing 2d computation).
Definition: lwpoly.c:575
LWPOLY * lwpoly_clone(const LWPOLY *g)
Definition: lwpoly.c:215
double ptarray_signed_area(const POINTARRAY *pa)
Returns the area in cartesian units.
Definition: ptarray.c:998
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:697
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:885
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:288
#define LW_FAILURE
Definition: liblwgeom.h:79
int lwpoly_is_closed(const LWPOLY *poly)
Definition: lwpoly.c:589
char lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
Definition: lwpoly.c:347
unsigned int uint32_t
Definition: uthash.h:78
LWPOLY * lwpoly_construct(int srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
Definition: lwpoly.c:43
int lwpoly_is_clockwise(LWPOLY *poly)
Definition: lwpoly.c:290
int ptarray_isccw(const POINTARRAY *pa)
Definition: ptarray.c:1029
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:77
LWPOLY * lwpoly_construct_envelope(int srid, double x1, double y1, double x2, double y2)
Definition: lwpoly.c:98
uint8_t type
Definition: liblwgeom.h:451
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:161
POINTARRAY ** rings
Definition: liblwgeom.h:457
LWPOLY * lwpoly_simplify(const LWPOLY *ipoly, double dist, int preserve_collapsed)
Definition: lwpoly.c:464
POINTARRAY * ptarray_clone_deep(const POINTARRAY *ptarray)
Deep clone a pointarray (also clones serialized pointlist)
Definition: ptarray.c:630
#define LW_INSIDE
Constants for point-in-polygon return values.
POINTARRAY * ptarray_force_dims(const POINTARRAY *pa, int hasz, int hasm)
Definition: ptarray.c:1038
int nrings
Definition: liblwgeom.h:455
int lwpoly_contains_point(const LWPOLY *poly, const POINT2D *pt)
Definition: lwpoly.c:622
LWPOLY * lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes)
Definition: lwpoly.c:368
LWPOLY * lwpoly_clone_deep(const LWPOLY *g)
Definition: lwpoly.c:230
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:140
void lwpoly_reverse(LWPOLY *poly)
Definition: lwpoly.c:314
LWPOLY * lwpoly_force_dims(const LWPOLY *poly, int hasz, int hasm)
Definition: lwpoly.c:421
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:614
LWPOLY * lwpoly_segmentize2d(LWPOLY *poly, double dist)
Definition: lwpoly.c:323
int ptarray_startpoint(const POINTARRAY *pa, POINT4D *pt)
Definition: ptarray.c:1873
double ptarray_length(const POINTARRAY *pts)
Find the 3d/2d length of the given POINTARRAY (depending on its dimensionality)
Definition: ptarray.c:1720
POINTARRAY * ptarray_simplify(POINTARRAY *inpts, double epsilon, unsigned int minpts)
Definition: ptarray.c:1601
#define FLAGS_SET_BBOX(flags, value)
Definition: liblwgeom.h:148
int maxrings
Definition: liblwgeom.h:456
LWPOLY * lwpoly_construct_circle(int srid, double x, double y, double radius, uint32_t segments_per_quarter, char exterior)
Definition: lwpoly.c:120
void printPA(POINTARRAY *pa)
Definition: lwgeom_api.c:472
int32_t srid
Definition: liblwgeom.h:454
int lwpoly_count_vertices(LWPOLY *poly)
Definition: lwpoly.c:452
char ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2)
Definition: ptarray.c:479
POINTARRAY * ptarray_remove_repeated_points_minpoints(const POINTARRAY *in, double tolerance, int minpoints)
Definition: ptarray.c:1538
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:174
POINTARRAY * ptarray_grid(const POINTARRAY *pa, const gridspec *grid)
Definition: ptarray.c:1890
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:237
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:648
void ptarray_reverse(POINTARRAY *pa)
Definition: ptarray.c:343
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:141
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
Definition: lwgeom.c:421
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:736
void lwgeom_set_srid(LWGEOM *geom, int srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
void lwpoly_force_clockwise(LWPOLY *poly)
Definition: lwpoly.c:270
uint8_t flags
Definition: liblwgeom.h:452
#define LW_OUTSIDE
void * lwalloc(size_t size)
Definition: lwutil.c:229
double y
Definition: liblwgeom.h:352
opts
Definition: ovdump.py:44
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:152
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:892
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
int lwpoly_is_empty(const LWPOLY *poly)
Definition: lwpoly.c:445
#define FLAGS_SET_READONLY(flags, value)
Definition: liblwgeom.h:150
POINTARRAY * points
Definition: liblwgeom.h:422
Snap to grid.