PostGIS  2.5.7dev-r@@SVN_REVISION@@
lwchaikins.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 
30 
31 static POINTARRAY * ptarray_chaikin(POINTARRAY *inpts, int preserve_endpoint, int isclosed)
32 {
33  uint32_t p, i, n_out_points=0, p1_set=0, p2_set=0;
34  POINT4D p1, p2;
36  double *dlist;
37  double deltaval, quarter_delta, val1, val2;
38  uint32_t ndims = 2 + ptarray_has_z(inpts) + ptarray_has_m(inpts);
39  int new_npoints = inpts->npoints * 2;
40  opts = ptarray_construct_empty(FLAGS_GET_Z(inpts->flags), FLAGS_GET_M(inpts->flags), new_npoints);
41 
42  dlist = (double*)(opts->serialized_pointlist);
43 
44  p1 = getPoint4d(inpts, 0);
45  /*if first point*/
46  if(preserve_endpoint)
47  {
49  n_out_points++;
50  }
51 
52  for (p=1;p<inpts->npoints;p++)
53  {
54  memcpy(&p2, &p1, sizeof(POINT4D));
55  p1 = getPoint4d(inpts, p);
56  if(p>0)
57  {
58  p1_set = p2_set = 0;
59  for (i=0;i<ndims;i++)
60  {
61  val1 = ((double*) &(p1))[i];
62  val2 = ((double*) &(p2))[i];
63  deltaval = val1 - val2;
64  quarter_delta = deltaval * 0.25;
65  if(!preserve_endpoint || p > 1)
66  {
67  dlist[n_out_points * ndims + i] = val2 + quarter_delta;
68  p1_set = 1;
69  }
70  if(!preserve_endpoint || p < inpts->npoints - 1)
71  {
72  dlist[(n_out_points + p1_set) * ndims + i] = val1 - quarter_delta;
73  p2_set = 1;
74  }
75  }
76  n_out_points+=(p1_set + p2_set);
77  }
78  }
79 
80  /*if last point*/
81  if(preserve_endpoint)
82  {
83  opts->npoints = n_out_points;
85  n_out_points++;
86  }
87 
88  if(isclosed && !preserve_endpoint)
89  {
90  opts->npoints = n_out_points;
91  POINT4D first_point = getPoint4d(opts, 0);
92  ptarray_append_point(opts, &first_point, LW_TRUE);
93  n_out_points++;
94  }
95  opts->npoints = n_out_points;
96 
97  return opts;
98 
99 }
100 
101 static LWLINE* lwline_chaikin(const LWLINE *iline, int n_iterations)
102 {
103  POINTARRAY *pa, *pa_new;
104  int j;
105  LWLINE *oline;
106 
107  if( lwline_is_empty(iline))
108  return lwline_clone(iline);
109 
110  pa = iline->points;
111  for (j=0;j<n_iterations;j++)
112  {
113  pa_new = ptarray_chaikin(pa,1,LW_FALSE);
114  if(j>0)
115  ptarray_free(pa);
116  pa=pa_new;
117  }
118  oline = lwline_construct(iline->srid, NULL, pa);
119 
120  oline->type = iline->type;
121  return oline;
122 
123 }
124 
125 
126 static LWPOLY* lwpoly_chaikin(const LWPOLY *ipoly, int n_iterations, int preserve_endpoint)
127 {
128  uint32_t i;
129  int j;
130  POINTARRAY *pa, *pa_new;
131  LWPOLY *opoly = lwpoly_construct_empty(ipoly->srid, FLAGS_GET_Z(ipoly->flags), FLAGS_GET_M(ipoly->flags));
132 
133  if( lwpoly_is_empty(ipoly) )
134  return opoly;
135  for (i = 0; i < ipoly->nrings; i++)
136  {
137  pa = ipoly->rings[i];
138  for(j=0;j<n_iterations;j++)
139  {
140  pa_new = ptarray_chaikin(pa,preserve_endpoint,LW_TRUE);
141  if(j>0)
142  ptarray_free(pa);
143  pa=pa_new;
144  }
145  if(pa->npoints>=4)
146  {
147  if( lwpoly_add_ring(opoly,pa ) == LW_FAILURE )
148  return NULL;
149  }
150  }
151 
152  opoly->type = ipoly->type;
153 
154  if( lwpoly_is_empty(opoly) )
155  return NULL;
156 
157  return opoly;
158 
159 }
160 
161 
162 static LWCOLLECTION* lwcollection_chaikin(const LWCOLLECTION *igeom, int n_iterations, int preserve_endpoint)
163 {
164  LWDEBUG(2, "Entered lwcollection_set_effective_area");
165  uint32_t i;
166 
167  LWCOLLECTION *out = lwcollection_construct_empty(igeom->type, igeom->srid, FLAGS_GET_Z(igeom->flags), FLAGS_GET_M(igeom->flags));
168 
169  if( lwcollection_is_empty(igeom) )
170  return out; /* should we return NULL instead ? */
171 
172  for( i = 0; i < igeom->ngeoms; i++ )
173  {
174  LWGEOM *ngeom = lwgeom_chaikin(igeom->geoms[i],n_iterations,preserve_endpoint);
175  if ( ngeom ) out = lwcollection_add_lwgeom(out, ngeom);
176  }
177 
178  return out;
179 }
180 
181 
182 LWGEOM* lwgeom_chaikin(const LWGEOM *igeom, int n_iterations, int preserve_endpoint)
183 {
184  LWDEBUG(2, "Entered lwgeom_set_effective_area");
185  switch (igeom->type)
186  {
187  case POINTTYPE:
188  case MULTIPOINTTYPE:
189  return lwgeom_clone(igeom);
190  case LINETYPE:
191  return (LWGEOM*)lwline_chaikin((LWLINE*)igeom, n_iterations);
192  case POLYGONTYPE:
193  return (LWGEOM*)lwpoly_chaikin((LWPOLY*)igeom,n_iterations,preserve_endpoint);
194  case MULTILINETYPE:
195  case MULTIPOLYGONTYPE:
196  case COLLECTIONTYPE:
197  return (LWGEOM*)lwcollection_chaikin((LWCOLLECTION *)igeom,n_iterations,preserve_endpoint);
198  default:
199  lwerror("lwgeom_chaikin: unsupported geometry type: %s",lwtype_name(igeom->type));
200  }
201  return NULL;
202 }
POINT4D getPoint4d(const POINTARRAY *pa, uint32_t n)
Definition: lwgeom_api.c:106
#define LW_FALSE
Definition: liblwgeom.h:77
#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
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
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:85
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:140
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
#define POLYGONTYPE
Definition: liblwgeom.h:87
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
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
LWGEOM * lwgeom_clone(const LWGEOM *lwgeom)
Clone LWGEOM object.
Definition: lwgeom.c:482
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
Definition: ptarray.c:156
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
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
LWLINE * lwline_clone(const LWLINE *lwgeom)
Definition: lwline.c:102
int lwline_is_empty(const LWLINE *line)
Definition: lwline.c:511
int lwpoly_is_empty(const LWPOLY *poly)
Definition: lwpoly.c:418
int ptarray_has_z(const POINTARRAY *pa)
Definition: ptarray.c:36
int ptarray_has_m(const POINTARRAY *pa)
Definition: ptarray.c:43
int lwcollection_is_empty(const LWCOLLECTION *col)
Definition: lwcollection.c:508
static LWLINE * lwline_chaikin(const LWLINE *iline, int n_iterations)
Definition: lwchaikins.c:101
LWGEOM * lwgeom_chaikin(const LWGEOM *igeom, int n_iterations, int preserve_endpoint)
Definition: lwchaikins.c:182
static LWPOLY * lwpoly_chaikin(const LWPOLY *ipoly, int n_iterations, int preserve_endpoint)
Definition: lwchaikins.c:126
static POINTARRAY * ptarray_chaikin(POINTARRAY *inpts, int preserve_endpoint, int isclosed)
Definition: lwchaikins.c:31
static LWCOLLECTION * lwcollection_chaikin(const LWCOLLECTION *igeom, int n_iterations, int preserve_endpoint)
Definition: lwchaikins.c:162
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
opts
Definition: ovdump.py:44
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
POINTARRAY * points
Definition: liblwgeom.h:425
uint8_t type
Definition: liblwgeom.h:421
int32_t srid
Definition: liblwgeom.h:424
POINTARRAY ** rings
Definition: liblwgeom.h:460
uint8_t type
Definition: liblwgeom.h:454
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 flags
Definition: liblwgeom.h:372
unsigned int uint32_t
Definition: uthash.h:78