PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwgeom_wrapx.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 2016 Sandro Santilli <strk@kbt.io>
22 *
23 **********************************************************************/
24
25#include "../postgis_config.h"
26/*#define POSTGIS_DEBUG_LEVEL 4*/
27#include "lwgeom_geos.h"
28#include "liblwgeom_internal.h"
29
30#include <string.h>
31#include <assert.h>
32
33LWGEOM* lwgeom_wrapx(const LWGEOM* lwgeom_in, double cutx, double amount);
34static LWCOLLECTION* lwcollection_wrapx(const LWCOLLECTION* lwcoll_in, double cutx, double amount);
35
36static LWGEOM*
37lwgeom_split_wrapx(const LWGEOM* geom_in, double cutx, double amount)
38{
39 LWGEOM *blade, *split;
40 POINTARRAY *bladepa;
41 POINT4D pt;
42 const GBOX *box_in;
43 AFFINE affine = {
44 1, 0, 0,
45 0, 1, 0,
46 0, 0, 1,
47 amount, 0, 0,
48 };
49
50 /* Extract box */
51 /* TODO: check if the bbox should be force-recomputed */
52 box_in = lwgeom_get_bbox(geom_in);
53 if ( ! box_in ) {
54 /* must be empty */
55 return lwgeom_clone_deep(geom_in);
56 }
57
58 LWDEBUGF(2, "BOX X range is %g..%g, cutx:%g, amount:%g", box_in->xmin, box_in->xmax, cutx, amount);
59
60 /* Check if geometry is fully on the side needing shift */
61 if ( ( amount < 0 && box_in->xmin >= cutx ) || ( amount > 0 && box_in->xmax <= cutx ) )
62 {
63 split = lwgeom_clone_deep(geom_in);
64 lwgeom_affine(split, &affine);
65 LWDEBUGG(2, split, "returning the translated geometry");
66 return split;
67 }
68
69 /* Check if geometry is fully on the side needing no shift */
70 if ( ( amount < 0 && box_in->xmax <= cutx ) || ( amount > 0 && box_in->xmin >= cutx ) )
71 {
72 split = lwgeom_clone_deep(geom_in);
73 LWDEBUGG(2, split, "returning the cloned geometry");
74 return split;
75 }
76
77 /* We need splitting here */
78
79 /* construct blade */
80 bladepa = ptarray_construct(0, 0, 2);
81 pt.x = cutx;
82 pt.y = box_in->ymin - 1;
83 ptarray_set_point4d(bladepa, 0, &pt);
84 pt.y = box_in->ymax + 1;
85 ptarray_set_point4d(bladepa, 1, &pt);
86 blade = lwline_as_lwgeom(lwline_construct(geom_in->srid, NULL, bladepa));
87
88 LWDEBUG(2, "splitting the geometry");
89
90 /* split by blade */
91 split = lwgeom_split(geom_in, blade);
92 lwgeom_free(blade);
93 if ( ! split ) {
94 lwerror("%s:%d - lwgeom_split_wrapx: %s", __FILE__, __LINE__, lwgeom_geos_errmsg);
95 return NULL;
96 }
97 LWDEBUGG(2, split, "split geometry");
98
99
100 /* iterate over components, translate if needed */
101 const LWCOLLECTION *col = lwgeom_as_lwcollection(split);
102 if ( ! col ) {
103 /* not split, this is unexpected */
104 lwnotice("WARNING: unexpected lack of split in lwgeom_split_wrapx");
105 return lwgeom_clone_deep(geom_in);
106 }
107 LWCOLLECTION *col_out = lwcollection_wrapx(col, cutx, amount);
108 lwgeom_free(split);
109
110 /* unary-union the result (homogenize too ?) */
112 LWDEBUGF(2, "col_out:%p, unaryunion_out:%p", col_out, out);
113 LWDEBUGG(2, out, "unary-unioned");
114
115 lwcollection_free(col_out);
116
117 return out;
118}
119
120static LWCOLLECTION*
121lwcollection_wrapx(const LWCOLLECTION* lwcoll_in, double cutx, double amount)
122{
123 LWGEOM** wrap_geoms;
124 LWCOLLECTION* out;
125 uint32_t i;
126 int outtype = lwcoll_in->type;
127
128 wrap_geoms = lwalloc(lwcoll_in->ngeoms * sizeof(LWGEOM*));
129 if ( ! wrap_geoms )
130 {
131 lwerror("Out of virtual memory");
132 return NULL;
133 }
134
135 for (i=0; i<lwcoll_in->ngeoms; ++i)
136 {
137 LWDEBUGF(3, "Wrapping collection element %d", i);
138 wrap_geoms[i] = lwgeom_wrapx(lwcoll_in->geoms[i], cutx, amount);
139 /* an exception should prevent this from ever returning NULL */
140 if ( ! wrap_geoms[i] ) {
141 uint32_t j;
142 lwnotice("Error wrapping geometry, cleaning up");
143 for (j = 0; j < i; j++)
144 {
145 lwnotice("cleaning geometry %d (%p)", j, (void *) wrap_geoms[j]);
146 lwgeom_free(wrap_geoms[j]);
147 }
148 lwfree(wrap_geoms);
149 lwnotice("cleanup complete");
150 return NULL;
151 }
152 if ( outtype != COLLECTIONTYPE ) {
153 if ( MULTITYPE[wrap_geoms[i]->type] != outtype )
154 {
155 outtype = COLLECTIONTYPE;
156 }
157 }
158 }
159
160 /* Now wrap_geoms has wrap_geoms_size geometries */
161 out = lwcollection_construct(outtype, lwcoll_in->srid, NULL,
162 lwcoll_in->ngeoms, wrap_geoms);
163
164 return out;
165}
166
167/* exported */
168LWGEOM*
169lwgeom_wrapx(const LWGEOM* lwgeom_in, double cutx, double amount)
170{
171 /* Nothing to wrap in an empty geom */
172 if ( lwgeom_is_empty(lwgeom_in) )
173 {
174 LWDEBUG(2, "geom is empty, cloning");
175 return lwgeom_clone_deep(lwgeom_in);
176 }
177
178 /* Nothing to wrap if shift amount is zero */
179 if ( amount == 0 )
180 {
181 LWDEBUG(2, "amount is zero, cloning");
182 return lwgeom_clone_deep(lwgeom_in);
183 }
184
185 switch (lwgeom_in->type)
186 {
187 case LINETYPE:
188 case POLYGONTYPE:
189 LWDEBUG(2, "split-wrapping line or polygon");
190 return lwgeom_split_wrapx(lwgeom_in, cutx, amount);
191
192 case POINTTYPE:
193 {
194 const LWPOINT *pt = lwgeom_as_lwpoint(lwgeom_clone_deep(lwgeom_in));
195 POINT4D pt4d;
196 getPoint4d_p(pt->point, 0, &pt4d);
197
198 LWDEBUGF(2, "POINT X is %g, cutx:%g, amount:%g", pt4d.x, cutx, amount);
199
200 if ( ( amount < 0 && pt4d.x > cutx ) || ( amount > 0 && pt4d.x < cutx ) )
201 {
202 pt4d.x += amount;
203 ptarray_set_point4d(pt->point, 0, &pt4d);
204 }
205 return lwpoint_as_lwgeom(pt);
206 }
207
208 case MULTIPOINTTYPE:
209 case MULTIPOLYGONTYPE:
210 case MULTILINETYPE:
211 case COLLECTIONTYPE:
212 LWDEBUG(2, "collection-wrapping multi");
214 lwcollection_wrapx((const LWCOLLECTION*)lwgeom_in, cutx, amount)
215 );
216
217 default:
218 lwerror("Wrapping of %s geometries is unsupported",
219 lwtype_name(lwgeom_in->type));
220 return NULL;
221 }
222
223}
char lwgeom_geos_errmsg[LWGEOM_GEOS_ERRMSG_MAXSIZE]
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition lwgeom.c:372
LWGEOM * lwgeom_unaryunion(const LWGEOM *geom1)
#define COLLECTIONTYPE
Definition liblwgeom.h:108
LWGEOM * lwgeom_split(const LWGEOM *lwgeom_in, const LWGEOM *blade_in)
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
#define MULTILINETYPE
Definition liblwgeom.h:106
#define LINETYPE
Definition liblwgeom.h:103
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
Definition lwgeom.c:261
#define MULTIPOINTTYPE
Definition liblwgeom.h:105
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
void * lwalloc(size_t size)
Definition lwutil.c:227
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
#define MULTIPOLYGONTYPE
Definition liblwgeom.h:107
void lwfree(void *mem)
Definition lwutil.c:248
#define POLYGONTYPE
Definition liblwgeom.h:104
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
Definition lwgeom.c:367
void lwgeom_affine(LWGEOM *geom, const AFFINE *affine)
Definition lwgeom.c:2111
void lwcollection_free(LWCOLLECTION *col)
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition lwgeom_api.c:125
const GBOX * lwgeom_get_bbox(const LWGEOM *lwgeom)
Get a non-empty geometry bounding box, computing and caching it if not already there.
Definition lwgeom.c:771
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
Definition lwgeom_api.c:369
LWGEOM * lwcollection_as_lwgeom(const LWCOLLECTION *obj)
Definition lwgeom.c:337
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
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
Definition lwgeom.c:557
uint8_t MULTITYPE[NUMTYPES]
Look-up for the correct MULTI* type promotion for singleton types.
Definition lwgeom.c:382
#define LWDEBUG(level, msg)
Definition lwgeom_log.h:101
#define LWDEBUGF(level, msg,...)
Definition lwgeom_log.h:106
void lwnotice(const char *fmt,...) __attribute__((format(printf
Write a notice out to the notice handler.
void void lwerror(const char *fmt,...) __attribute__((format(printf
Write a notice out to the error handler.
#define LWDEBUGG(level, geom, msg)
Definition lwgeom_log.h:111
static LWGEOM * lwgeom_split_wrapx(const LWGEOM *geom_in, double cutx, double amount)
static LWCOLLECTION * lwcollection_wrapx(const LWCOLLECTION *lwcoll_in, double cutx, double amount)
LWGEOM * lwgeom_wrapx(const LWGEOM *lwgeom_in, double cutx, double amount)
wrap geometry on given cut x value
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition lwinline.h:127
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
double ymax
Definition liblwgeom.h:357
double xmax
Definition liblwgeom.h:355
double ymin
Definition liblwgeom.h:356
double xmin
Definition liblwgeom.h:354
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
POINTARRAY * point
Definition liblwgeom.h:471
double x
Definition liblwgeom.h:414
double y
Definition liblwgeom.h:414