PostGIS  2.1.10dev-r@@SVN_REVISION@@
lwhomogenize.c
Go to the documentation of this file.
1 /**********************************************************************
2  * $Id: lwhomogenize.c 13134 2014-12-01 08:47:21Z strk $
3  *
4  * PostGIS - Spatial Types for PostgreSQL
5  * http://postgis.net
6  * Copyright 2010 Olivier Courtin <olivier.courtin@oslandia.com>
7  *
8  * This is free software; you can redistribute and/or modify it under
9  * the terms of the GNU General Public Licence. See the COPYING file.
10  *
11  **********************************************************************/
12 
13 #include <stdlib.h>
14 #include "liblwgeom_internal.h"
15 #include "lwgeom_log.h"
16 
17 
18 typedef struct {
19  int cnt[NUMTYPES];
22 
23 static void
25 {
26  int i;
27  for ( i = 0; i < NUMTYPES; i++ )
28  {
29  buffer->cnt[i] = 0;
30  buffer->buf[i] = NULL;
31  }
32 }
33 
34 /*
35 static void
36 free_homogenizebuffer(HomogenizeBuffer *buffer)
37 {
38  int i;
39  for ( i = 0; i < NUMTYPES; i++ )
40  {
41  if ( buffer->buf[i] )
42  {
43  lwcollection_free(buffer->buf[i]);
44  }
45  }
46 }
47 */
48 
49 /*
50 ** Given a generic collection, return the "simplest" form.
51 **
52 ** eg: GEOMETRYCOLLECTION(MULTILINESTRING()) => MULTILINESTRING()
53 **
54 ** GEOMETRYCOLLECTION(MULTILINESTRING(), MULTILINESTRING(), POINT())
55 ** => GEOMETRYCOLLECTION(MULTILINESTRING(), POINT())
56 **
57 ** In general, if the subcomponents are homogeneous, return a properly
58 ** typed collection.
59 ** Otherwise, return a generic collection, with the subtypes in minimal
60 ** typed collections.
61 */
62 static void
64 {
65  int i;
66 
67  if ( ! col ) return;
68  if ( lwgeom_is_empty(lwcollection_as_lwgeom(col)) ) return;
69  for ( i = 0; i < col->ngeoms; i++ )
70  {
71  LWGEOM *geom = col->geoms[i];
72  switch(geom->type)
73  {
74  case POINTTYPE:
75  case LINETYPE:
76  case CIRCSTRINGTYPE:
77  case COMPOUNDTYPE:
78  case TRIANGLETYPE:
79  case CURVEPOLYTYPE:
80  case POLYGONTYPE:
81  {
82  /* Init if necessary */
83  if ( ! buffer->buf[geom->type] )
84  {
86  bufcol->type = lwtype_get_collectiontype(geom->type);
87  buffer->buf[geom->type] = bufcol;
88  }
89  /* Add sub-geom to buffer */
90  lwcollection_add_lwgeom(buffer->buf[geom->type], lwgeom_clone(geom));
91  /* Increment count for this singleton type */
92  buffer->cnt[geom->type] = buffer->cnt[geom->type] + 1;
93  }
94  default:
95  {
97  }
98  }
99  }
100  return;
101 }
102 
103 static LWGEOM*
105 {
106  int i;
107  int ntypes = 0;
108  int type = 0;
109  LWGEOM *outgeom = NULL;
110 
112 
113  /* Sort all the parts into a buffer */
114  init_homogenizebuffer(&buffer);
115  lwcollection_build_buffer(col, &buffer);
116 
117  /* Check for homogeneity */
118  for ( i = 0; i < NUMTYPES; i++ )
119  {
120  if ( buffer.cnt[i] > 0 )
121  {
122  ntypes++;
123  type = i;
124  }
125  }
126 
127  /* No types? Huh. Return empty. */
128  if ( ntypes == 0 )
129  {
130  LWCOLLECTION *outcol;
132  outgeom = lwcollection_as_lwgeom(outcol);
133  }
134  /* One type, return homogeneous collection */
135  else if ( ntypes == 1 )
136  {
137  LWCOLLECTION *outcol;
138  outcol = buffer.buf[type];
139  if ( outcol->ngeoms == 1 )
140  {
141  outgeom = outcol->geoms[0];
142  outcol->ngeoms=0; lwcollection_free(outcol);
143  }
144  else
145  {
146  outgeom = lwcollection_as_lwgeom(outcol);
147  }
148  outgeom->srid = col->srid;
149  }
150  /* Bah, more than out type, return anonymous collection */
151  else if ( ntypes > 1 )
152  {
153  int j;
154  LWCOLLECTION *outcol;
156  for ( j = 0; j < NUMTYPES; j++ )
157  {
158  if ( buffer.buf[j] )
159  {
160  LWCOLLECTION *bcol = buffer.buf[j];
161  if ( bcol->ngeoms == 1 )
162  {
163  lwcollection_add_lwgeom(outcol, bcol->geoms[0]);
164  bcol->ngeoms=0; lwcollection_free(bcol);
165  }
166  else
167  {
169  }
170  }
171  }
172  outgeom = lwcollection_as_lwgeom(outcol);
173  }
174 
175  return outgeom;
176 }
177 
178 
179 
180 
181 
182 /*
183 ** Given a generic geometry, return the "simplest" form.
184 **
185 ** eg:
186 ** LINESTRING() => LINESTRING()
187 **
188 ** MULTILINESTRING(with a single line) => LINESTRING()
189 **
190 ** GEOMETRYCOLLECTION(MULTILINESTRING()) => MULTILINESTRING()
191 **
192 ** GEOMETRYCOLLECTION(MULTILINESTRING(), MULTILINESTRING(), POINT())
193 ** => GEOMETRYCOLLECTION(MULTILINESTRING(), POINT())
194 */
195 LWGEOM *
197 {
198  LWGEOM *hgeom;
199 
200  /* EMPTY Geometry */
201  if (lwgeom_is_empty(geom))
202  {
203  if( lwgeom_is_collection(geom) )
204  {
206  }
207 
208  return lwgeom_clone(geom);
209  }
210 
211  switch (geom->type)
212  {
213 
214  /* Return simple geometries untouched */
215  case POINTTYPE:
216  case LINETYPE:
217  case CIRCSTRINGTYPE:
218  case COMPOUNDTYPE:
219  case TRIANGLETYPE:
220  case CURVEPOLYTYPE:
221  case POLYGONTYPE:
222  return lwgeom_clone(geom);
223 
224  /* Process homogeneous geometries lightly */
225  case MULTIPOINTTYPE:
226  case MULTILINETYPE:
227  case MULTIPOLYGONTYPE:
228  case MULTICURVETYPE:
229  case MULTISURFACETYPE:
231  case TINTYPE:
232  {
233  LWCOLLECTION *col = (LWCOLLECTION*)geom;
234 
235  /* Strip single-entry multi-geometries down to singletons */
236  if ( col->ngeoms == 1 )
237  {
238  hgeom = lwgeom_clone((LWGEOM*)(col->geoms[0]));
239  hgeom->srid = geom->srid;
240  if (geom->bbox)
241  hgeom->bbox = gbox_copy(geom->bbox);
242  return hgeom;
243  }
244 
245  /* Return proper multigeometry untouched */
246  return lwgeom_clone(geom);
247  }
248 
249  /* Work on anonymous collections separately */
250  case COLLECTIONTYPE:
251  return lwcollection_homogenize((LWCOLLECTION *) geom);
252  }
253 
254  /* Unknown type */
255  lwerror("lwgeom_homogenize: Geometry Type not supported (%i)",
256  lwtype_name(geom->type));
257 
258  return NULL; /* Never get here! */
259 }
#define LINETYPE
Definition: liblwgeom.h:61
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition: g_box.c:362
GBOX * bbox
Definition: liblwgeom.h:354
int lwtype_get_collectiontype(uint8_t type)
Given an lwtype number, what homogeneous collection can hold it?
Definition: lwgeom.c:982
#define MULTICURVETYPE
Definition: liblwgeom.h:70
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:947
uint8_t type
Definition: liblwgeom.h:459
#define POLYGONTYPE
Definition: liblwgeom.h:62
#define CURVEPOLYTYPE
Definition: liblwgeom.h:69
#define COMPOUNDTYPE
Definition: liblwgeom.h:68
#define MULTIPOINTTYPE
Definition: liblwgeom.h:63
#define TRIANGLETYPE
Definition: liblwgeom.h:73
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:72
int cnt[NUMTYPES]
Definition: lwhomogenize.c:19
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:792
int32_t srid
Definition: liblwgeom.h:355
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:67
uint8_t flags
Definition: liblwgeom.h:460
static void init_homogenizebuffer(HomogenizeBuffer *buffer)
Definition: lwhomogenize.c:24
Datum buffer(PG_FUNCTION_ARGS)
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:164
static LWGEOM * lwcollection_homogenize(const LWCOLLECTION *col)
Definition: lwhomogenize.c:104
LWGEOM ** geoms
Definition: liblwgeom.h:465
LWGEOM * lwgeom_homogenize(const LWGEOM *geom)
Definition: lwhomogenize.c:196
#define TINTYPE
Definition: liblwgeom.h:74
LWCOLLECTION * buf[NUMTYPES]
Definition: lwhomogenize.c:20
#define NUMTYPES
Definition: liblwgeom.h:76
int32_t srid
Definition: liblwgeom.h:462
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:106
LWGEOM * lwgeom_clone(const LWGEOM *lwgeom)
Clone LWGEOM object.
Definition: lwgeom.c:351
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:65
#define MULTISURFACETYPE
Definition: liblwgeom.h:71
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition: lwgeom.c:143
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:60
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:107
uint8_t type
Definition: liblwgeom.h:352
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:316
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:67
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:1229
static void lwcollection_build_buffer(const LWCOLLECTION *col, HomogenizeBuffer *buffer)
Definition: lwhomogenize.c:63
#define MULTILINETYPE
Definition: liblwgeom.h:64
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:81
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:799
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:174
#define COLLECTIONTYPE
Definition: liblwgeom.h:66
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition: lwgeom.c:219