PostGIS  2.5.7dev-r@@SVN_REVISION@@
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 
29 static LWGEOM* lwgeom_filter_m_ignore_null(LWGEOM *geom,double min,double max, int returnm);
30 
31 static 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 }
83 static 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 
99 static 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 
115 static 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 
153 static 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 
173 static 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("Unsupported geometry type: %s [%d] in function %s", lwtype_name((geom)->type), (geom)->type, __func__);
216  }
217  return geom_out;
218 
219 }
220 
221 LWGEOM* 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("Unsupported geometry type: %s [%d] in function %s", lwtype_name((geom)->type), (geom)->type, __func__);
262  }
263  }
264  /*Shouldn't be possible*/
265  return NULL;
266 }
267 
268 
269 
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition: lwgeom.c:330
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
#define LW_FAILURE
Definition: liblwgeom.h:79
#define MULTILINETYPE
Definition: liblwgeom.h:89
#define LINETYPE
Definition: liblwgeom.h:86
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition: lwgeom.c:320
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
LWLINE * lwline_construct_empty(int srid, char hasz, char hasm)
Definition: lwline.c:64
int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
Add a ring, allocating extra space if necessary.
Definition: lwpoly.c:247
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:62
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:140
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:335
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:152
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
#define POLYGONTYPE
Definition: liblwgeom.h:87
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:141
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:328
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
void lwpoly_free(LWPOLY *poly)
Definition: lwpoly.c:175
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:151
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
LWPOLY * lwpoly_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoly.c:161
int lwcollection_is_empty(const LWCOLLECTION *col)
Definition: lwcollection.c:508
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
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 LWPOINT * lwpoint_filterm(LWPOINT *pt, double min, double max, int returnm)
Definition: lwmval.c:83
static LWGEOM * lwgeom_filter_m_ignore_null(LWGEOM *geom, double min, double max, int returnm)
Definition: lwmval.c:173
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
static LWPOLY * lwpoly_filterm(LWPOLY *poly, double min, double max, int returnm)
Definition: lwmval.c:115
type
Definition: ovdump.py:41
uint32_t ngeoms
Definition: liblwgeom.h:510
uint8_t type
Definition: liblwgeom.h:506
uint8_t flags
Definition: liblwgeom.h:507
LWGEOM ** geoms
Definition: liblwgeom.h:512
int32_t srid
Definition: liblwgeom.h:509
uint8_t type
Definition: liblwgeom.h:399
uint8_t flags
Definition: liblwgeom.h:400
int32_t srid
Definition: liblwgeom.h:402
POINTARRAY * points
Definition: liblwgeom.h:425
int32_t srid
Definition: liblwgeom.h:424
POINTARRAY * point
Definition: liblwgeom.h:414
int32_t srid
Definition: liblwgeom.h:413
POINTARRAY ** rings
Definition: liblwgeom.h:460
uint32_t nrings
Definition: liblwgeom.h:458
uint8_t flags
Definition: liblwgeom.h:455
int32_t srid
Definition: liblwgeom.h:457
uint32_t npoints
Definition: liblwgeom.h:374
uint8_t * serialized_pointlist
Definition: liblwgeom.h:369
uint8_t flags
Definition: liblwgeom.h:372
unsigned int uint32_t
Definition: uthash.h:78