PostGIS  3.7.0dev-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(int32_t 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 = lwflags(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(int32_t 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(int32_t srid, double x, double y, double radius, uint32_t segments_per_quarter, char exterior)
121 {
122  const uint32_t 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(int32_t srid, char hasz, char hasm)
162 {
163  LWPOLY *result = lwalloc(sizeof(LWPOLY));
164  result->type = POLYGONTYPE;
165  result->flags = lwflags(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
176 {
177  uint32_t t;
178 
179  if (!poly) return;
180 
181  if (poly->bbox) lwfree(poly->bbox);
182 
183  if ( poly->rings )
184  {
185  for (t = 0; t < poly->nrings; t++)
186  if (poly->rings[t]) ptarray_free(poly->rings[t]);
187  lwfree(poly->rings);
188  }
189 
190  lwfree(poly);
191 }
192 
193 void printLWPOLY(LWPOLY *poly)
194 {
195  uint32_t t;
196  lwnotice("LWPOLY {");
197  lwnotice(" ndims = %i", (int)FLAGS_NDIMS(poly->flags));
198  lwnotice(" SRID = %i", (int)poly->srid);
199  lwnotice(" nrings = %i", (int)poly->nrings);
200  for (t=0; t<poly->nrings; t++)
201  {
202  lwnotice(" RING # %i :",t);
203  printPA(poly->rings[t]);
204  }
205  lwnotice("}");
206 }
207 
208 /* @brief Clone LWLINE object. Serialized point lists are not copied.
209  *
210  * @see ptarray_clone
211  */
212 LWPOLY *
214 {
215  uint32_t i;
216  LWPOLY *ret = lwalloc(sizeof(LWPOLY));
217  memcpy(ret, g, sizeof(LWPOLY));
218  ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
219  for ( i = 0; i < g->nrings; i++ ) {
220  ret->rings[i] = ptarray_clone(g->rings[i]);
221  }
222  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
223  return ret;
224 }
225 
226 /* Deep clone LWPOLY object. POINTARRAY are copied, as is ring array */
227 LWPOLY *
229 {
230  uint32_t i;
231  LWPOLY *ret = lwalloc(sizeof(LWPOLY));
232  memcpy(ret, g, sizeof(LWPOLY));
233  if ( g->bbox ) ret->bbox = gbox_copy(g->bbox);
234  ret->rings = lwalloc(sizeof(POINTARRAY *)*g->nrings);
235  for ( i = 0; i < ret->nrings; i++ )
236  {
237  ret->rings[i] = ptarray_clone_deep(g->rings[i]);
238  }
239  FLAGS_SET_READONLY(ret->flags,0);
240  return ret;
241 }
242 
246 int
248 {
249  if( ! poly || ! pa )
250  return LW_FAILURE;
251 
252  /* We have used up our storage, add some more. */
253  if( poly->nrings >= poly->maxrings )
254  {
255  int new_maxrings = 2 * (poly->nrings + 1);
256  poly->rings = lwrealloc(poly->rings, new_maxrings * sizeof(POINTARRAY*));
257  poly->maxrings = new_maxrings;
258  }
259 
260  /* Add the new ring entry. */
261  poly->rings[poly->nrings] = pa;
262  poly->nrings++;
263 
264  return LW_SUCCESS;
265 }
266 
267 void
268 lwpoly_force_orientation(LWPOLY *poly, int orientation)
269 {
270  /* No-op no orientation */
271  if (orientation == LW_NONE) return;
272 
273  /* No-op empties */
274  if (lwpoly_is_empty(poly)) return;
275 
276  /* External ring */
277  if (!ptarray_has_orientation(poly->rings[0], orientation))
279 
280  /* Internal rings must run opposite to external */
281  for (uint32_t i = 1; i < poly->nrings; i++)
282  if (!ptarray_has_orientation(poly->rings[i], -1 * orientation))
284 }
285 
286 int
287 lwpoly_has_orientation(const LWPOLY *poly, int orientation)
288 {
289  if (lwpoly_is_empty(poly))
290  return LW_TRUE;
291 
292  /* Exterior ring matches orientation? */
293  if(!ptarray_has_orientation(poly->rings[0], orientation))
294  return LW_FALSE;
295 
296  /* Interior rings are opposite of orientation? */
297  for (uint32_t i = 1; i < poly->nrings; i++)
298  if (!ptarray_has_orientation(poly->rings[i], -1 * orientation))
299  return LW_FALSE;
300 
301  return LW_TRUE;
302 }
303 
304 void
306 {
308 }
309 
310 LWPOLY *
311 lwpoly_segmentize2d(const LWPOLY *poly, double dist)
312 {
313  POINTARRAY **newrings;
314  uint32_t i;
315 
316  newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
317  for (i=0; i<poly->nrings; i++)
318  {
319  newrings[i] = ptarray_segmentize2d(poly->rings[i], dist);
320  if ( ! newrings[i] )
321  {
322  uint32_t j = 0;
323  for (j = 0; j < i; j++)
324  ptarray_free(newrings[j]);
325  lwfree(newrings);
326  return NULL;
327  }
328  }
329  return lwpoly_construct(poly->srid, NULL,
330  poly->nrings, newrings);
331 }
332 
333 /*
334  * check coordinate equality
335  * ring and coordinate order is considered
336  */
337 char
338 lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
339 {
340  uint32_t i;
341 
342  if ( p1->nrings != p2->nrings ) return 0;
343  for (i=0; i<p1->nrings; i++)
344  {
345  if ( ! ptarray_same(p1->rings[i], p2->rings[i]) )
346  return 0;
347  }
348  return 1;
349 }
350 
351 /*
352  * Construct a polygon from a LWLINE being
353  * the shell and an array of LWLINE (possibly NULL) being holes.
354  * Pointarrays from input geoms are cloned.
355  * SRID must be the same for each input line.
356  * Input lines must have at least 4 points, and be closed.
357  */
358 LWPOLY *
360  uint32_t nholes, const LWLINE **holes)
361 {
362  uint32_t nrings;
363  POINTARRAY **rings = lwalloc((nholes+1)*sizeof(POINTARRAY *));
364  int32_t srid = shell->srid;
365  LWPOLY *ret;
366 
367  if ( shell->points->npoints < 4 )
368  lwerror("lwpoly_from_lwlines: shell must have at least 4 points");
369  if ( ! ptarray_is_closed_2d(shell->points) )
370  lwerror("lwpoly_from_lwlines: shell must be closed");
371  rings[0] = ptarray_clone_deep(shell->points);
372 
373  for (nrings=1; nrings<=nholes; nrings++)
374  {
375  const LWLINE *hole = holes[nrings-1];
376 
377  if ( hole->srid != srid )
378  lwerror("lwpoly_from_lwlines: mixed SRIDs in input lines");
379 
380  if ( hole->points->npoints < 4 )
381  lwerror("lwpoly_from_lwlines: holes must have at least 4 points");
382  if ( ! ptarray_is_closed_2d(hole->points) )
383  lwerror("lwpoly_from_lwlines: holes must be closed");
384 
385  rings[nrings] = ptarray_clone_deep(hole->points);
386  }
387 
388  ret = lwpoly_construct(srid, NULL, nrings, rings);
389  return ret;
390 }
391 
392 LWPOLY*
393 lwpoly_force_dims(const LWPOLY *poly, int hasz, int hasm, double zval, double mval)
394 {
395  LWPOLY *polyout;
396 
397  /* Return 2D empty */
398  if( lwpoly_is_empty(poly) )
399  {
400  polyout = lwpoly_construct_empty(poly->srid, hasz, hasm);
401  }
402  else
403  {
404  POINTARRAY **rings = NULL;
405  uint32_t i;
406  rings = lwalloc(sizeof(POINTARRAY*) * poly->nrings);
407  for( i = 0; i < poly->nrings; i++ )
408  {
409  rings[i] = ptarray_force_dims(poly->rings[i], hasz, hasm, zval, mval);
410  }
411  polyout = lwpoly_construct(poly->srid, NULL, poly->nrings, rings);
412  }
413  polyout->type = poly->type;
414  return polyout;
415 }
416 
417 uint32_t lwpoly_count_vertices(const LWPOLY *poly)
418 {
419  uint32_t i = 0;
420  uint32_t v = 0; /* vertices */
421  assert(poly);
422  for ( i = 0; i < poly->nrings; i ++ )
423  {
424  v += poly->rings[i]->npoints;
425  }
426  return v;
427 }
428 
432 double
433 lwpoly_area(const LWPOLY *poly)
434 {
435  double poly_area = 0.0;
436  uint32_t i;
437 
438  if ( ! poly )
439  lwerror("lwpoly_area called with null polygon pointer!");
440 
441  for ( i=0; i < poly->nrings; i++ )
442  {
443  POINTARRAY *ring = poly->rings[i];
444  double ringarea = 0.0;
445 
446  /* Empty or messed-up ring. */
447  if ( ring->npoints < 3 )
448  continue;
449 
450  ringarea = fabs(ptarray_signed_area(ring));
451  if ( i == 0 ) /* Outer ring, positive area! */
452  poly_area += ringarea;
453  else /* Inner ring, negative area! */
454  poly_area -= ringarea;
455  }
456 
457  return poly_area;
458 }
459 
460 
465 double
467 {
468  double result=0.0;
469  uint32_t i;
470 
471  LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
472 
473  for (i=0; i<poly->nrings; i++)
474  result += ptarray_length(poly->rings[i]);
475 
476  return result;
477 }
478 
483 double
485 {
486  double result=0.0;
487  uint32_t i;
488 
489  LWDEBUGF(2, "in lwgeom_polygon_perimeter (%d rings)", poly->nrings);
490 
491  for (i=0; i<poly->nrings; i++)
492  result += ptarray_length_2d(poly->rings[i]);
493 
494  return result;
495 }
496 
497 int
499 {
500  uint32_t i = 0;
501 
502  if ( poly->nrings == 0 )
503  return LW_TRUE;
504 
505  for ( i = 0; i < poly->nrings; i++ )
506  {
507  if (FLAGS_GET_Z(poly->flags))
508  {
509  if ( ! ptarray_is_closed_3d(poly->rings[i]) )
510  return LW_FALSE;
511  }
512  else
513  {
514  if ( ! ptarray_is_closed_2d(poly->rings[i]) )
515  return LW_FALSE;
516  }
517  }
518 
519  return LW_TRUE;
520 }
521 
522 int
524 {
525  if ( poly->nrings < 1 )
526  return LW_FAILURE;
527  return ptarray_startpoint(poly->rings[0], pt);
528 }
529 
530 int
531 lwpoly_contains_point(const LWPOLY *poly, const POINT2D *pt)
532 {
533  uint32_t i;
534  int t;
535 
536  if ( lwpoly_is_empty(poly) )
537  return LW_OUTSIDE;
538 
539  t = ptarray_contains_point(poly->rings[0], pt);
540 
541  if (t == LW_INSIDE)
542  {
543  for (i = 1; i < poly->nrings; i++)
544  {
545  t = ptarray_contains_point(poly->rings[i], pt);
546  if (t == LW_INSIDE)
547  return LW_OUTSIDE;
548  if (t == LW_BOUNDARY)
549  {
550  return LW_BOUNDARY;
551  }
552  }
553  return LW_INSIDE;
554  }
555  else
556  return t;
557 }
558 
559 
char result[OUT_DOUBLE_BUFFER_SIZE]
Definition: cu_print.c:267
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition: gbox.c:438
#define LW_FALSE
Definition: liblwgeom.h:94
void lwgeom_set_srid(LWGEOM *geom, int32_t srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
Definition: lwgeom.c:1638
#define LW_FAILURE
Definition: liblwgeom.h:96
int ptarray_is_closed_3d(const POINTARRAY *pa)
Definition: ptarray.c:723
#define LW_SUCCESS
Definition: liblwgeom.h:97
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:357
#define FLAGS_SET_BBOX(flags, value)
Definition: liblwgeom.h:174
POINTARRAY * ptarray_clone_deep(const POINTARRAY *ptarray)
Deep clone a pointarray (also clones serialized pointlist)
Definition: ptarray.c:643
void printPA(POINTARRAY *pa)
Definition: lwgeom_api.c:440
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:1975
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:165
void * lwrealloc(void *mem, size_t size)
Definition: lwutil.c:242
void lwfree(void *mem)
Definition: lwutil.c:248
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:179
#define POLYGONTYPE
Definition: liblwgeom.h:104
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:59
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:166
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:327
#define FLAGS_GET_ZM(flags)
Definition: liblwgeom.h:180
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,...
Definition: ptarray.c:147
void * lwalloc(size_t size)
Definition: lwutil.c:227
#define FLAGS_SET_READONLY(flags, value)
Definition: liblwgeom.h:176
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:710
lwflags_t lwflags(int hasz, int hasm, int geodetic)
Construct a new flags bitmask.
Definition: lwutil.c:477
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:93
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
Definition: lwgeom.c:496
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:215
void lwgeom_add_bbox(LWGEOM *lwgeom)
Compute a bbox if not already computed.
Definition: lwgeom.c:723
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:413
POINTARRAY * ptarray_force_dims(const POINTARRAY *pa, int hasz, int hasm, double zval, double mval)
Definition: ptarray.c:1188
#define LW_INSIDE
Constants for point-in-polygon return values.
#define LW_BOUNDARY
void ptarray_reverse_in_place(POINTARRAY *pa)
Definition: ptarray.c:339
double ptarray_length(const POINTARRAY *pts)
Find the 3d/2d length of the given POINTARRAY (depending on its dimensionality)
Definition: ptarray.c:2003
#define LW_NONE
double ptarray_signed_area(const POINTARRAY *pa)
Returns the area in cartesian units.
Definition: ptarray.c:1143
POINTARRAY * ptarray_clone(const POINTARRAY *ptarray)
Clone a POINTARRAY object.
Definition: ptarray.c:674
int ptarray_startpoint(const POINTARRAY *pa, POINT4D *pt)
Definition: ptarray.c:2219
char ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2)
Definition: ptarray.c:484
int ptarray_contains_point(const POINTARRAY *pa, const POINT2D *pt)
The following is based on the "Fast Winding Number Inclusion of a Point in a Polygon" algorithm by Da...
Definition: ptarray.c:755
int ptarray_has_orientation(const POINTARRAY *pa, int orientation)
Definition: ptarray.c:1174
int lwpoly_is_empty(const LWPOLY *poly)
#define LW_OUTSIDE
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:106
void lwnotice(const char *fmt,...) __attribute__((format(printf
Write a notice out to the notice handler.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
LWPOLY * lwpoly_construct_circle(int32_t srid, double x, double y, double radius, uint32_t segments_per_quarter, char exterior)
Definition: lwpoly.c:120
LWPOLY * lwpoly_clone_deep(const LWPOLY *g)
Definition: lwpoly.c:228
int lwpoly_startpoint(const LWPOLY *poly, POINT4D *pt)
Definition: lwpoly.c:523
void printLWPOLY(LWPOLY *poly)
Definition: lwpoly.c:193
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring to a polygon.
Definition: lwpoly.c:247
double lwpoly_area(const LWPOLY *poly)
Find the area of the outer ring - sum (area of inner rings).
Definition: lwpoly.c:433
LWPOLY * lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D *p4)
Definition: lwpoly.c:80
LWPOLY * lwpoly_construct_envelope(int32_t srid, double x1, double y1, double x2, double y2)
Definition: lwpoly.c:98
int lwpoly_has_orientation(const LWPOLY *poly, int orientation)
Definition: lwpoly.c:287
void lwpoly_force_orientation(LWPOLY *poly, int orientation)
Definition: lwpoly.c:268
LWPOLY * lwpoly_force_dims(const LWPOLY *poly, int hasz, int hasm, double zval, double mval)
Definition: lwpoly.c:393
uint32_t lwpoly_count_vertices(const LWPOLY *poly)
Definition: lwpoly.c:417
char lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
Definition: lwpoly.c:338
void lwpoly_release(LWPOLY *lwpoly)
Definition: lwpoly.c:305
double lwpoly_perimeter_2d(const LWPOLY *poly)
Compute the sum of polygon rings length (forcing 2d computation).
Definition: lwpoly.c:484
LWPOLY * lwpoly_segmentize2d(const LWPOLY *poly, double dist)
Definition: lwpoly.c:311
int lwpoly_contains_point(const LWPOLY *poly, const POINT2D *pt)
Definition: lwpoly.c:531
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:175
LWPOLY * lwpoly_clone(const LWPOLY *g)
Definition: lwpoly.c:213
LWPOLY * lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes)
Definition: lwpoly.c:359
int lwpoly_is_closed(const LWPOLY *poly)
Definition: lwpoly.c:498
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwpoly.c:161
LWPOLY * lwpoly_construct(int32_t srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
Definition: lwpoly.c:43
double lwpoly_perimeter(const LWPOLY *poly)
Compute the sum of polygon rings length.
Definition: lwpoly.c:466
POINTARRAY * points
Definition: liblwgeom.h:483
int32_t srid
Definition: liblwgeom.h:484
POINTARRAY ** rings
Definition: liblwgeom.h:519
uint8_t type
Definition: liblwgeom.h:522
uint32_t maxrings
Definition: liblwgeom.h:525
uint32_t nrings
Definition: liblwgeom.h:524
GBOX * bbox
Definition: liblwgeom.h:518
lwflags_t flags
Definition: liblwgeom.h:521
int32_t srid
Definition: liblwgeom.h:520
double x
Definition: liblwgeom.h:414
double y
Definition: liblwgeom.h:414
uint32_t npoints
Definition: liblwgeom.h:427