geo_coder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. data/Gemfile +12 -0
  2. data/Gemfile.lock +32 -0
  3. data/History.txt +6 -0
  4. data/Makefile +13 -0
  5. data/Manifest.txt +18 -0
  6. data/README.rdoc +197 -0
  7. data/Rakefile +53 -0
  8. data/TODO.txt +8 -0
  9. data/VERSION +1 -0
  10. data/bin/build_indexes +8 -0
  11. data/bin/rebuild_cluster +22 -0
  12. data/bin/rebuild_metaphones +23 -0
  13. data/bin/tiger_import +59 -0
  14. data/demos/demo/app/ext/geocodewrap.rb +84 -0
  15. data/demos/demo/app/views/index.builder +13 -0
  16. data/demos/demo/app/views/index.erb +71 -0
  17. data/demos/demo/config.ru +12 -0
  18. data/demos/demo/config/bootstraps.rb +130 -0
  19. data/demos/demo/config/geoenvironment.rb +25 -0
  20. data/demos/demo/geocoder_helper.rb +12 -0
  21. data/demos/demo/geocom_geocode.rb +10 -0
  22. data/demos/demo/main.rb +3 -0
  23. data/demos/demo/rakefile.rb +17 -0
  24. data/demos/demo/tmp/restart.txt +0 -0
  25. data/demos/simpledemo/views/index.builder +13 -0
  26. data/demos/simpledemo/views/index.erb +69 -0
  27. data/demos/simpledemo/ws.rb +83 -0
  28. data/doc/Makefile +7 -0
  29. data/doc/html4css1.css +279 -0
  30. data/doc/lookup.rst +193 -0
  31. data/doc/parsing.rst +125 -0
  32. data/doc/voidspace.css +147 -0
  33. data/geo_coder.gemspec +172 -0
  34. data/lib/geocoder/us.rb +21 -0
  35. data/lib/geocoder/us/address.rb +290 -0
  36. data/lib/geocoder/us/constants.rb +670 -0
  37. data/lib/geocoder/us/database.rb +745 -0
  38. data/lib/geocoder/us/import.rb +181 -0
  39. data/lib/geocoder/us/import/tiger.rb +13 -0
  40. data/lib/geocoder/us/numbers.rb +58 -0
  41. data/navteq/README +4 -0
  42. data/navteq/convert.sql +37 -0
  43. data/navteq/navteq_import +39 -0
  44. data/navteq/prepare.sql +92 -0
  45. data/sql/cluster.sql +16 -0
  46. data/sql/convert.sql +80 -0
  47. data/sql/create.sql +37 -0
  48. data/sql/index.sql +12 -0
  49. data/sql/place.csv +104944 -0
  50. data/sql/place.sql +104948 -0
  51. data/sql/setup.sql +78 -0
  52. data/src/Makefile +13 -0
  53. data/src/README +14 -0
  54. data/src/liblwgeom/Makefile +75 -0
  55. data/src/liblwgeom/box2d.c +54 -0
  56. data/src/liblwgeom/lex.yy.c +4799 -0
  57. data/src/liblwgeom/liblwgeom.h +1405 -0
  58. data/src/liblwgeom/lwalgorithm.c +946 -0
  59. data/src/liblwgeom/lwalgorithm.h +52 -0
  60. data/src/liblwgeom/lwcircstring.c +759 -0
  61. data/src/liblwgeom/lwcollection.c +541 -0
  62. data/src/liblwgeom/lwcompound.c +118 -0
  63. data/src/liblwgeom/lwcurvepoly.c +86 -0
  64. data/src/liblwgeom/lwgeom.c +886 -0
  65. data/src/liblwgeom/lwgeom_api.c +2201 -0
  66. data/src/liblwgeom/lwgparse.c +1219 -0
  67. data/src/liblwgeom/lwgunparse.c +1054 -0
  68. data/src/liblwgeom/lwline.c +525 -0
  69. data/src/liblwgeom/lwmcurve.c +125 -0
  70. data/src/liblwgeom/lwmline.c +137 -0
  71. data/src/liblwgeom/lwmpoint.c +138 -0
  72. data/src/liblwgeom/lwmpoly.c +141 -0
  73. data/src/liblwgeom/lwmsurface.c +129 -0
  74. data/src/liblwgeom/lwpoint.c +439 -0
  75. data/src/liblwgeom/lwpoly.c +579 -0
  76. data/src/liblwgeom/lwsegmentize.c +1047 -0
  77. data/src/liblwgeom/lwutil.c +369 -0
  78. data/src/liblwgeom/measures.c +861 -0
  79. data/src/liblwgeom/postgis_config.h +93 -0
  80. data/src/liblwgeom/ptarray.c +847 -0
  81. data/src/liblwgeom/vsprintf.c +179 -0
  82. data/src/liblwgeom/wktparse.h +126 -0
  83. data/src/liblwgeom/wktparse.lex +74 -0
  84. data/src/liblwgeom/wktparse.tab.c +2353 -0
  85. data/src/liblwgeom/wktparse.tab.h +145 -0
  86. data/src/liblwgeom/wktparse.y +385 -0
  87. data/src/libsqlite3_geocoder/Makefile +22 -0
  88. data/src/libsqlite3_geocoder/Makefile.nix +15 -0
  89. data/src/libsqlite3_geocoder/Makefile.redhat +15 -0
  90. data/src/libsqlite3_geocoder/extension.c +121 -0
  91. data/src/libsqlite3_geocoder/extension.h +13 -0
  92. data/src/libsqlite3_geocoder/levenshtein.c +42 -0
  93. data/src/libsqlite3_geocoder/metaphon.c +278 -0
  94. data/src/libsqlite3_geocoder/util.c +37 -0
  95. data/src/libsqlite3_geocoder/wkb_compress.c +54 -0
  96. data/src/metaphone/Makefile +7 -0
  97. data/src/metaphone/README +49 -0
  98. data/src/metaphone/extension.c +37 -0
  99. data/src/metaphone/metaphon.c +251 -0
  100. data/src/shp2sqlite/Makefile +37 -0
  101. data/src/shp2sqlite/Makefile.nix +36 -0
  102. data/src/shp2sqlite/Makefile.redhat +35 -0
  103. data/src/shp2sqlite/dbfopen.c +1595 -0
  104. data/src/shp2sqlite/getopt.c +695 -0
  105. data/src/shp2sqlite/getopt.h +127 -0
  106. data/src/shp2sqlite/shapefil.h +500 -0
  107. data/src/shp2sqlite/shp2sqlite.c +1974 -0
  108. data/src/shp2sqlite/shpopen.c +1894 -0
  109. data/tests/address.rb +236 -0
  110. data/tests/benchmark.rb +20 -0
  111. data/tests/constants.rb +57 -0
  112. data/tests/data/address-sample.csv +52 -0
  113. data/tests/data/db-test.csv +57 -0
  114. data/tests/data/locations.csv +4 -0
  115. data/tests/database.rb +137 -0
  116. data/tests/generate.rb +34 -0
  117. data/tests/numbers.rb +46 -0
  118. data/tests/run.rb +11 -0
  119. 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, &center);
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
+