PostGIS  2.4.9dev-r@@SVN_REVISION@@
lwcircstring.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 /* basic LWCIRCSTRING functions */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include "liblwgeom_internal.h"
32 #include "lwgeom_log.h"
33 
34 void printLWCIRCSTRING(LWCIRCSTRING *curve);
37 char lwcircstring_same(const LWCIRCSTRING *me, const LWCIRCSTRING *you);
38 LWCIRCSTRING *lwcircstring_from_lwpointarray(int srid, uint32_t npoints, LWPOINT **points);
42 void lwcircstring_setPoint4d(LWCIRCSTRING *curve, uint32_t index, POINT4D *newpoint);
43 
44 
45 
46 /*
47  * Construct a new LWCIRCSTRING. points will *NOT* be copied
48  * use SRID=SRID_UNKNOWN for unknown SRID (will have 8bit type's S = 0)
49  */
51 lwcircstring_construct(int srid, GBOX *bbox, POINTARRAY *points)
52 {
53  LWCIRCSTRING *result;
54 
55  /*
56  * The first arc requires three points. Each additional
57  * arc requires two more points. Thus the minimum point count
58  * is three, and the count must be odd.
59  */
60  if (points->npoints % 2 != 1 || points->npoints < 3)
61  {
62  lwnotice("lwcircstring_construct: invalid point count %d", points->npoints);
63  }
64 
65  result = (LWCIRCSTRING*) lwalloc(sizeof(LWCIRCSTRING));
66 
67  result->type = CIRCSTRINGTYPE;
68 
69  result->flags = points->flags;
70  FLAGS_SET_BBOX(result->flags, bbox?1:0);
71 
72  result->srid = srid;
73  result->points = points;
74  result->bbox = bbox;
75 
76  return result;
77 }
78 
80 lwcircstring_construct_empty(int srid, char hasz, char hasm)
81 {
82  LWCIRCSTRING *result = lwalloc(sizeof(LWCIRCSTRING));
83  result->type = CIRCSTRINGTYPE;
84  result->flags = gflags(hasz,hasm,0);
85  result->srid = srid;
86  result->points = ptarray_construct_empty(hasz, hasm, 1);
87  result->bbox = NULL;
88  return result;
89 }
90 
91 void
93 {
95 }
96 
97 
99 {
100  if ( ! curve ) return;
101 
102  if ( curve->bbox )
103  lwfree(curve->bbox);
104  if ( curve->points )
105  ptarray_free(curve->points);
106  lwfree(curve);
107 }
108 
109 
110 
112 {
113  lwnotice("LWCIRCSTRING {");
114  lwnotice(" ndims = %i", (int)FLAGS_NDIMS(curve->flags));
115  lwnotice(" srid = %i", (int)curve->srid);
116  printPA(curve->points);
117  lwnotice("}");
118 }
119 
120 /* @brief Clone LWCIRCSTRING object. Serialized point lists are not copied.
121  *
122  * @see ptarray_clone
123  */
124 LWCIRCSTRING *
126 {
127  return (LWCIRCSTRING *)lwline_clone((LWLINE *)g);
128 }
129 
130 
132 {
133  ptarray_reverse(curve->points);
134 }
135 
136 /* check coordinate equality */
137 char
139 {
140  return ptarray_same(me->points, you->points);
141 }
142 
143 /*
144  * Construct a LWCIRCSTRING from an array of LWPOINTs
145  * LWCIRCSTRING dimensions are large enough to host all input dimensions.
146  */
147 LWCIRCSTRING *
148 lwcircstring_from_lwpointarray(int srid, uint32_t npoints, LWPOINT **points)
149 {
150  int zmflag=0;
151  uint32_t i;
152  POINTARRAY *pa;
153  uint8_t *newpoints, *ptr;
154  size_t ptsize, size;
155 
156  /*
157  * Find output dimensions, check integrity
158  */
159  for (i = 0; i < npoints; i++)
160  {
161  if (points[i]->type != POINTTYPE)
162  {
163  lwerror("lwcurve_from_lwpointarray: invalid input type: %s",
164  lwtype_name(points[i]->type));
165  return NULL;
166  }
167  if (FLAGS_GET_Z(points[i]->flags)) zmflag |= 2;
168  if (FLAGS_GET_M(points[i]->flags)) zmflag |= 1;
169  if (zmflag == 3) break;
170  }
171 
172  if (zmflag == 0) ptsize = 2 * sizeof(double);
173  else if (zmflag == 3) ptsize = 4 * sizeof(double);
174  else ptsize = 3 * sizeof(double);
175 
176  /*
177  * Allocate output points array
178  */
179  size = ptsize * npoints;
180  newpoints = lwalloc(size);
181  memset(newpoints, 0, size);
182 
183  ptr = newpoints;
184  for (i = 0; i < npoints; i++)
185  {
186  size = ptarray_point_size(points[i]->point);
187  memcpy(ptr, getPoint_internal(points[i]->point, 0), size);
188  ptr += ptsize;
189  }
190  pa = ptarray_construct_reference_data(zmflag&2, zmflag&1, npoints, newpoints);
191 
192  return lwcircstring_construct(srid, NULL, pa);
193 }
194 
195 /*
196  * Construct a LWCIRCSTRING from a LWMPOINT
197  */
198 LWCIRCSTRING *
200 {
201  uint32_t i;
202  POINTARRAY *pa;
203  char zmflag = FLAGS_GET_ZM(mpoint->flags);
204  size_t ptsize, size;
205  uint8_t *newpoints, *ptr;
206 
207  if (zmflag == 0) ptsize = 2 * sizeof(double);
208  else if (zmflag == 3) ptsize = 4 * sizeof(double);
209  else ptsize = 3 * sizeof(double);
210 
211  /* Allocate space for output points */
212  size = ptsize * mpoint->ngeoms;
213  newpoints = lwalloc(size);
214  memset(newpoints, 0, size);
215 
216  ptr = newpoints;
217  for (i = 0; i < mpoint->ngeoms; i++)
218  {
219  memcpy(ptr,
220  getPoint_internal(mpoint->geoms[i]->point, 0),
221  ptsize);
222  ptr += ptsize;
223  }
224 
225  pa = ptarray_construct_reference_data(zmflag&2, zmflag&1, mpoint->ngeoms, newpoints);
226 
227  LWDEBUGF(3, "lwcurve_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
228 
229  return lwcircstring_construct(srid, NULL, pa);
230 }
231 
232 LWCIRCSTRING *
234 {
235  POINTARRAY *newpa;
236  LWCIRCSTRING *ret;
237 
238  newpa = ptarray_addPoint(curve->points,
239  getPoint_internal(point->point, 0),
240  FLAGS_NDIMS(point->flags), where);
241  ret = lwcircstring_construct(curve->srid, NULL, newpa);
242 
243  return ret;
244 }
245 
246 LWCIRCSTRING *
248 {
249  POINTARRAY *newpa;
250  LWCIRCSTRING *ret;
251 
252  newpa = ptarray_removePoint(curve->points, index);
253  ret = lwcircstring_construct(curve->srid, NULL, newpa);
254 
255  return ret;
256 }
257 
258 /*
259  * Note: input will be changed, make sure you have permissions for this.
260  * */
261 void
263 {
264  ptarray_set_point4d(curve->points, index, newpoint);
265 }
266 
267 int
269 {
270  if (FLAGS_GET_Z(curve->flags))
271  return ptarray_is_closed_3d(curve->points);
272 
273  return ptarray_is_closed_2d(curve->points);
274 }
275 
277 {
278  if ( !circ->points || circ->points->npoints < 1 )
279  return LW_TRUE;
280  return LW_FALSE;
281 }
282 
284 {
285  return lwcircstring_length_2d(circ);
286 }
287 
289 {
290  if ( lwcircstring_is_empty(circ) )
291  return 0.0;
292 
293  return ptarray_arc_length_2d(circ->points);
294 }
295 
296 /*
297  * Returns freshly allocated #LWPOINT that corresponds to the index where.
298  * Returns NULL if the geometry is empty or the index invalid.
299  */
301  POINT4D pt;
302  LWPOINT *lwpoint;
303  POINTARRAY *pa;
304 
305  if ( lwcircstring_is_empty(circ) || where < 0 || where >= circ->points->npoints )
306  return NULL;
307 
309  pt = getPoint4d(circ->points, where);
310  ptarray_append_point(pa, &pt, LW_TRUE);
311  lwpoint = lwpoint_construct(circ->srid, NULL, pa);
312  return lwpoint;
313 }
314 
315 /*
316 * Snap to grid
317 */
319 {
320  LWCIRCSTRING *oline;
321  POINTARRAY *opa;
322 
323  opa = ptarray_grid(line->points, grid);
324 
325  /* Skip line3d with less then 2 points */
326  if ( opa->npoints < 2 ) return NULL;
327 
328  /* TODO: grid bounding box... */
329  oline = lwcircstring_construct(line->srid, NULL, opa);
330 
331  return oline;
332 }
333 
void ptarray_set_point4d(POINTARRAY *pa, int n, const POINT4D *p4d)
Definition: lwgeom_api.c:437
LWCIRCSTRING * lwcircstring_addpoint(LWCIRCSTRING *curve, LWPOINT *point, uint32_t where)
Definition: lwcircstring.c:233
LWCIRCSTRING * lwcircstring_from_lwpointarray(int srid, uint32_t npoints, LWPOINT **points)
Definition: lwcircstring.c:148
uint8_t flags
Definition: liblwgeom.h:441
void lwnotice(const char *fmt,...)
Write a notice out to the notice handler.
Definition: lwutil.c:177
void lwcircstring_setPoint4d(LWCIRCSTRING *curve, uint32_t index, POINT4D *newpoint)
Definition: lwcircstring.c:262
void lwfree(void *mem)
Definition: lwutil.c:244
LWLINE * lwline_clone(const LWLINE *lwgeom)
Definition: lwline.c:102
int npoints
Definition: liblwgeom.h:371
int ptarray_is_closed_3d(const POINTARRAY *pa)
Definition: ptarray.c:710
int32_t srid
Definition: liblwgeom.h:443
LWGEOM * lwcircstring_as_lwgeom(const LWCIRCSTRING *obj)
Definition: lwgeom.c:273
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
Definition: ptarray.c:70
void ptarray_free(POINTARRAY *pa)
Definition: ptarray.c:330
#define FLAGS_GET_ZM(flags)
Definition: liblwgeom.h:153
double lwcircstring_length_2d(const LWCIRCSTRING *circ)
Definition: lwcircstring.c:288
uint8_t flags
Definition: liblwgeom.h:465
LWCIRCSTRING * lwcircstring_clone(const LWCIRCSTRING *g)
Definition: lwcircstring.c:125
POINTARRAY * point
Definition: liblwgeom.h:411
int ptarray_is_closed_2d(const POINTARRAY *pa)
Definition: ptarray.c:697
unsigned int uint32_t
Definition: uthash.h:78
POINTARRAY * ptarray_addPoint(const POINTARRAY *pa, uint8_t *p, size_t pdims, uint32_t where)
Add a point in a pointarray.
Definition: ptarray.c:504
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
POINT4D getPoint4d(const POINTARRAY *pa, int n)
Definition: lwgeom_api.c:105
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, then a duplicate point will not be added.
Definition: ptarray.c:156
#define LW_FALSE
Definition: liblwgeom.h:77
int lwcircstring_is_closed(const LWCIRCSTRING *curve)
Definition: lwcircstring.c:268
LWCIRCSTRING * lwcircstring_construct_empty(int srid, char hasz, char hasm)
Definition: lwcircstring.c:80
uint8_t flags
Definition: liblwgeom.h:369
LWCIRCSTRING * lwcircstring_removepoint(LWCIRCSTRING *curve, uint32_t index)
Definition: lwcircstring.c:247
void printLWCIRCSTRING(LWCIRCSTRING *curve)
Definition: lwcircstring.c:111
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:76
void lwcircstring_free(LWCIRCSTRING *curve)
Definition: lwcircstring.c:98
uint8_t type
Definition: liblwgeom.h:440
uint8_t * getPoint_internal(const POINTARRAY *pa, int n)
Definition: ptarray.c:1753
int ptarray_point_size(const POINTARRAY *pa)
Definition: ptarray.c:54
POINTARRAY * ptarray_construct_reference_data(char hasz, char hasm, uint32_t npoints, uint8_t *ptlist)
Construct a new POINTARRAY, referencing to the data from ptlist.
Definition: ptarray.c:295
LWPOINT ** geoms
Definition: liblwgeom.h:470
#define FLAGS_GET_Z(flags)
Macros for manipulating the &#39;flags&#39; byte.
Definition: liblwgeom.h:140
uint8_t gflags(int hasz, int hasm, int geodetic)
Construct a new flags char.
Definition: g_util.c:145
GBOX * bbox
Definition: liblwgeom.h:442
void lwcircstring_reverse(LWCIRCSTRING *curve)
Definition: lwcircstring.c:131
char lwcircstring_same(const LWCIRCSTRING *me, const LWCIRCSTRING *you)
Definition: lwcircstring.c:138
uint8_t flags
Definition: liblwgeom.h:408
#define FLAGS_SET_BBOX(flags, value)
Definition: liblwgeom.h:148
LWCIRCSTRING * lwcircstring_from_lwmpoint(int srid, LWMPOINT *mpoint)
Definition: lwcircstring.c:199
void printPA(POINTARRAY *pa)
Definition: lwgeom_api.c:472
char ptarray_same(const POINTARRAY *pa1, const POINTARRAY *pa2)
Definition: ptarray.c:479
double ptarray_arc_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY, using circular arc interpolation between each coordinate ...
Definition: ptarray.c:1665
void lwcircstring_release(LWCIRCSTRING *lwcirc)
Definition: lwcircstring.c:92
POINTARRAY * ptarray_grid(const POINTARRAY *pa, const gridspec *grid)
Definition: ptarray.c:1890
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
LWPOINT * lwcircstring_get_lwpoint(const LWCIRCSTRING *circ, int where)
Definition: lwcircstring.c:300
void ptarray_reverse(POINTARRAY *pa)
Definition: ptarray.c:343
#define FLAGS_GET_M(flags)
Definition: liblwgeom.h:141
void lwgeom_release(LWGEOM *lwgeom)
Free the containing LWGEOM and the associated BOX.
Definition: lwgeom.c:421
type
Definition: ovdump.py:41
POINTARRAY * points
Definition: liblwgeom.h:444
#define CIRCSTRINGTYPE
Definition: liblwgeom.h:92
POINTARRAY * ptarray_removePoint(POINTARRAY *pa, uint32_t where)
Remove a point from a pointarray.
Definition: ptarray.c:557
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
void * lwalloc(size_t size)
Definition: lwutil.c:229
int lwcircstring_is_empty(const LWCIRCSTRING *circ)
Definition: lwcircstring.c:276
int ngeoms
Definition: liblwgeom.h:468
#define LWDEBUGF(level, msg,...)
Definition: lwgeom_log.h:88
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:152
double lwcircstring_length(const LWCIRCSTRING *circ)
Definition: lwcircstring.c:283
unsigned char uint8_t
Definition: uthash.h:79
LWCIRCSTRING * lwcircstring_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwcircstring.c:51
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
LWCIRCSTRING * lwcircstring_grid(const LWCIRCSTRING *line, const gridspec *grid)
Definition: lwcircstring.c:318
Snap to grid.