PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
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 * 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 2009-2010 Sandro Santilli <strk@kbt.io>
22 *
23 **********************************************************************/
24
25
26#include "postgres.h"
27#include "fmgr.h"
28#include "funcapi.h"
29#include "utils/builtins.h"
30
31
32#include "../postgis_config.h"
33/*#define POSTGIS_DEBUG_LEVEL 4*/
34
35#include "lwgeom_geos.h"
36#include "liblwgeom.h"
37#include "lwgeom_pg.h"
38
39#include <string.h>
40#include <assert.h>
41
42Datum ST_MakeValid(PG_FUNCTION_ARGS);
44Datum ST_MakeValid(PG_FUNCTION_ARGS)
45{
46 GSERIALIZED *in, *out;
47 LWGEOM *lwgeom_in, *lwgeom_out;
48
49 in = PG_GETARG_GSERIALIZED_P_COPY(0);
50 lwgeom_in = lwgeom_from_gserialized(in);
51
52 switch ( lwgeom_in->type )
53 {
54 case POINTTYPE:
55 case MULTIPOINTTYPE:
56 case LINETYPE:
57 case POLYGONTYPE:
58 case MULTILINETYPE:
60 case COLLECTIONTYPE:
61 break;
62
63 default:
64 lwpgerror("ST_MakeValid: unsupported geometry type %s",
65 lwtype_name(lwgeom_in->type));
66 PG_RETURN_NULL();
67 break;
68 }
69
70 if(PG_NARGS() > 1 && ! PG_ARGISNULL(1)) {
71 char *make_valid_params_str = text_to_cstring(PG_GETARG_TEXT_P(1));
72 lwgeom_out = lwgeom_make_valid_params(lwgeom_in, make_valid_params_str);
73 }
74 else {
75 lwgeom_out = lwgeom_make_valid(lwgeom_in);
76 }
77
78 if ( ! lwgeom_out )
79 {
80 PG_FREE_IF_COPY(in, 0);
81 PG_RETURN_NULL();
82 }
83
84 out = geometry_serialize(lwgeom_out);
85 if ( lwgeom_out != lwgeom_in ) {
86 lwgeom_free(lwgeom_out);
87 }
88 PG_FREE_IF_COPY(in, 0);
89
90 PG_RETURN_POINTER(out);
91}
92
93/* Uses GEOS internally */
94static LWGEOM* lwgeom_clean(LWGEOM* lwgeom_in);
95static LWGEOM*
97{
98 LWGEOM* lwgeom_out;
99
100 lwgeom_out = lwgeom_make_valid(lwgeom_in);
101 if ( ! lwgeom_out )
102 {
103 return NULL;
104 }
105
106 /* Check dimensionality is the same as input */
107 if ( lwgeom_dimensionality(lwgeom_in) != lwgeom_dimensionality(lwgeom_out) )
108 {
109 lwpgnotice("lwgeom_clean: dimensional collapse (%d to %d)",
110 lwgeom_dimensionality(lwgeom_in), lwgeom_dimensionality(lwgeom_out));
111
112 return NULL;
113 }
114
115 /* Check that the output is not a collection if the input wasn't */
116 if ( lwgeom_out->type == COLLECTIONTYPE &&
117 lwgeom_in->type != COLLECTIONTYPE )
118 {
119 lwpgnotice("lwgeom_clean: mixed-type output (%s) "
120 "from single-type input (%s)",
121 lwtype_name(lwgeom_out->type),
122 lwtype_name(lwgeom_in->type));
123 return NULL;
124 }
125
126 /* Force right-hand-rule (will only affect polygons) */
127 /* gout := ST_ForceRHR(gout); */
128
129 /* Remove repeated duplicated points ? */
130 /* gout = ST_RemoveRepeatedPoints(gout); */
131
132 return lwgeom_out;
133}
134
135
136Datum ST_CleanGeometry(PG_FUNCTION_ARGS);
138Datum ST_CleanGeometry(PG_FUNCTION_ARGS)
139{
140 GSERIALIZED *in, *out;
141 LWGEOM *lwgeom_in, *lwgeom_out;
142
143 in = PG_GETARG_GSERIALIZED_P(0);
144 lwgeom_in = lwgeom_from_gserialized(in);
145
146 /* Short-circuit: empty geometry are the cleanest ! */
147#if 0
148 if ( lwgeom_is_empty(lwgeom_in) )
149 {
150 out = geometry_serialize(lwgeom_in);
151 PG_FREE_IF_COPY(in, 0);
152 PG_RETURN_POINTER(out);
153 }
154#endif
155
156 lwgeom_out = lwgeom_clean(lwgeom_in);
157 if ( ! lwgeom_out )
158 {
159 PG_FREE_IF_COPY(in, 0);
160 PG_RETURN_NULL();
161 }
162
163 out = geometry_serialize(lwgeom_out);
164 PG_RETURN_POINTER(out);
165}
166
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define COLLECTIONTYPE
Definition liblwgeom.h:108
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
LWGEOM * lwgeom_make_valid_params(LWGEOM *geom, char *make_valid_params)
#define MULTILINETYPE
Definition liblwgeom.h:106
#define LINETYPE
Definition liblwgeom.h:103
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
#define POLYGONTYPE
Definition liblwgeom.h:104
int lwgeom_dimensionality(const LWGEOM *geom)
Return the dimensionality (relating to point/line/poly) of an lwgeom.
Definition lwgeom.c:1517
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
This library is the generic geometry handling section of PostGIS.
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
static LWGEOM * lwgeom_clean(LWGEOM *lwgeom_in)
Datum ST_CleanGeometry(PG_FUNCTION_ARGS)
Datum ST_MakeValid(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(ST_MakeValid)
uint8_t type
Definition liblwgeom.h:462