geo_coder 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|