PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches
lwcompound.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 (C) 2001-2006 Refractions Research Inc.
22 *
23 **********************************************************************/
24
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include "liblwgeom_internal.h"
30#include "lwgeom_log.h"
31
32
33uint32_t
35{
36 if ( compound->type != COMPOUNDTYPE )
37 lwerror("%s only supports compound curves", __func__);
38 return compound->ngeoms;
39}
40
41const LWGEOM *
42lwcollection_getsubcurve(const LWCOMPOUND *compound, uint32_t curvenum)
43{
44 return (const LWGEOM *)compound->geoms[curvenum];
45}
46
47int
49{
50 int hasz = lwgeom_has_z(lwcompound_as_lwgeom(compound));
52 return LW_FALSE;
53
54 for (uint32_t i = 0; i < compound->ngeoms; i++)
55 {
56 uint32_t i_end = i == 0 ? compound->ngeoms - 1 : i - 1;
57 const LWLINE *geom_start = (LWLINE *)(compound->geoms[i]);
58 const LWLINE *geom_end = (LWLINE *)(compound->geoms[i_end]);
59 const POINTARRAY *pa_start = geom_start->points;
60 const POINTARRAY *pa_end = geom_end->points;
61 if (hasz)
62 {
63 const POINT3D *pt_start = getPoint3d_cp(pa_start, 0);
64 const POINT3D *pt_end = getPoint3d_cp(pa_end, pa_end->npoints-1);
65 if (!p3d_same(pt_start, pt_end))
66 return LW_FALSE;
67 }
68 else
69 {
70 const POINT2D *pt_start = getPoint2d_cp(pa_start, 0);
71 const POINT2D *pt_end = getPoint2d_cp(pa_end, pa_end->npoints-1);
72 if (!p2d_same(pt_start, pt_end))
73 return LW_FALSE;
74 }
75 }
76
77 return LW_TRUE;
78}
79
80int
82{
83 int hasz = lwgeom_has_z(lwcompound_as_lwgeom(compound));
85 return LW_TRUE;
86
87 for (uint32_t i = 1; i < compound->ngeoms; i++)
88 {
89 const LWLINE *geom_start = (LWLINE *)(compound->geoms[i]);
90 const LWLINE *geom_end = (LWLINE *)(compound->geoms[i-1]);
91 const POINTARRAY *pa_start = geom_start->points;
92 const POINTARRAY *pa_end = geom_end->points;
93 if (hasz)
94 {
95 const POINT3D *pt_start = getPoint3d_cp(pa_start, 0);
96 const POINT3D *pt_end = getPoint3d_cp(pa_end, pa_end->npoints-1);
97 if (!p3d_same(pt_start, pt_end))
98 return LW_FALSE;
99 }
100 else
101 {
102 const POINT2D *pt_start = getPoint2d_cp(pa_start, 0);
103 const POINT2D *pt_end = getPoint2d_cp(pa_end, pa_end->npoints-1);
104 if (!p2d_same(pt_start, pt_end))
105 return LW_FALSE;
106 }
107 }
108
109 return LW_TRUE;
110}
111
112double lwcompound_length(const LWCOMPOUND *comp)
113{
114 return lwcompound_length_2d(comp);
115}
116
118{
119 uint32_t i;
120 double length = 0.0;
121 if ( lwgeom_is_empty((LWGEOM*)comp) )
122 return 0.0;
123
124 for (i = 0; i < comp->ngeoms; i++)
125 {
126 length += lwgeom_length_2d(comp->geoms[i]);
127 }
128 return length;
129}
130
132{
133 LWCOLLECTION *col = (LWCOLLECTION*)comp;
134
135 /* Empty things can't continuously join up with other things */
136 if ( lwgeom_is_empty(geom) )
137 {
138 LWDEBUG(4, "Got an empty component for a compound curve!");
139 return LW_FAILURE;
140 }
141
142 if( col->ngeoms > 0 )
143 {
144 POINT4D last, first;
145 /* First point of the component we are adding */
146 LWLINE *newline = (LWLINE*)geom;
147 /* Last point of the previous component */
148 LWLINE *prevline = (LWLINE*)(col->geoms[col->ngeoms-1]);
149
150 getPoint4d_p(newline->points, 0, &first);
151 getPoint4d_p(prevline->points, prevline->points->npoints-1, &last);
152
153 if ( !(FP_EQUALS(first.x,last.x) && FP_EQUALS(first.y,last.y)) )
154 {
155 LWDEBUG(4, "Components don't join up end-to-end!");
156 LWDEBUGF(4, "first pt (%g %g %g %g) last pt (%g %g %g %g)", first.x, first.y, first.z, first.m, last.x, last.y, last.z, last.m);
157 return LW_FAILURE;
158 }
159 }
160
161 col = lwcollection_add_lwgeom(col, geom);
162 return LW_SUCCESS;
163}
164
166lwcompound_construct_empty(int32_t srid, char hasz, char hasm)
167{
169 return ret;
170}
171
172int lwgeom_contains_point(const LWGEOM *geom, const POINT2D *pt)
173{
174 switch( geom->type )
175 {
176 case LINETYPE:
177 return ptarray_contains_point(((LWLINE*)geom)->points, pt);
178 case CIRCSTRINGTYPE:
179 return ptarrayarc_contains_point(((LWCIRCSTRING*)geom)->points, pt);
180 case COMPOUNDTYPE:
181 return lwcompound_contains_point((LWCOMPOUND*)geom, pt);
182 }
183 lwerror("lwgeom_contains_point failed");
184 return LW_FAILURE;
185}
186
187/*
188 * Use a ray-casting count to determine if the point
189 * is inside or outside of the compound curve. Ray-casting
190 * is run against each component of the overall arc, and
191 * the even/odd test run against the total of all components.
192 * Returns LW_INSIDE / LW_BOUNDARY / LW_OUTSIDE
193 */
194int
196{
197 int intersections = 0;
198
200 return LW_OUTSIDE;
201
202 for (uint32_t j = 0; j < comp->ngeoms; j++)
203 {
204 int on_boundary = LW_FALSE;
205 const LWGEOM *sub = comp->geoms[j];
206 if (sub->type == LINETYPE)
207 {
208 LWLINE *lwline = lwgeom_as_lwline(sub);
209 intersections += ptarray_raycast_intersections(lwline->points, pt, &on_boundary);
210 }
211 else if (sub->type == CIRCSTRINGTYPE)
212 {
214 intersections += ptarrayarc_raycast_intersections(lwcirc->points, pt, &on_boundary);
215 }
216 else
217 {
218 lwerror("%s: unsupported type %s", __func__, lwtype_name(sub->type));
219 }
220 if (on_boundary)
221 return LW_BOUNDARY;
222 }
223
224 /*
225 * Odd number of intersections means inside.
226 * Even means outside.
227 */
228 return (intersections % 2) ? LW_INSIDE : LW_OUTSIDE;
229}
230
233{
234 LWCOMPOUND* ogeom = lwcompound_construct_empty(lwline->srid, FLAGS_GET_Z(lwline->flags), FLAGS_GET_M(lwline->flags));
235 lwcompound_add_lwgeom(ogeom, lwgeom_clone((LWGEOM*)lwline));
236 /* ogeom->bbox = lwline->bbox; */
237 return ogeom;
238}
239
240LWPOINT*
241lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, uint32_t where)
242{
243 uint32_t i;
244 uint32_t count = 0;
245 uint32_t npoints = 0;
246 if ( lwgeom_is_empty((LWGEOM*)lwcmp) )
247 return NULL;
248
249 npoints = lwgeom_count_vertices((LWGEOM*)lwcmp);
250 if ( where >= npoints )
251 {
252 lwerror("%s: index %d is not in range of number of vertices (%d) in input", __func__, where, npoints);
253 return NULL;
254 }
255
256 for ( i = 0; i < lwcmp->ngeoms; i++ )
257 {
258 LWGEOM* part = lwcmp->geoms[i];
259 uint32_t npoints_part = lwgeom_count_vertices(part);
260 if ( where >= count && where < count + npoints_part )
261 {
262 return lwline_get_lwpoint((LWLINE*)part, where - count);
263 }
264 else
265 {
266 count += npoints_part;
267 }
268 }
269
270 return NULL;
271}
272
273
274
275LWPOINT *
277{
278 return lwcompound_get_lwpoint(lwcmp, 0);
279}
280
281LWPOINT *
283{
284 LWLINE *lwline;
285 if ( lwcmp->ngeoms < 1 )
286 {
287 return NULL;
288 }
289
290 lwline = (LWLINE*)(lwcmp->geoms[lwcmp->ngeoms-1]);
291
292 if ( (!lwline) || (!lwline->points) || (lwline->points->npoints < 1) )
293 {
294 return NULL;
295 }
296
297 return lwline_get_lwpoint(lwline, lwline->points->npoints-1);
298}
299
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition lwutil.c:216
#define LW_FALSE
Definition liblwgeom.h:94
#define COMPOUNDTYPE
Definition liblwgeom.h:110
#define LW_FAILURE
Definition liblwgeom.h:96
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition lwline.c:319
#define LINETYPE
Definition liblwgeom.h:103
LWGEOM * lwcompound_as_lwgeom(const LWCOMPOUND *obj)
Definition lwgeom.c:352
#define LW_SUCCESS
Definition liblwgeom.h:97
LWGEOM * lwgeom_clone(const LWGEOM *lwgeom)
Clone LWGEOM object.
Definition lwgeom.c:519
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition lwgeom.c:962
#define FLAGS_GET_Z(flags)
Definition liblwgeom.h:165
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition lwgeom.c:1337
LWCIRCSTRING * lwgeom_as_lwcircstring(const LWGEOM *lwgeom)
Definition lwgeom.c:216
#define CIRCSTRINGTYPE
Definition liblwgeom.h:109
double lwgeom_length_2d(const LWGEOM *geom)
Definition lwgeom.c:2088
#define FLAGS_GET_M(flags)
Definition liblwgeom.h:166
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition lwgeom_api.c:125
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition lwgeom.c:207
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
#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.
#define LW_INSIDE
Constants for point-in-polygon return values.
#define LW_BOUNDARY
int ptarrayarc_contains_point(const POINTARRAY *pa, const POINT2D *pt)
For POINTARRAYs representing CIRCULARSTRINGS.
Definition ptarray.c:1123
int p3d_same(const POINT3D *p1, const POINT3D *p2)
Definition lwalgorithm.c:41
int ptarray_raycast_intersections(const POINTARRAY *pa, const POINT2D *p, int *on_boundary)
Definition ptarray.c:827
int ptarrayarc_raycast_intersections(const POINTARRAY *pa, const POINT2D *p, int *on_boundary)
Definition ptarray.c:944
#define FP_EQUALS(A, B)
int ptarray_contains_point(const POINTARRAY *pa, const POINT2D *pt)
The following is based on the "Fast Winding Number Inclusion of a Point in a Polygon" algorithm by Da...
Definition ptarray.c:755
#define LW_OUTSIDE
int p2d_same(const POINT2D *p1, const POINT2D *p2)
Definition lwalgorithm.c:57
uint32_t lwcompound_num_curves(const LWCOMPOUND *compound)
Definition lwcompound.c:34
double lwcompound_length_2d(const LWCOMPOUND *comp)
Definition lwcompound.c:117
int lwcompound_contains_point(const LWCOMPOUND *comp, const POINT2D *pt)
Definition lwcompound.c:195
LWPOINT * lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, uint32_t where)
Definition lwcompound.c:241
int lwcompound_is_closed(const LWCOMPOUND *compound)
Definition lwcompound.c:48
LWPOINT * lwcompound_get_endpoint(const LWCOMPOUND *lwcmp)
Definition lwcompound.c:282
double lwcompound_length(const LWCOMPOUND *comp)
Definition lwcompound.c:112
int lwcompound_is_valid(const LWCOMPOUND *compound)
Definition lwcompound.c:81
LWPOINT * lwcompound_get_startpoint(const LWCOMPOUND *lwcmp)
Definition lwcompound.c:276
LWCOMPOUND * lwcompound_construct_from_lwline(const LWLINE *lwline)
Construct an equivalent compound curve from a linestring.
Definition lwcompound.c:232
LWCOMPOUND * lwcompound_construct_empty(int32_t srid, char hasz, char hasm)
Definition lwcompound.c:166
int lwgeom_contains_point(const LWGEOM *geom, const POINT2D *pt)
Definition lwcompound.c:172
int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom)
Add a component, allocating extra space if necessary.
Definition lwcompound.c:131
const LWGEOM * lwcollection_getsubcurve(const LWCOMPOUND *compound, uint32_t curvenum)
Definition lwcompound.c:42
#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 const POINT3D * getPoint3d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT3D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition lwinline.h:109
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
static const POINT2D * getPoint2d_cp(const POINTARRAY *pa, uint32_t n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from.
Definition lwinline.h:97
POINTARRAY * points
Definition liblwgeom.h:507
uint32_t ngeoms
Definition liblwgeom.h:580
LWGEOM ** geoms
Definition liblwgeom.h:575
uint32_t ngeoms
Definition liblwgeom.h:594
uint8_t type
Definition liblwgeom.h:592
LWGEOM ** geoms
Definition liblwgeom.h:589
uint8_t type
Definition liblwgeom.h:462
lwflags_t flags
Definition liblwgeom.h:485
POINTARRAY * points
Definition liblwgeom.h:483
int32_t srid
Definition liblwgeom.h:484
double m
Definition liblwgeom.h:414
double x
Definition liblwgeom.h:414
double z
Definition liblwgeom.h:414
double y
Definition liblwgeom.h:414
uint32_t npoints
Definition liblwgeom.h:427