PostGIS  2.2.7dev-r@@SVN_REVISION@@
postgis/lwgeom_geos_clean.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  *
6  * Copyright 2009-2010 Sandro Santilli <strk@keybit.net>
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  * ST_MakeValid
14  *
15  * Attempts to make an invalid geometries valid w/out losing
16  * points.
17  *
18  * Polygons may become lines or points or a collection of
19  * polygons lines and points (collapsed ring cases).
20  *
21  * Author: Sandro Santilli <strk@keybit.net>
22  *
23  * Work done for Faunalia (http://www.faunalia.it) with fundings
24  * from Regione Toscana - Sistema Informativo per il Governo
25  * del Territorio e dell'Ambiente (RT-SIGTA).
26  *
27  * Thanks to Dr. Horst Duester for previous work on a plpgsql version
28  * of the cleanup logic [1]
29  *
30  * Thanks to Andrea Peri for recommandations on constraints.
31  *
32  * [1] http://www.sogis1.so.ch/sogis/dl/postgis/cleanGeometry.sql
33  *
34  *
35  **********************************************************************/
36 
37 #include "postgres.h"
38 #include "fmgr.h"
39 #include "funcapi.h"
40 
41 #include "../postgis_config.h"
42 #include "lwgeom_geos.h"
43 #include "liblwgeom.h"
44 #include "lwgeom_pg.h"
45 
46 #include <string.h>
47 #include <assert.h>
48 
49 /* #define POSTGIS_DEBUG_LEVEL 4 */
50 
51 Datum ST_MakeValid(PG_FUNCTION_ARGS);
53 Datum ST_MakeValid(PG_FUNCTION_ARGS)
54 {
55 #if POSTGIS_GEOS_VERSION < 33
56  elog(ERROR, "You need GEOS-3.3.0 or up for ST_MakeValid");
57  PG_RETURN_NULL();
58 #else /* POSTGIS_GEOS_VERSION >= 33 */
59 
60  GSERIALIZED *in, *out;
61  LWGEOM *lwgeom_in, *lwgeom_out;
62 
63  in = PG_GETARG_GSERIALIZED_P(0);
64  lwgeom_in = lwgeom_from_gserialized(in);
65 
66  switch ( lwgeom_in->type )
67  {
68  case POINTTYPE:
69  case MULTIPOINTTYPE:
70  case LINETYPE:
71  case POLYGONTYPE:
72  case MULTILINETYPE:
73  case MULTIPOLYGONTYPE:
74  case COLLECTIONTYPE:
75  break;
76 
77  default:
78  lwpgerror("ST_MakeValid: unsupported geometry type %s",
79  lwtype_name(lwgeom_in->type));
80  PG_RETURN_NULL();
81  break;
82  }
83 
84  lwgeom_out = lwgeom_make_valid(lwgeom_in);
85  if ( ! lwgeom_out )
86  {
87  PG_FREE_IF_COPY(in, 0);
88  PG_RETURN_NULL();
89  }
90 
91  out = geometry_serialize(lwgeom_out);
92 
93  PG_RETURN_POINTER(out);
94 #endif /* POSTGIS_GEOS_VERSION >= 33 */
95 }
96 
97 #if POSTGIS_GEOS_VERSION >= 33
98 
99 /* Uses GEOS internally */
100 static LWGEOM* lwgeom_clean(LWGEOM* lwgeom_in);
101 static LWGEOM*
102 lwgeom_clean(LWGEOM* lwgeom_in)
103 {
104  LWGEOM* lwgeom_out;
105 
106  lwgeom_out = lwgeom_make_valid(lwgeom_in);
107  if ( ! lwgeom_out )
108  {
109  return NULL;
110  }
111 
112  /* Check dimensionality is the same as input */
113  if ( lwgeom_dimensionality(lwgeom_in) != lwgeom_dimensionality(lwgeom_out) )
114  {
115  lwpgnotice("lwgeom_clean: dimensional collapse (%d to %d)",
116  lwgeom_dimensionality(lwgeom_in), lwgeom_dimensionality(lwgeom_out));
117 
118  return NULL;
119  }
120 
121  /* Check that the output is not a collection if the input wasn't */
122  if ( lwgeom_out->type == COLLECTIONTYPE &&
123  lwgeom_in->type != COLLECTIONTYPE )
124  {
125  lwpgnotice("lwgeom_clean: mixed-type output (%s) "
126  "from single-type input (%s)",
127  lwtype_name(lwgeom_out->type),
128  lwtype_name(lwgeom_in->type));
129  return NULL;
130  }
131 
132  /* Force right-hand-rule (will only affect polygons) */
133  /* gout := ST_ForceRHR(gout); */
134 
135  /* Remove repeated duplicated points ? */
136  /* gout = ST_RemoveRepeatedPoints(gout); */
137 
138  return lwgeom_out;
139 }
140 
141 #endif /* POSTGIS_GEOS_VERSION >= 33 */
142 
143 
144 Datum ST_CleanGeometry(PG_FUNCTION_ARGS);
146 Datum ST_CleanGeometry(PG_FUNCTION_ARGS)
147 {
148 #if POSTGIS_GEOS_VERSION < 33
149  elog(ERROR, "You need GEOS-3.3.0 or up for ST_CleanGeometry");
150  PG_RETURN_NULL();
151 #else /* POSTGIS_GEOS_VERSION >= 33 */
152 
153  GSERIALIZED *in, *out;
154  LWGEOM *lwgeom_in, *lwgeom_out;
155 
156  in = PG_GETARG_GSERIALIZED_P(0);
157  lwgeom_in = lwgeom_from_gserialized(in);
158 
159  /* Short-circuit: empty geometry are the cleanest ! */
160 #if 0
161  if ( lwgeom_is_empty(lwgeom_in) )
162  {
163  out = geometry_serialize(lwgeom_in);
164  PG_FREE_IF_COPY(in, 0);
165  PG_RETURN_POINTER(out);
166  }
167 #endif
168 
169  lwgeom_out = lwgeom_clean(lwgeom_in);
170  if ( ! lwgeom_out )
171  {
172  PG_FREE_IF_COPY(in, 0);
173  PG_RETURN_NULL();
174  }
175 
176  out = geometry_serialize(lwgeom_out);
177  PG_RETURN_POINTER(out);
178 
179 #endif /* POSTGIS_GEOS_VERSION >= 33 */
180 }
181 
#define LINETYPE
Definition: liblwgeom.h:71
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
#define POLYGONTYPE
Definition: liblwgeom.h:72
Datum ST_CleanGeometry(PG_FUNCTION_ARGS)
#define MULTIPOINTTYPE
Definition: liblwgeom.h:73
int lwgeom_dimensionality(LWGEOM *geom)
Return the dimensionality (relating to point/line/poly) of an lwgeom.
Definition: lwgeom.c:1362
PG_FUNCTION_INFO_V1(ST_MakeValid)
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:188
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
Datum ST_MakeValid(PG_FUNCTION_ARGS)
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:75
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:70
uint8_t type
Definition: liblwgeom.h:380
static LWGEOM * lwgeom_clean(LWGEOM *lwgeom_in)
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:1297
#define MULTILINETYPE
Definition: liblwgeom.h:74
#define COLLECTIONTYPE
Definition: liblwgeom.h:76
This library is the generic geometry handling section of PostGIS.