PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwhomogenize.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 2010 Olivier Courtin <olivier.courtin@oslandia.com>
22 *
23 **********************************************************************/
24
25
26#include <stdlib.h>
27#include "liblwgeom_internal.h"
28#include "lwgeom_log.h"
29
30
31typedef struct {
32 int cnt[NUMTYPES];
35
36static void
38{
39 int i;
40 for ( i = 0; i < NUMTYPES; i++ )
41 {
42 buffer->cnt[i] = 0;
43 buffer->buf[i] = NULL;
44 }
45}
46
47/*
48static void
49free_homogenizebuffer(HomogenizeBuffer *buffer)
50{
51 int i;
52 for ( i = 0; i < NUMTYPES; i++ )
53 {
54 if ( buffer->buf[i] )
55 {
56 lwcollection_free(buffer->buf[i]);
57 }
58 }
59}
60*/
61
62/*
63** Given a generic collection, return the "simplest" form.
64**
65** eg: GEOMETRYCOLLECTION(MULTILINESTRING()) => MULTILINESTRING()
66**
67** GEOMETRYCOLLECTION(MULTILINESTRING(), MULTILINESTRING(), POINT())
68** => GEOMETRYCOLLECTION(MULTILINESTRING(), POINT())
69**
70** In general, if the subcomponents are homogeneous, return a properly
71** typed collection.
72** Otherwise, return a generic collection, with the subtypes in minimal
73** typed collections.
74*/
75static void
77{
78 uint32_t i;
79
80 if (!col || lwcollection_is_empty(col))
81 return;
82
83 for (i = 0; i < col->ngeoms; i++)
84 {
85 LWGEOM *geom = col->geoms[i];
86 switch (geom->type)
87 {
88 case POINTTYPE:
89 case LINETYPE:
90 case CIRCSTRINGTYPE:
91 case COMPOUNDTYPE:
92 case TRIANGLETYPE:
93 case CURVEPOLYTYPE:
94 case POLYGONTYPE:
95 /* Init if necessary */
96 if (!buffer->buf[geom->type])
97 {
100 bufcol->type = lwtype_get_collectiontype(geom->type);
101 buffer->buf[geom->type] = bufcol;
102 }
103 /* Add sub-geom to buffer */
105 /* Increment count for this singleton type */
106 buffer->cnt[geom->type]++;
107 break;
108 default:
110 break;
111 }
112 }
113}
114
115static LWGEOM*
117{
118 int i;
119 int ntypes = 0;
120 int type = 0;
121 LWGEOM *outgeom = NULL;
122
124
125 /* Sort all the parts into a buffer */
128
129 /* Check for homogeneity */
130 for ( i = 0; i < NUMTYPES; i++ )
131 {
132 if ( buffer.cnt[i] > 0 )
133 {
134 ntypes++;
135 type = i;
136 }
137 }
138
139 /* No types? Huh. Return empty. */
140 if ( ntypes == 0 )
141 {
142 LWCOLLECTION *outcol;
144 outgeom = lwcollection_as_lwgeom(outcol);
145 }
146 /* One type, return homogeneous collection */
147 else if ( ntypes == 1 )
148 {
149 LWCOLLECTION *outcol;
150 outcol = buffer.buf[type];
151 if ( outcol->ngeoms == 1 )
152 {
153 outgeom = outcol->geoms[0];
154 outcol->ngeoms=0; lwcollection_free(outcol);
155 }
156 else
157 {
158 outgeom = lwcollection_as_lwgeom(outcol);
159 }
160 outgeom->srid = col->srid;
161 }
162 /* Bah, more than out type, return anonymous collection */
163 else if ( ntypes > 1 )
164 {
165 int j;
166 LWCOLLECTION *outcol;
168 for ( j = 0; j < NUMTYPES; j++ )
169 {
170 if ( buffer.buf[j] )
171 {
172 LWCOLLECTION *bcol = buffer.buf[j];
173 if ( bcol->ngeoms == 1 )
174 {
175 lwcollection_add_lwgeom(outcol, bcol->geoms[0]);
176 bcol->ngeoms=0; lwcollection_free(bcol);
177 }
178 else
179 {
181 }
182 }
183 }
184 outgeom = lwcollection_as_lwgeom(outcol);
185 }
186
187 return outgeom;
188}
189
190
191
192
193
194/*
195** Given a generic geometry, return the "simplest" form.
196**
197** eg:
198** LINESTRING() => LINESTRING()
199**
200** MULTILINESTRING(with a single line) => LINESTRING()
201**
202** GEOMETRYCOLLECTION(MULTILINESTRING()) => MULTILINESTRING()
203**
204** GEOMETRYCOLLECTION(MULTILINESTRING(), MULTILINESTRING(), POINT())
205** => GEOMETRYCOLLECTION(MULTILINESTRING(), POINT())
206*/
207LWGEOM *
209{
210 LWGEOM *hgeom;
211
212 /* EMPTY Geometry */
213 if (lwgeom_is_empty(geom))
214 {
215 if( lwgeom_is_collection(geom) )
216 {
218 }
219
220 return lwgeom_clone_deep(geom);
221 }
222
223 switch (geom->type)
224 {
225
226 /* Return simple geometries untouched */
227 case POINTTYPE:
228 case LINETYPE:
229 case CIRCSTRINGTYPE:
230 case COMPOUNDTYPE:
231 case TRIANGLETYPE:
232 case CURVEPOLYTYPE:
233 case POLYGONTYPE:
234 return lwgeom_clone_deep(geom);
235
236 /* Process homogeneous geometries lightly */
237 case MULTIPOINTTYPE:
238 case MULTILINETYPE:
239 case MULTIPOLYGONTYPE:
240 case MULTICURVETYPE:
241 case MULTISURFACETYPE:
243 case TINTYPE:
244 {
245 LWCOLLECTION *col = (LWCOLLECTION*)geom;
246
247 /* Strip single-entry multi-geometries down to singletons */
248 if ( col->ngeoms == 1 )
249 {
250 hgeom = lwgeom_clone_deep((LWGEOM *)(col->geoms[0]));
251 hgeom->srid = geom->srid;
252 if (geom->bbox)
253 hgeom->bbox = gbox_copy(geom->bbox);
254 return hgeom;
255 }
256
257 /* Return proper multigeometry untouched */
258 return lwgeom_clone_deep(geom);
259 }
260
261 /* Work on anonymous collections separately */
262 case COLLECTIONTYPE:
263 return lwcollection_homogenize((LWCOLLECTION *) geom);
264 }
265
266 /* Unknown type */
267 lwerror("lwgeom_homogenize: Geometry Type not supported (%s)",
268 lwtype_name(geom->type));
269
270 return NULL; /* Never get here! */
271}
GBOX * gbox_copy(const GBOX *box)
Return a copy of the GBOX, based on dimensionality of flags.
Definition gbox.c:438
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
uint32_t lwtype_get_collectiontype(uint8_t type)
Given an lwtype number, what homogeneous collection can hold it?
Definition lwgeom.c:1222
#define COLLECTIONTYPE
Definition liblwgeom.h:108
#define COMPOUNDTYPE
Definition liblwgeom.h:110
#define CURVEPOLYTYPE
Definition liblwgeom.h:111
#define MULTILINETYPE
Definition liblwgeom.h:106
#define MULTISURFACETYPE
Definition liblwgeom.h:113
#define LINETYPE
Definition liblwgeom.h:103
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition lwgeom.c:261
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition lwgeom.c:962
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
#define FLAGS_GET_Z(flags)
Definition liblwgeom.h:165
#define TINTYPE
Definition liblwgeom.h:116
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM contains sub-geometries or not This basically just checks that the struct ...
Definition lwgeom.c:1125
#define POLYGONTYPE
Definition liblwgeom.h:104
#define POLYHEDRALSURFACETYPE
Definition liblwgeom.h:114
#define CIRCSTRINGTYPE
Definition liblwgeom.h:109
#define FLAGS_GET_M(flags)
Definition liblwgeom.h:166
void lwcollection_free(LWCOLLECTION *col)
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
#define MULTICURVETYPE
Definition liblwgeom.h:112
#define TRIANGLETYPE
Definition liblwgeom.h:115
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition lwgeom.c:969
#define NUMTYPES
Definition liblwgeom.h:118
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition lwgeom.c:337
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition lwgeom.c:557
int lwcollection_is_empty(const LWCOLLECTION *col)
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
static void lwcollection_build_buffer(const LWCOLLECTION *col, HomogenizeBuffer *buffer)
LWGEOM * lwgeom_homogenize(const LWGEOM *geom)
static LWGEOM * lwcollection_homogenize(const LWCOLLECTION *col)
static void init_homogenizebuffer(HomogenizeBuffer *buffer)
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition lwinline.h:199
Datum buffer(PG_FUNCTION_ARGS)
#define ntypes
int cnt[NUMTYPES]
lwflags_t flags
Definition liblwgeom.h:577
uint32_t ngeoms
Definition liblwgeom.h:580
uint8_t type
Definition liblwgeom.h:578
LWGEOM ** geoms
Definition liblwgeom.h:575
int32_t srid
Definition liblwgeom.h:576
uint8_t type
Definition liblwgeom.h:462
GBOX * bbox
Definition liblwgeom.h:458
int32_t srid
Definition liblwgeom.h:460