PostGIS  2.4.9dev-r@@SVN_REVISION@@
lwgeom.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) 2001-2006 Refractions Research Inc.
22  *
23  **********************************************************************/
24 
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 
30 #include "liblwgeom_internal.h"
31 #include "lwgeom_log.h"
32 
33 
35 void
37 {
38  LWCOLLECTION *coll;
39  int i;
40 
41  switch (lwgeom->type)
42  {
43  case POLYGONTYPE:
44  lwpoly_force_clockwise((LWPOLY *)lwgeom);
45  return;
46 
47  case TRIANGLETYPE:
49  return;
50 
51  /* Not handle POLYHEDRALSURFACE and TIN
52  as they are supposed to be well oriented */
53  case MULTIPOLYGONTYPE:
54  case COLLECTIONTYPE:
55  coll = (LWCOLLECTION *)lwgeom;
56  for (i=0; i<coll->ngeoms; i++)
57  lwgeom_force_clockwise(coll->geoms[i]);
58  return;
59  }
60 }
61 
63 int
65 {
66  switch (lwgeom->type)
67  {
68  case POLYGONTYPE:
69  return lwpoly_is_clockwise((LWPOLY *)lwgeom);
70 
71  case TRIANGLETYPE:
72  return lwtriangle_is_clockwise((LWTRIANGLE *)lwgeom);
73 
74  case MULTIPOLYGONTYPE:
75  case COLLECTIONTYPE:
76  {
77  int i;
78  LWCOLLECTION* coll = (LWCOLLECTION *)lwgeom;
79 
80  for (i=0; i < coll->ngeoms; i++)
81  if (!lwgeom_is_clockwise(coll->geoms[i]))
82  return LW_FALSE;
83  return LW_TRUE;
84  }
85  default:
86  return LW_TRUE;
87  return LW_FALSE;
88  }
89 }
90 
92 void
94 {
95  int i;
96  LWCOLLECTION *col;
97 
98  switch (lwgeom->type)
99  {
100  case LINETYPE:
101  lwline_reverse((LWLINE *)lwgeom);
102  return;
103  case POLYGONTYPE:
104  lwpoly_reverse((LWPOLY *)lwgeom);
105  return;
106  case TRIANGLETYPE:
107  lwtriangle_reverse((LWTRIANGLE *)lwgeom);
108  return;
109  case CIRCSTRINGTYPE:
111  return;
112  case MULTICURVETYPE:
113  case MULTILINETYPE:
114  case MULTIPOLYGONTYPE:
115  case MULTISURFACETYPE:
117  case TINTYPE:
118  case COLLECTIONTYPE:
119  case COMPOUNDTYPE:
120  case CURVEPOLYTYPE:
121  col = (LWCOLLECTION *)lwgeom;
122  for (i=0; i<col->ngeoms; i++)
123  lwgeom_reverse(col->geoms[i]);
124  return;
125  }
126 }
127 
128 LWPOINT *
129 lwgeom_as_lwpoint(const LWGEOM *lwgeom)
130 {
131  if ( lwgeom == NULL ) return NULL;
132  if ( lwgeom->type == POINTTYPE )
133  return (LWPOINT *)lwgeom;
134  else return NULL;
135 }
136 
137 LWLINE *
138 lwgeom_as_lwline(const LWGEOM *lwgeom)
139 {
140  if ( lwgeom == NULL ) return NULL;
141  if ( lwgeom->type == LINETYPE )
142  return (LWLINE *)lwgeom;
143  else return NULL;
144 }
145 
146 LWCIRCSTRING *
148 {
149  if ( lwgeom == NULL ) return NULL;
150  if ( lwgeom->type == CIRCSTRINGTYPE )
151  return (LWCIRCSTRING *)lwgeom;
152  else return NULL;
153 }
154 
155 LWCOMPOUND *
157 {
158  if ( lwgeom == NULL ) return NULL;
159  if ( lwgeom->type == COMPOUNDTYPE )
160  return (LWCOMPOUND *)lwgeom;
161  else return NULL;
162 }
163 
164 LWCURVEPOLY *
166 {
167  if ( lwgeom == NULL ) return NULL;
168  if ( lwgeom->type == CURVEPOLYTYPE )
169  return (LWCURVEPOLY *)lwgeom;
170  else return NULL;
171 }
172 
173 LWPOLY *
174 lwgeom_as_lwpoly(const LWGEOM *lwgeom)
175 {
176  if ( lwgeom == NULL ) return NULL;
177  if ( lwgeom->type == POLYGONTYPE )
178  return (LWPOLY *)lwgeom;
179  else return NULL;
180 }
181 
182 LWTRIANGLE *
184 {
185  if ( lwgeom == NULL ) return NULL;
186  if ( lwgeom->type == TRIANGLETYPE )
187  return (LWTRIANGLE *)lwgeom;
188  else return NULL;
189 }
190 
191 LWCOLLECTION *
193 {
194  if ( lwgeom == NULL ) return NULL;
195  if ( lwgeom_is_collection(lwgeom) )
196  return (LWCOLLECTION*)lwgeom;
197  else return NULL;
198 }
199 
200 LWMPOINT *
202 {
203  if ( lwgeom == NULL ) return NULL;
204  if ( lwgeom->type == MULTIPOINTTYPE )
205  return (LWMPOINT *)lwgeom;
206  else return NULL;
207 }
208 
209 LWMLINE *
210 lwgeom_as_lwmline(const LWGEOM *lwgeom)
211 {
212  if ( lwgeom == NULL ) return NULL;
213  if ( lwgeom->type == MULTILINETYPE )
214  return (LWMLINE *)lwgeom;
215  else return NULL;
216 }
217 
218 LWMPOLY *
219 lwgeom_as_lwmpoly(const LWGEOM *lwgeom)
220 {
221  if ( lwgeom == NULL ) return NULL;
222  if ( lwgeom->type == MULTIPOLYGONTYPE )
223  return (LWMPOLY *)lwgeom;
224  else return NULL;
225 }
226 
227 LWPSURFACE *
229 {
230  if ( lwgeom->type == POLYHEDRALSURFACETYPE )
231  return (LWPSURFACE *)lwgeom;
232  else return NULL;
233 }
234 
235 LWTIN *
236 lwgeom_as_lwtin(const LWGEOM *lwgeom)
237 {
238  if ( lwgeom->type == TINTYPE )
239  return (LWTIN *)lwgeom;
240  else return NULL;
241 }
242 
244 {
245  return (LWGEOM *)obj;
246 }
247 
249 {
250  return (LWGEOM *)obj;
251 }
252 
254 {
255  if ( obj == NULL ) return NULL;
256  return (LWGEOM *)obj;
257 }
259 {
260  if ( obj == NULL ) return NULL;
261  return (LWGEOM *)obj;
262 }
264 {
265  if ( obj == NULL ) return NULL;
266  return (LWGEOM *)obj;
267 }
269 {
270  if ( obj == NULL ) return NULL;
271  return (LWGEOM *)obj;
272 }
274 {
275  if ( obj == NULL ) return NULL;
276  return (LWGEOM *)obj;
277 }
279 {
280  if ( obj == NULL ) return NULL;
281  return (LWGEOM *)obj;
282 }
284 {
285  if ( obj == NULL ) return NULL;
286  return (LWGEOM *)obj;
287 }
289 {
290  if ( obj == NULL ) return NULL;
291  return (LWGEOM *)obj;
292 }
294 {
295  if ( obj == NULL ) return NULL;
296  return (LWGEOM *)obj;
297 }
299 {
300  if ( obj == NULL ) return NULL;
301  return (LWGEOM *)obj;
302 }
304 {
305  if ( obj == NULL ) return NULL;
306  return (LWGEOM *)obj;
307 }
308 
309 
314 {
315  0,
316  MULTIPOINTTYPE, /* 1 */
317  MULTILINETYPE, /* 2 */
318  MULTIPOLYGONTYPE, /* 3 */
319  0,0,0,0,
320  MULTICURVETYPE, /* 8 */
321  MULTICURVETYPE, /* 9 */
322  MULTISURFACETYPE, /* 10 */
323  POLYHEDRALSURFACETYPE, /* 11 */
324  0, 0,
325  TINTYPE, /* 14 */
326  0
327 };
328 
332 LWGEOM *
333 lwgeom_as_multi(const LWGEOM *lwgeom)
334 {
335  LWGEOM **ogeoms;
336  LWGEOM *ogeom = NULL;
337  GBOX *box = NULL;
338  int type;
339 
340  type = lwgeom->type;
341 
342  if ( ! MULTITYPE[type] ) return lwgeom_clone(lwgeom);
343 
344  if( lwgeom_is_empty(lwgeom) )
345  {
347  MULTITYPE[type],
348  lwgeom->srid,
349  FLAGS_GET_Z(lwgeom->flags),
350  FLAGS_GET_M(lwgeom->flags)
351  );
352  }
353  else
354  {
355  ogeoms = lwalloc(sizeof(LWGEOM*));
356  ogeoms[0] = lwgeom_clone(lwgeom);
357 
358  /* Sub-geometries are not allowed to have bboxes or SRIDs, move the bbox to the collection */
359  box = ogeoms[0]->bbox;
360  ogeoms[0]->bbox = NULL;
361  ogeoms[0]->srid = SRID_UNKNOWN;
362 
363  ogeom = (LWGEOM *)lwcollection_construct(MULTITYPE[type], lwgeom->srid, box, 1, ogeoms);
364  }
365 
366  return ogeom;
367 }
368 
372 LWGEOM *
373 lwgeom_as_curve(const LWGEOM *lwgeom)
374 {
375  LWGEOM *ogeom;
376  int type = lwgeom->type;
377  /*
378  int hasz = FLAGS_GET_Z(lwgeom->flags);
379  int hasm = FLAGS_GET_M(lwgeom->flags);
380  int srid = lwgeom->srid;
381  */
382 
383  switch(type)
384  {
385  case LINETYPE:
386  /* turn to COMPOUNDCURVE */
387  ogeom = (LWGEOM*)lwcompound_construct_from_lwline((LWLINE*)lwgeom);
388  break;
389  case POLYGONTYPE:
391  break;
392  case MULTILINETYPE:
393  /* turn to MULTICURVE */
394  ogeom = lwgeom_clone(lwgeom);
395  ogeom->type = MULTICURVETYPE;
396  break;
397  case MULTIPOLYGONTYPE:
398  /* turn to MULTISURFACE */
399  ogeom = lwgeom_clone(lwgeom);
400  ogeom->type = MULTISURFACETYPE;
401  break;
402  case COLLECTIONTYPE:
403  default:
404  ogeom = lwgeom_clone(lwgeom);
405  break;
406  }
407 
408  /* TODO: copy bbox from input geom ? */
409 
410  return ogeom;
411 }
412 
413 
420 void
422 {
423  if ( ! lwgeom )
424  lwerror("lwgeom_release: someone called on 0x0");
425 
426  LWDEBUGF(3, "releasing type %s", lwtype_name(lwgeom->type));
427 
428  /* Drop bounding box (always a copy) */
429  if ( lwgeom->bbox )
430  {
431  LWDEBUGF(3, "lwgeom_release: releasing bbox. %p", lwgeom->bbox);
432  lwfree(lwgeom->bbox);
433  }
434  lwfree(lwgeom);
435 
436 }
437 
438 
439 /* @brief Clone LWGEOM object. Serialized point lists are not copied.
440  *
441  * @see ptarray_clone
442  */
443 LWGEOM *
444 lwgeom_clone(const LWGEOM *lwgeom)
445 {
446  LWDEBUGF(2, "lwgeom_clone called with %p, %s",
447  lwgeom, lwtype_name(lwgeom->type));
448 
449  switch (lwgeom->type)
450  {
451  case POINTTYPE:
452  return (LWGEOM *)lwpoint_clone((LWPOINT *)lwgeom);
453  case LINETYPE:
454  return (LWGEOM *)lwline_clone((LWLINE *)lwgeom);
455  case CIRCSTRINGTYPE:
456  return (LWGEOM *)lwcircstring_clone((LWCIRCSTRING *)lwgeom);
457  case POLYGONTYPE:
458  return (LWGEOM *)lwpoly_clone((LWPOLY *)lwgeom);
459  case TRIANGLETYPE:
460  return (LWGEOM *)lwtriangle_clone((LWTRIANGLE *)lwgeom);
461  case COMPOUNDTYPE:
462  case CURVEPOLYTYPE:
463  case MULTICURVETYPE:
464  case MULTISURFACETYPE:
465  case MULTIPOINTTYPE:
466  case MULTILINETYPE:
467  case MULTIPOLYGONTYPE:
469  case TINTYPE:
470  case COLLECTIONTYPE:
471  return (LWGEOM *)lwcollection_clone((LWCOLLECTION *)lwgeom);
472  default:
473  lwerror("lwgeom_clone: Unknown geometry type: %s", lwtype_name(lwgeom->type));
474  return NULL;
475  }
476 }
477 
481 LWGEOM *
482 lwgeom_clone_deep(const LWGEOM *lwgeom)
483 {
484  LWDEBUGF(2, "lwgeom_clone called with %p, %s",
485  lwgeom, lwtype_name(lwgeom->type));
486 
487  switch (lwgeom->type)
488  {
489  case POINTTYPE:
490  case LINETYPE:
491  case CIRCSTRINGTYPE:
492  case TRIANGLETYPE:
493  return (LWGEOM *)lwline_clone_deep((LWLINE *)lwgeom);
494  case POLYGONTYPE:
495  return (LWGEOM *)lwpoly_clone_deep((LWPOLY *)lwgeom);
496  case COMPOUNDTYPE:
497  case CURVEPOLYTYPE:
498  case MULTICURVETYPE:
499  case MULTISURFACETYPE:
500  case MULTIPOINTTYPE:
501  case MULTILINETYPE:
502  case MULTIPOLYGONTYPE:
504  case TINTYPE:
505  case COLLECTIONTYPE:
506  return (LWGEOM *)lwcollection_clone_deep((LWCOLLECTION *)lwgeom);
507  default:
508  lwerror("lwgeom_clone_deep: Unknown geometry type: %s", lwtype_name(lwgeom->type));
509  return NULL;
510  }
511 }
512 
513 
517 char*
518 lwgeom_to_ewkt(const LWGEOM *lwgeom)
519 {
520  char* wkt = NULL;
521  size_t wkt_size = 0;
522 
523  wkt = lwgeom_to_wkt(lwgeom, WKT_EXTENDED, 12, &wkt_size);
524 
525  if ( ! wkt )
526  {
527  lwerror("Error writing geom %p to WKT", lwgeom);
528  }
529 
530  return wkt;
531 }
532 
543 char
544 lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
545 {
546  LWDEBUGF(2, "lwgeom_same(%s, %s) called",
547  lwtype_name(lwgeom1->type),
548  lwtype_name(lwgeom2->type));
549 
550  if ( lwgeom1->type != lwgeom2->type )
551  {
552  LWDEBUG(3, " type differ");
553 
554  return LW_FALSE;
555  }
556 
557  if ( FLAGS_GET_ZM(lwgeom1->flags) != FLAGS_GET_ZM(lwgeom2->flags) )
558  {
559  LWDEBUG(3, " ZM flags differ");
560 
561  return LW_FALSE;
562  }
563 
564  /* Check boxes if both already computed */
565  if ( lwgeom1->bbox && lwgeom2->bbox )
566  {
567  /*lwnotice("bbox1:%p, bbox2:%p", lwgeom1->bbox, lwgeom2->bbox);*/
568  if ( ! gbox_same(lwgeom1->bbox, lwgeom2->bbox) )
569  {
570  LWDEBUG(3, " bounding boxes differ");
571 
572  return LW_FALSE;
573  }
574  }
575 
576  /* geoms have same type, invoke type-specific function */
577  switch (lwgeom1->type)
578  {
579  case POINTTYPE:
580  return lwpoint_same((LWPOINT *)lwgeom1,
581  (LWPOINT *)lwgeom2);
582  case LINETYPE:
583  return lwline_same((LWLINE *)lwgeom1,
584  (LWLINE *)lwgeom2);
585  case POLYGONTYPE:
586  return lwpoly_same((LWPOLY *)lwgeom1,
587  (LWPOLY *)lwgeom2);
588  case TRIANGLETYPE:
589  return lwtriangle_same((LWTRIANGLE *)lwgeom1,
590  (LWTRIANGLE *)lwgeom2);
591  case CIRCSTRINGTYPE:
592  return lwcircstring_same((LWCIRCSTRING *)lwgeom1,
593  (LWCIRCSTRING *)lwgeom2);
594  case MULTIPOINTTYPE:
595  case MULTILINETYPE:
596  case MULTIPOLYGONTYPE:
597  case MULTICURVETYPE:
598  case MULTISURFACETYPE:
599  case COMPOUNDTYPE:
600  case CURVEPOLYTYPE:
602  case TINTYPE:
603  case COLLECTIONTYPE:
604  return lwcollection_same((LWCOLLECTION *)lwgeom1,
605  (LWCOLLECTION *)lwgeom2);
606  default:
607  lwerror("lwgeom_same: unsupported geometry type: %s",
608  lwtype_name(lwgeom1->type));
609  return LW_FALSE;
610  }
611 
612 }
613 
614 int
615 lwpoint_inside_circle(const LWPOINT *p, double cx, double cy, double rad)
616 {
617  const POINT2D *pt;
618  POINT2D center;
619 
620  if ( ! p || ! p->point )
621  return LW_FALSE;
622 
623  pt = getPoint2d_cp(p->point, 0);
624 
625  center.x = cx;
626  center.y = cy;
627 
628  if ( distance2d_pt_pt(pt, &center) < rad )
629  return LW_TRUE;
630 
631  return LW_FALSE;
632 }
633 
634 void
636 {
637  if ( lwgeom->bbox ) lwfree(lwgeom->bbox);
638  lwgeom->bbox = NULL;
639  FLAGS_SET_BBOX(lwgeom->flags, 0);
640 }
641 
647 void
649 {
650  /* an empty LWGEOM has no bbox */
651  if ( lwgeom_is_empty(lwgeom) ) return;
652 
653  if ( lwgeom->bbox ) return;
654  FLAGS_SET_BBOX(lwgeom->flags, 1);
655  lwgeom->bbox = gbox_new(lwgeom->flags);
656  lwgeom_calculate_gbox(lwgeom, lwgeom->bbox);
657 }
658 
659 void
661 {
662  if ( lwgeom_is_empty(lwgeom) ) return;
663 
664  FLAGS_SET_BBOX(lwgeom->flags, 1);
665 
666  if ( ! ( gbox || lwgeom->bbox ) )
667  {
668  lwgeom->bbox = gbox_new(lwgeom->flags);
669  lwgeom_calculate_gbox(lwgeom, lwgeom->bbox);
670  }
671  else if ( gbox && ! lwgeom->bbox )
672  {
673  lwgeom->bbox = gbox_clone(gbox);
674  }
675 
676  if ( lwgeom_is_collection(lwgeom) )
677  {
678  int i;
679  LWCOLLECTION *lwcol = (LWCOLLECTION*)lwgeom;
680 
681  for ( i = 0; i < lwcol->ngeoms; i++ )
682  {
683  lwgeom_add_bbox_deep(lwcol->geoms[i], lwgeom->bbox);
684  }
685  }
686 }
687 
688 const GBOX *
690 {
691  /* add it if not already there */
692  lwgeom_add_bbox((LWGEOM *)lwg);
693  return lwg->bbox;
694 }
695 
696 
701 int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
702 {
703  gbox->flags = lwgeom->flags;
704  if( FLAGS_GET_GEODETIC(lwgeom->flags) )
705  return lwgeom_calculate_gbox_geodetic(lwgeom, gbox);
706  else
707  return lwgeom_calculate_gbox_cartesian(lwgeom, gbox);
708 }
709 
710 void
712 {
713  lwgeom->srid = SRID_UNKNOWN; /* TODO: To be changed to SRID_UNKNOWN */
714 }
715 
716 LWGEOM *
717 lwgeom_segmentize2d(LWGEOM *lwgeom, double dist)
718 {
719  switch (lwgeom->type)
720  {
721  case LINETYPE:
722  return (LWGEOM *)lwline_segmentize2d((LWLINE *)lwgeom,
723  dist);
724  case POLYGONTYPE:
725  return (LWGEOM *)lwpoly_segmentize2d((LWPOLY *)lwgeom,
726  dist);
727  case MULTILINETYPE:
728  case MULTIPOLYGONTYPE:
729  case COLLECTIONTYPE:
731  (LWCOLLECTION *)lwgeom, dist);
732 
733  default:
734  return lwgeom_clone(lwgeom);
735  }
736 }
737 
738 LWGEOM*
740 {
741  return lwgeom_force_dims(geom, 0, 0);
742 }
743 
744 LWGEOM*
746 {
747  return lwgeom_force_dims(geom, 1, 0);
748 }
749 
750 LWGEOM*
752 {
753  return lwgeom_force_dims(geom, 0, 1);
754 }
755 
756 LWGEOM*
758 {
759  return lwgeom_force_dims(geom, 1, 1);
760 }
761 
762 LWGEOM*
763 lwgeom_force_dims(const LWGEOM *geom, int hasz, int hasm)
764 {
765  switch(geom->type)
766  {
767  case POINTTYPE:
768  return lwpoint_as_lwgeom(lwpoint_force_dims((LWPOINT*)geom, hasz, hasm));
769  case CIRCSTRINGTYPE:
770  case LINETYPE:
771  case TRIANGLETYPE:
772  return lwline_as_lwgeom(lwline_force_dims((LWLINE*)geom, hasz, hasm));
773  case POLYGONTYPE:
774  return lwpoly_as_lwgeom(lwpoly_force_dims((LWPOLY*)geom, hasz, hasm));
775  case COMPOUNDTYPE:
776  case CURVEPOLYTYPE:
777  case MULTICURVETYPE:
778  case MULTISURFACETYPE:
779  case MULTIPOINTTYPE:
780  case MULTILINETYPE:
781  case MULTIPOLYGONTYPE:
783  case TINTYPE:
784  case COLLECTIONTYPE:
785  return lwcollection_as_lwgeom(lwcollection_force_dims((LWCOLLECTION*)geom, hasz, hasm));
786  default:
787  lwerror("lwgeom_force_2d: unsupported geom type: %s", lwtype_name(geom->type));
788  return NULL;
789  }
790 }
791 
792 LWGEOM*
793 lwgeom_force_sfs(LWGEOM *geom, int version)
794 {
795  LWCOLLECTION *col;
796  int i;
797  LWGEOM *g;
798 
799  /* SFS 1.2 version */
800  if (version == 120)
801  {
802  switch(geom->type)
803  {
804  /* SQL/MM types */
805  case CIRCSTRINGTYPE:
806  case COMPOUNDTYPE:
807  case CURVEPOLYTYPE:
808  case MULTICURVETYPE:
809  case MULTISURFACETYPE:
810  return lwgeom_stroke(geom, 32);
811 
812  case COLLECTIONTYPE:
813  col = (LWCOLLECTION*)geom;
814  for ( i = 0; i < col->ngeoms; i++ )
815  col->geoms[i] = lwgeom_force_sfs((LWGEOM*)col->geoms[i], version);
816 
817  return lwcollection_as_lwgeom((LWCOLLECTION*)geom);
818 
819  default:
820  return (LWGEOM *)geom;
821  }
822  }
823 
824 
825  /* SFS 1.1 version */
826  switch(geom->type)
827  {
828  /* SQL/MM types */
829  case CIRCSTRINGTYPE:
830  case COMPOUNDTYPE:
831  case CURVEPOLYTYPE:
832  case MULTICURVETYPE:
833  case MULTISURFACETYPE:
834  return lwgeom_stroke(geom, 32);
835 
836  /* SFS 1.2 types */
837  case TRIANGLETYPE:
838  g = lwpoly_as_lwgeom(lwpoly_from_lwlines((LWLINE*)geom, 0, NULL));
839  lwgeom_free(geom);
840  return g;
841 
842  case TINTYPE:
843  col = (LWCOLLECTION*) geom;
844  for ( i = 0; i < col->ngeoms; i++ )
845  {
846  g = lwpoly_as_lwgeom(lwpoly_from_lwlines((LWLINE*)col->geoms[i], 0, NULL));
847  lwgeom_free(col->geoms[i]);
848  col->geoms[i] = g;
849  }
850  col->type = COLLECTIONTYPE;
851  return lwmpoly_as_lwgeom((LWMPOLY*)geom);
852 
854  geom->type = COLLECTIONTYPE;
855  return (LWGEOM *)geom;
856 
857  /* Collection */
858  case COLLECTIONTYPE:
859  col = (LWCOLLECTION*)geom;
860  for ( i = 0; i < col->ngeoms; i++ )
861  col->geoms[i] = lwgeom_force_sfs((LWGEOM*)col->geoms[i], version);
862 
863  return lwcollection_as_lwgeom((LWCOLLECTION*)geom);
864 
865  default:
866  return (LWGEOM *)geom;
867  }
868 }
869 
870 int32_t
872 {
873  if ( ! geom ) return SRID_UNKNOWN;
874  return geom->srid;
875 }
876 
877 uint32_t
879 {
880  if ( ! geom ) return 0;
881  return geom->type;
882 }
883 
884 int
885 lwgeom_has_z(const LWGEOM *geom)
886 {
887  if ( ! geom ) return LW_FALSE;
888  return FLAGS_GET_Z(geom->flags);
889 }
890 
891 int
892 lwgeom_has_m(const LWGEOM *geom)
893 {
894  if ( ! geom ) return LW_FALSE;
895  return FLAGS_GET_M(geom->flags);
896 }
897 
898 int
899 lwgeom_ndims(const LWGEOM *geom)
900 {
901  if ( ! geom ) return 0;
902  return FLAGS_NDIMS(geom->flags);
903 }
904 
905 
906 void
908 {
909  LWPOINT *pt;
910  LWLINE *ln;
911  LWPOLY *ply;
912  LWCOLLECTION *col;
913  int i;
914 
915  FLAGS_SET_GEODETIC(geom->flags, value);
916  if ( geom->bbox )
917  FLAGS_SET_GEODETIC(geom->bbox->flags, value);
918 
919  switch(geom->type)
920  {
921  case POINTTYPE:
922  pt = (LWPOINT*)geom;
923  if ( pt->point )
924  FLAGS_SET_GEODETIC(pt->point->flags, value);
925  break;
926  case LINETYPE:
927  ln = (LWLINE*)geom;
928  if ( ln->points )
929  FLAGS_SET_GEODETIC(ln->points->flags, value);
930  break;
931  case POLYGONTYPE:
932  ply = (LWPOLY*)geom;
933  for ( i = 0; i < ply->nrings; i++ )
934  FLAGS_SET_GEODETIC(ply->rings[i]->flags, value);
935  break;
936  case MULTIPOINTTYPE:
937  case MULTILINETYPE:
938  case MULTIPOLYGONTYPE:
939  case COLLECTIONTYPE:
940  col = (LWCOLLECTION*)geom;
941  for ( i = 0; i < col->ngeoms; i++ )
942  lwgeom_set_geodetic(col->geoms[i], value);
943  break;
944  default:
945  lwerror("lwgeom_set_geodetic: unsupported geom type: %s", lwtype_name(geom->type));
946  return;
947  }
948 }
949 
950 void
952 {
953  int i;
954  switch (lwgeom->type)
955  {
956  LWPOINT *point;
957  LWLINE *line;
958  LWPOLY *poly;
959  LWTRIANGLE *triangle;
960  LWCOLLECTION *coll;
961 
962  case POINTTYPE:
963  point = (LWPOINT *)lwgeom;
965  return;
966  case LINETYPE:
967  line = (LWLINE *)lwgeom;
969  return;
970  case POLYGONTYPE:
971  poly = (LWPOLY *)lwgeom;
972  for (i=0; i<poly->nrings; i++)
973  ptarray_longitude_shift(poly->rings[i]);
974  return;
975  case TRIANGLETYPE:
976  triangle = (LWTRIANGLE *)lwgeom;
977  ptarray_longitude_shift(triangle->points);
978  return;
979  case MULTIPOINTTYPE:
980  case MULTILINETYPE:
981  case MULTIPOLYGONTYPE:
983  case TINTYPE:
984  case COLLECTIONTYPE:
985  coll = (LWCOLLECTION *)lwgeom;
986  for (i=0; i<coll->ngeoms; i++)
987  lwgeom_longitude_shift(coll->geoms[i]);
988  return;
989  default:
990  lwerror("lwgeom_longitude_shift: unsupported geom type: %s",
991  lwtype_name(lwgeom->type));
992  }
993 }
994 
995 int
997 {
998  int type = geom->type;
999 
1000  if( lwgeom_is_empty(geom) )
1001  return LW_FALSE;
1002 
1003  /* Test linear types for closure */
1004  switch (type)
1005  {
1006  case LINETYPE:
1007  return lwline_is_closed((LWLINE*)geom);
1008  case POLYGONTYPE:
1009  return lwpoly_is_closed((LWPOLY*)geom);
1010  case CIRCSTRINGTYPE:
1011  return lwcircstring_is_closed((LWCIRCSTRING*)geom);
1012  case COMPOUNDTYPE:
1013  return lwcompound_is_closed((LWCOMPOUND*)geom);
1014  case TINTYPE:
1015  return lwtin_is_closed((LWTIN*)geom);
1016  case POLYHEDRALSURFACETYPE:
1017  return lwpsurface_is_closed((LWPSURFACE*)geom);
1018  }
1019 
1020  /* Recurse into collections and see if anything is not closed */
1021  if ( lwgeom_is_collection(geom) )
1022  {
1023  LWCOLLECTION *col = lwgeom_as_lwcollection(geom);
1024  int i;
1025  int closed;
1026  for ( i = 0; i < col->ngeoms; i++ )
1027  {
1028  closed = lwgeom_is_closed(col->geoms[i]);
1029  if ( ! closed )
1030  return LW_FALSE;
1031  }
1032  return LW_TRUE;
1033  }
1034 
1035  /* All non-linear non-collection types we will call closed */
1036  return LW_TRUE;
1037 }
1038 
1039 int
1041 {
1042  if( ! geom ) return LW_FALSE;
1043  return lwtype_is_collection(geom->type);
1044 }
1045 
1047 int
1049 {
1050 
1051  switch (type)
1052  {
1053  case MULTIPOINTTYPE:
1054  case MULTILINETYPE:
1055  case MULTIPOLYGONTYPE:
1056  case COLLECTIONTYPE:
1057  case CURVEPOLYTYPE:
1058  case COMPOUNDTYPE:
1059  case MULTICURVETYPE:
1060  case MULTISURFACETYPE:
1061  case POLYHEDRALSURFACETYPE:
1062  case TINTYPE:
1063  return LW_TRUE;
1064  break;
1065 
1066  default:
1067  return LW_FALSE;
1068  }
1069 }
1070 
1074 int
1076 {
1077  switch (type)
1078  {
1079  case POINTTYPE:
1080  return MULTIPOINTTYPE;
1081  case LINETYPE:
1082  return MULTILINETYPE;
1083  case POLYGONTYPE:
1084  return MULTIPOLYGONTYPE;
1085  case CIRCSTRINGTYPE:
1086  return MULTICURVETYPE;
1087  case COMPOUNDTYPE:
1088  return MULTICURVETYPE;
1089  case CURVEPOLYTYPE:
1090  return MULTISURFACETYPE;
1091  case TRIANGLETYPE:
1092  return TINTYPE;
1093  default:
1094  return COLLECTIONTYPE;
1095  }
1096 }
1097 
1098 
1099 void lwgeom_free(LWGEOM *lwgeom)
1100 {
1101 
1102  /* There's nothing here to free... */
1103  if( ! lwgeom ) return;
1104 
1105  LWDEBUGF(5,"freeing a %s",lwtype_name(lwgeom->type));
1106 
1107  switch (lwgeom->type)
1108  {
1109  case POINTTYPE:
1110  lwpoint_free((LWPOINT *)lwgeom);
1111  break;
1112  case LINETYPE:
1113  lwline_free((LWLINE *)lwgeom);
1114  break;
1115  case POLYGONTYPE:
1116  lwpoly_free((LWPOLY *)lwgeom);
1117  break;
1118  case CIRCSTRINGTYPE:
1119  lwcircstring_free((LWCIRCSTRING *)lwgeom);
1120  break;
1121  case TRIANGLETYPE:
1122  lwtriangle_free((LWTRIANGLE *)lwgeom);
1123  break;
1124  case MULTIPOINTTYPE:
1125  lwmpoint_free((LWMPOINT *)lwgeom);
1126  break;
1127  case MULTILINETYPE:
1128  lwmline_free((LWMLINE *)lwgeom);
1129  break;
1130  case MULTIPOLYGONTYPE:
1131  lwmpoly_free((LWMPOLY *)lwgeom);
1132  break;
1133  case POLYHEDRALSURFACETYPE:
1134  lwpsurface_free((LWPSURFACE *)lwgeom);
1135  break;
1136  case TINTYPE:
1137  lwtin_free((LWTIN *)lwgeom);
1138  break;
1139  case CURVEPOLYTYPE:
1140  case COMPOUNDTYPE:
1141  case MULTICURVETYPE:
1142  case MULTISURFACETYPE:
1143  case COLLECTIONTYPE:
1144  lwcollection_free((LWCOLLECTION *)lwgeom);
1145  break;
1146  default:
1147  lwerror("lwgeom_free called with unknown type (%d) %s", lwgeom->type, lwtype_name(lwgeom->type));
1148  }
1149  return;
1150 }
1151 
1152 int lwgeom_needs_bbox(const LWGEOM *geom)
1153 {
1154  assert(geom);
1155  if ( geom->type == POINTTYPE )
1156  {
1157  return LW_FALSE;
1158  }
1159  else if ( geom->type == LINETYPE )
1160  {
1161  if ( lwgeom_count_vertices(geom) <= 2 )
1162  return LW_FALSE;
1163  else
1164  return LW_TRUE;
1165  }
1166  else if ( geom->type == MULTIPOINTTYPE )
1167  {
1168  if ( ((LWCOLLECTION*)geom)->ngeoms == 1 )
1169  return LW_FALSE;
1170  else
1171  return LW_TRUE;
1172  }
1173  else if ( geom->type == MULTILINETYPE )
1174  {
1175  if ( ((LWCOLLECTION*)geom)->ngeoms == 1 && lwgeom_count_vertices(geom) <= 2 )
1176  return LW_FALSE;
1177  else
1178  return LW_TRUE;
1179  }
1180  else
1181  {
1182  return LW_TRUE;
1183  }
1184 }
1185 
1190 {
1191  int result = 0;
1192 
1193  /* Null? Zero. */
1194  if( ! geom ) return 0;
1195 
1196  LWDEBUGF(4, "lwgeom_count_vertices got type %s",
1197  lwtype_name(geom->type));
1198 
1199  /* Empty? Zero. */
1200  if( lwgeom_is_empty(geom) ) return 0;
1201 
1202  switch (geom->type)
1203  {
1204  case POINTTYPE:
1205  result = 1;
1206  break;
1207  case TRIANGLETYPE:
1208  case CIRCSTRINGTYPE:
1209  case LINETYPE:
1210  result = lwline_count_vertices((LWLINE *)geom);
1211  break;
1212  case POLYGONTYPE:
1213  result = lwpoly_count_vertices((LWPOLY *)geom);
1214  break;
1215  case COMPOUNDTYPE:
1216  case CURVEPOLYTYPE:
1217  case MULTICURVETYPE:
1218  case MULTISURFACETYPE:
1219  case MULTIPOINTTYPE:
1220  case MULTILINETYPE:
1221  case MULTIPOLYGONTYPE:
1222  case POLYHEDRALSURFACETYPE:
1223  case TINTYPE:
1224  case COLLECTIONTYPE:
1225  result = lwcollection_count_vertices((LWCOLLECTION *)geom);
1226  break;
1227  default:
1228  lwerror("%s: unsupported input geometry type: %s",
1229  __func__, lwtype_name(geom->type));
1230  break;
1231  }
1232  LWDEBUGF(3, "counted %d vertices", result);
1233  return result;
1234 }
1235 
1241 int lwgeom_dimension(const LWGEOM *geom)
1242 {
1243 
1244  /* Null? Zero. */
1245  if( ! geom ) return -1;
1246 
1247  LWDEBUGF(4, "lwgeom_dimension got type %s",
1248  lwtype_name(geom->type));
1249 
1250  /* Empty? Zero. */
1251  /* if( lwgeom_is_empty(geom) ) return 0; */
1252 
1253  switch (geom->type)
1254  {
1255  case POINTTYPE:
1256  case MULTIPOINTTYPE:
1257  return 0;
1258  case CIRCSTRINGTYPE:
1259  case LINETYPE:
1260  case COMPOUNDTYPE:
1261  case MULTICURVETYPE:
1262  case MULTILINETYPE:
1263  return 1;
1264  case TRIANGLETYPE:
1265  case POLYGONTYPE:
1266  case CURVEPOLYTYPE:
1267  case MULTISURFACETYPE:
1268  case MULTIPOLYGONTYPE:
1269  case TINTYPE:
1270  return 2;
1271  case POLYHEDRALSURFACETYPE:
1272  {
1273  /* A closed polyhedral surface contains a volume. */
1274  int closed = lwpsurface_is_closed((LWPSURFACE*)geom);
1275  return ( closed ? 3 : 2 );
1276  }
1277  case COLLECTIONTYPE:
1278  {
1279  int maxdim = 0, i;
1280  LWCOLLECTION *col = (LWCOLLECTION*)geom;
1281  for( i = 0; i < col->ngeoms; i++ )
1282  {
1283  int dim = lwgeom_dimension(col->geoms[i]);
1284  maxdim = ( dim > maxdim ? dim : maxdim );
1285  }
1286  return maxdim;
1287  }
1288  default:
1289  lwerror("%s: unsupported input geometry type: %s",
1290  __func__, lwtype_name(geom->type));
1291  }
1292  return -1;
1293 }
1294 
1298 int lwgeom_count_rings(const LWGEOM *geom)
1299 {
1300  int result = 0;
1301 
1302  /* Null? Empty? Zero. */
1303  if( ! geom || lwgeom_is_empty(geom) )
1304  return 0;
1305 
1306  switch (geom->type)
1307  {
1308  case POINTTYPE:
1309  case CIRCSTRINGTYPE:
1310  case COMPOUNDTYPE:
1311  case MULTICURVETYPE:
1312  case MULTIPOINTTYPE:
1313  case MULTILINETYPE:
1314  case LINETYPE:
1315  result = 0;
1316  break;
1317  case TRIANGLETYPE:
1318  result = 1;
1319  break;
1320  case POLYGONTYPE:
1321  result = ((LWPOLY *)geom)->nrings;
1322  break;
1323  case CURVEPOLYTYPE:
1324  result = ((LWCURVEPOLY *)geom)->nrings;
1325  break;
1326  case MULTISURFACETYPE:
1327  case MULTIPOLYGONTYPE:
1328  case POLYHEDRALSURFACETYPE:
1329  case TINTYPE:
1330  case COLLECTIONTYPE:
1331  {
1332  LWCOLLECTION *col = (LWCOLLECTION*)geom;
1333  int i = 0;
1334  for( i = 0; i < col->ngeoms; i++ )
1335  result += lwgeom_count_rings(col->geoms[i]);
1336  break;
1337  }
1338  default:
1339  lwerror("lwgeom_count_rings: unsupported input geometry type: %s", lwtype_name(geom->type));
1340  break;
1341  }
1342  LWDEBUGF(3, "counted %d rings", result);
1343  return result;
1344 }
1345 
1346 int lwgeom_is_empty(const LWGEOM *geom)
1347 {
1348  int result = LW_FALSE;
1349  LWDEBUGF(4, "lwgeom_is_empty: got type %s",
1350  lwtype_name(geom->type));
1351 
1352  switch (geom->type)
1353  {
1354  case POINTTYPE:
1355  return lwpoint_is_empty((LWPOINT*)geom);
1356  break;
1357  case LINETYPE:
1358  return lwline_is_empty((LWLINE*)geom);
1359  break;
1360  case CIRCSTRINGTYPE:
1361  return lwcircstring_is_empty((LWCIRCSTRING*)geom);
1362  break;
1363  case POLYGONTYPE:
1364  return lwpoly_is_empty((LWPOLY*)geom);
1365  break;
1366  case TRIANGLETYPE:
1367  return lwtriangle_is_empty((LWTRIANGLE*)geom);
1368  break;
1369  case MULTIPOINTTYPE:
1370  case MULTILINETYPE:
1371  case MULTIPOLYGONTYPE:
1372  case COMPOUNDTYPE:
1373  case CURVEPOLYTYPE:
1374  case MULTICURVETYPE:
1375  case MULTISURFACETYPE:
1376  case POLYHEDRALSURFACETYPE:
1377  case TINTYPE:
1378  case COLLECTIONTYPE:
1379  return lwcollection_is_empty((LWCOLLECTION *)geom);
1380  break;
1381  default:
1382  lwerror("lwgeom_is_empty: unsupported input geometry type: %s",
1383  lwtype_name(geom->type));
1384  break;
1385  }
1386  return result;
1387 }
1388 
1389 int lwgeom_has_srid(const LWGEOM *geom)
1390 {
1391  if ( geom->srid != SRID_UNKNOWN )
1392  return LW_TRUE;
1393 
1394  return LW_FALSE;
1395 }
1396 
1397 
1399 {
1400  int i;
1401  int dimensionality = 0;
1402  for ( i = 0; i < col->ngeoms; i++ )
1403  {
1404  int d = lwgeom_dimensionality(col->geoms[i]);
1405  if ( d > dimensionality )
1406  dimensionality = d;
1407  }
1408  return dimensionality;
1409 }
1410 
1412 {
1413  int dim;
1414 
1415  LWDEBUGF(3, "lwgeom_dimensionality got type %s",
1416  lwtype_name(geom->type));
1417 
1418  switch (geom->type)
1419  {
1420  case POINTTYPE:
1421  case MULTIPOINTTYPE:
1422  return 0;
1423  break;
1424  case LINETYPE:
1425  case CIRCSTRINGTYPE:
1426  case MULTILINETYPE:
1427  case COMPOUNDTYPE:
1428  case MULTICURVETYPE:
1429  return 1;
1430  break;
1431  case POLYGONTYPE:
1432  case TRIANGLETYPE:
1433  case CURVEPOLYTYPE:
1434  case MULTIPOLYGONTYPE:
1435  case MULTISURFACETYPE:
1436  return 2;
1437  break;
1438 
1439  case POLYHEDRALSURFACETYPE:
1440  case TINTYPE:
1441  dim = lwgeom_is_closed(geom)?3:2;
1442  return dim;
1443  break;
1444 
1445  case COLLECTIONTYPE:
1446  return lwcollection_dimensionality((LWCOLLECTION *)geom);
1447  break;
1448  default:
1449  lwerror("lwgeom_dimensionality: unsupported input geometry type: %s",
1450  lwtype_name(geom->type));
1451  break;
1452  }
1453  return 0;
1454 }
1455 
1456 extern LWGEOM* lwgeom_remove_repeated_points(const LWGEOM *in, double tolerance)
1457 {
1458  LWDEBUGF(4, "lwgeom_remove_repeated_points got type %s",
1459  lwtype_name(in->type));
1460 
1461  if(lwgeom_is_empty(in))
1462  {
1463  return lwgeom_clone_deep(in);
1464  }
1465 
1466  switch (in->type)
1467  {
1468  case MULTIPOINTTYPE:
1469  return lwmpoint_remove_repeated_points((LWMPOINT*)in, tolerance);
1470  break;
1471  case LINETYPE:
1472  return lwline_remove_repeated_points((LWLINE*)in, tolerance);
1473 
1474  case MULTILINETYPE:
1475  case COLLECTIONTYPE:
1476  case MULTIPOLYGONTYPE:
1477  case POLYHEDRALSURFACETYPE:
1478  return lwcollection_remove_repeated_points((LWCOLLECTION *)in, tolerance);
1479 
1480  case POLYGONTYPE:
1481  return lwpoly_remove_repeated_points((LWPOLY *)in, tolerance);
1482  break;
1483 
1484  case POINTTYPE:
1485  case TRIANGLETYPE:
1486  case TINTYPE:
1487  /* No point is repeated for a single point, or for Triangle or TIN */
1488  return lwgeom_clone_deep(in);
1489 
1490  case CIRCSTRINGTYPE:
1491  case COMPOUNDTYPE:
1492  case MULTICURVETYPE:
1493  case CURVEPOLYTYPE:
1494  case MULTISURFACETYPE:
1495  /* Dunno how to handle these, will return untouched */
1496  return lwgeom_clone_deep(in);
1497 
1498  default:
1499  lwnotice("%s: unsupported geometry type: %s",
1500  __func__, lwtype_name(in->type));
1501  return lwgeom_clone_deep(in);
1502  break;
1503  }
1504  return 0;
1505 }
1506 
1508 {
1510  return in;
1511 }
1512 
1514 {
1515  LWCOLLECTION *col;
1516  LWPOLY *poly;
1517  int i;
1518 
1519  if ( (!in) || lwgeom_is_empty(in) ) return;
1520 
1521  /* TODO: check for lwgeom NOT having the specified dimension ? */
1522 
1523  LWDEBUGF(4, "lwgeom_flip_coordinates, got type: %s",
1524  lwtype_name(in->type));
1525 
1526  switch (in->type)
1527  {
1528  case POINTTYPE:
1529  ptarray_swap_ordinates(lwgeom_as_lwpoint(in)->point, o1, o2);
1530  break;
1531 
1532  case LINETYPE:
1533  ptarray_swap_ordinates(lwgeom_as_lwline(in)->points, o1, o2);
1534  break;
1535 
1536  case CIRCSTRINGTYPE:
1537  ptarray_swap_ordinates(lwgeom_as_lwcircstring(in)->points, o1, o2);
1538  break;
1539 
1540  case POLYGONTYPE:
1541  poly = (LWPOLY *) in;
1542  for (i=0; i<poly->nrings; i++)
1543  {
1544  ptarray_swap_ordinates(poly->rings[i], o1, o2);
1545  }
1546  break;
1547 
1548  case TRIANGLETYPE:
1549  ptarray_swap_ordinates(lwgeom_as_lwtriangle(in)->points, o1, o2);
1550  break;
1551 
1552  case MULTIPOINTTYPE:
1553  case MULTILINETYPE:
1554  case MULTIPOLYGONTYPE:
1555  case COLLECTIONTYPE:
1556  case COMPOUNDTYPE:
1557  case CURVEPOLYTYPE:
1558  case MULTISURFACETYPE:
1559  case MULTICURVETYPE:
1560  case POLYHEDRALSURFACETYPE:
1561  case TINTYPE:
1562  col = (LWCOLLECTION *) in;
1563  for (i=0; i<col->ngeoms; i++)
1564  {
1565  lwgeom_swap_ordinates(col->geoms[i], o1, o2);
1566  }
1567  break;
1568 
1569  default:
1570  lwerror("lwgeom_swap_ordinates: unsupported geometry type: %s",
1571  lwtype_name(in->type));
1572  return;
1573  }
1574 
1575  /* only refresh bbox if X or Y changed */
1576  if ( in->bbox && (o1 < 2 || o2 < 2) )
1577  {
1578  lwgeom_drop_bbox(in);
1579  lwgeom_add_bbox(in);
1580  }
1581 }
1582 
1583 void lwgeom_set_srid(LWGEOM *geom, int32_t srid)
1584 {
1585  int i;
1586 
1587  LWDEBUGF(4,"entered with srid=%d",srid);
1588 
1589  geom->srid = srid;
1590 
1591  if ( lwgeom_is_collection(geom) )
1592  {
1593  /* All the children are set to the same SRID value */
1594  LWCOLLECTION *col = lwgeom_as_lwcollection(geom);
1595  for ( i = 0; i < col->ngeoms; i++ )
1596  {
1597  lwgeom_set_srid(col->geoms[i], srid);
1598  }
1599  }
1600 }
1601 
1602 LWGEOM* lwgeom_simplify(const LWGEOM *igeom, double dist, int preserve_collapsed)
1603 {
1604  switch (igeom->type)
1605  {
1606  case POINTTYPE:
1607  case MULTIPOINTTYPE:
1608  return lwgeom_clone(igeom);
1609  case LINETYPE:
1610  return (LWGEOM*)lwline_simplify((LWLINE*)igeom, dist, preserve_collapsed);
1611  case POLYGONTYPE:
1612  return (LWGEOM*)lwpoly_simplify((LWPOLY*)igeom, dist, preserve_collapsed);
1613  case MULTILINETYPE:
1614  case MULTIPOLYGONTYPE:
1615  case COLLECTIONTYPE:
1616  return (LWGEOM*)lwcollection_simplify((LWCOLLECTION *)igeom, dist, preserve_collapsed);
1617  default:
1618  lwerror("%s: unsupported geometry type: %s", __func__, lwtype_name(igeom->type));
1619  }
1620  return NULL;
1621 }
1622 
1623 double lwgeom_area(const LWGEOM *geom)
1624 {
1625  int type = geom->type;
1626 
1627  if ( type == POLYGONTYPE )
1628  return lwpoly_area((LWPOLY*)geom);
1629  else if ( type == CURVEPOLYTYPE )
1630  return lwcurvepoly_area((LWCURVEPOLY*)geom);
1631  else if (type == TRIANGLETYPE )
1632  return lwtriangle_area((LWTRIANGLE*)geom);
1633  else if ( lwgeom_is_collection(geom) )
1634  {
1635  double area = 0.0;
1636  int i;
1637  LWCOLLECTION *col = (LWCOLLECTION*)geom;
1638  for ( i = 0; i < col->ngeoms; i++ )
1639  area += lwgeom_area(col->geoms[i]);
1640  return area;
1641  }
1642  else
1643  return 0.0;
1644 }
1645 
1646 double lwgeom_perimeter(const LWGEOM *geom)
1647 {
1648  int type = geom->type;
1649  if ( type == POLYGONTYPE )
1650  return lwpoly_perimeter((LWPOLY*)geom);
1651  else if ( type == CURVEPOLYTYPE )
1652  return lwcurvepoly_perimeter((LWCURVEPOLY*)geom);
1653  else if ( type == TRIANGLETYPE )
1654  return lwtriangle_perimeter((LWTRIANGLE*)geom);
1655  else if ( lwgeom_is_collection(geom) )
1656  {
1657  double perimeter = 0.0;
1658  int i;
1659  LWCOLLECTION *col = (LWCOLLECTION*)geom;
1660  for ( i = 0; i < col->ngeoms; i++ )
1661  perimeter += lwgeom_perimeter(col->geoms[i]);
1662  return perimeter;
1663  }
1664  else
1665  return 0.0;
1666 }
1667 
1668 double lwgeom_perimeter_2d(const LWGEOM *geom)
1669 {
1670  int type = geom->type;
1671  if ( type == POLYGONTYPE )
1672  return lwpoly_perimeter_2d((LWPOLY*)geom);
1673  else if ( type == CURVEPOLYTYPE )
1674  return lwcurvepoly_perimeter_2d((LWCURVEPOLY*)geom);
1675  else if ( type == TRIANGLETYPE )
1676  return lwtriangle_perimeter_2d((LWTRIANGLE*)geom);
1677  else if ( lwgeom_is_collection(geom) )
1678  {
1679  double perimeter = 0.0;
1680  int i;
1681  LWCOLLECTION *col = (LWCOLLECTION*)geom;
1682  for ( i = 0; i < col->ngeoms; i++ )
1683  perimeter += lwgeom_perimeter_2d(col->geoms[i]);
1684  return perimeter;
1685  }
1686  else
1687  return 0.0;
1688 }
1689 
1690 double lwgeom_length(const LWGEOM *geom)
1691 {
1692  int type = geom->type;
1693  if ( type == LINETYPE )
1694  return lwline_length((LWLINE*)geom);
1695  else if ( type == CIRCSTRINGTYPE )
1696  return lwcircstring_length((LWCIRCSTRING*)geom);
1697  else if ( type == COMPOUNDTYPE )
1698  return lwcompound_length((LWCOMPOUND*)geom);
1699  else if ( lwgeom_is_collection(geom) )
1700  {
1701  double length = 0.0;
1702  int i;
1703  LWCOLLECTION *col = (LWCOLLECTION*)geom;
1704  for ( i = 0; i < col->ngeoms; i++ )
1705  length += lwgeom_length(col->geoms[i]);
1706  return length;
1707  }
1708  else
1709  return 0.0;
1710 }
1711 
1712 double lwgeom_length_2d(const LWGEOM *geom)
1713 {
1714  int type = geom->type;
1715  if ( type == LINETYPE )
1716  return lwline_length_2d((LWLINE*)geom);
1717  else if ( type == CIRCSTRINGTYPE )
1718  return lwcircstring_length_2d((LWCIRCSTRING*)geom);
1719  else if ( type == COMPOUNDTYPE )
1720  return lwcompound_length_2d((LWCOMPOUND*)geom);
1721  else if ( lwgeom_is_collection(geom) )
1722  {
1723  double length = 0.0;
1724  int i;
1725  LWCOLLECTION *col = (LWCOLLECTION*)geom;
1726  for ( i = 0; i < col->ngeoms; i++ )
1727  length += lwgeom_length_2d(col->geoms[i]);
1728  return length;
1729  }
1730  else
1731  return 0.0;
1732 }
1733 
1734 void
1735 lwgeom_affine(LWGEOM *geom, const AFFINE *affine)
1736 {
1737  int type = geom->type;
1738  int i;
1739 
1740  switch(type)
1741  {
1742  /* Take advantage of fact tht pt/ln/circ/tri have same memory structure */
1743  case POINTTYPE:
1744  case LINETYPE:
1745  case CIRCSTRINGTYPE:
1746  case TRIANGLETYPE:
1747  {
1748  LWLINE *l = (LWLINE*)geom;
1749  ptarray_affine(l->points, affine);
1750  break;
1751  }
1752  case POLYGONTYPE:
1753  {
1754  LWPOLY *p = (LWPOLY*)geom;
1755  for( i = 0; i < p->nrings; i++ )
1756  ptarray_affine(p->rings[i], affine);
1757  break;
1758  }
1759  case CURVEPOLYTYPE:
1760  {
1761  LWCURVEPOLY *c = (LWCURVEPOLY*)geom;
1762  for( i = 0; i < c->nrings; i++ )
1763  lwgeom_affine(c->rings[i], affine);
1764  break;
1765  }
1766  default:
1767  {
1768  if( lwgeom_is_collection(geom) )
1769  {
1770  LWCOLLECTION *c = (LWCOLLECTION*)geom;
1771  for( i = 0; i < c->ngeoms; i++ )
1772  {
1773  lwgeom_affine(c->geoms[i], affine);
1774  }
1775  }
1776  else
1777  {
1778  lwerror("lwgeom_affine: unable to handle type '%s'", lwtype_name(type));
1779  }
1780  }
1781  }
1782 
1783 }
1784 
1785 void
1786 lwgeom_scale(LWGEOM *geom, const POINT4D *factor)
1787 {
1788  int type = geom->type;
1789  int i;
1790 
1791  switch(type)
1792  {
1793  /* Take advantage of fact tht pt/ln/circ/tri have same memory structure */
1794  case POINTTYPE:
1795  case LINETYPE:
1796  case CIRCSTRINGTYPE:
1797  case TRIANGLETYPE:
1798  {
1799  LWLINE *l = (LWLINE*)geom;
1800  ptarray_scale(l->points, factor);
1801  break;
1802  }
1803  case POLYGONTYPE:
1804  {
1805  LWPOLY *p = (LWPOLY*)geom;
1806  for( i = 0; i < p->nrings; i++ )
1807  ptarray_scale(p->rings[i], factor);
1808  break;
1809  }
1810  case CURVEPOLYTYPE:
1811  {
1812  LWCURVEPOLY *c = (LWCURVEPOLY*)geom;
1813  for( i = 0; i < c->nrings; i++ )
1814  lwgeom_scale(c->rings[i], factor);
1815  break;
1816  }
1817  default:
1818  {
1819  if( lwgeom_is_collection(geom) )
1820  {
1821  LWCOLLECTION *c = (LWCOLLECTION*)geom;
1822  for( i = 0; i < c->ngeoms; i++ )
1823  {
1824  lwgeom_scale(c->geoms[i], factor);
1825  }
1826  }
1827  else
1828  {
1829  lwerror("lwgeom_scale: unable to handle type '%s'", lwtype_name(type));
1830  }
1831  }
1832  }
1833 
1834  /* Recompute bbox if needed */
1835 
1836  if ( geom->bbox )
1837  {
1838  /* TODO: expose a gbox_scale function */
1839  geom->bbox->xmin *= factor->x;
1840  geom->bbox->xmax *= factor->x;
1841  geom->bbox->ymin *= factor->y;
1842  geom->bbox->ymax *= factor->y;
1843  geom->bbox->zmin *= factor->z;
1844  geom->bbox->zmax *= factor->z;
1845  geom->bbox->mmin *= factor->m;
1846  geom->bbox->mmax *= factor->m;
1847  }
1848 }
1849 
1850 LWGEOM*
1851 lwgeom_construct_empty(uint8_t type, int srid, char hasz, char hasm)
1852 {
1853  switch(type)
1854  {
1855  case POINTTYPE:
1856  return lwpoint_as_lwgeom(lwpoint_construct_empty(srid, hasz, hasm));
1857  case LINETYPE:
1858  return lwline_as_lwgeom(lwline_construct_empty(srid, hasz, hasm));
1859  case POLYGONTYPE:
1860  return lwpoly_as_lwgeom(lwpoly_construct_empty(srid, hasz, hasm));
1861  case CURVEPOLYTYPE:
1862  return lwcurvepoly_as_lwgeom(lwcurvepoly_construct_empty(srid, hasz, hasm));
1863  case CIRCSTRINGTYPE:
1864  return lwcircstring_as_lwgeom(lwcircstring_construct_empty(srid, hasz, hasm));
1865  case TRIANGLETYPE:
1866  return lwtriangle_as_lwgeom(lwtriangle_construct_empty(srid, hasz, hasm));
1867  case COMPOUNDTYPE:
1868  case MULTIPOINTTYPE:
1869  case MULTILINETYPE:
1870  case MULTIPOLYGONTYPE:
1871  case COLLECTIONTYPE:
1872  return lwcollection_as_lwgeom(lwcollection_construct_empty(type, srid, hasz, hasm));
1873  default:
1874  lwerror("lwgeom_construct_empty: unsupported geometry type: %s",
1875  lwtype_name(type));
1876  return NULL;
1877  }
1878 }
1879 
1880 int
1881 lwgeom_startpoint(const LWGEOM* lwgeom, POINT4D* pt)
1882 {
1883  if ( ! lwgeom )
1884  return LW_FAILURE;
1885 
1886  switch( lwgeom->type )
1887  {
1888  case POINTTYPE:
1889  return ptarray_startpoint(((LWPOINT*)lwgeom)->point, pt);
1890  case TRIANGLETYPE:
1891  case CIRCSTRINGTYPE:
1892  case LINETYPE:
1893  return ptarray_startpoint(((LWLINE*)lwgeom)->points, pt);
1894  case POLYGONTYPE:
1895  return lwpoly_startpoint((LWPOLY*)lwgeom, pt);
1896  case CURVEPOLYTYPE:
1897  case COMPOUNDTYPE:
1898  case MULTIPOINTTYPE:
1899  case MULTILINETYPE:
1900  case MULTIPOLYGONTYPE:
1901  case COLLECTIONTYPE:
1902  return lwcollection_startpoint((LWCOLLECTION*)lwgeom, pt);
1903  default:
1904  lwerror("int: unsupported geometry type: %s",
1905  lwtype_name(lwgeom->type));
1906  return LW_FAILURE;
1907  }
1908 }
1909 
1910 
1911 LWGEOM *
1912 lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid)
1913 {
1914  switch ( lwgeom->type )
1915  {
1916  case POINTTYPE:
1917  return (LWGEOM *)lwpoint_grid((LWPOINT *)lwgeom, grid);
1918  case LINETYPE:
1919  return (LWGEOM *)lwline_grid((LWLINE *)lwgeom, grid);
1920  case POLYGONTYPE:
1921  return (LWGEOM *)lwpoly_grid((LWPOLY *)lwgeom, grid);
1922  case MULTIPOINTTYPE:
1923  case MULTILINETYPE:
1924  case MULTIPOLYGONTYPE:
1925  case COLLECTIONTYPE:
1926  case COMPOUNDTYPE:
1927  return (LWGEOM *)lwcollection_grid((LWCOLLECTION *)lwgeom, grid);
1928  case CIRCSTRINGTYPE:
1929  return (LWGEOM *)lwcircstring_grid((LWCIRCSTRING *)lwgeom, grid);
1930  default:
1931  lwerror("lwgeom_grid: Unsupported geometry type: %s",
1932  lwtype_name(lwgeom->type));
1933  return NULL;
1934  }
1935 }
1936 
1937 
1938 /* Prototype for recursion */
1939 static int
1940 lwgeom_subdivide_recursive(const LWGEOM *geom, int maxvertices, int depth, LWCOLLECTION *col, const GBOX *clip);
1941 
1942 static int
1943 lwgeom_subdivide_recursive(const LWGEOM *geom, int maxvertices, int depth, LWCOLLECTION *col, const GBOX *clip)
1944 {
1945  const int maxdepth = 50;
1946  int nvertices = 0;
1947  int i, n = 0;
1948  double width = clip->xmax - clip->xmin;
1949  double height = clip->ymax - clip->ymin;
1950  GBOX subbox1, subbox2;
1951  LWGEOM *clipped1, *clipped2;
1952 
1953  if ( geom->type == POLYHEDRALSURFACETYPE || geom->type == TINTYPE )
1954  {
1955  lwerror("%s: unsupported geometry type '%s'", __func__, lwtype_name(geom->type));
1956  }
1957 
1958  if ( width == 0.0 && height == 0.0 )
1959  {
1960  if ( geom->type == POINTTYPE )
1961  {
1963  return 1;
1964  }
1965  else
1966  {
1967  return 0;
1968  }
1969  }
1970 
1971  /* Always just recurse into collections */
1972  if ( lwgeom_is_collection(geom) && geom->type != MULTIPOINTTYPE )
1973  {
1974  LWCOLLECTION *incol = (LWCOLLECTION*)geom;
1975  int n = 0;
1976  for ( i = 0; i < incol->ngeoms; i++ )
1977  {
1978  /* Don't increment depth yet, since we aren't actually subdividing geomtries yet */
1979  n += lwgeom_subdivide_recursive(incol->geoms[i], maxvertices, depth, col, clip);
1980  }
1981  return n;
1982  }
1983 
1984  /* But don't go too far. 2^50 ~= 10^15, that's enough subdivision */
1985  /* Just add what's left */
1986  if ( depth > maxdepth )
1987  {
1989  return 1;
1990  }
1991 
1992  nvertices = lwgeom_count_vertices(geom);
1993  /* Skip empties entirely */
1994  if ( nvertices == 0 )
1995  {
1996  return 0;
1997  }
1998 
1999  /* If it is under the vertex tolerance, just add it, we're done */
2000  if ( nvertices < maxvertices )
2001  {
2003  return 1;
2004  }
2005 
2006  subbox1 = subbox2 = *clip;
2007  if ( width > height )
2008  {
2009  subbox1.xmax = subbox2.xmin = (clip->xmin + clip->xmax)/2;
2010  }
2011  else
2012  {
2013  subbox1.ymax = subbox2.ymin = (clip->ymin + clip->ymax)/2;
2014  }
2015 
2016  if ( height == 0 )
2017  {
2018  subbox1.ymax += FP_TOLERANCE;
2019  subbox2.ymax += FP_TOLERANCE;
2020  subbox1.ymin -= FP_TOLERANCE;
2021  subbox2.ymin -= FP_TOLERANCE;
2022  }
2023 
2024  if ( width == 0 )
2025  {
2026  subbox1.xmax += FP_TOLERANCE;
2027  subbox2.xmax += FP_TOLERANCE;
2028  subbox1.xmin -= FP_TOLERANCE;
2029  subbox2.xmin -= FP_TOLERANCE;
2030  }
2031 
2032  clipped1 = lwgeom_clip_by_rect(geom, subbox1.xmin, subbox1.ymin, subbox1.xmax, subbox1.ymax);
2033  clipped2 = lwgeom_clip_by_rect(geom, subbox2.xmin, subbox2.ymin, subbox2.xmax, subbox2.ymax);
2034 
2035  ++depth;
2036 
2037  if ( clipped1 )
2038  {
2039  n += lwgeom_subdivide_recursive(clipped1, maxvertices, depth, col, &subbox1);
2040  lwgeom_free(clipped1);
2041  }
2042 
2043  if ( clipped2 )
2044  {
2045  n += lwgeom_subdivide_recursive(clipped2, maxvertices, depth, col, &subbox2);
2046  lwgeom_free(clipped2);
2047  }
2048 
2049  return n;
2050 
2051 }
2052 
2053 LWCOLLECTION *
2054 lwgeom_subdivide(const LWGEOM *geom, int maxvertices)
2055 {
2056  static int startdepth = 0;
2057  static int minmaxvertices = 8;
2058  LWCOLLECTION *col;
2059  GBOX clip;
2060 
2062 
2063  if ( lwgeom_is_empty(geom) )
2064  return col;
2065 
2066  if ( maxvertices < minmaxvertices )
2067  {
2068  lwcollection_free(col);
2069  lwerror("%s: cannot subdivide to fewer than %d vertices per output", __func__, minmaxvertices);
2070  }
2071 
2072  clip = *(lwgeom_get_bbox(geom));
2073  lwgeom_subdivide_recursive(geom, maxvertices, startdepth, col, &clip);
2074  lwgeom_set_srid((LWGEOM*)col, geom->srid);
2075  return col;
2076 }
2077 
2078 
2079 int
2081 {
2082  int type = geom->type;
2083 
2084  if( type != LINETYPE )
2085  {
2086  lwnotice("Geometry is not a LINESTRING");
2087  return LW_FALSE;
2088  }
2089  return lwline_is_trajectory((LWLINE*)geom);
2090 }
2091 
LWMPOINT * lwgeom_as_lwmpoint(const LWGEOM *lwgeom)
Definition: lwgeom.c:201
LWCIRCSTRING * lwcircstring_grid(const LWCIRCSTRING *line, const gridspec *grid)
Definition: lwcircstring.c:318
double x
Definition: liblwgeom.h:352
#define LINETYPE
Definition: liblwgeom.h:86
int lwgeom_calculate_gbox_geodetic(const LWGEOM *geom, GBOX *gbox)
Calculate the geodetic bounding box for an LWGEOM.
Definition: lwgeodetic.c:3012
LWPOINT * lwpoint_force_dims(const LWPOINT *lwpoint, int hasz, int hasm)
Definition: lwpoint.c:271
int lwtriangle_is_clockwise(LWTRIANGLE *triangle)
Definition: lwtriangle.c:113
int lwcollection_count_vertices(LWCOLLECTION *col)
Definition: lwcollection.c:514
LWGEOM * lwgeom_stroke(const LWGEOM *geom, uint32_t perQuad)
Definition: lwstroke.c:767
static int lwcollection_dimensionality(LWCOLLECTION *col)
Definition: lwgeom.c:1398
int lwgeom_startpoint(const LWGEOM *lwgeom, POINT4D *pt)
Definition: lwgeom.c:1881
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:288
LWPSURFACE * lwgeom_as_lwpsurface(const LWGEOM *lwgeom)
Definition: lwgeom.c:228
GBOX * gbox_new(uint8_t flags)
Create a new gbox with the dimensionality indicated by the flags.
Definition: g_box.c:43
GBOX * bbox
Definition: liblwgeom.h:398
void lwgeom_add_bbox_deep(LWGEOM *lwgeom, GBOX *gbox)
Compute a box for geom and all sub-geometries, if not already computed.
Definition: lwgeom.c:660
LWPOLY * lwpoly_clone_deep(const LWPOLY *lwgeom)
Definition: lwpoly.c:230
LWLINE * lwline_construct_empty(int srid, char hasz, char hasm)
Definition: lwline.c:64
POINTARRAY * points
Definition: liblwgeom.h:433
char lwpoint_same(const LWPOINT *p1, const LWPOINT *p2)
Definition: lwpoint.c:264
double lwcircstring_length(const LWCIRCSTRING *circ)
Definition: lwcircstring.c:283
double m
Definition: liblwgeom.h:352
#define MULTICURVETYPE
Definition: liblwgeom.h:95
void lwgeom_drop_bbox(LWGEOM *lwgeom)
Call this function to drop BBOX and SRID from LWGEOM.
Definition: lwgeom.c:635
GEOGRAPHIC_POINT center
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwcollection.c:43
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
Definition: lwout_wkt.c:669
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
void lwgeom_scale(LWGEOM *geom, const POINT4D *factor)
Definition: lwgeom.c:1786
LWGEOM * lwgeom_force_3dm(const LWGEOM *geom)
Definition: lwgeom.c:751
void lwgeom_drop_srid(LWGEOM *lwgeom)
Definition: lwgeom.c:711
void lwmline_free(LWMLINE *mline)
Definition: lwmline.c:112
LWLINE * lwline_segmentize2d(LWLINE *line, double dist)
Definition: lwline.c:147
void lwfree(void *mem)
Definition: lwutil.c:244
LWTRIANGLE * lwtriangle_construct_empty(int srid, char hasz, char hasm)
Definition: lwtriangle.c:58
int lwline_count_vertices(LWLINE *line)
Definition: lwline.c:533
int32_t lwgeom_get_srid(const LWGEOM *geom)
Return SRID number.
Definition: lwgeom.c:871
LWPOLY * lwpoly_simplify(const LWPOLY *ipoly, double dist, int preserve_collapsed)
Definition: lwpoly.c:464
LWGEOM ** rings
Definition: liblwgeom.h:535
LWLINE * lwline_clone(const LWLINE *lwgeom)
Definition: lwline.c:102
int lwtin_is_closed(const LWTIN *tin)
Definition: lwtin.c:93
void ptarray_scale(POINTARRAY *pa, const POINT4D *factor)
Scale a pointarray.
Definition: ptarray.c:1851
uint8_t type
Definition: liblwgeom.h:503
double lwgeom_length(const LWGEOM *geom)
Definition: lwgeom.c:1690
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:892
void lwcircstring_free(LWCIRCSTRING *curve)
Definition: lwcircstring.c:98
void lwgeom_force_clockwise(LWGEOM *lwgeom)
Force Right-hand-rule on LWGEOM polygons.
Definition: lwgeom.c:36
#define FLAGS_GET_GEODETIC(flags)
Definition: liblwgeom.h:143
#define POLYGONTYPE
Definition: liblwgeom.h:87
Datum area(PG_FUNCTION_ARGS)
void lwtin_free(LWTIN *tin)
Definition: lwtin.c:39
uint8_t flags
Definition: liblwgeom.h:397
double xmax
Definition: liblwgeom.h:293
#define CURVEPOLYTYPE
Definition: liblwgeom.h:94
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
LWGEOM * lwgeom_clip_by_rect(const LWGEOM *geom1, double x0, double y0, double x1, double y1)
#define COMPOUNDTYPE
Definition: liblwgeom.h:93
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:174
int lwgeom_ndims(const LWGEOM *geom)
Return the number of dimensions (2, 3, 4) in a geometry.
Definition: lwgeom.c:899
void lwgeom_longitude_shift(LWGEOM *lwgeom)
Definition: lwgeom.c:951
void lwline_free(LWLINE *line)
Definition: lwline.c:76
LWGEOM * lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid)
Definition: lwgeom.c:1912
LWGEOM * lwgeom_segmentize2d(LWGEOM *lwgeom, double dist)
Definition: lwgeom.c:717
void lwgeom_swap_ordinates(LWGEOM *in, LWORD o1, LWORD o2)
Swap ordinate values in every vertex of the geometry.
Definition: lwgeom.c:1513
int lwgeom_count_rings(const LWGEOM *geom)
Count rings in an LWGEOM.
Definition: lwgeom.c:1298
double lwtriangle_perimeter_2d(const LWTRIANGLE *triangle)
Definition: lwtriangle.c:224
#define FLAGS_GET_ZM(flags)
Definition: liblwgeom.h:153
double lwcircstring_length_2d(const LWCIRCSTRING *circ)
Definition: lwcircstring.c:288
LWTRIANGLE * lwtriangle_clone(const LWTRIANGLE *lwgeom)
Definition: lwtriangle.c:99
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
double lwline_length_2d(const LWLINE *line)
Definition: lwline.c:586
#define TRIANGLETYPE
Definition: liblwgeom.h:98
void lwtriangle_reverse(LWTRIANGLE *triangle)
Definition: lwtriangle.c:119
LWGEOM * lwmpoint_remove_repeated_points(const LWMPOINT *in, double tolerance)
Definition: lwmpoint.c:92
int lwline_is_trajectory(const LWLINE *geom)
Definition: lwline.c:477
LWGEOM * lwmpoint_as_lwgeom(const LWMPOINT *obj)
Definition: lwgeom.c:263
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:97
int lwgeom_count_vertices(const LWGEOM *geom)
Count points in an LWGEOM.
Definition: lwgeom.c:1189
LWGEOM * lwgeom_simplify(const LWGEOM *igeom, double dist, int preserve_collapsed)
Definition: lwgeom.c:1602
void lwtriangle_force_clockwise(LWTRIANGLE *triangle)
Definition: lwtriangle.c:106
LWLINE * lwline_grid(const LWLINE *line, const gridspec *grid)
Definition: lwline.c:595
LWPOINT * lwpoint_grid(const LWPOINT *point, const gridspec *grid)
Definition: lwpoint.c:300
int lwcompound_is_closed(const LWCOMPOUND *curve)
Definition: lwcompound.c:35
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:303
double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2)
The old function nessecary for ptarray_segmentize2d in ptarray.c.
Definition: measures.c:2317
#define FLAGS_SET_GEODETIC(flags, value)
Definition: liblwgeom.h:149
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:151
void lwpoly_force_clockwise(LWPOLY *poly)
Definition: lwpoly.c:270
LWTRIANGLE * lwgeom_as_lwtriangle(const LWGEOM *lwgeom)
Definition: lwgeom.c:183
double lwtriangle_area(const LWTRIANGLE *triangle)
Find the area of the outer ring.
Definition: lwtriangle.c:192
POINTARRAY * point
Definition: liblwgeom.h:411
int lwpoly_is_clockwise(LWPOLY *poly)
Definition: lwpoly.c:290
int32_t srid
Definition: liblwgeom.h:399
int lwgeom_is_closed(const LWGEOM *geom)
Return true or false depending on whether a geometry is a linear feature that closes on itself...
Definition: lwgeom.c:996
LWGEOM * lwpsurface_as_lwgeom(const LWPSURFACE *obj)
Definition: lwgeom.c:248
double lwtriangle_perimeter(const LWTRIANGLE *triangle)
Definition: lwtriangle.c:215
char lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2)
geom1 same as geom2 iff
Definition: lwgeom.c:544
void lwcircstring_reverse(LWCIRCSTRING *curve)
Definition: lwcircstring.c:131
#define LW_FAILURE
Definition: liblwgeom.h:79
LWGEOM * lwtin_as_lwgeom(const LWTIN *obj)
Definition: lwgeom.c:243
char lwcollection_same(const LWCOLLECTION *p1, const LWCOLLECTION *p2)
check for same geometry composition
Definition: lwcollection.c:262
LWGEOM * lwgeom_remove_repeated_points(const LWGEOM *in, double tolerance)
Remove repeated points!
Definition: lwgeom.c:1456
unsigned int uint32_t
Definition: uthash.h:78
double x
Definition: liblwgeom.h:328
LWCOMPOUND * lwgeom_as_lwcompound(const LWGEOM *lwgeom)
Definition: lwgeom.c:156
int lwtriangle_is_empty(const LWTRIANGLE *triangle)
Definition: lwtriangle.c:181
LWCURVEPOLY * lwgeom_as_lwcurvepoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:165
LWCURVEPOLY * lwcurvepoly_construct_from_lwpoly(LWPOLY *lwpoly)
Construct an equivalent curve polygon from a polygon.
Definition: lwcurvepoly.c:53
LWGEOM * lwcollection_remove_repeated_points(const LWCOLLECTION *in, double tolerance)
Definition: lwcollection.c:460
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep-clone an LWGEOM object.
Definition: lwgeom.c:482
void lwmpoly_free(LWMPOLY *mpoly)
Definition: lwmpoly.c:53
void lwmpoint_free(LWMPOINT *mpt)
Definition: lwmpoint.c:72
double zmax
Definition: liblwgeom.h:297
double ymin
Definition: liblwgeom.h:294
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
LWGEOM * lwmpoly_as_lwgeom(const LWMPOLY *obj)
Definition: lwgeom.c:253
double lwgeom_area(const LWGEOM *geom)
Definition: lwgeom.c:1623
char lwcircstring_same(const LWCIRCSTRING *p1, const LWCIRCSTRING *p2)
Definition: lwcircstring.c:138
double lwgeom_perimeter(const LWGEOM *geom)
Definition: lwgeom.c:1646
double lwcompound_length_2d(const LWCOMPOUND *comp)
Definition: lwcompound.c:74
int lwgeom_is_trajectory(const LWGEOM *geom)
Return LW_TRUE or LW_FALSE depending on whether or not a geometry is a linestring with measure value ...
Definition: lwgeom.c:2080
int lwcollection_is_empty(const LWCOLLECTION *col)
Definition: lwcollection.c:501
double xmin
Definition: liblwgeom.h:292
LWCIRCSTRING * lwcircstring_construct_empty(int srid, char hasz, char hasm)
Definition: lwcircstring.c:80
char lwtriangle_same(const LWTRIANGLE *p1, const LWTRIANGLE *p2)
Definition: lwtriangle.c:133
#define LW_FALSE
Definition: liblwgeom.h:77
uint8_t type
Definition: liblwgeom.h:451
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:373
LWPOLY * lwpoly_force_dims(const LWPOLY *lwpoly, int hasz, int hasm)
Definition: lwpoly.c:421
LWGEOM * lwgeom_force_3dz(const LWGEOM *geom)
Definition: lwgeom.c:745
uint8_t flags
Definition: liblwgeom.h:369
void ptarray_swap_ordinates(POINTARRAY *pa, LWORD o1, LWORD o2)
Swap ordinate values o1 and o2 on a given POINTARRAY.
Definition: ptarray.c:388
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:174
int lwgeom_has_srid(const LWGEOM *geom)
Return true or false depending on whether a geometry has a valid SRID set.
Definition: lwgeom.c:1389
LWPOINT * lwpoint_clone(const LWPOINT *lwgeom)
Definition: lwpoint.c:239
double lwgeom_perimeter_2d(const LWGEOM *geom)
Definition: lwgeom.c:1668
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:138
LWGEOM ** geoms
Definition: liblwgeom.h:509
int lwpoly_is_closed(const LWPOLY *poly)
Definition: lwpoly.c:589
double lwcompound_length(const LWCOMPOUND *comp)
Definition: lwcompound.c:69
int lwcircstring_is_closed(const LWCIRCSTRING *curve)
Definition: lwcircstring.c:268
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:188
#define TINTYPE
Definition: liblwgeom.h:99
LWCOLLECTION * lwcollection_simplify(const LWCOLLECTION *igeom, double dist, int preserve_collapsed)
Definition: lwcollection.c:526
uint8_t type
Definition: liblwgeom.h:440
void lwgeom_affine(LWGEOM *geom, const AFFINE *affine)
Definition: lwgeom.c:1735
LWMLINE * lwgeom_as_lwmline(const LWGEOM *lwgeom)
Definition: lwgeom.c:210
POINTARRAY ** rings
Definition: liblwgeom.h:457
LWCIRCSTRING * lwcircstring_clone(const LWCIRCSTRING *curve)
Definition: lwcircstring.c:125
LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate MULTI* type.
Definition: lwgeom.c:333
LWGEOM * lwcurvepoly_as_lwgeom(const LWCURVEPOLY *obj)
Definition: lwgeom.c:278
int lwtype_is_collection(uint8_t type)
Return TRUE if the geometry may contain sub-geometries, i.e.
Definition: lwgeom.c:1048
LWGEOM * lwgeom_force_4d(const LWGEOM *geom)
Definition: lwgeom.c:757
double lwpoly_area(const LWPOLY *poly)
Find the area of the outer ring - sum (area of inner rings).
Definition: lwpoly.c:524
int lwgeom_dimensionality(LWGEOM *geom)
Return the dimensionality (relating to point/line/poly) of an lwgeom.
Definition: lwgeom.c:1411
int lwpoly_is_empty(const LWPOLY *poly)
Definition: lwpoly.c:445
LWCURVEPOLY * lwcurvepoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwcurvepoly.c:36
uint8_t MULTITYPE[NUMTYPES]
Look-up for the correct MULTI* type promotion for singleton types.
Definition: lwgeom.c:313
double lwcurvepoly_perimeter_2d(const LWCURVEPOLY *poly)
Definition: lwcurvepoly.c:160
LWGEOM * lwgeom_clone(const LWGEOM *lwgeom)
Clone LWGEOM object.
Definition: lwgeom.c:444
#define FP_TOLERANCE
Floating point comparators.
LWGEOM * lwcircstring_as_lwgeom(const LWCIRCSTRING *obj)
Definition: lwgeom.c:273
int nrings
Definition: liblwgeom.h:455
LWPOLY * lwpoly_grid(const LWPOLY *poly, const gridspec *grid)
Definition: lwpoly.c:642
#define NUMTYPES
Definition: liblwgeom.h:101
double ymax
Definition: liblwgeom.h:295
enum LWORD_T LWORD
Ordinate names.
double y
Definition: liblwgeom.h:328
int lwpsurface_is_closed(const LWPSURFACE *psurface)
Definition: lwpsurface.c:99
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:140
int lwcollection_startpoint(const LWCOLLECTION *col, POINT4D *pt)
Definition: lwcollection.c:580
double z
Definition: liblwgeom.h:352
LWCOMPOUND * lwcompound_construct_from_lwline(const LWLINE *lwpoly)
Construct an equivalent compound curve from a linestring.
Definition: lwcompound.c:204
LWCOLLECTION * lwcollection_clone_deep(const LWCOLLECTION *lwgeom)
Deep clone LWCOLLECTION object.
Definition: lwcollection.c:149
int lwpoly_startpoint(const LWPOLY *lwpoly, POINT4D *pt)
Definition: lwpoly.c:614
double lwpoly_perimeter_2d(const LWPOLY *poly)
Compute the sum of polygon rings length (forcing 2d computation).
Definition: lwpoly.c:575
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:192
int lwcircstring_is_empty(const LWCIRCSTRING *circ)
Definition: lwcircstring.c:276
uint8_t flags
Definition: liblwgeom.h:291
double lwpoly_perimeter(const LWPOLY *poly)
Compute the sum of polygon rings length.
Definition: lwpoly.c:557
void lwtriangle_free(LWTRIANGLE *triangle)
Definition: lwtriangle.c:69
LWCOLLECTION * lwcollection_segmentize2d(LWCOLLECTION *coll, double dist)
Definition: lwcollection.c:237
void lwpsurface_free(LWPSURFACE *psurf)
Definition: lwpsurface.c:39
LWCIRCSTRING * lwgeom_as_lwcircstring(const LWGEOM *lwgeom)
Definition: lwgeom.c:147
void lwgeom_set_geodetic(LWGEOM *geom, int value)
Set the FLAGS geodetic bit on geometry an all sub-geometries and pointlists.
Definition: lwgeom.c:907
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:268
LWCOLLECTION * lwcollection_force_dims(const LWCOLLECTION *lwcol, int hasz, int hasm)
Definition: lwcollection.c:478
LWCOLLECTION * lwgeom_subdivide(const LWGEOM *geom, int maxvertices)
Definition: lwgeom.c:2054
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1346
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
double lwgeom_length_2d(const LWGEOM *geom)
Definition: lwgeom.c:1712
LWGEOM * lwgeom_force_dims(const LWGEOM *geom, int hasz, int hasm)
Definition: lwgeom.c:763
void lwpoly_reverse(LWPOLY *poly)
Definition: lwpoly.c:314
int ptarray_startpoint(const POINTARRAY *pa, POINT4D *pt)
Definition: ptarray.c:1873
int lwline_is_empty(const LWLINE *line)
Definition: lwline.c:525
LWGEOM * lwline_remove_repeated_points(const LWLINE *in, double tolerance)
Definition: lwline.c:456
LWGEOM * lwgeom_force_2d(const LWGEOM *geom)
Strip out the Z/M components of an LWGEOM.
Definition: lwgeom.c:739
#define WKT_EXTENDED
Definition: liblwgeom.h:2085
LWGEOM * lwpoly_remove_repeated_points(const LWPOLY *in, double tolerance)
Definition: lwpoly.c:402
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition: lwgeom.c:129
LWPOLY * lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes)
Definition: lwpoly.c:368
#define FLAGS_SET_BBOX(flags, value)
Definition: liblwgeom.h:148
int lwpoint_inside_circle(const LWPOINT *p, double cx, double cy, double rad)
Definition: lwgeom.c:615
double lwcurvepoly_perimeter(const LWCURVEPOLY *poly)
Definition: lwcurvepoly.c:148
void lwline_reverse(LWLINE *line)
Definition: lwline.c:140
LWLINE * lwline_force_dims(const LWLINE *lwline, int hasz, int hasm)
Definition: lwline.c:506
LWGEOM * lwgeom_force_sfs(LWGEOM *geom, int version)
Definition: lwgeom.c:793
int lwgeom_is_collection(const LWGEOM *geom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:1040
void ptarray_longitude_shift(POINTARRAY *pa)
Longitude shift for a pointarray.
Definition: ptarray.c:1417
double lwline_length(const LWLINE *line)
Definition: lwline.c:579
int lwgeom_dimension(const LWGEOM *geom)
For an LWGEOM, returns 0 for points, 1 for lines, 2 for polygons, 3 for volume, and the max dimension...
Definition: lwgeom.c:1241
#define MULTISURFACETYPE
Definition: liblwgeom.h:96
double mmin
Definition: liblwgeom.h:298
int lwline_is_closed(const LWLINE *line)
Definition: lwline.c:468
double zmin
Definition: liblwgeom.h:296
char * lwgeom_to_ewkt(const LWGEOM *lwgeom)
Return an alloced string.
Definition: lwgeom.c:518
LWMPOLY * lwgeom_as_lwmpoly(const LWGEOM *lwgeom)
Definition: lwgeom.c:219
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:885
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
int lwpoint_is_empty(const LWPOINT *point)
Definition: lwpoint.c:291
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:161
LWGEOM * lwmline_as_lwgeom(const LWMLINE *obj)
Definition: lwgeom.c:258
void lwgeom_add_bbox(LWGEOM *lwgeom)
Ensure there&#39;s a box in the LWGEOM.
Definition: lwgeom.c:648
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:141
LWCOLLECTION * lwcollection_grid(const LWCOLLECTION *coll, const gridspec *grid)
Definition: lwcollection.c:589
int lwgeom_needs_bbox(const LWGEOM *geom)
Check whether or not a lwgeom is big enough to warrant a bounding box.
Definition: lwgeom.c:1152
int lwtype_get_collectiontype(uint8_t type)
Given an lwtype number, what homogeneous collection can hold it?
Definition: lwgeom.c:1075
uint8_t type
Definition: liblwgeom.h:396
type
Definition: ovdump.py:41
LWCOLLECTION * lwcollection_clone(const LWCOLLECTION *lwgeom)
Clone LWCOLLECTION object.
Definition: lwcollection.c:123
double mmax
Definition: liblwgeom.h:299
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:340
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:298
LWGEOM * lwgeom_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwgeom.c:1851
int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox)
Calculate the gbox for this goemetry, a cartesian box or geodetic box, depending on how it is flagged...
Definition: lwgeom.c:701
int lwgeom_is_clockwise(LWGEOM *lwgeom)
Check clockwise orientation on LWGEOM polygons.
Definition: lwgeom.c:64
GBOX * gbox_clone(const GBOX *gbox)
Definition: g_box.c:56
LWTIN * lwgeom_as_lwtin(const LWGEOM *lwgeom)
Definition: lwgeom.c:236
void lwgeom_set_srid(LWGEOM *geom, int32_t srid)
Definition: lwgeom.c:1583
int value
Definition: genraster.py:61
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:92
LWPOLY * lwpoly_segmentize2d(LWPOLY *line, double dist)
Definition: lwpoly.c:323
static int lwgeom_subdivide_recursive(const LWGEOM *geom, int maxvertices, int depth, LWCOLLECTION *col, const GBOX *clip)
Definition: lwgeom.c:1943
void * lwalloc(size_t size)
Definition: lwutil.c:229
LWGEOM * lwtriangle_as_lwgeom(const LWTRIANGLE *obj)
Definition: lwgeom.c:293
void lwgeom_free(LWGEOM *lwgeom)
Definition: lwgeom.c:1099
int lwpoly_count_vertices(LWPOLY *poly)
Definition: lwpoly.c:452
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwgeom.c:878
double y
Definition: liblwgeom.h:352
#define MULTILINETYPE
Definition: liblwgeom.h:89
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
LWPOLY * lwpoly_clone(const LWPOLY *lwgeom)
Definition: lwpoly.c:215
LWLINE * lwline_clone_deep(const LWLINE *lwgeom)
Definition: lwline.c:118
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:152
unsigned char uint8_t
Definition: uthash.h:79
double lwcurvepoly_area(const LWCURVEPOLY *curvepoly)
This should be rewritten to make use of the curve itself.
Definition: lwcurvepoly.c:134
int gbox_same(const GBOX *g1, const GBOX *g2)
Check if 2 given Gbox are the same.
Definition: g_box.c:176
LWGEOM * lwgeom_flip_coordinates(LWGEOM *in)
Reverse the X and Y coordinate order.
Definition: lwgeom.c:1507
char lwpoly_same(const LWPOLY *p1, const LWPOLY *p2)
Definition: lwpoly.c:347
LWGEOM * lwcompound_as_lwgeom(const LWCOMPOUND *obj)
Definition: lwgeom.c:283
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
Definition: lwgeom.c:421
char lwline_same(const LWLINE *p1, const LWLINE *p2)
Definition: lwline.c:156
LWLINE * lwline_simplify(const LWLINE *iline, double dist, int preserve_collapsed)
Definition: lwline.c:541
LWGEOM * lwgeom_as_curve(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate CURVE* type.
Definition: lwgeom.c:373
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
uint8_t type
Definition: liblwgeom.h:490
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
void ptarray_affine(POINTARRAY *pa, const AFFINE *affine)
Affine transform a pointarray.
Definition: ptarray.c:1800
void lwgeom_reverse(LWGEOM *lwgeom)
Reverse vertex order of LWGEOM.
Definition: lwgeom.c:93
POINTARRAY * points
Definition: liblwgeom.h:422
const GBOX * lwgeom_get_bbox(const LWGEOM *lwg)
Get a non-empty geometry bounding box, computing and caching it if not already there.
Definition: lwgeom.c:689
int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox)
Calculate the 2-4D bounding box of a geometry.
Definition: g_box.c:683
Snap to grid.