PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwmval.c
Go to the documentation of this file.
1
2/**********************************************************************
3 *
4 * PostGIS - Spatial Types for PostgreSQL
5 * http://postgis.net
6 *
7 * PostGIS is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * PostGIS is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with PostGIS. If not, see <http://www.gnu.org/licenses/>.
19 *
20 **********************************************************************
21 *
22 * Copyright 2018 Nicklas Avén
23 *
24 **********************************************************************/
25
26
27#include "liblwgeom_internal.h"
28
29static LWGEOM* lwgeom_filter_m_ignore_null(LWGEOM *geom,double min,double max, int returnm);
30
31static POINTARRAY* ptarray_filterm(POINTARRAY *pa,double min, double max, int returnm)
32{
33 LWDEBUGF(2, "Entered %s", __func__);
34
35 /*Check if M exists
36 * This should already be tested earlier so we don't handle it properly.
37 * If this happens it is because the function is used in another context than filterM
38 and we throw an error*/
39 if(!FLAGS_GET_M(pa->flags))
40 lwerror("missing m-value in function %s\n",__func__);
41
42 /*Dimensions in input geometry*/
43 int ndims = FLAGS_NDIMS(pa->flags);
44
45 /*Dimensions in result*/
46 int res_ndims;
47 if(returnm)
48 res_ndims = ndims;
49 else
50 res_ndims = ndims-1;
51
52 int pointsize = res_ndims * sizeof(double);
53
54 double m_val;
55
56 //M-value will always be the last dimension
57 int m_pos = ndims-1;
58
59 uint32_t i, counter=0;
60 for(i=0;i<pa->npoints;i++)
61 {
62 m_val = *((double*)pa->serialized_pointlist + i*ndims + m_pos);
63 if(m_val >= min && m_val <= max)
64 counter++;
65 }
66
67 POINTARRAY *pa_res = ptarray_construct(FLAGS_GET_Z(pa->flags),returnm * FLAGS_GET_M(pa->flags), counter);
68
69 double *res_cursor = (double*) pa_res->serialized_pointlist;
70 for(i=0;i<pa->npoints;i++)
71 {
72 m_val = *((double*)pa->serialized_pointlist + i*ndims + m_pos);
73 if(m_val >= min && m_val <= max)
74 {
75 memcpy(res_cursor, (double*) pa->serialized_pointlist + i*ndims, pointsize);
76 res_cursor+=res_ndims;
77 }
78 }
79
80 return pa_res;
81
82}
83static LWPOINT* lwpoint_filterm(LWPOINT *pt,double min,double max, int returnm)
84{
85 LWDEBUGF(2, "Entered %s", __func__);
86
87 POINTARRAY *pa;
88
89 pa = ptarray_filterm(pt->point, min, max,returnm);
90 if(pa->npoints < 1)
91 {
92 ptarray_free(pa);
93 return NULL;
94 }
95 return lwpoint_construct(pt->srid, NULL, pa);
96
97}
98
99static LWLINE* lwline_filterm(LWLINE *line,double min,double max, int returnm)
100{
101 LWDEBUGF(2, "Entered %s", __func__);
102
103 POINTARRAY *pa;
104 pa = ptarray_filterm(line->points, min, max,returnm);
105
106 if(pa->npoints < 2 )
107 {
108 ptarray_free(pa);
109 return NULL;
110 }
111
112 return lwline_construct(line->srid, NULL, pa);
113}
114
115static LWPOLY* lwpoly_filterm(LWPOLY *poly,double min,double max, int returnm)
116{
117 LWDEBUGF(2, "Entered %s", __func__);
118 int i, nrings;
119 LWPOLY *poly_res = lwpoly_construct_empty(poly->srid, FLAGS_GET_Z(poly->flags),returnm * FLAGS_GET_M(poly->flags));
120
121 nrings = poly->nrings;
122 for( i = 0; i < nrings; i++ )
123 {
124 /* Ret number of points */
125 POINTARRAY *pa = ptarray_filterm(poly->rings[i], min, max,returnm);
126
127 /* Skip empty rings */
128 if( pa == NULL )
129 continue;
130
131 if(pa->npoints>=4)
132 {
133 if (lwpoly_add_ring(poly_res, pa) == LW_FAILURE )
134 {
135 LWDEBUG(2, "Unable to add ring to polygon");
136 lwerror("Unable to add ring to polygon");
137 }
138 }
139 else if (i==0)
140 {
141 ptarray_free(pa);
142 lwpoly_free(poly_res);
143 return NULL;
144 }
145 else
146 ptarray_free(pa);
147 }
148 return poly_res;
149}
150
151
152
153static LWCOLLECTION* lwcollection_filterm(const LWCOLLECTION *igeom,double min,double max, int returnm)
154{
155 LWDEBUGF(2, "Entered %s",__func__);
156
157 uint32_t i;
158
159 LWCOLLECTION *out = lwcollection_construct_empty(igeom->type, igeom->srid, FLAGS_GET_Z(igeom->flags),returnm * FLAGS_GET_M(igeom->flags));
160
161 if( lwcollection_is_empty(igeom) )
162 return out;
163
164 for( i = 0; i < igeom->ngeoms; i++ )
165 {
166 LWGEOM *ngeom = lwgeom_filter_m_ignore_null(igeom->geoms[i],min, max,returnm);
167 if ( ngeom ) out = lwcollection_add_lwgeom(out, ngeom);
168 }
169
170 return out;
171}
172
173static LWGEOM* lwgeom_filter_m_ignore_null(LWGEOM *geom,double min,double max, int returnm)
174{
175 LWDEBUGF(2, "Entered %s",__func__);
176
177 LWGEOM *geom_out = NULL;
178
179 if(!FLAGS_GET_M(geom->flags))
180 return geom;
181 switch ( geom->type )
182 {
183 case POINTTYPE:
184 {
185 LWDEBUGF(4,"Type found is Point, %d", geom->type);
186 geom_out = lwpoint_as_lwgeom(lwpoint_filterm((LWPOINT*) geom, min, max,returnm));
187 break;
188 }
189 case LINETYPE:
190 {
191 LWDEBUGF(4,"Type found is Linestring, %d", geom->type);
192 geom_out = lwline_as_lwgeom(lwline_filterm((LWLINE*) geom, min,max,returnm));
193 break;
194 }
195 /* Polygon has 'nrings' and 'rings' elements */
196 case POLYGONTYPE:
197 {
198 LWDEBUGF(4,"Type found is Polygon, %d", geom->type);
199 geom_out = lwpoly_as_lwgeom(lwpoly_filterm((LWPOLY*)geom, min, max,returnm));
200 break;
201 }
202
203 /* All these Collection types have 'ngeoms' and 'geoms' elements */
204 case MULTIPOINTTYPE:
205 case MULTILINETYPE:
206 case MULTIPOLYGONTYPE:
207 case COLLECTIONTYPE:
208 {
209 LWDEBUGF(4,"Type found is collection, %d", geom->type);
210 geom_out = (LWGEOM*) lwcollection_filterm((LWCOLLECTION*) geom, min, max,returnm);
211 break;
212 }
213 /* Unknown type! */
214 default:
215 lwerror("%s: Unsupported geometry type: %s", __func__, lwtype_name(geom->type));
216 }
217 return geom_out;
218
219}
220
221LWGEOM* lwgeom_filter_m(LWGEOM *geom,double min,double max, int returnm)
222{
223 LWDEBUGF(2, "Entered %s",__func__);
224
225 LWGEOM *ngeom = lwgeom_filter_m_ignore_null(geom,min, max,returnm);
226
227 if(ngeom)
228 return ngeom;
229 else
230 {
231 switch ( geom->type )
232 {
233 case POINTTYPE:
234 {
235 return (LWGEOM*) lwpoint_construct_empty(geom->srid, FLAGS_GET_Z(geom->flags), returnm * FLAGS_GET_M(geom->flags));
236 break;
237 }
238 case LINETYPE:
239 {
240 return (LWGEOM*) lwline_construct_empty(geom->srid, FLAGS_GET_Z(geom->flags), returnm * FLAGS_GET_M(geom->flags));
241 break;
242 }
243 /* Polygon has 'nrings' and 'rings' elements */
244 case POLYGONTYPE:
245 {
246 return (LWGEOM*) lwpoly_construct_empty(geom->srid, FLAGS_GET_Z(geom->flags), returnm * FLAGS_GET_M(geom->flags));
247 break;
248 }
249
250 /* All these Collection types have 'ngeoms' and 'geoms' elements */
251 case MULTIPOINTTYPE:
252 case MULTILINETYPE:
253 case MULTIPOLYGONTYPE:
254 case COLLECTIONTYPE:
255 {
256 return (LWGEOM*) lwcollection_construct_empty(geom->type, geom->srid, FLAGS_GET_Z(geom->flags), returnm * FLAGS_GET_M(geom->flags));
257 break;
258 }
259 /* Unknown type! */
260 default:
261 lwerror("%s: Unsupported geometry type: %s", __func__, lwtype_name(geom->type));
262 }
263 }
264 /*Shouldn't be possible*/
265 return NULL;
266}
267
268
269
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
#define COLLECTIONTYPE
Definition liblwgeom.h:108
#define LW_FAILURE
Definition liblwgeom.h:96
#define MULTILINETYPE
Definition liblwgeom.h:106
#define LINETYPE
Definition liblwgeom.h:103
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition lwpoint.c:129
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition lwpoly.c:247
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
#define FLAGS_GET_Z(flags)
Definition liblwgeom.h:165
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
#define FLAGS_NDIMS(flags)
Definition liblwgeom.h:179
#define POLYGONTYPE
Definition liblwgeom.h:104
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
LWPOINT * lwpoint_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwpoint.c:151
#define FLAGS_GET_M(flags)
Definition liblwgeom.h:166
void ptarray_free(POINTARRAY *pa)
Definition ptarray.c:327
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
void lwpoly_free(LWPOLY *poly)
Definition lwpoly.c:175
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
LWPOLY * lwpoly_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwpoly.c:161
LWLINE * lwline_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwline.c:55
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition lwgeom.c:357
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
Definition ptarray.c:51
int lwcollection_is_empty(const LWCOLLECTION *col)
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:101
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
static POINTARRAY * ptarray_filterm(POINTARRAY *pa, double min, double max, int returnm)
Definition lwmval.c:31
static LWCOLLECTION * lwcollection_filterm(const LWCOLLECTION *igeom, double min, double max, int returnm)
Definition lwmval.c:153
static LWGEOM * lwgeom_filter_m_ignore_null(LWGEOM *geom, double min, double max, int returnm)
Definition lwmval.c:173
static LWPOLY * lwpoly_filterm(LWPOLY *poly, double min, double max, int returnm)
Definition lwmval.c:115
static LWPOINT * lwpoint_filterm(LWPOINT *pt, double min, double max, int returnm)
Definition lwmval.c:83
static LWLINE * lwline_filterm(LWLINE *line, double min, double max, int returnm)
Definition lwmval.c:99
LWGEOM * lwgeom_filter_m(LWGEOM *geom, double min, double max, int returnm)
Definition lwmval.c:221
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
int32_t srid
Definition liblwgeom.h:460
lwflags_t flags
Definition liblwgeom.h:461
POINTARRAY * points
Definition liblwgeom.h:483
int32_t srid
Definition liblwgeom.h:484
POINTARRAY * point
Definition liblwgeom.h:471
int32_t srid
Definition liblwgeom.h:472
POINTARRAY ** rings
Definition liblwgeom.h:519
uint32_t nrings
Definition liblwgeom.h:524
lwflags_t flags
Definition liblwgeom.h:521
int32_t srid
Definition liblwgeom.h:520
lwflags_t flags
Definition liblwgeom.h:431
uint32_t npoints
Definition liblwgeom.h:427
uint8_t * serialized_pointlist
Definition liblwgeom.h:434