PostGIS  3.2.2dev-r@@SVN_REVISION@@
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 
33 
34 int
36 {
37  size_t size;
38  int npoints=0;
39 
40  if ( lwgeom_has_z((LWGEOM*)compound) )
41  {
42  size = sizeof(POINT3D);
43  }
44  else
45  {
46  size = sizeof(POINT2D);
47  }
48 
49  if ( compound->geoms[compound->ngeoms - 1]->type == CIRCSTRINGTYPE )
50  {
51  npoints = ((LWCIRCSTRING *)compound->geoms[compound->ngeoms - 1])->points->npoints;
52  }
53  else if (compound->geoms[compound->ngeoms - 1]->type == LINETYPE)
54  {
55  npoints = ((LWLINE *)compound->geoms[compound->ngeoms - 1])->points->npoints;
56  }
57 
58  if ( memcmp(getPoint_internal( (POINTARRAY *)compound->geoms[0]->data, 0),
59  getPoint_internal( (POINTARRAY *)compound->geoms[compound->ngeoms - 1]->data,
60  npoints - 1),
61  size) )
62  {
63  return LW_FALSE;
64  }
65 
66  return LW_TRUE;
67 }
68 
69 double lwcompound_length(const LWCOMPOUND *comp)
70 {
71  return lwcompound_length_2d(comp);
72 }
73 
74 double lwcompound_length_2d(const LWCOMPOUND *comp)
75 {
76  uint32_t i;
77  double length = 0.0;
78  if ( lwgeom_is_empty((LWGEOM*)comp) )
79  return 0.0;
80 
81  for (i = 0; i < comp->ngeoms; i++)
82  {
83  length += lwgeom_length_2d(comp->geoms[i]);
84  }
85  return length;
86 }
87 
89 {
90  LWCOLLECTION *col = (LWCOLLECTION*)comp;
91 
92  /* Empty things can't continuously join up with other things */
93  if ( lwgeom_is_empty(geom) )
94  {
95  LWDEBUG(4, "Got an empty component for a compound curve!");
96  return LW_FAILURE;
97  }
98 
99  if( col->ngeoms > 0 )
100  {
101  POINT4D last, first;
102  /* First point of the component we are adding */
103  LWLINE *newline = (LWLINE*)geom;
104  /* Last point of the previous component */
105  LWLINE *prevline = (LWLINE*)(col->geoms[col->ngeoms-1]);
106 
107  getPoint4d_p(newline->points, 0, &first);
108  getPoint4d_p(prevline->points, prevline->points->npoints-1, &last);
109 
110  if ( !(FP_EQUALS(first.x,last.x) && FP_EQUALS(first.y,last.y)) )
111  {
112  LWDEBUG(4, "Components don't join up end-to-end!");
113  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);
114  return LW_FAILURE;
115  }
116  }
117 
118  col = lwcollection_add_lwgeom(col, geom);
119  return LW_SUCCESS;
120 }
121 
122 LWCOMPOUND *
123 lwcompound_construct_empty(int32_t srid, char hasz, char hasm)
124 {
126  return ret;
127 }
128 
129 int lwgeom_contains_point(const LWGEOM *geom, const POINT2D *pt)
130 {
131  switch( geom->type )
132  {
133  case LINETYPE:
134  return ptarray_contains_point(((LWLINE*)geom)->points, pt);
135  case CIRCSTRINGTYPE:
136  return ptarrayarc_contains_point(((LWCIRCSTRING*)geom)->points, pt);
137  case COMPOUNDTYPE:
138  return lwcompound_contains_point((LWCOMPOUND*)geom, pt);
139  }
140  lwerror("lwgeom_contains_point failed");
141  return LW_FAILURE;
142 }
143 
144 
145 /*
146  * Use a ray-casting count to determine if the point
147  * is inside or outside of the compound curve. Ray-casting
148  * is run against each component of the overall arc, and
149  * the even/odd test run against the total of all components.
150  * Returns LW_INSIDE / LW_BOUNDARY / LW_OUTSIDE
151  */
152 int
154 {
155  int intersections = 0;
156 
158  return LW_OUTSIDE;
159 
160  for (uint32_t j = 0; j < comp->ngeoms; j++)
161  {
162  int on_boundary = LW_FALSE;
163  const LWGEOM *sub = comp->geoms[j];
164  if (sub->type == LINETYPE)
165  {
166  LWLINE *lwline = lwgeom_as_lwline(sub);
167  intersections += ptarray_raycast_intersections(lwline->points, pt, &on_boundary);
168  }
169  else if (sub->type == CIRCSTRINGTYPE)
170  {
171  LWCIRCSTRING *lwcirc = lwgeom_as_lwcircstring(sub);
172  intersections += ptarrayarc_raycast_intersections(lwcirc->points, pt, &on_boundary);
173  }
174  else
175  {
176  lwerror("%s: unsupported type %s", __func__, lwtype_name(sub->type));
177  }
178  if (on_boundary)
179  return LW_BOUNDARY;
180  }
181 
182  /*
183  * Odd number of intersections means inside.
184  * Even means outside.
185  */
186  return (intersections % 2) ? LW_INSIDE : LW_OUTSIDE;
187 }
188 
189 LWCOMPOUND *
191 {
192  LWCOMPOUND* ogeom = lwcompound_construct_empty(lwline->srid, FLAGS_GET_Z(lwline->flags), FLAGS_GET_M(lwline->flags));
193  lwcompound_add_lwgeom(ogeom, lwgeom_clone((LWGEOM*)lwline));
194  /* ogeom->bbox = lwline->bbox; */
195  return ogeom;
196 }
197 
198 LWPOINT*
199 lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, uint32_t where)
200 {
201  uint32_t i;
202  uint32_t count = 0;
203  uint32_t npoints = 0;
204  if ( lwgeom_is_empty((LWGEOM*)lwcmp) )
205  return NULL;
206 
207  npoints = lwgeom_count_vertices((LWGEOM*)lwcmp);
208  if ( where >= npoints )
209  {
210  lwerror("%s: index %d is not in range of number of vertices (%d) in input", __func__, where, npoints);
211  return NULL;
212  }
213 
214  for ( i = 0; i < lwcmp->ngeoms; i++ )
215  {
216  LWGEOM* part = lwcmp->geoms[i];
217  uint32_t npoints_part = lwgeom_count_vertices(part);
218  if ( where >= count && where < count + npoints_part )
219  {
220  return lwline_get_lwpoint((LWLINE*)part, where - count);
221  }
222  else
223  {
224  count += npoints_part;
225  }
226  }
227 
228  return NULL;
229 }
230 
231 
232 
233 LWPOINT *
235 {
236  return lwcompound_get_lwpoint(lwcmp, 0);
237 }
238 
239 LWPOINT *
241 {
242  LWLINE *lwline;
243  if ( lwcmp->ngeoms < 1 )
244  {
245  return NULL;
246  }
247 
248  lwline = (LWLINE*)(lwcmp->geoms[lwcmp->ngeoms-1]);
249 
250  if ( (!lwline) || (!lwline->points) || (lwline->points->npoints < 1) )
251  {
252  return NULL;
253  }
254 
255  return lwline_get_lwpoint(lwline, lwline->points->npoints-1);
256 }
257 
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:162
LWGEOM * lwcompound_as_lwgeom(const LWCOMPOUND *obj)
Definition: lwgeom.c:307
#define LW_FALSE
Definition: liblwgeom.h:108
#define COMPOUNDTYPE
Definition: liblwgeom.h:124
#define LW_FAILURE
Definition: liblwgeom.h:110
#define LINETYPE
Definition: liblwgeom.h:117
#define LW_SUCCESS
Definition: liblwgeom.h:111
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:917
#define FLAGS_GET_Z(flags)
Definition: liblwgeom.h:179
uint32_t lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1229
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:123
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm)
Definition: lwcollection.c:92
double lwgeom_length_2d(const LWGEOM *geom)
Definition: lwgeom.c:1980
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:216
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:180
int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point)
Definition: lwgeom_api.c:126
LWGEOM * lwgeom_clone(const LWGEOM *lwgeom)
Clone LWGEOM object.
Definition: lwgeom.c:474
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:188
LWCIRCSTRING * lwgeom_as_lwcircstring(const LWGEOM *lwgeom)
Definition: lwgeom.c:171
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:107
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition: lwline.c:309
#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:1110
int ptarray_raycast_intersections(const POINTARRAY *pa, const POINT2D *p, int *on_boundary)
Definition: ptarray.c:818
int ptarrayarc_raycast_intersections(const POINTARRAY *pa, const POINT2D *p, int *on_boundary)
Definition: ptarray.c:935
#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:746
#define LW_OUTSIDE
double lwcompound_length_2d(const LWCOMPOUND *comp)
Definition: lwcompound.c:74
int lwcompound_contains_point(const LWCOMPOUND *comp, const POINT2D *pt)
Definition: lwcompound.c:153
LWPOINT * lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, uint32_t where)
Definition: lwcompound.c:199
int lwcompound_is_closed(const LWCOMPOUND *compound)
Definition: lwcompound.c:35
LWCOMPOUND * lwcompound_construct_from_lwline(const LWLINE *lwline)
Construct an equivalent compound curve from a linestring.
Definition: lwcompound.c:190
LWPOINT * lwcompound_get_startpoint(const LWCOMPOUND *lwcmp)
Definition: lwcompound.c:234
double lwcompound_length(const LWCOMPOUND *comp)
Definition: lwcompound.c:69
int lwgeom_contains_point(const LWGEOM *geom, const POINT2D *pt)
Definition: lwcompound.c:129
LWCOMPOUND * lwcompound_construct_empty(int32_t srid, char hasz, char hasm)
Definition: lwcompound.c:123
int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom)
Add a component, allocating extra space if necessary.
Definition: lwcompound.c:88
LWPOINT * lwcompound_get_endpoint(const LWCOMPOUND *lwcmp)
Definition: lwcompound.c:240
#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 uint8_t * getPoint_internal(const POINTARRAY *pa, uint32_t n)
Definition: lwinline.h:77
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:203
int count
Definition: genraster.py:57
POINTARRAY * points
Definition: liblwgeom.h:521
uint32_t ngeoms
Definition: liblwgeom.h:594
LWGEOM ** geoms
Definition: liblwgeom.h:589
uint32_t ngeoms
Definition: liblwgeom.h:608
LWGEOM ** geoms
Definition: liblwgeom.h:603
void * data
Definition: liblwgeom.h:473
uint8_t type
Definition: liblwgeom.h:476
lwflags_t flags
Definition: liblwgeom.h:499
POINTARRAY * points
Definition: liblwgeom.h:497
int32_t srid
Definition: liblwgeom.h:498
double m
Definition: liblwgeom.h:428
double x
Definition: liblwgeom.h:428
double z
Definition: liblwgeom.h:428
double y
Definition: liblwgeom.h:428
uint32_t npoints
Definition: liblwgeom.h:441