PostGIS  2.4.9dev-r@@SVN_REVISION@@
lwout_encoded_polyline.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 2014 Kashif Rasul <kashif.rasul@gmail.com> and
22  * Shoaib Burq <saburq@gmail.com>
23  *
24  **********************************************************************/
25 
26 #include "stringbuffer.h"
27 #include "liblwgeom_internal.h"
28 
29 static char* lwline_to_encoded_polyline(const LWLINE*, int precision);
30 static char* lwmmpoint_to_encoded_polyline(const LWMPOINT*, int precision);
31 static char* pointarray_to_encoded_polyline(const POINTARRAY*, int precision);
32 
33 /* takes a GEOMETRY and returns an Encoded Polyline representation */
34 extern char*
36 {
37  int type = geom->type;
38  switch (type)
39  {
40  case LINETYPE:
41  return lwline_to_encoded_polyline((LWLINE*)geom, precision);
42  case MULTIPOINTTYPE:
43  return lwmmpoint_to_encoded_polyline((LWMPOINT*)geom, precision);
44  default:
45  lwerror("lwgeom_to_encoded_polyline: '%s' geometry type not supported",
46  lwtype_name(type));
47  return NULL;
48  }
49 }
50 
51 static char*
53 {
54  return pointarray_to_encoded_polyline(line->points, precision);
55 }
56 
57 static char*
59 {
60  LWLINE* line = lwline_from_lwmpoint(mpoint->srid, mpoint);
61  char* encoded_polyline = lwline_to_encoded_polyline(line, precision);
62 
63  lwline_free(line);
64  return encoded_polyline;
65 }
66 
67 static char*
69 {
70  int i;
71  const POINT2D* prevPoint;
72  int* delta;
73  char* encoded_polyline = NULL;
74  stringbuffer_t* sb;
75  double scale = pow(10, precision);
76 
77  /* Empty input is empty string */
78  if (pa->npoints == 0) {
79  encoded_polyline = lwalloc(1 * sizeof(char));
80  encoded_polyline[0] = 0;
81  return encoded_polyline;
82  }
83 
84  delta = lwalloc(2 * sizeof(int) * pa->npoints);
85 
86  /* Take the double value and multiply it by 1x10^precision, rounding the
87  * result */
88  prevPoint = getPoint2d_cp(pa, 0);
89  delta[0] = round(prevPoint->y * scale);
90  delta[1] = round(prevPoint->x * scale);
91 
92  /* Points only include the offset from the previous point */
93  for (i = 1; i < pa->npoints; i++)
94  {
95  const POINT2D* point = getPoint2d_cp(pa, i);
96  delta[2 * i] = round(point->y * scale) - round(prevPoint->y * scale);
97  delta[(2 * i) + 1] =
98  round(point->x * scale) - round(prevPoint->x * scale);
99  prevPoint = point;
100  }
101 
102  /* value to binary: a negative value must be calculated using its two's
103  * complement */
104  for (i = 0; i < pa->npoints * 2; i++)
105  {
106  /* Multiply by 2 for a signed left shift */
107  delta[i] *= 2;
108  /* if value is negative, invert this encoding */
109  if (delta[i] < 0) {
110  delta[i] = ~(delta[i]);
111  }
112  }
113 
114  sb = stringbuffer_create();
115  for (i = 0; i < pa->npoints * 2; i++)
116  {
117  int numberToEncode = delta[i];
118 
119  while (numberToEncode >= 0x20)
120  {
121  /* Place the 5-bit chunks into reverse order or
122  each value with 0x20 if another bit chunk follows and add 63*/
123  int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63;
124  stringbuffer_aprintf(sb, "%c", (char)nextValue);
125 
126  /* Break the binary value out into 5-bit chunks */
127  numberToEncode >>= 5;
128  }
129 
130  numberToEncode += 63;
131  stringbuffer_aprintf(sb, "%c", (char)numberToEncode);
132  }
133 
134  lwfree(delta);
135  encoded_polyline = stringbuffer_getstringcopy(sb);
137 
138  return encoded_polyline;
139 }
#define LINETYPE
Definition: liblwgeom.h:86
static char * pointarray_to_encoded_polyline(const POINTARRAY *, int precision)
stringbuffer_t * stringbuffer_create(void)
Allocate a new stringbuffer_t.
Definition: stringbuffer.c:35
void lwfree(void *mem)
Definition: lwutil.c:244
int npoints
Definition: liblwgeom.h:371
char * stringbuffer_getstringcopy(stringbuffer_t *s)
Returns a newly allocated string large enough to contain the current state of the string...
Definition: stringbuffer.c:160
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
void lwline_free(LWLINE *line)
Definition: lwline.c:76
static char * lwline_to_encoded_polyline(const LWLINE *, int precision)
int stringbuffer_aprintf(stringbuffer_t *s, const char *fmt,...)
Appends a formatted string to the current string buffer, using the format and argument list provided...
Definition: stringbuffer.c:253
double x
Definition: liblwgeom.h:328
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
const POINT2D * getPoint2d_cp(const POINTARRAY *pa, int n)
Returns a POINT2D pointer into the POINTARRAY serialized_ptlist, suitable for reading from...
Definition: lwgeom_api.c:373
LWLINE * lwline_from_lwmpoint(int srid, const LWMPOINT *mpoint)
Definition: lwline.c:290
static char * lwmmpoint_to_encoded_polyline(const LWMPOINT *, int precision)
uint8_t precision
Definition: cu_in_twkb.c:25
double y
Definition: liblwgeom.h:328
void stringbuffer_destroy(stringbuffer_t *s)
Free the stringbuffer_t and all memory managed within it.
Definition: stringbuffer.c:78
char * lwgeom_to_encoded_polyline(const LWGEOM *geom, int precision)
uint8_t type
Definition: liblwgeom.h:396
type
Definition: ovdump.py:41
void * lwalloc(size_t size)
Definition: lwutil.c:229
int32_t srid
Definition: liblwgeom.h:467
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:190
POINTARRAY * points
Definition: liblwgeom.h:422