PostGIS  2.4.9dev-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  int 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(int 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 int
146 {
147  int i;
148  LWLINE *lwline;
149  LWCIRCSTRING *lwcirc;
150  int wn = 0;
151  int winding_number = 0;
152  int result;
153 
154  for ( i = 0; i < comp->ngeoms; i++ )
155  {
156  LWGEOM *lwgeom = comp->geoms[i];
157  if ( lwgeom->type == LINETYPE )
158  {
159  lwline = lwgeom_as_lwline(lwgeom);
160  if ( comp->ngeoms == 1 )
161  {
162  return ptarray_contains_point(lwline->points, pt);
163  }
164  else
165  {
166  /* Don't check closure while doing p-i-p test */
167  result = ptarray_contains_point_partial(lwline->points, pt, LW_FALSE, &winding_number);
168  }
169  }
170  else
171  {
172  lwcirc = lwgeom_as_lwcircstring(lwgeom);
173  if ( ! lwcirc ) {
174  lwerror("Unexpected component of type %s in compound curve", lwtype_name(lwgeom->type));
175  return 0;
176  }
177  if ( comp->ngeoms == 1 )
178  {
179  return ptarrayarc_contains_point(lwcirc->points, pt);
180  }
181  else
182  {
183  /* Don't check closure while doing p-i-p test */
184  result = ptarrayarc_contains_point_partial(lwcirc->points, pt, LW_FALSE, &winding_number);
185  }
186  }
187 
188  /* Propogate boundary condition */
189  if ( result == LW_BOUNDARY )
190  return LW_BOUNDARY;
191 
192  wn += winding_number;
193  }
194 
195  /* Outside */
196  if (wn == 0)
197  return LW_OUTSIDE;
198 
199  /* Inside */
200  return LW_INSIDE;
201 }
202 
203 LWCOMPOUND *
205 {
206  LWCOMPOUND* ogeom = lwcompound_construct_empty(lwline->srid, FLAGS_GET_Z(lwline->flags), FLAGS_GET_M(lwline->flags));
207  lwcompound_add_lwgeom(ogeom, lwgeom_clone((LWGEOM*)lwline));
208  /* ogeom->bbox = lwline->bbox; */
209  return ogeom;
210 }
211 
212 LWPOINT*
213 lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, int where)
214 {
215  int i;
216  int count = 0;
217  int npoints = 0;
218  if ( lwgeom_is_empty((LWGEOM*)lwcmp) )
219  return NULL;
220 
221  npoints = lwgeom_count_vertices((LWGEOM*)lwcmp);
222  if ( where < 0 || where >= npoints )
223  {
224  lwerror("%s: index %d is not in range of number of vertices (%d) in input", __func__, where, npoints);
225  return NULL;
226  }
227 
228  for ( i = 0; i < lwcmp->ngeoms; i++ )
229  {
230  LWGEOM* part = lwcmp->geoms[i];
231  int npoints_part = lwgeom_count_vertices(part);
232  if ( where >= count && where < count + npoints_part )
233  {
234  return lwline_get_lwpoint((LWLINE*)part, where - count);
235  }
236  else
237  {
238  count += npoints_part;
239  }
240  }
241 
242  return NULL;
243 }
244 
245 
246 
247 LWPOINT *
249 {
250  return lwcompound_get_lwpoint(lwcmp, 0);
251 }
252 
253 LWPOINT *
255 {
256  LWLINE *lwline;
257  if ( lwcmp->ngeoms < 1 )
258  {
259  return NULL;
260  }
261 
262  lwline = (LWLINE*)(lwcmp->geoms[lwcmp->ngeoms-1]);
263 
264  if ( (!lwline) || (!lwline->points) || (lwline->points->npoints < 1) )
265  {
266  return NULL;
267  }
268 
269  return lwline_get_lwpoint(lwline, lwline->points->npoints-1);
270 }
271 
double x
Definition: liblwgeom.h:352
#define LINETYPE
Definition: liblwgeom.h:86
int lwgeom_contains_point(const LWGEOM *geom, const POINT2D *pt)
Definition: lwcompound.c:129
double m
Definition: liblwgeom.h:352
int npoints
Definition: liblwgeom.h:371
LWCOMPOUND * lwcompound_construct_from_lwline(const LWLINE *lwline)
Construct an equivalent compound curve from a linestring.
Definition: lwcompound.c:204
#define COMPOUNDTYPE
Definition: liblwgeom.h:93
int ptarrayarc_contains_point(const POINTARRAY *pa, const POINT2D *pt)
For POINTARRAYs representing CIRCULARSTRINGS.
Definition: ptarray.c:835
#define LW_SUCCESS
Definition: liblwgeom.h:80
#define LWDEBUG(level, msg)
Definition: lwgeom_log.h:83
int32_t srid
Definition: liblwgeom.h:421
LWGEOM ** geoms
Definition: liblwgeom.h:522
double lwgeom_length_2d(const LWGEOM *geom)
Definition: lwgeom.c:1712
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:885
double lwcompound_length(const LWCOMPOUND *comp)
Definition: lwcompound.c:69
#define LW_FAILURE
Definition: liblwgeom.h:79
void * data
Definition: liblwgeom.h:400
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
#define LW_FALSE
Definition: liblwgeom.h:77
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
LWGEOM ** geoms
Definition: liblwgeom.h:509
int ptarray_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int check_closed, int *winding_number)
Definition: ptarray.c:742
uint8_t * getPoint_internal(const POINTARRAY *pa, int n)
Definition: ptarray.c:1753
int count
Definition: genraster.py:56
#define LW_INSIDE
Constants for point-in-polygon return values.
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:140
int lwcompound_is_closed(const LWCOMPOUND *compound)
Definition: lwcompound.c:35
LWPOINT * lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, int where)
Definition: lwcompound.c:213
double z
Definition: liblwgeom.h:352
int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom)
Add a component, allocating extra space if necessary.
Definition: lwcompound.c:88
LWCOMPOUND * lwcompound_construct_empty(int srid, char hasz, char hasm)
Definition: lwcompound.c:123
LWGEOM * lwgeom_clone(const LWGEOM *lwgeom)
Clone LWGEOM object.
Definition: lwgeom.c:444
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:138
LWCIRCSTRING * lwgeom_as_lwcircstring(const LWGEOM *lwgeom)
Definition: lwgeom.c:147
int lwcompound_contains_point(const LWCOMPOUND *comp, const POINT2D *pt)
Definition: lwcompound.c:145
#define LW_BOUNDARY
int ngeoms
Definition: liblwgeom.h:520
LWPOINT * lwcompound_get_startpoint(const LWCOMPOUND *lwcmp)
Definition: lwcompound.c:248
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:141
LWPOINT * lwline_get_lwpoint(const LWLINE *line, int where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition: lwline.c:324
uint8_t type
Definition: liblwgeom.h:396
#define FP_EQUALS(A, B)
int ptarray_contains_point(const POINTARRAY *pa, const POINT2D *pt)
Return 1 if the point is inside the POINTARRAY, -1 if it is outside, and 0 if it is on the boundary...
Definition: ptarray.c:736
POINTARRAY * points
Definition: liblwgeom.h:444
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:92
#define LW_OUTSIDE
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1346
int lwgeom_count_vertices(const LWGEOM *geom)
Count the total number of vertices in any LWGEOM.
Definition: lwgeom.c:1189
double y
Definition: liblwgeom.h:352
LWCOLLECTION * lwcollection_construct_empty(uint8_t type, int srid, char hasz, char hasm)
Definition: lwcollection.c:94
uint8_t flags
Definition: liblwgeom.h:419
LWPOINT * lwcompound_get_endpoint(const LWCOMPOUND *lwcmp)
Definition: lwcompound.c:254
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
int ptarrayarc_contains_point_partial(const POINTARRAY *pa, const POINT2D *pt, int check_closed, int *winding_number)
Definition: ptarray.c:841
double lwcompound_length_2d(const LWCOMPOUND *comp)
Definition: lwcompound.c:74
LWCOLLECTION * lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom)
Appends geom to the collection managed by col.
Definition: lwcollection.c:187
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:122
POINTARRAY * points
Definition: liblwgeom.h:422