PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
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
31static 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;
35 POINTARRAY *opts;
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 {
48 ptarray_append_point(opts, &p1, LW_TRUE);
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;
84 ptarray_append_point(opts, &p1, LW_TRUE);
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
101static 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
126static 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
162static 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
182LWGEOM* 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}
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
POINT4D getPoint4d(const POINTARRAY *pa, uint32_t n)
Definition lwgeom_api.c:107
#define LW_FALSE
Definition liblwgeom.h:94
#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
#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
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition ptarray.c:59
LWGEOM * lwgeom_clone(const LWGEOM *lwgeom)
Clone LWGEOM object.
Definition lwgeom.c:519
#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 POLYGONTYPE
Definition liblwgeom.h:104
#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)
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:147
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:93
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
int lwline_is_empty(const LWLINE *line)
LWLINE * lwline_clone(const LWLINE *lwgeom)
Definition lwline.c:93
int lwpoly_is_empty(const LWPOLY *poly)
int ptarray_has_z(const POINTARRAY *pa)
Definition ptarray.c:37
int ptarray_has_m(const POINTARRAY *pa)
Definition ptarray.c:44
int lwcollection_is_empty(const LWCOLLECTION *col)
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
static LWPOLY * lwpoly_chaikin(const LWPOLY *ipoly, int n_iterations, int preserve_endpoint)
Definition lwchaikins.c:126
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
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:101
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
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
POINTARRAY * points
Definition liblwgeom.h:483
uint8_t type
Definition liblwgeom.h:486
int32_t srid
Definition liblwgeom.h:484
POINTARRAY ** rings
Definition liblwgeom.h:519
uint8_t type
Definition liblwgeom.h:522
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