geo_coder 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +12 -0
- data/Gemfile.lock +32 -0
- data/History.txt +6 -0
- data/Makefile +13 -0
- data/Manifest.txt +18 -0
- data/README.rdoc +197 -0
- data/Rakefile +53 -0
- data/TODO.txt +8 -0
- data/VERSION +1 -0
- data/bin/build_indexes +8 -0
- data/bin/rebuild_cluster +22 -0
- data/bin/rebuild_metaphones +23 -0
- data/bin/tiger_import +59 -0
- data/demos/demo/app/ext/geocodewrap.rb +84 -0
- data/demos/demo/app/views/index.builder +13 -0
- data/demos/demo/app/views/index.erb +71 -0
- data/demos/demo/config.ru +12 -0
- data/demos/demo/config/bootstraps.rb +130 -0
- data/demos/demo/config/geoenvironment.rb +25 -0
- data/demos/demo/geocoder_helper.rb +12 -0
- data/demos/demo/geocom_geocode.rb +10 -0
- data/demos/demo/main.rb +3 -0
- data/demos/demo/rakefile.rb +17 -0
- data/demos/demo/tmp/restart.txt +0 -0
- data/demos/simpledemo/views/index.builder +13 -0
- data/demos/simpledemo/views/index.erb +69 -0
- data/demos/simpledemo/ws.rb +83 -0
- data/doc/Makefile +7 -0
- data/doc/html4css1.css +279 -0
- data/doc/lookup.rst +193 -0
- data/doc/parsing.rst +125 -0
- data/doc/voidspace.css +147 -0
- data/geo_coder.gemspec +172 -0
- data/lib/geocoder/us.rb +21 -0
- data/lib/geocoder/us/address.rb +290 -0
- data/lib/geocoder/us/constants.rb +670 -0
- data/lib/geocoder/us/database.rb +745 -0
- data/lib/geocoder/us/import.rb +181 -0
- data/lib/geocoder/us/import/tiger.rb +13 -0
- data/lib/geocoder/us/numbers.rb +58 -0
- data/navteq/README +4 -0
- data/navteq/convert.sql +37 -0
- data/navteq/navteq_import +39 -0
- data/navteq/prepare.sql +92 -0
- data/sql/cluster.sql +16 -0
- data/sql/convert.sql +80 -0
- data/sql/create.sql +37 -0
- data/sql/index.sql +12 -0
- data/sql/place.csv +104944 -0
- data/sql/place.sql +104948 -0
- data/sql/setup.sql +78 -0
- data/src/Makefile +13 -0
- data/src/README +14 -0
- data/src/liblwgeom/Makefile +75 -0
- data/src/liblwgeom/box2d.c +54 -0
- data/src/liblwgeom/lex.yy.c +4799 -0
- data/src/liblwgeom/liblwgeom.h +1405 -0
- data/src/liblwgeom/lwalgorithm.c +946 -0
- data/src/liblwgeom/lwalgorithm.h +52 -0
- data/src/liblwgeom/lwcircstring.c +759 -0
- data/src/liblwgeom/lwcollection.c +541 -0
- data/src/liblwgeom/lwcompound.c +118 -0
- data/src/liblwgeom/lwcurvepoly.c +86 -0
- data/src/liblwgeom/lwgeom.c +886 -0
- data/src/liblwgeom/lwgeom_api.c +2201 -0
- data/src/liblwgeom/lwgparse.c +1219 -0
- data/src/liblwgeom/lwgunparse.c +1054 -0
- data/src/liblwgeom/lwline.c +525 -0
- data/src/liblwgeom/lwmcurve.c +125 -0
- data/src/liblwgeom/lwmline.c +137 -0
- data/src/liblwgeom/lwmpoint.c +138 -0
- data/src/liblwgeom/lwmpoly.c +141 -0
- data/src/liblwgeom/lwmsurface.c +129 -0
- data/src/liblwgeom/lwpoint.c +439 -0
- data/src/liblwgeom/lwpoly.c +579 -0
- data/src/liblwgeom/lwsegmentize.c +1047 -0
- data/src/liblwgeom/lwutil.c +369 -0
- data/src/liblwgeom/measures.c +861 -0
- data/src/liblwgeom/postgis_config.h +93 -0
- data/src/liblwgeom/ptarray.c +847 -0
- data/src/liblwgeom/vsprintf.c +179 -0
- data/src/liblwgeom/wktparse.h +126 -0
- data/src/liblwgeom/wktparse.lex +74 -0
- data/src/liblwgeom/wktparse.tab.c +2353 -0
- data/src/liblwgeom/wktparse.tab.h +145 -0
- data/src/liblwgeom/wktparse.y +385 -0
- data/src/libsqlite3_geocoder/Makefile +22 -0
- data/src/libsqlite3_geocoder/Makefile.nix +15 -0
- data/src/libsqlite3_geocoder/Makefile.redhat +15 -0
- data/src/libsqlite3_geocoder/extension.c +121 -0
- data/src/libsqlite3_geocoder/extension.h +13 -0
- data/src/libsqlite3_geocoder/levenshtein.c +42 -0
- data/src/libsqlite3_geocoder/metaphon.c +278 -0
- data/src/libsqlite3_geocoder/util.c +37 -0
- data/src/libsqlite3_geocoder/wkb_compress.c +54 -0
- data/src/metaphone/Makefile +7 -0
- data/src/metaphone/README +49 -0
- data/src/metaphone/extension.c +37 -0
- data/src/metaphone/metaphon.c +251 -0
- data/src/shp2sqlite/Makefile +37 -0
- data/src/shp2sqlite/Makefile.nix +36 -0
- data/src/shp2sqlite/Makefile.redhat +35 -0
- data/src/shp2sqlite/dbfopen.c +1595 -0
- data/src/shp2sqlite/getopt.c +695 -0
- data/src/shp2sqlite/getopt.h +127 -0
- data/src/shp2sqlite/shapefil.h +500 -0
- data/src/shp2sqlite/shp2sqlite.c +1974 -0
- data/src/shp2sqlite/shpopen.c +1894 -0
- data/tests/address.rb +236 -0
- data/tests/benchmark.rb +20 -0
- data/tests/constants.rb +57 -0
- data/tests/data/address-sample.csv +52 -0
- data/tests/data/db-test.csv +57 -0
- data/tests/data/locations.csv +4 -0
- data/tests/database.rb +137 -0
- data/tests/generate.rb +34 -0
- data/tests/numbers.rb +46 -0
- data/tests/run.rb +11 -0
- metadata +237 -0
@@ -0,0 +1,1047 @@
|
|
1
|
+
/**********************************************************************
|
2
|
+
* $Id: lwsegmentize.c 3807 2009-03-08 21:15:00Z pramsey $
|
3
|
+
*
|
4
|
+
* PostGIS - Spatial Types for PostgreSQL
|
5
|
+
* http://postgis.refractions.net
|
6
|
+
* Copyright 2001-2006 Refractions Research Inc.
|
7
|
+
*
|
8
|
+
* This is free software; you can redistribute and/or modify it under
|
9
|
+
* the terms of the GNU General Public Licence. See the COPYING file.
|
10
|
+
*
|
11
|
+
**********************************************************************/
|
12
|
+
|
13
|
+
#include <stdio.h>
|
14
|
+
#include <stdlib.h>
|
15
|
+
#include <stdarg.h>
|
16
|
+
#include <string.h>
|
17
|
+
#include <math.h>
|
18
|
+
|
19
|
+
#include "liblwgeom.h"
|
20
|
+
|
21
|
+
|
22
|
+
double interpolate_arc(double angle, double zm1, double a1, double zm2, double a2);
|
23
|
+
POINTARRAY *lwcircle_segmentize(POINT4D *p1, POINT4D *p2, POINT4D *p3, uint32 perQuad);
|
24
|
+
LWLINE *lwcurve_segmentize(LWCIRCSTRING *icurve, uint32 perQuad);
|
25
|
+
LWLINE *lwcompound_segmentize(LWCOMPOUND *icompound, uint32 perQuad);
|
26
|
+
LWPOLY *lwcurvepoly_segmentize(LWCURVEPOLY *curvepoly, uint32 perQuad);
|
27
|
+
LWMLINE *lwmcurve_segmentize(LWMCURVE *mcurve, uint32 perQuad);
|
28
|
+
LWMPOLY *lwmsurface_segmentize(LWMSURFACE *msurface, uint32 perQuad);
|
29
|
+
LWCOLLECTION *lwcollection_segmentize(LWCOLLECTION *collection, uint32 perQuad);
|
30
|
+
LWGEOM *append_segment(LWGEOM *geom, POINTARRAY *pts, int type, int SRID);
|
31
|
+
LWGEOM *pta_desegmentize(POINTARRAY *points, int type, int SRID);
|
32
|
+
LWGEOM *lwline_desegmentize(LWLINE *line);
|
33
|
+
LWGEOM *lwpolygon_desegmentize(LWPOLY *poly);
|
34
|
+
LWGEOM *lwmline_desegmentize(LWMLINE *mline);
|
35
|
+
LWGEOM *lwmpolygon_desegmentize(LWMPOLY *mpoly);
|
36
|
+
LWGEOM *lwgeom_desegmentize(LWGEOM *geom);
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
/*
|
41
|
+
* Tolerance used to determine equality.
|
42
|
+
*/
|
43
|
+
#define EPSILON_SQLMM 1e-8
|
44
|
+
|
45
|
+
/*
|
46
|
+
* Determines (recursively in the case of collections) whether the geometry
|
47
|
+
* contains at least on arc geometry or segment.
|
48
|
+
*/
|
49
|
+
uint32
|
50
|
+
has_arc(LWGEOM *geom)
|
51
|
+
{
|
52
|
+
LWCOLLECTION *col;
|
53
|
+
int i;
|
54
|
+
|
55
|
+
LWDEBUG(2, "has_arc called.");
|
56
|
+
|
57
|
+
switch(lwgeom_getType(geom->type))
|
58
|
+
{
|
59
|
+
case POINTTYPE:
|
60
|
+
case LINETYPE:
|
61
|
+
case POLYGONTYPE:
|
62
|
+
case MULTIPOINTTYPE:
|
63
|
+
case MULTILINETYPE:
|
64
|
+
case MULTIPOLYGONTYPE:
|
65
|
+
return 0;
|
66
|
+
case CIRCSTRINGTYPE:
|
67
|
+
return 1;
|
68
|
+
/* It's a collection that MAY contain an arc */
|
69
|
+
default:
|
70
|
+
col = (LWCOLLECTION *)geom;
|
71
|
+
for(i=0; i<col->ngeoms; i++)
|
72
|
+
{
|
73
|
+
if(has_arc(col->geoms[i]) == 1) return 1;
|
74
|
+
}
|
75
|
+
return 0;
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
/*
|
80
|
+
* Determines the center of the circle defined by the three given points.
|
81
|
+
* In the event the circle is complete, the midpoint of the segment defined
|
82
|
+
* by the first and second points is returned. If the points are colinear,
|
83
|
+
* as determined by equal slopes, then NULL is returned. If the interior
|
84
|
+
* point is coincident with either end point, they are taken as colinear.
|
85
|
+
*/
|
86
|
+
double
|
87
|
+
lwcircle_center(POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D **result)
|
88
|
+
{
|
89
|
+
POINT4D *c;
|
90
|
+
double cx, cy, cr;
|
91
|
+
double temp, bc, cd, det;
|
92
|
+
|
93
|
+
LWDEBUGF(2, "lwcircle_center called (%.16f, %.16f), (%.16f, %.16f), (%.16f, %.16f).", p1->x, p1->y, p2->x, p2->y, p3->x, p3->y);
|
94
|
+
|
95
|
+
/* Closed circle */
|
96
|
+
if(fabs(p1->x - p3->x) < EPSILON_SQLMM
|
97
|
+
&& fabs(p1->y - p3->y) < EPSILON_SQLMM)
|
98
|
+
{
|
99
|
+
cx = p1->x + (p2->x - p1->x) / 2.0;
|
100
|
+
cy = p1->y + (p2->y - p1->y) / 2.0;
|
101
|
+
c = lwalloc(sizeof(POINT2D));
|
102
|
+
c->x = cx;
|
103
|
+
c->y = cy;
|
104
|
+
*result = c;
|
105
|
+
cr = sqrt((cx-p1->x)*(cx-p1->x)+(cy-p1->y)*(cy-p1->y));
|
106
|
+
return cr;
|
107
|
+
}
|
108
|
+
|
109
|
+
temp = p2->x*p2->x + p2->y*p2->y;
|
110
|
+
bc = (p1->x*p1->x + p1->y*p1->y - temp) / 2.0;
|
111
|
+
cd = (temp - p3->x*p3->x - p3->y*p3->y) / 2.0;
|
112
|
+
det = (p1->x - p2->x)*(p2->y - p3->y)-(p2->x - p3->x)*(p1->y - p2->y);
|
113
|
+
|
114
|
+
/* Check colinearity */
|
115
|
+
if(fabs(det) < EPSILON_SQLMM)
|
116
|
+
{
|
117
|
+
*result = NULL;
|
118
|
+
return -1.0;
|
119
|
+
}
|
120
|
+
|
121
|
+
det = 1.0 / det;
|
122
|
+
cx = (bc*(p2->y - p3->y)-cd*(p1->y - p2->y))*det;
|
123
|
+
cy = ((p1->x - p2->x)*cd-(p2->x - p3->x)*bc)*det;
|
124
|
+
c = lwalloc(sizeof(POINT4D));
|
125
|
+
c->x = cx;
|
126
|
+
c->y = cy;
|
127
|
+
*result = c;
|
128
|
+
cr = sqrt((cx-p1->x)*(cx-p1->x)+(cy-p1->y)*(cy-p1->y));
|
129
|
+
return cr;
|
130
|
+
}
|
131
|
+
|
132
|
+
double
|
133
|
+
interpolate_arc(double angle, double zm1, double a1, double zm2, double a2)
|
134
|
+
{
|
135
|
+
double frac = fabs((angle - a1) / (a2 - a1));
|
136
|
+
double result = frac * (zm2 - zm1) + zm1;
|
137
|
+
|
138
|
+
LWDEBUG(2, "interpolate_arc called.");
|
139
|
+
|
140
|
+
LWDEBUGF(3, "interpolate_arc: angle=%.16f, a1=%.16f, a2=%.16f, z1=%.16f, z2=%.16f, frac=%.16f, result=%.16f", angle, a1, a2, zm1, zm2, frac, result);
|
141
|
+
|
142
|
+
return result;
|
143
|
+
}
|
144
|
+
|
145
|
+
/*******************************************************************************
|
146
|
+
* Begin curve segmentize functions
|
147
|
+
******************************************************************************/
|
148
|
+
|
149
|
+
POINTARRAY *
|
150
|
+
lwcircle_segmentize(POINT4D *p1, POINT4D *p2, POINT4D *p3, uint32 perQuad)
|
151
|
+
{
|
152
|
+
POINTARRAY *result;
|
153
|
+
POINT4D pbuf;
|
154
|
+
size_t ptsize = sizeof(POINT4D);
|
155
|
+
unsigned int ptcount;
|
156
|
+
uchar *pt;
|
157
|
+
|
158
|
+
POINT4D *center;
|
159
|
+
double radius = 0.0,
|
160
|
+
sweep = 0.0,
|
161
|
+
angle = 0.0,
|
162
|
+
increment = 0.0;
|
163
|
+
double a1, a2, a3, i;
|
164
|
+
|
165
|
+
LWDEBUG(2, "lwcircle_segmentize called. ");
|
166
|
+
|
167
|
+
radius = lwcircle_center(p1, p2, p3, ¢er);
|
168
|
+
|
169
|
+
LWDEBUGF(3, "lwcircle_segmentize, (%.16f, %.16f) radius=%.16f", center->x, center->y, radius);
|
170
|
+
|
171
|
+
if(radius < 0)
|
172
|
+
{
|
173
|
+
return NULL;
|
174
|
+
}
|
175
|
+
|
176
|
+
a1 = atan2(p1->y - center->y, p1->x - center->x);
|
177
|
+
a2 = atan2(p2->y - center->y, p2->x - center->x);
|
178
|
+
a3 = atan2(p3->y - center->y, p3->x - center->x);
|
179
|
+
|
180
|
+
LWDEBUGF(3, "a1 = %.16f, a2 = %.16f, a3 = %.16f", a1, a2, a3);
|
181
|
+
|
182
|
+
if(fabs(p1->x - p3->x) < EPSILON_SQLMM
|
183
|
+
&& fabs(p1->y - p3->y) < EPSILON_SQLMM)
|
184
|
+
{
|
185
|
+
sweep = 2*M_PI;
|
186
|
+
}
|
187
|
+
/* Clockwise */
|
188
|
+
else if(a1 > a2 && a2 > a3)
|
189
|
+
{
|
190
|
+
sweep = a3 - a1;
|
191
|
+
}
|
192
|
+
/* Counter-clockwise */
|
193
|
+
else if(a1 < a2 && a2 < a3)
|
194
|
+
{
|
195
|
+
sweep = a3 - a1;
|
196
|
+
}
|
197
|
+
/* Clockwise, wrap */
|
198
|
+
else if((a1 < a2 && a1 > a3) || (a2 < a3 && a1 > a3))
|
199
|
+
{
|
200
|
+
sweep = a3 - a1 + 2*M_PI;
|
201
|
+
}
|
202
|
+
/* Counter-clockwise, wrap */
|
203
|
+
else if((a1 > a2 && a1 < a3) || (a2 > a3 && a1 < a3))
|
204
|
+
{
|
205
|
+
sweep = a3 - a1 - 2*M_PI;
|
206
|
+
}
|
207
|
+
else
|
208
|
+
{
|
209
|
+
sweep = 0.0;
|
210
|
+
}
|
211
|
+
|
212
|
+
ptcount = ceil(fabs(perQuad * sweep / M_PI_2));
|
213
|
+
|
214
|
+
result = ptarray_construct(1, 1, ptcount);
|
215
|
+
|
216
|
+
increment = M_PI_2 / perQuad;
|
217
|
+
if(sweep < 0) increment *= -1.0;
|
218
|
+
angle = a1;
|
219
|
+
|
220
|
+
LWDEBUGF(3, "ptcount: %d, perQuad: %d, sweep: %.16f, increment: %.16f", ptcount, perQuad, sweep, increment);
|
221
|
+
|
222
|
+
for(i = 0; i < ptcount - 1; i++)
|
223
|
+
{
|
224
|
+
pt = getPoint_internal(result, i);
|
225
|
+
angle += increment;
|
226
|
+
if(increment > 0.0 && angle > M_PI) angle -= 2*M_PI;
|
227
|
+
if(increment < 0.0 && angle < -1*M_PI) angle -= 2*M_PI;
|
228
|
+
pbuf.x = center->x + radius*cos(angle);
|
229
|
+
pbuf.y = center->y + radius*sin(angle);
|
230
|
+
if((sweep > 0 && angle < a2) || (sweep < 0 && angle > a2))
|
231
|
+
{
|
232
|
+
if((sweep > 0 && a1 < a2) || (sweep < 0 && a1 > a2))
|
233
|
+
{
|
234
|
+
pbuf.z = interpolate_arc(angle, p1->z, a1, p2->z, a2);
|
235
|
+
pbuf.m = interpolate_arc(angle, p1->m, a1, p2->m, a2);
|
236
|
+
}
|
237
|
+
else
|
238
|
+
{
|
239
|
+
if(sweep > 0)
|
240
|
+
{
|
241
|
+
pbuf.z = interpolate_arc(angle, p1->z, a1-(2*M_PI), p2->z, a2);
|
242
|
+
pbuf.m = interpolate_arc(angle, p1->m, a1-(2*M_PI), p2->m, a2);
|
243
|
+
}
|
244
|
+
else
|
245
|
+
{
|
246
|
+
pbuf.z = interpolate_arc(angle, p1->z, a1+(2*M_PI), p2->z, a2);
|
247
|
+
pbuf.m = interpolate_arc(angle, p1->m, a1+(2*M_PI), p2->m, a2);
|
248
|
+
}
|
249
|
+
}
|
250
|
+
}
|
251
|
+
else
|
252
|
+
{
|
253
|
+
if((sweep > 0 && a2 < a3) || (sweep < 0 && a2 > a3))
|
254
|
+
{
|
255
|
+
pbuf.z = interpolate_arc(angle, p2->z, a2, p3->z, a3);
|
256
|
+
pbuf.m = interpolate_arc(angle, p2->m, a2, p3->m, a3);
|
257
|
+
}
|
258
|
+
else
|
259
|
+
{
|
260
|
+
if(sweep > 0)
|
261
|
+
{
|
262
|
+
pbuf.z = interpolate_arc(angle, p2->z, a2-(2*M_PI), p3->z, a3);
|
263
|
+
pbuf.m = interpolate_arc(angle, p2->m, a2-(2*M_PI), p3->m, a3);
|
264
|
+
}
|
265
|
+
else
|
266
|
+
{
|
267
|
+
pbuf.z = interpolate_arc(angle, p2->z, a2+(2*M_PI), p3->z, a3);
|
268
|
+
pbuf.m = interpolate_arc(angle, p2->m, a2+(2*M_PI), p3->m, a3);
|
269
|
+
}
|
270
|
+
}
|
271
|
+
}
|
272
|
+
memcpy(pt, (uchar *)&pbuf, ptsize);
|
273
|
+
}
|
274
|
+
|
275
|
+
pt = getPoint_internal(result, ptcount - 1);
|
276
|
+
memcpy(pt, (uchar *)p3, ptsize);
|
277
|
+
|
278
|
+
lwfree(center);
|
279
|
+
|
280
|
+
return result;
|
281
|
+
}
|
282
|
+
|
283
|
+
LWLINE *
|
284
|
+
lwcurve_segmentize(LWCIRCSTRING *icurve, uint32 perQuad)
|
285
|
+
{
|
286
|
+
LWLINE *oline;
|
287
|
+
DYNPTARRAY *ptarray;
|
288
|
+
POINTARRAY *tmp;
|
289
|
+
uint32 i, j;
|
290
|
+
POINT4D *p1 = lwalloc(sizeof(POINT4D));
|
291
|
+
POINT4D *p2 = lwalloc(sizeof(POINT4D));
|
292
|
+
POINT4D *p3 = lwalloc(sizeof(POINT4D));
|
293
|
+
POINT4D *p4 = lwalloc(sizeof(POINT4D));
|
294
|
+
|
295
|
+
|
296
|
+
LWDEBUGF(2, "lwcurve_segmentize called., dim = %d", icurve->points->dims);
|
297
|
+
|
298
|
+
ptarray = dynptarray_create(icurve->points->npoints, icurve->points->dims);
|
299
|
+
if(!getPoint4d_p(icurve->points, 0, p4))
|
300
|
+
{
|
301
|
+
lwerror("lwcurve_segmentize: Cannot extract point.");
|
302
|
+
}
|
303
|
+
dynptarray_addPoint4d(ptarray, p4, 1);
|
304
|
+
|
305
|
+
for(i = 2; i < icurve->points->npoints; i+=2)
|
306
|
+
{
|
307
|
+
LWDEBUGF(3, "lwcurve_segmentize: arc ending at point %d", i);
|
308
|
+
|
309
|
+
getPoint4d_p(icurve->points, i - 2, p1);
|
310
|
+
getPoint4d_p(icurve->points, i - 1, p2);
|
311
|
+
getPoint4d_p(icurve->points, i, p3);
|
312
|
+
tmp = lwcircle_segmentize(p1, p2, p3, perQuad);
|
313
|
+
|
314
|
+
LWDEBUGF(3, "lwcurve_segmentize: generated %d points", tmp->npoints);
|
315
|
+
|
316
|
+
for(j = 0; j < tmp->npoints; j++)
|
317
|
+
{
|
318
|
+
getPoint4d_p(tmp, j, p4);
|
319
|
+
dynptarray_addPoint4d(ptarray, p4, 1);
|
320
|
+
}
|
321
|
+
lwfree(tmp);
|
322
|
+
}
|
323
|
+
oline = lwline_construct(icurve->SRID, NULL, ptarray_clone(ptarray->pa));
|
324
|
+
|
325
|
+
lwfree(p1);
|
326
|
+
lwfree(p2);
|
327
|
+
lwfree(p3);
|
328
|
+
lwfree(p4);
|
329
|
+
lwfree(ptarray);
|
330
|
+
return oline;
|
331
|
+
}
|
332
|
+
|
333
|
+
LWLINE *
|
334
|
+
lwcompound_segmentize(LWCOMPOUND *icompound, uint32 perQuad)
|
335
|
+
{
|
336
|
+
LWLINE *oline;
|
337
|
+
LWGEOM *geom;
|
338
|
+
DYNPTARRAY *ptarray = NULL;
|
339
|
+
LWLINE *tmp = NULL;
|
340
|
+
uint32 i, j;
|
341
|
+
POINT4D *p = NULL;
|
342
|
+
|
343
|
+
LWDEBUG(2, "lwcompound_segmentize called.");
|
344
|
+
|
345
|
+
p = lwalloc(sizeof(POINT4D));
|
346
|
+
|
347
|
+
ptarray = dynptarray_create(2, ((POINTARRAY *)icompound->geoms[0]->data)->dims);
|
348
|
+
|
349
|
+
for(i = 0; i < icompound->ngeoms; i++)
|
350
|
+
{
|
351
|
+
geom = icompound->geoms[i];
|
352
|
+
if(lwgeom_getType(geom->type) == CIRCSTRINGTYPE)
|
353
|
+
{
|
354
|
+
tmp = lwcurve_segmentize((LWCIRCSTRING *)geom, perQuad);
|
355
|
+
for(j = 0; j < tmp->points->npoints; j++)
|
356
|
+
{
|
357
|
+
getPoint4d_p(tmp->points, j, p);
|
358
|
+
dynptarray_addPoint4d(ptarray, p, 0);
|
359
|
+
}
|
360
|
+
lwfree(tmp);
|
361
|
+
}
|
362
|
+
else if(lwgeom_getType(geom->type) == LINETYPE)
|
363
|
+
{
|
364
|
+
tmp = (LWLINE *)geom;
|
365
|
+
for(j = 0; j < tmp->points->npoints; j++)
|
366
|
+
{
|
367
|
+
getPoint4d_p(tmp->points, j, p);
|
368
|
+
dynptarray_addPoint4d(ptarray, p, 0);
|
369
|
+
}
|
370
|
+
}
|
371
|
+
else
|
372
|
+
{
|
373
|
+
lwerror("Unsupported geometry type %d found.", lwgeom_getType(geom->type));
|
374
|
+
return NULL;
|
375
|
+
}
|
376
|
+
}
|
377
|
+
oline = lwline_construct(icompound->SRID, NULL, ptarray_clone(ptarray->pa));
|
378
|
+
lwfree(ptarray);
|
379
|
+
lwfree(p);
|
380
|
+
return oline;
|
381
|
+
}
|
382
|
+
|
383
|
+
LWPOLY *
|
384
|
+
lwcurvepoly_segmentize(LWCURVEPOLY *curvepoly, uint32 perQuad)
|
385
|
+
{
|
386
|
+
LWPOLY *ogeom;
|
387
|
+
LWGEOM *tmp;
|
388
|
+
LWLINE *line;
|
389
|
+
POINTARRAY **ptarray;
|
390
|
+
int i;
|
391
|
+
|
392
|
+
LWDEBUG(2, "lwcurvepoly_segmentize called.");
|
393
|
+
|
394
|
+
ptarray = lwalloc(sizeof(POINTARRAY *)*curvepoly->nrings);
|
395
|
+
|
396
|
+
for(i = 0; i < curvepoly->nrings; i++)
|
397
|
+
{
|
398
|
+
tmp = curvepoly->rings[i];
|
399
|
+
if(lwgeom_getType(tmp->type) == CIRCSTRINGTYPE)
|
400
|
+
{
|
401
|
+
line = lwcurve_segmentize((LWCIRCSTRING *)tmp, perQuad);
|
402
|
+
ptarray[i] = ptarray_clone(line->points);
|
403
|
+
lwfree(line);
|
404
|
+
}
|
405
|
+
else if(lwgeom_getType(tmp->type) == LINETYPE)
|
406
|
+
{
|
407
|
+
line = (LWLINE *)tmp;
|
408
|
+
ptarray[i] = ptarray_clone(line->points);
|
409
|
+
}
|
410
|
+
else
|
411
|
+
{
|
412
|
+
lwerror("Invalid ring type found in CurvePoly.");
|
413
|
+
return NULL;
|
414
|
+
}
|
415
|
+
}
|
416
|
+
|
417
|
+
ogeom = lwpoly_construct(curvepoly->SRID, NULL, curvepoly->nrings, ptarray);
|
418
|
+
return ogeom;
|
419
|
+
}
|
420
|
+
|
421
|
+
LWMLINE *
|
422
|
+
lwmcurve_segmentize(LWMCURVE *mcurve, uint32 perQuad)
|
423
|
+
{
|
424
|
+
LWMLINE *ogeom;
|
425
|
+
LWGEOM *tmp;
|
426
|
+
LWGEOM **lines;
|
427
|
+
int i;
|
428
|
+
|
429
|
+
LWDEBUGF(2, "lwmcurve_segmentize called, geoms=%d, dim=%d.", mcurve->ngeoms, TYPE_NDIMS(mcurve->type));
|
430
|
+
|
431
|
+
lines = lwalloc(sizeof(LWGEOM *)*mcurve->ngeoms);
|
432
|
+
|
433
|
+
for(i = 0; i < mcurve->ngeoms; i++)
|
434
|
+
{
|
435
|
+
tmp = mcurve->geoms[i];
|
436
|
+
if(lwgeom_getType(tmp->type) == CIRCSTRINGTYPE)
|
437
|
+
{
|
438
|
+
lines[i] = (LWGEOM *)lwcurve_segmentize((LWCIRCSTRING *)tmp, perQuad);
|
439
|
+
}
|
440
|
+
else if(lwgeom_getType(tmp->type) == LINETYPE)
|
441
|
+
{
|
442
|
+
lines[i] = (LWGEOM *)lwline_construct(mcurve->SRID, NULL, ptarray_clone(((LWLINE *)tmp)->points));
|
443
|
+
}
|
444
|
+
else
|
445
|
+
{
|
446
|
+
lwerror("Unsupported geometry found in MultiCurve.");
|
447
|
+
return NULL;
|
448
|
+
}
|
449
|
+
}
|
450
|
+
|
451
|
+
ogeom = (LWMLINE *)lwcollection_construct(MULTILINETYPE, mcurve->SRID, NULL, mcurve->ngeoms, lines);
|
452
|
+
return ogeom;
|
453
|
+
}
|
454
|
+
|
455
|
+
LWMPOLY *
|
456
|
+
lwmsurface_segmentize(LWMSURFACE *msurface, uint32 perQuad)
|
457
|
+
{
|
458
|
+
LWMPOLY *ogeom;
|
459
|
+
LWGEOM *tmp;
|
460
|
+
LWPOLY *poly;
|
461
|
+
LWGEOM **polys;
|
462
|
+
POINTARRAY **ptarray;
|
463
|
+
int i, j;
|
464
|
+
|
465
|
+
LWDEBUG(2, "lwmsurface_segmentize called.");
|
466
|
+
|
467
|
+
polys = lwalloc(sizeof(LWGEOM *)*msurface->ngeoms);
|
468
|
+
|
469
|
+
for(i = 0; i < msurface->ngeoms; i++)
|
470
|
+
{
|
471
|
+
tmp = msurface->geoms[i];
|
472
|
+
if(lwgeom_getType(tmp->type) == CURVEPOLYTYPE)
|
473
|
+
{
|
474
|
+
polys[i] = (LWGEOM *)lwcurvepoly_segmentize((LWCURVEPOLY *)tmp, perQuad);
|
475
|
+
}
|
476
|
+
else if(lwgeom_getType(tmp->type) == POLYGONTYPE)
|
477
|
+
{
|
478
|
+
poly = (LWPOLY *)tmp;
|
479
|
+
ptarray = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
|
480
|
+
for(j = 0; j < poly->nrings; j++)
|
481
|
+
{
|
482
|
+
ptarray[j] = ptarray_clone(poly->rings[j]);
|
483
|
+
}
|
484
|
+
polys[i] = (LWGEOM *)lwpoly_construct(msurface->SRID, NULL, poly->nrings, ptarray);
|
485
|
+
}
|
486
|
+
}
|
487
|
+
ogeom = (LWMPOLY *)lwcollection_construct(MULTIPOLYGONTYPE, msurface->SRID, NULL, msurface->ngeoms, polys);
|
488
|
+
return ogeom;
|
489
|
+
}
|
490
|
+
|
491
|
+
LWCOLLECTION *
|
492
|
+
lwcollection_segmentize(LWCOLLECTION *collection, uint32 perQuad)
|
493
|
+
{
|
494
|
+
LWCOLLECTION *ocol;
|
495
|
+
LWGEOM *tmp;
|
496
|
+
LWGEOM **geoms;
|
497
|
+
int i;
|
498
|
+
|
499
|
+
LWDEBUG(2, "lwcollection_segmentize called.");
|
500
|
+
|
501
|
+
geoms = lwalloc(sizeof(LWGEOM *)*collection->ngeoms);
|
502
|
+
|
503
|
+
for(i=0; i<collection->ngeoms; i++)
|
504
|
+
{
|
505
|
+
tmp = collection->geoms[i];
|
506
|
+
switch(lwgeom_getType(tmp->type)) {
|
507
|
+
case CIRCSTRINGTYPE:
|
508
|
+
geoms[i] = (LWGEOM *)lwcurve_segmentize((LWCIRCSTRING *)tmp, perQuad);
|
509
|
+
break;
|
510
|
+
case COMPOUNDTYPE:
|
511
|
+
geoms[i] = (LWGEOM *)lwcompound_segmentize((LWCOMPOUND *)tmp, perQuad);
|
512
|
+
break;
|
513
|
+
case CURVEPOLYTYPE:
|
514
|
+
geoms[i] = (LWGEOM *)lwcurvepoly_segmentize((LWCURVEPOLY *)tmp, perQuad);
|
515
|
+
break;
|
516
|
+
case COLLECTIONTYPE:
|
517
|
+
geoms[i] = (LWGEOM *)lwcollection_segmentize((LWCOLLECTION *)tmp, perQuad);
|
518
|
+
break;
|
519
|
+
default:
|
520
|
+
geoms[i] = lwgeom_clone(tmp);
|
521
|
+
break;
|
522
|
+
}
|
523
|
+
}
|
524
|
+
ocol = lwcollection_construct(COLLECTIONTYPE, collection->SRID, NULL, collection->ngeoms, geoms);
|
525
|
+
return ocol;
|
526
|
+
}
|
527
|
+
|
528
|
+
LWGEOM *
|
529
|
+
lwgeom_segmentize(LWGEOM *geom, uint32 perQuad)
|
530
|
+
{
|
531
|
+
LWGEOM * ogeom = NULL;
|
532
|
+
switch(lwgeom_getType(geom->type)) {
|
533
|
+
case CIRCSTRINGTYPE:
|
534
|
+
ogeom = (LWGEOM *)lwcurve_segmentize((LWCIRCSTRING *)geom, perQuad);
|
535
|
+
break;
|
536
|
+
case COMPOUNDTYPE:
|
537
|
+
ogeom = (LWGEOM *)lwcompound_segmentize((LWCOMPOUND *)geom, perQuad);
|
538
|
+
break;
|
539
|
+
case CURVEPOLYTYPE:
|
540
|
+
ogeom = (LWGEOM *)lwcurvepoly_segmentize((LWCURVEPOLY *)geom, perQuad);
|
541
|
+
break;
|
542
|
+
case MULTICURVETYPE:
|
543
|
+
ogeom = (LWGEOM *)lwmcurve_segmentize((LWMCURVE *)geom, perQuad);
|
544
|
+
break;
|
545
|
+
case MULTISURFACETYPE:
|
546
|
+
ogeom = (LWGEOM *)lwmsurface_segmentize((LWMSURFACE *)geom, perQuad);
|
547
|
+
break;
|
548
|
+
case COLLECTIONTYPE:
|
549
|
+
ogeom = (LWGEOM *)lwcollection_segmentize((LWCOLLECTION *)geom, perQuad);
|
550
|
+
break;
|
551
|
+
default:
|
552
|
+
ogeom = lwgeom_clone(geom);
|
553
|
+
}
|
554
|
+
return ogeom;
|
555
|
+
}
|
556
|
+
|
557
|
+
/*******************************************************************************
|
558
|
+
* End curve segmentize functions
|
559
|
+
******************************************************************************/
|
560
|
+
LWGEOM *
|
561
|
+
append_segment(LWGEOM *geom, POINTARRAY *pts, int type, int SRID)
|
562
|
+
{
|
563
|
+
LWGEOM *result;
|
564
|
+
int currentType, i;
|
565
|
+
|
566
|
+
LWDEBUGF(2, "append_segment called %p, %p, %d, %d", geom, pts, type, SRID);
|
567
|
+
|
568
|
+
if(geom == NULL)
|
569
|
+
{
|
570
|
+
if(type == LINETYPE)
|
571
|
+
{
|
572
|
+
LWDEBUG(3, "append_segment: line to NULL");
|
573
|
+
|
574
|
+
return (LWGEOM *)lwline_construct(SRID, NULL, pts);
|
575
|
+
}
|
576
|
+
else if(type == CIRCSTRINGTYPE)
|
577
|
+
{
|
578
|
+
#if POSTGIS_DEBUG_LEVEL >= 4
|
579
|
+
POINT4D tmp;
|
580
|
+
|
581
|
+
LWDEBUGF(4, "append_segment: curve to NULL %d", pts->npoints);
|
582
|
+
|
583
|
+
for(i=0; i<pts->npoints; i++)
|
584
|
+
{
|
585
|
+
getPoint4d_p(pts, i, &tmp);
|
586
|
+
LWDEBUGF(4, "new point: (%.16f,%.16f)",tmp.x,tmp.y);
|
587
|
+
}
|
588
|
+
#endif
|
589
|
+
return (LWGEOM *)lwcircstring_construct(SRID, NULL, pts);
|
590
|
+
}
|
591
|
+
else
|
592
|
+
{
|
593
|
+
lwerror("Invalid segment type %d.", type);
|
594
|
+
}
|
595
|
+
}
|
596
|
+
|
597
|
+
currentType = lwgeom_getType(geom->type);
|
598
|
+
if(currentType == LINETYPE && type == LINETYPE)
|
599
|
+
{
|
600
|
+
POINTARRAY *newPoints;
|
601
|
+
POINT4D pt;
|
602
|
+
LWLINE *line = (LWLINE *)geom;
|
603
|
+
|
604
|
+
LWDEBUG(3, "append_segment: line to line");
|
605
|
+
|
606
|
+
newPoints = ptarray_construct(TYPE_HASZ(pts->dims), TYPE_HASM(pts->dims), pts->npoints + line->points->npoints - 1);
|
607
|
+
for(i=0; i<line->points->npoints; i++)
|
608
|
+
{
|
609
|
+
getPoint4d_p(line->points, i, &pt);
|
610
|
+
LWDEBUGF(5, "copying to %p [%d]", newPoints, i);
|
611
|
+
setPoint4d(newPoints, i, &pt);
|
612
|
+
}
|
613
|
+
for(i=1; i<pts->npoints; i++)
|
614
|
+
{
|
615
|
+
getPoint4d_p(pts, i, &pt);
|
616
|
+
setPoint4d(newPoints, i + line->points->npoints - 1, &pt);
|
617
|
+
}
|
618
|
+
result = (LWGEOM *)lwline_construct(SRID, NULL, newPoints);
|
619
|
+
lwgeom_release(geom);
|
620
|
+
return result;
|
621
|
+
}
|
622
|
+
else if(currentType == CIRCSTRINGTYPE && type == CIRCSTRINGTYPE)
|
623
|
+
{
|
624
|
+
POINTARRAY *newPoints;
|
625
|
+
POINT4D pt;
|
626
|
+
LWCIRCSTRING *curve = (LWCIRCSTRING *)geom;
|
627
|
+
|
628
|
+
LWDEBUG(3, "append_segment: circularstring to circularstring");
|
629
|
+
|
630
|
+
newPoints = ptarray_construct(TYPE_HASZ(pts->dims), TYPE_HASM(pts->dims), pts->npoints + curve->points->npoints - 1);
|
631
|
+
|
632
|
+
LWDEBUGF(3, "New array length: %d", pts->npoints + curve->points->npoints - 1);
|
633
|
+
|
634
|
+
for(i=0; i<curve->points->npoints; i++)
|
635
|
+
{
|
636
|
+
getPoint4d_p(curve->points, i, &pt);
|
637
|
+
|
638
|
+
LWDEBUGF(3, "orig point %d: (%.16f,%.16f)", i, pt.x, pt.y);
|
639
|
+
|
640
|
+
setPoint4d(newPoints, i, &pt);
|
641
|
+
}
|
642
|
+
for(i=1; i<pts->npoints;i++)
|
643
|
+
{
|
644
|
+
getPoint4d_p(pts, i, &pt);
|
645
|
+
|
646
|
+
LWDEBUGF(3, "new point %d: (%.16f,%.16f)", i + curve->points->npoints - 1, pt.x, pt.y);
|
647
|
+
|
648
|
+
setPoint4d(newPoints, i + curve->points->npoints - 1, &pt);
|
649
|
+
}
|
650
|
+
result = (LWGEOM *)lwcircstring_construct(SRID, NULL, newPoints);
|
651
|
+
lwgeom_release(geom);
|
652
|
+
return result;
|
653
|
+
}
|
654
|
+
else if(currentType == CIRCSTRINGTYPE && type == LINETYPE)
|
655
|
+
{
|
656
|
+
LWLINE *line;
|
657
|
+
LWGEOM **geomArray;
|
658
|
+
|
659
|
+
LWDEBUG(3, "append_segment: line to curve");
|
660
|
+
|
661
|
+
geomArray = lwalloc(sizeof(LWGEOM *)*2);
|
662
|
+
geomArray[0] = lwgeom_clone(geom);
|
663
|
+
|
664
|
+
line = lwline_construct(SRID, NULL, pts);
|
665
|
+
geomArray[1] = lwgeom_clone((LWGEOM *)line);
|
666
|
+
|
667
|
+
result = (LWGEOM *)lwcollection_construct(COMPOUNDTYPE, SRID, NULL, 2, geomArray);
|
668
|
+
lwfree((LWGEOM *)line);
|
669
|
+
lwgeom_release(geom);
|
670
|
+
return result;
|
671
|
+
}
|
672
|
+
else if(currentType == LINETYPE && type == CIRCSTRINGTYPE)
|
673
|
+
{
|
674
|
+
LWCIRCSTRING *curve;
|
675
|
+
LWGEOM **geomArray;
|
676
|
+
|
677
|
+
LWDEBUG(3, "append_segment: circularstring to line");
|
678
|
+
|
679
|
+
geomArray = lwalloc(sizeof(LWGEOM *)*2);
|
680
|
+
geomArray[0] = lwgeom_clone(geom);
|
681
|
+
|
682
|
+
curve = lwcircstring_construct(SRID, NULL, pts);
|
683
|
+
geomArray[1] = lwgeom_clone((LWGEOM *)curve);
|
684
|
+
|
685
|
+
result = (LWGEOM *)lwcollection_construct(COMPOUNDTYPE, SRID, NULL, 2, geomArray);
|
686
|
+
lwfree((LWGEOM *)curve);
|
687
|
+
lwgeom_release(geom);
|
688
|
+
return result;
|
689
|
+
}
|
690
|
+
else if(currentType == COMPOUNDTYPE)
|
691
|
+
{
|
692
|
+
LWGEOM *newGeom;
|
693
|
+
LWCOMPOUND *compound;
|
694
|
+
int count;
|
695
|
+
LWGEOM **geomArray;
|
696
|
+
|
697
|
+
compound = (LWCOMPOUND *)geom;
|
698
|
+
count = compound->ngeoms + 1;
|
699
|
+
geomArray = lwalloc(sizeof(LWGEOM *)*count);
|
700
|
+
for(i=0; i<compound->ngeoms; i++)
|
701
|
+
{
|
702
|
+
geomArray[i] = lwgeom_clone(compound->geoms[i]);
|
703
|
+
}
|
704
|
+
if(type == LINETYPE)
|
705
|
+
{
|
706
|
+
LWDEBUG(3, "append_segment: line to compound");
|
707
|
+
|
708
|
+
newGeom = (LWGEOM *)lwline_construct(SRID, NULL, pts);
|
709
|
+
}
|
710
|
+
else if(type == CIRCSTRINGTYPE)
|
711
|
+
{
|
712
|
+
LWDEBUG(3, "append_segment: circularstring to compound");
|
713
|
+
|
714
|
+
newGeom = (LWGEOM *)lwcircstring_construct(SRID, NULL, pts);
|
715
|
+
}
|
716
|
+
else
|
717
|
+
{
|
718
|
+
lwerror("Invalid segment type %d.", type);
|
719
|
+
return NULL;
|
720
|
+
}
|
721
|
+
geomArray[compound->ngeoms] = lwgeom_clone(newGeom);
|
722
|
+
|
723
|
+
result = (LWGEOM *)lwcollection_construct(COMPOUNDTYPE, SRID, NULL, count, geomArray);
|
724
|
+
lwfree(newGeom);
|
725
|
+
lwgeom_release(geom);
|
726
|
+
return result;
|
727
|
+
}
|
728
|
+
lwerror("Invalid state %d-%d", currentType, type);
|
729
|
+
return NULL;
|
730
|
+
}
|
731
|
+
|
732
|
+
LWGEOM *
|
733
|
+
pta_desegmentize(POINTARRAY *points, int type, int SRID)
|
734
|
+
{
|
735
|
+
int i, j, commit, isline, count;
|
736
|
+
double last_angle, last_length;
|
737
|
+
double dxab, dyab, dxbc, dybc, theta, length;
|
738
|
+
POINT4D a, b, c, tmp;
|
739
|
+
POINTARRAY *pts;
|
740
|
+
LWGEOM *geom = NULL;
|
741
|
+
|
742
|
+
LWDEBUG(2, "pta_desegmentize called.");
|
743
|
+
|
744
|
+
getPoint4d_p(points, 0, &a);
|
745
|
+
getPoint4d_p(points, 1, &b);
|
746
|
+
getPoint4d_p(points, 2, &c);
|
747
|
+
|
748
|
+
dxab = b.x - a.x;
|
749
|
+
dyab = b.y - a.y;
|
750
|
+
dxbc = c.x - b.x;
|
751
|
+
dybc = c.y - b.y;
|
752
|
+
|
753
|
+
theta = atan2(dyab, dxab);
|
754
|
+
last_angle = theta - atan2(dybc, dxbc);
|
755
|
+
last_length = sqrt(dxbc*dxbc+dybc*dybc);
|
756
|
+
length = sqrt(dxab*dxab+dyab*dyab);
|
757
|
+
if((last_length - length) < EPSILON_SQLMM)
|
758
|
+
{
|
759
|
+
isline = -1;
|
760
|
+
LWDEBUG(3, "Starting as unknown.");
|
761
|
+
}
|
762
|
+
else
|
763
|
+
{
|
764
|
+
isline = 1;
|
765
|
+
LWDEBUG(3, "Starting as line.");
|
766
|
+
}
|
767
|
+
|
768
|
+
commit = 0;
|
769
|
+
for(i=3; i<points->npoints; i++)
|
770
|
+
{
|
771
|
+
getPoint4d_p(points, i-2, &a);
|
772
|
+
getPoint4d_p(points, i-1, &b);
|
773
|
+
getPoint4d_p(points, i, &c);
|
774
|
+
|
775
|
+
dxab = b.x - a.x;
|
776
|
+
dyab = b.y - a.y;
|
777
|
+
dxbc = c.x - b.x;
|
778
|
+
dybc = c.y - b.y;
|
779
|
+
|
780
|
+
LWDEBUGF(3, "(dxab, dyab, dxbc, dybc) (%.16f, %.16f, %.16f, %.16f)", dxab, dyab, dxbc, dybc);
|
781
|
+
|
782
|
+
theta = atan2(dyab, dxab);
|
783
|
+
theta = theta - atan2(dybc, dxbc);
|
784
|
+
length = sqrt(dxbc*dxbc+dybc*dybc);
|
785
|
+
|
786
|
+
LWDEBUGF(3, "Last/current length and angle %.16f/%.16f, %.16f/%.16f", last_angle, theta, last_length, length);
|
787
|
+
|
788
|
+
/* Found a line segment */
|
789
|
+
if(fabs(length - last_length) > EPSILON_SQLMM ||
|
790
|
+
fabs(theta - last_angle) > EPSILON_SQLMM)
|
791
|
+
{
|
792
|
+
last_length = length;
|
793
|
+
last_angle = theta;
|
794
|
+
/* We are tracking a line, keep going */
|
795
|
+
if(isline > 0)
|
796
|
+
{
|
797
|
+
}
|
798
|
+
/* We were tracking a circularstring, commit it and start line*/
|
799
|
+
else if(isline == 0)
|
800
|
+
{
|
801
|
+
LWDEBUGF(3, "Building circularstring, %d - %d", commit, i);
|
802
|
+
|
803
|
+
count = i - commit;
|
804
|
+
pts = ptarray_construct(
|
805
|
+
TYPE_HASZ(type),
|
806
|
+
TYPE_HASM(type),
|
807
|
+
3);
|
808
|
+
getPoint4d_p(points, commit, &tmp);
|
809
|
+
setPoint4d(pts, 0, &tmp);
|
810
|
+
getPoint4d_p(points,
|
811
|
+
commit + count/2, &tmp);
|
812
|
+
setPoint4d(pts, 1, &tmp);
|
813
|
+
getPoint4d_p(points, i - 1, &tmp);
|
814
|
+
setPoint4d(pts, 2, &tmp);
|
815
|
+
|
816
|
+
commit = i-1;
|
817
|
+
geom = append_segment(geom, pts, CIRCSTRINGTYPE, SRID);
|
818
|
+
isline = -1;
|
819
|
+
|
820
|
+
/*
|
821
|
+
* We now need to move ahead one point to
|
822
|
+
* determine if it's a potential new curve,
|
823
|
+
* since the last_angle value is corrupt.
|
824
|
+
*/
|
825
|
+
i++;
|
826
|
+
getPoint4d_p(points, i-2, &a);
|
827
|
+
getPoint4d_p(points, i-1, &b);
|
828
|
+
getPoint4d_p(points, i, &c);
|
829
|
+
|
830
|
+
dxab = b.x - a.x;
|
831
|
+
dyab = b.y - a.y;
|
832
|
+
dxbc = c.x - b.x;
|
833
|
+
dybc = c.y - b.y;
|
834
|
+
|
835
|
+
theta = atan2(dyab, dxab);
|
836
|
+
last_angle = theta - atan2(dybc, dxbc);
|
837
|
+
last_length = sqrt(dxbc*dxbc+dybc*dybc);
|
838
|
+
length = sqrt(dxab*dxab+dyab*dyab);
|
839
|
+
if((last_length - length) < EPSILON_SQLMM)
|
840
|
+
{
|
841
|
+
isline = -1;
|
842
|
+
LWDEBUG(3, "Restarting as unknown.");
|
843
|
+
}
|
844
|
+
else
|
845
|
+
{
|
846
|
+
isline = 1;
|
847
|
+
LWDEBUG(3, "Restarting as line.");
|
848
|
+
}
|
849
|
+
|
850
|
+
|
851
|
+
}
|
852
|
+
/* We didn't know what we were tracking, now we do. */
|
853
|
+
else
|
854
|
+
{
|
855
|
+
LWDEBUG(3, "It's a line");
|
856
|
+
isline = 1;
|
857
|
+
}
|
858
|
+
}
|
859
|
+
/* Found a circularstring segment */
|
860
|
+
else
|
861
|
+
{
|
862
|
+
/* We were tracking a circularstring, commit it and start line */
|
863
|
+
if(isline > 0)
|
864
|
+
{
|
865
|
+
LWDEBUGF(3, "Building line, %d - %d", commit, i-2);
|
866
|
+
|
867
|
+
count = i - commit - 2;
|
868
|
+
|
869
|
+
pts = ptarray_construct(
|
870
|
+
TYPE_HASZ(type),
|
871
|
+
TYPE_HASM(type),
|
872
|
+
count);
|
873
|
+
for(j=commit;j<i-2;j++)
|
874
|
+
{
|
875
|
+
getPoint4d_p(points, j, &tmp);
|
876
|
+
setPoint4d(pts, j-commit, &tmp);
|
877
|
+
}
|
878
|
+
|
879
|
+
commit = i-3;
|
880
|
+
geom = append_segment(geom, pts, LINETYPE, SRID);
|
881
|
+
isline = -1;
|
882
|
+
}
|
883
|
+
/* We are tracking a circularstring, keep going */
|
884
|
+
else if(isline == 0)
|
885
|
+
{
|
886
|
+
;
|
887
|
+
}
|
888
|
+
/* We didn't know what we were tracking, now we do */
|
889
|
+
else
|
890
|
+
{
|
891
|
+
LWDEBUG(3, "It's a circularstring");
|
892
|
+
isline = 0;
|
893
|
+
}
|
894
|
+
}
|
895
|
+
}
|
896
|
+
count = i - commit;
|
897
|
+
if(isline == 0 && count > 2)
|
898
|
+
{
|
899
|
+
LWDEBUGF(3, "Finishing circularstring %d,%d.", commit, i);
|
900
|
+
|
901
|
+
pts = ptarray_construct(
|
902
|
+
TYPE_HASZ(type),
|
903
|
+
TYPE_HASM(type),
|
904
|
+
3);
|
905
|
+
getPoint4d_p(points, commit, &tmp);
|
906
|
+
setPoint4d(pts, 0, &tmp);
|
907
|
+
getPoint4d_p(points, commit + count/2, &tmp);
|
908
|
+
setPoint4d(pts, 1, &tmp);
|
909
|
+
getPoint4d_p(points, i - 1, &tmp);
|
910
|
+
setPoint4d(pts, 2, &tmp);
|
911
|
+
|
912
|
+
geom = append_segment(geom, pts, CIRCSTRINGTYPE, SRID);
|
913
|
+
}
|
914
|
+
else
|
915
|
+
{
|
916
|
+
LWDEBUGF(3, "Finishing line %d,%d.", commit, i);
|
917
|
+
|
918
|
+
pts = ptarray_construct(
|
919
|
+
TYPE_HASZ(type),
|
920
|
+
TYPE_HASM(type),
|
921
|
+
count);
|
922
|
+
for(j=commit;j<i;j++)
|
923
|
+
{
|
924
|
+
getPoint4d_p(points, j, &tmp);
|
925
|
+
setPoint4d(pts, j-commit, &tmp);
|
926
|
+
}
|
927
|
+
geom = append_segment(geom, pts, LINETYPE, SRID);
|
928
|
+
}
|
929
|
+
return geom;
|
930
|
+
}
|
931
|
+
|
932
|
+
LWGEOM *
|
933
|
+
lwline_desegmentize(LWLINE *line)
|
934
|
+
{
|
935
|
+
LWDEBUG(2, "lwline_desegmentize called.");
|
936
|
+
|
937
|
+
return pta_desegmentize(line->points, line->type, line->SRID);
|
938
|
+
}
|
939
|
+
|
940
|
+
LWGEOM *
|
941
|
+
lwpolygon_desegmentize(LWPOLY *poly)
|
942
|
+
{
|
943
|
+
LWGEOM **geoms;
|
944
|
+
int i, hascurve = 0;
|
945
|
+
|
946
|
+
LWDEBUG(2, "lwpolygon_desegmentize called.");
|
947
|
+
|
948
|
+
geoms = lwalloc(sizeof(LWGEOM *)*poly->nrings);
|
949
|
+
for(i=0; i<poly->nrings; i++)
|
950
|
+
{
|
951
|
+
geoms[i] = pta_desegmentize(poly->rings[i], poly->type, poly->SRID);
|
952
|
+
if(lwgeom_getType(geoms[i]->type) == CIRCSTRINGTYPE ||
|
953
|
+
lwgeom_getType(geoms[i]->type) == COMPOUNDTYPE)
|
954
|
+
{
|
955
|
+
hascurve = 1;
|
956
|
+
}
|
957
|
+
}
|
958
|
+
if(hascurve == 0)
|
959
|
+
{
|
960
|
+
for(i=0; i<poly->nrings; i++)
|
961
|
+
{
|
962
|
+
lwfree(geoms[i]);
|
963
|
+
}
|
964
|
+
return lwgeom_clone((LWGEOM *)poly);
|
965
|
+
}
|
966
|
+
|
967
|
+
return (LWGEOM *)lwcollection_construct(CURVEPOLYTYPE, poly->SRID, NULL, poly->nrings, geoms);
|
968
|
+
}
|
969
|
+
|
970
|
+
LWGEOM *
|
971
|
+
lwmline_desegmentize(LWMLINE *mline)
|
972
|
+
{
|
973
|
+
LWGEOM **geoms;
|
974
|
+
int i, hascurve = 0;
|
975
|
+
|
976
|
+
LWDEBUG(2, "lwmline_desegmentize called.");
|
977
|
+
|
978
|
+
geoms = lwalloc(sizeof(LWGEOM *)*mline->ngeoms);
|
979
|
+
for(i=0; i<mline->ngeoms; i++)
|
980
|
+
{
|
981
|
+
geoms[i] = lwline_desegmentize((LWLINE *)mline->geoms[i]);
|
982
|
+
if(lwgeom_getType(geoms[i]->type) == CIRCSTRINGTYPE ||
|
983
|
+
lwgeom_getType(geoms[i]->type) == COMPOUNDTYPE)
|
984
|
+
{
|
985
|
+
hascurve = 1;
|
986
|
+
}
|
987
|
+
}
|
988
|
+
if(hascurve == 0)
|
989
|
+
{
|
990
|
+
for(i=0; i<mline->ngeoms; i++)
|
991
|
+
{
|
992
|
+
lwfree(geoms[i]);
|
993
|
+
}
|
994
|
+
return lwgeom_clone((LWGEOM *)mline);
|
995
|
+
}
|
996
|
+
return (LWGEOM *)lwcollection_construct(MULTICURVETYPE, mline->SRID, NULL, mline->ngeoms, geoms);
|
997
|
+
}
|
998
|
+
|
999
|
+
LWGEOM *
|
1000
|
+
lwmpolygon_desegmentize(LWMPOLY *mpoly)
|
1001
|
+
{
|
1002
|
+
LWGEOM **geoms;
|
1003
|
+
int i, hascurve = 0;
|
1004
|
+
|
1005
|
+
LWDEBUG(2, "lwmpoly_desegmentize called.");
|
1006
|
+
|
1007
|
+
geoms = lwalloc(sizeof(LWGEOM *)*mpoly->ngeoms);
|
1008
|
+
for(i=0; i<mpoly->ngeoms; i++)
|
1009
|
+
{
|
1010
|
+
geoms[i] = lwpolygon_desegmentize((LWPOLY *)mpoly->geoms[i]);
|
1011
|
+
if(lwgeom_getType(geoms[i]->type) == CURVEPOLYTYPE)
|
1012
|
+
{
|
1013
|
+
hascurve = 1;
|
1014
|
+
}
|
1015
|
+
}
|
1016
|
+
if(hascurve == 0)
|
1017
|
+
{
|
1018
|
+
for(i=0; i<mpoly->ngeoms; i++)
|
1019
|
+
{
|
1020
|
+
lwfree(geoms[i]);
|
1021
|
+
}
|
1022
|
+
return lwgeom_clone((LWGEOM *)mpoly);
|
1023
|
+
}
|
1024
|
+
return (LWGEOM *)lwcollection_construct(MULTISURFACETYPE, mpoly->SRID, NULL, mpoly->ngeoms, geoms);
|
1025
|
+
}
|
1026
|
+
|
1027
|
+
LWGEOM *
|
1028
|
+
lwgeom_desegmentize(LWGEOM *geom)
|
1029
|
+
{
|
1030
|
+
int type = lwgeom_getType(geom->type);
|
1031
|
+
|
1032
|
+
LWDEBUG(2, "lwgeom_desegmentize called.");
|
1033
|
+
|
1034
|
+
switch(type) {
|
1035
|
+
case LINETYPE:
|
1036
|
+
return lwline_desegmentize((LWLINE *)geom);
|
1037
|
+
case POLYGONTYPE:
|
1038
|
+
return lwpolygon_desegmentize((LWPOLY *)geom);
|
1039
|
+
case MULTILINETYPE:
|
1040
|
+
return lwmline_desegmentize((LWMLINE *)geom);
|
1041
|
+
case MULTIPOLYGONTYPE:
|
1042
|
+
return lwmpolygon_desegmentize((LWMPOLY *)geom);
|
1043
|
+
default:
|
1044
|
+
return lwgeom_clone(geom);
|
1045
|
+
}
|
1046
|
+
}
|
1047
|
+
|