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,52 @@
|
|
|
1
|
+
/**********************************************************************
|
|
2
|
+
* $Id: lwalgorithm.h 3688 2009-02-11 21:48:13Z pramsey $
|
|
3
|
+
*
|
|
4
|
+
* PostGIS - Spatial Types for PostgreSQL
|
|
5
|
+
* http://postgis.refractions.net
|
|
6
|
+
* Copyright 2008 Paul Ramsey
|
|
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 <math.h>
|
|
14
|
+
#include "liblwgeom.h"
|
|
15
|
+
|
|
16
|
+
enum CG_SEGMENT_INTERSECTION_TYPE {
|
|
17
|
+
SEG_ERROR = -1,
|
|
18
|
+
SEG_NO_INTERSECTION = 0,
|
|
19
|
+
SEG_COLINEAR = 1,
|
|
20
|
+
SEG_CROSS_LEFT = 2,
|
|
21
|
+
SEG_CROSS_RIGHT = 3,
|
|
22
|
+
SEG_TOUCH_LEFT = 4,
|
|
23
|
+
SEG_TOUCH_RIGHT = 5
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
double lw_segment_side(POINT2D *p1, POINT2D *p2, POINT2D *q);
|
|
27
|
+
int lw_segment_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2);
|
|
28
|
+
int lw_segment_envelope_intersects(POINT2D p1, POINT2D p2, POINT2D q1, POINT2D q2);
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
enum CG_LINE_CROSS_TYPE {
|
|
32
|
+
LINE_NO_CROSS = 0,
|
|
33
|
+
LINE_CROSS_LEFT = -1,
|
|
34
|
+
LINE_CROSS_RIGHT = 1,
|
|
35
|
+
LINE_MULTICROSS_END_LEFT = -2,
|
|
36
|
+
LINE_MULTICROSS_END_RIGHT = 2,
|
|
37
|
+
LINE_MULTICROSS_END_SAME_FIRST_LEFT = -3,
|
|
38
|
+
LINE_MULTICROSS_END_SAME_FIRST_RIGHT = 3
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
int lwline_crossing_direction(LWLINE *l1, LWLINE *l2);
|
|
42
|
+
|
|
43
|
+
double lwpoint_get_ordinate(const POINT4D *p, int ordinate);
|
|
44
|
+
void lwpoint_set_ordinate(POINT4D *p, int ordinate, double value);
|
|
45
|
+
int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int ndims, int ordinate, double interpolation_value);
|
|
46
|
+
LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double from, double to);
|
|
47
|
+
LWCOLLECTION *lwmline_clip_to_ordinate_range(LWMLINE *mline, int ordinate, double from, double to);
|
|
48
|
+
|
|
49
|
+
int lwgeom_geohash_precision(BOX3D bbox, BOX3D *bounds);
|
|
50
|
+
char *lwgeom_geohash(const LWGEOM *lwgeom, int precision);
|
|
51
|
+
char *geohash_point(double longitude, double latitude, int precision);
|
|
52
|
+
|
|
@@ -0,0 +1,759 @@
|
|
|
1
|
+
/**********************************************************************
|
|
2
|
+
* $Id: lwcircstring.c 3639 2009-02-04 00:28:37Z 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
|
+
/* basic LWCIRCSTRING functions */
|
|
14
|
+
|
|
15
|
+
#include <stdio.h>
|
|
16
|
+
#include <stdlib.h>
|
|
17
|
+
#include <string.h>
|
|
18
|
+
#include <math.h>
|
|
19
|
+
#include "liblwgeom.h"
|
|
20
|
+
|
|
21
|
+
BOX3D *lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3);
|
|
22
|
+
void printLWCIRCSTRING(LWCIRCSTRING *curve);
|
|
23
|
+
void lwcircstring_reverse(LWCIRCSTRING *curve);
|
|
24
|
+
LWCIRCSTRING *lwcircstring_segmentize2d(LWCIRCSTRING *curve, double dist);
|
|
25
|
+
char lwcircstring_same(const LWCIRCSTRING *me, const LWCIRCSTRING *you);
|
|
26
|
+
LWCIRCSTRING *lwcircstring_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points);
|
|
27
|
+
LWCIRCSTRING *lwcircstring_from_lwmpoint(int SRID, LWMPOINT *mpoint);
|
|
28
|
+
LWCIRCSTRING *lwcircstring_addpoint(LWCIRCSTRING *curve, LWPOINT *point, unsigned int where);
|
|
29
|
+
LWCIRCSTRING *lwcircstring_removepoint(LWCIRCSTRING *curve, unsigned int index);
|
|
30
|
+
void lwcircstring_setPoint4d(LWCIRCSTRING *curve, unsigned int index, POINT4D *newpoint);
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
#ifndef MAXFLOAT
|
|
35
|
+
#define MAXFLOAT 3.402823466e+38F
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* Construct a new LWCIRCSTRING. points will *NOT* be copied
|
|
40
|
+
* use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
|
|
41
|
+
*/
|
|
42
|
+
LWCIRCSTRING *
|
|
43
|
+
lwcircstring_construct(int SRID, BOX2DFLOAT4 *bbox, POINTARRAY *points)
|
|
44
|
+
{
|
|
45
|
+
LWCIRCSTRING *result;
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
* The first arc requires three points. Each additional
|
|
49
|
+
* arc requires two more points. Thus the minimum point count
|
|
50
|
+
* is three, and the count must be odd.
|
|
51
|
+
*/
|
|
52
|
+
if(points->npoints % 2 != 1 || points->npoints < 3)
|
|
53
|
+
{
|
|
54
|
+
lwerror("lwcircstring_construct: invalid point count %d", points->npoints);
|
|
55
|
+
return NULL;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
result = (LWCIRCSTRING*) lwalloc(sizeof(LWCIRCSTRING));
|
|
59
|
+
|
|
60
|
+
result->type = lwgeom_makeType_full(
|
|
61
|
+
TYPE_HASZ(points->dims),
|
|
62
|
+
TYPE_HASM(points->dims),
|
|
63
|
+
(SRID!=-1), CIRCSTRINGTYPE, 0);
|
|
64
|
+
result->SRID = SRID;
|
|
65
|
+
result->points = points;
|
|
66
|
+
result->bbox = bbox;
|
|
67
|
+
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/*
|
|
72
|
+
* given the LWGEOM serialized form (or a point into a multi* one)
|
|
73
|
+
* construct a proper LWCIRCSTRING.
|
|
74
|
+
* serialized_form should point to the 8bit type format (with type = 8)
|
|
75
|
+
* See serialized form doc
|
|
76
|
+
*/
|
|
77
|
+
LWCIRCSTRING *
|
|
78
|
+
lwcircstring_deserialize(uchar *serialized_form)
|
|
79
|
+
{
|
|
80
|
+
uchar type;
|
|
81
|
+
LWCIRCSTRING *result;
|
|
82
|
+
uchar *loc=NULL;
|
|
83
|
+
uint32 npoints;
|
|
84
|
+
POINTARRAY *pa;
|
|
85
|
+
|
|
86
|
+
type = (uchar)serialized_form[0];
|
|
87
|
+
if(lwgeom_getType(type) != CIRCSTRINGTYPE)
|
|
88
|
+
{
|
|
89
|
+
lwerror("lwcircstring_deserialize: attempt to deserialize a circularstring which is really a %s", lwgeom_typename(type));
|
|
90
|
+
return NULL;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
result = (LWCIRCSTRING*) lwalloc(sizeof(LWCIRCSTRING));
|
|
94
|
+
result->type = type;
|
|
95
|
+
|
|
96
|
+
loc = serialized_form + 1;
|
|
97
|
+
|
|
98
|
+
if(lwgeom_hasBBOX(type))
|
|
99
|
+
{
|
|
100
|
+
LWDEBUG(3, "lwcircstring_deserialize: input has bbox");
|
|
101
|
+
|
|
102
|
+
result->bbox = lwalloc(sizeof(BOX2DFLOAT4));
|
|
103
|
+
memcpy(result->bbox, loc, sizeof(BOX2DFLOAT4));
|
|
104
|
+
loc += sizeof(BOX2DFLOAT4);
|
|
105
|
+
}
|
|
106
|
+
else
|
|
107
|
+
{
|
|
108
|
+
LWDEBUG(3, "lwcircstring_deserialize: input lacks bbox");
|
|
109
|
+
|
|
110
|
+
result->bbox = NULL;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if(lwgeom_hasSRID(type))
|
|
114
|
+
{
|
|
115
|
+
LWDEBUG(3, "lwcircstring_deserialize: input has srid");
|
|
116
|
+
|
|
117
|
+
result->SRID = lw_get_int32(loc);
|
|
118
|
+
loc += 4; /* type + SRID */
|
|
119
|
+
}
|
|
120
|
+
else
|
|
121
|
+
{
|
|
122
|
+
LWDEBUG(3, "lwcircstring_deserialize: input lacks srid");
|
|
123
|
+
|
|
124
|
+
result->SRID = -1;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/* we've read the type (1 byte) and SRID (4 bytes, if present) */
|
|
128
|
+
|
|
129
|
+
npoints = lw_get_uint32(loc);
|
|
130
|
+
|
|
131
|
+
LWDEBUGF(3, "circstring npoints = %d", npoints);
|
|
132
|
+
|
|
133
|
+
loc += 4;
|
|
134
|
+
pa = pointArray_construct(loc, TYPE_HASZ(type), TYPE_HASM(type), npoints);
|
|
135
|
+
result->points = pa;
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/*
|
|
140
|
+
* convert this circularstring into its serialized form
|
|
141
|
+
* result's first char will be the 8bit type. See serialized form doc
|
|
142
|
+
*/
|
|
143
|
+
uchar *
|
|
144
|
+
lwcircstring_serialize(LWCIRCSTRING *curve)
|
|
145
|
+
{
|
|
146
|
+
size_t size, retsize;
|
|
147
|
+
uchar * result;
|
|
148
|
+
|
|
149
|
+
if(curve == NULL) {
|
|
150
|
+
lwerror("lwcircstring_serialize:: given null curve");
|
|
151
|
+
return NULL;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
size = lwcircstring_serialize_size(curve);
|
|
155
|
+
result = lwalloc(size);
|
|
156
|
+
lwcircstring_serialize_buf(curve, result, &retsize);
|
|
157
|
+
if(retsize != size)
|
|
158
|
+
lwerror("lwcircstring_serialize_size returned %d, ..serialize_buf returned %d", size, retsize);
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/*
|
|
163
|
+
* convert this circularstring into its serialized form writing it into
|
|
164
|
+
* the given buffer, and returning number of bytes written into
|
|
165
|
+
* the given int pointer.
|
|
166
|
+
* result's first char will be the 8bit type. See serialized form doc
|
|
167
|
+
*/
|
|
168
|
+
void lwcircstring_serialize_buf(LWCIRCSTRING *curve, uchar *buf, size_t *retsize)
|
|
169
|
+
{
|
|
170
|
+
char hasSRID;
|
|
171
|
+
uchar *loc;
|
|
172
|
+
int ptsize;
|
|
173
|
+
size_t size;
|
|
174
|
+
|
|
175
|
+
LWDEBUGF(2, "lwcircstring_serialize_buf(%p, %p, %p) called",
|
|
176
|
+
curve, buf, retsize);
|
|
177
|
+
|
|
178
|
+
if(curve == NULL)
|
|
179
|
+
{
|
|
180
|
+
lwerror("lwcircstring_serialize:: given null curve");
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if(TYPE_GETZM(curve->type) != TYPE_GETZM(curve->points->dims))
|
|
185
|
+
{
|
|
186
|
+
lwerror("Dimensions mismatch in lwcircstring");
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
ptsize = pointArray_ptsize(curve->points);
|
|
191
|
+
|
|
192
|
+
hasSRID = (curve->SRID != -1);
|
|
193
|
+
|
|
194
|
+
buf[0] = (uchar)lwgeom_makeType_full(
|
|
195
|
+
TYPE_HASZ(curve->type), TYPE_HASM(curve->type),
|
|
196
|
+
hasSRID, CIRCSTRINGTYPE, curve->bbox ? 1 : 0);
|
|
197
|
+
loc = buf+1;
|
|
198
|
+
|
|
199
|
+
LWDEBUGF(3, "lwcircstring_serialize_buf added type (%d)", curve->type);
|
|
200
|
+
|
|
201
|
+
if(curve->bbox)
|
|
202
|
+
{
|
|
203
|
+
memcpy(loc, curve->bbox, sizeof(BOX2DFLOAT4));
|
|
204
|
+
loc += sizeof(BOX2DFLOAT4);
|
|
205
|
+
|
|
206
|
+
LWDEBUG(3, "lwcircstring_serialize_buf added BBOX");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if(hasSRID)
|
|
210
|
+
{
|
|
211
|
+
memcpy(loc, &curve->SRID, sizeof(int32));
|
|
212
|
+
loc += sizeof(int32);
|
|
213
|
+
|
|
214
|
+
LWDEBUG(3, "lwcircstring_serialize_buf added SRID");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
memcpy(loc, &curve->points->npoints, sizeof(uint32));
|
|
218
|
+
loc += sizeof(uint32);
|
|
219
|
+
|
|
220
|
+
LWDEBUGF(3, "lwcircstring_serialize_buf added npoints (%d)",
|
|
221
|
+
curve->points->npoints);
|
|
222
|
+
|
|
223
|
+
/* copy in points */
|
|
224
|
+
size = curve->points->npoints * ptsize;
|
|
225
|
+
memcpy(loc, getPoint_internal(curve->points, 0), size);
|
|
226
|
+
loc += size;
|
|
227
|
+
|
|
228
|
+
LWDEBUGF(3, "lwcircstring_serialize_buf copied serialized_pointlist (%d bytes)",
|
|
229
|
+
ptsize * curve->points->npoints);
|
|
230
|
+
|
|
231
|
+
if(retsize) *retsize = loc-buf;
|
|
232
|
+
|
|
233
|
+
LWDEBUGF(3, "lwcircstring_serialize_buf returning (loc: %p, size: %d)",
|
|
234
|
+
loc, loc-buf);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/* find length of this deserialized circularstring */
|
|
238
|
+
size_t
|
|
239
|
+
lwcircstring_serialize_size(LWCIRCSTRING *curve)
|
|
240
|
+
{
|
|
241
|
+
size_t size = 1; /* type */
|
|
242
|
+
|
|
243
|
+
LWDEBUG(2, "lwcircstring_serialize_size called");
|
|
244
|
+
|
|
245
|
+
if(curve->SRID != -1) size += 4; /* SRID */
|
|
246
|
+
if(curve->bbox) size += sizeof(BOX2DFLOAT4);
|
|
247
|
+
|
|
248
|
+
size += 4; /* npoints */
|
|
249
|
+
size += pointArray_ptsize(curve->points) * curve->points->npoints;
|
|
250
|
+
|
|
251
|
+
LWDEBUGF(3, "lwcircstring_serialize_size returning %d", size);
|
|
252
|
+
|
|
253
|
+
return size;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
BOX3D *
|
|
257
|
+
lwcircle_compute_box3d(POINT4D *p1, POINT4D *p2, POINT4D *p3)
|
|
258
|
+
{
|
|
259
|
+
double x1, x2, y1, y2, z1, z2;
|
|
260
|
+
double angle, radius, sweep;
|
|
261
|
+
/* angles from center */
|
|
262
|
+
double a1, a2, a3;
|
|
263
|
+
/* angles from center once a1 is rotated to zero */
|
|
264
|
+
double r2, r3;
|
|
265
|
+
double xe = 0.0, ye = 0.0;
|
|
266
|
+
POINT4D *center;
|
|
267
|
+
int i;
|
|
268
|
+
BOX3D *box;
|
|
269
|
+
|
|
270
|
+
LWDEBUG(2, "lwcircle_compute_box3d called.");
|
|
271
|
+
|
|
272
|
+
center = lwalloc(sizeof(POINT4D));
|
|
273
|
+
radius = lwcircle_center(p1, p2, p3, ¢er);
|
|
274
|
+
if(radius < 0.0) return NULL;
|
|
275
|
+
|
|
276
|
+
/*
|
|
277
|
+
top = center->y + radius;
|
|
278
|
+
left = center->x - radius;
|
|
279
|
+
|
|
280
|
+
LWDEBUGF(3, "lwcircle_compute_box3d: center (%.16f, %.16f)", center->x, center->y);
|
|
281
|
+
*/
|
|
282
|
+
|
|
283
|
+
x1 = MAXFLOAT;
|
|
284
|
+
x2 = -1 * MAXFLOAT;
|
|
285
|
+
y1 = MAXFLOAT;
|
|
286
|
+
y2 = -1 * MAXFLOAT;
|
|
287
|
+
|
|
288
|
+
a1 = atan2(p1->y - center->y, p1->x - center->x);
|
|
289
|
+
a2 = atan2(p2->y - center->y, p2->x - center->x);
|
|
290
|
+
a3 = atan2(p3->y - center->y, p3->x - center->x);
|
|
291
|
+
|
|
292
|
+
/* Rotate a2 and a3 such that a1 = 0 */
|
|
293
|
+
r2 = a2 - a1;
|
|
294
|
+
r3 = a3 - a1;
|
|
295
|
+
|
|
296
|
+
/*
|
|
297
|
+
* There are six cases here I'm interested in
|
|
298
|
+
* Clockwise:
|
|
299
|
+
* 1. a1-a2 < 180 == r2 < 0 && (r3 > 0 || r3 < r2)
|
|
300
|
+
* 2. a1-a2 > 180 == r2 > 0 && (r3 > 0 && r3 < r2)
|
|
301
|
+
* 3. a1-a2 > 180 == r2 > 0 && (r3 > r2 || r3 < 0)
|
|
302
|
+
* Counter-clockwise:
|
|
303
|
+
* 4. a1-a2 < 180 == r2 > 0 && (r3 < 0 || r3 > r2)
|
|
304
|
+
* 5. a1-a2 > 180 == r2 < 0 && (r3 < 0 && r3 > r2)
|
|
305
|
+
* 6. a1-a2 > 180 == r2 < 0 && (r3 < r2 || r3 > 0)
|
|
306
|
+
* 3 and 6 are invalid cases where a3 is the midpoint.
|
|
307
|
+
* BBOX is fundamental, so these cannot error out and will instead
|
|
308
|
+
* calculate the sweep using a3 as the middle point.
|
|
309
|
+
*/
|
|
310
|
+
|
|
311
|
+
/* clockwise 1 */
|
|
312
|
+
if(FP_LT(r2, 0) && (FP_GT(r3, 0) || FP_LT(r3, r2)))
|
|
313
|
+
{
|
|
314
|
+
sweep = (FP_GT(r3, 0)) ? (r3 - 2 * M_PI) : r3;
|
|
315
|
+
}
|
|
316
|
+
/* clockwise 2 */
|
|
317
|
+
else if(FP_GT(r2, 0) && FP_GT(r3, 0) && FP_LT(r3, r2))
|
|
318
|
+
{
|
|
319
|
+
sweep = (FP_GT(r3, 0)) ? (r3 - 2 * M_PI) : r3;
|
|
320
|
+
}
|
|
321
|
+
/* counter-clockwise 4 */
|
|
322
|
+
else if(FP_GT(r2, 0) && (FP_LT(r3, 0) || FP_GT(r3, r2)))
|
|
323
|
+
{
|
|
324
|
+
sweep = (FP_LT(r3, 0)) ? (r3 + 2 * M_PI) : r3;
|
|
325
|
+
}
|
|
326
|
+
/* counter-clockwise 5 */
|
|
327
|
+
else if(FP_LT(r2, 0) && FP_LT(r3, 0) && FP_GT(r3, r2))
|
|
328
|
+
{
|
|
329
|
+
sweep = (FP_LT(r3, 0)) ? (r3 + 2 * M_PI) : r3;
|
|
330
|
+
}
|
|
331
|
+
/* clockwise invalid 3 */
|
|
332
|
+
else if(FP_GT(r2, 0) && (FP_GT(r3, r2) || FP_LT(r3, 0)))
|
|
333
|
+
{
|
|
334
|
+
sweep = (FP_GT(r2, 0)) ? (r2 - 2 * M_PI) : r2;
|
|
335
|
+
}
|
|
336
|
+
/* clockwise invalid 6 */
|
|
337
|
+
else
|
|
338
|
+
{
|
|
339
|
+
sweep = (FP_LT(r2, 0)) ? (r2 + 2 * M_PI) : r2;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
LWDEBUGF(3, "a1 %.16f, a2 %.16f, a3 %.16f, sweep %.16f", a1, a2, a3, sweep);
|
|
343
|
+
|
|
344
|
+
angle = 0.0;
|
|
345
|
+
for(i=0; i < 6; i++)
|
|
346
|
+
{
|
|
347
|
+
switch(i) {
|
|
348
|
+
/* right extent */
|
|
349
|
+
case 0:
|
|
350
|
+
angle = 0.0;
|
|
351
|
+
xe = center->x + radius;
|
|
352
|
+
ye = center->y;
|
|
353
|
+
break;
|
|
354
|
+
/* top extent */
|
|
355
|
+
case 1:
|
|
356
|
+
angle = M_PI_2;
|
|
357
|
+
xe = center->x;
|
|
358
|
+
ye = center->y + radius;
|
|
359
|
+
break;
|
|
360
|
+
/* left extent */
|
|
361
|
+
case 2:
|
|
362
|
+
angle = M_PI;
|
|
363
|
+
xe = center->x - radius;
|
|
364
|
+
ye = center->y;
|
|
365
|
+
break;
|
|
366
|
+
/* bottom extent */
|
|
367
|
+
case 3:
|
|
368
|
+
angle = -1 * M_PI_2;
|
|
369
|
+
xe = center->x;
|
|
370
|
+
ye = center->y - radius;
|
|
371
|
+
break;
|
|
372
|
+
/* first point */
|
|
373
|
+
case 4:
|
|
374
|
+
angle = a1;
|
|
375
|
+
xe = p1->x;
|
|
376
|
+
ye = p1->y;
|
|
377
|
+
break;
|
|
378
|
+
/* last point */
|
|
379
|
+
case 5:
|
|
380
|
+
angle = a3;
|
|
381
|
+
xe = p3->x;
|
|
382
|
+
ye = p3->y;
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
/* determine if the extents are outside the arc */
|
|
386
|
+
if(i < 4)
|
|
387
|
+
{
|
|
388
|
+
if(FP_GT(sweep, 0.0))
|
|
389
|
+
{
|
|
390
|
+
if(FP_LT(a3, a1))
|
|
391
|
+
{
|
|
392
|
+
if(FP_GT(angle, (a3 + 2 * M_PI)) || FP_LT(angle, a1)) continue;
|
|
393
|
+
}
|
|
394
|
+
else
|
|
395
|
+
{
|
|
396
|
+
if(FP_GT(angle, a3) || FP_LT(angle, a1)) continue;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
else
|
|
400
|
+
{
|
|
401
|
+
if(FP_GT(a3, a1))
|
|
402
|
+
{
|
|
403
|
+
if(FP_LT(angle, (a3 - 2 * M_PI)) || FP_GT(angle, a1)) continue;
|
|
404
|
+
}
|
|
405
|
+
else
|
|
406
|
+
{
|
|
407
|
+
if(FP_LT(angle, a3) || FP_GT(angle, a1)) continue;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
LWDEBUGF(3, "lwcircle_compute_box3d: potential extreame %d (%.16f, %.16f)", i, xe, ye);
|
|
413
|
+
|
|
414
|
+
x1 = (FP_LT(x1, xe)) ? x1 : xe;
|
|
415
|
+
y1 = (FP_LT(y1, ye)) ? y1 : ye;
|
|
416
|
+
x2 = (FP_GT(x2, xe)) ? x2 : xe;
|
|
417
|
+
y2 = (FP_GT(y2, ye)) ? y2 : ye;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
LWDEBUGF(3, "lwcircle_compute_box3d: extreames found (%.16f %.16f, %.16f %.16f)", x1, y1, x2, y2);
|
|
421
|
+
|
|
422
|
+
/*
|
|
423
|
+
x1 = center->x + x1 * radius;
|
|
424
|
+
x2 = center->x + x2 * radius;
|
|
425
|
+
y1 = center->y + y1 * radius;
|
|
426
|
+
y2 = center->y + y2 * radius;
|
|
427
|
+
*/
|
|
428
|
+
z1 = (FP_LT(p1->z, p2->z)) ? p1->z : p2->z;
|
|
429
|
+
z1 = (FP_LT(z1, p3->z)) ? z1 : p3->z;
|
|
430
|
+
z2 = (FP_GT(p1->z, p2->z)) ? p1->z : p2->z;
|
|
431
|
+
z2 = (FP_GT(z2, p3->z)) ? z2 : p3->z;
|
|
432
|
+
|
|
433
|
+
box = lwalloc(sizeof(BOX3D));
|
|
434
|
+
box->xmin = x1; box->xmax = x2;
|
|
435
|
+
box->ymin = y1; box->ymax = y2;
|
|
436
|
+
box->zmin = z1; box->zmax = z2;
|
|
437
|
+
|
|
438
|
+
lwfree(center);
|
|
439
|
+
|
|
440
|
+
return box;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/*
|
|
444
|
+
* Find bounding box (standard one)
|
|
445
|
+
* zmin=zmax=NO_Z_VALUE if 2d
|
|
446
|
+
* TODO: This ignores curvature, which should be taken into account.
|
|
447
|
+
*/
|
|
448
|
+
BOX3D *
|
|
449
|
+
lwcircstring_compute_box3d(LWCIRCSTRING *curve)
|
|
450
|
+
{
|
|
451
|
+
BOX3D *box, *tmp;
|
|
452
|
+
int i;
|
|
453
|
+
POINT4D *p1 = lwalloc(sizeof(POINT4D));
|
|
454
|
+
POINT4D *p2 = lwalloc(sizeof(POINT4D));
|
|
455
|
+
POINT4D *p3 = lwalloc(sizeof(POINT4D));
|
|
456
|
+
|
|
457
|
+
LWDEBUG(2, "lwcircstring_compute_box3d called.");
|
|
458
|
+
|
|
459
|
+
/* initialize box values */
|
|
460
|
+
box = lwalloc(sizeof(BOX3D));
|
|
461
|
+
box->xmin = MAXFLOAT; box->xmax = -1 * MAXFLOAT;
|
|
462
|
+
box->ymin = MAXFLOAT; box->ymax = -1 * MAXFLOAT;
|
|
463
|
+
box->zmin = MAXFLOAT; box->zmax = -1 * MAXFLOAT;
|
|
464
|
+
|
|
465
|
+
for(i = 2; i < curve->points->npoints; i+=2)
|
|
466
|
+
{
|
|
467
|
+
getPoint4d_p(curve->points, i-2, p1);
|
|
468
|
+
getPoint4d_p(curve->points, i-1, p2);
|
|
469
|
+
getPoint4d_p(curve->points, i, p3);
|
|
470
|
+
tmp = lwcircle_compute_box3d(p1, p2, p3);
|
|
471
|
+
if(tmp == NULL) continue;
|
|
472
|
+
box->xmin = (box->xmin < tmp->xmin) ? box->xmin : tmp->xmin;
|
|
473
|
+
box->xmax = (box->xmax > tmp->xmax) ? box->xmax : tmp->xmax;
|
|
474
|
+
box->ymin = (box->ymin < tmp->ymin) ? box->ymin : tmp->ymin;
|
|
475
|
+
box->ymax = (box->ymax > tmp->ymax) ? box->ymax : tmp->ymax;
|
|
476
|
+
box->zmin = (box->zmin < tmp->zmin) ? box->zmin : tmp->zmin;
|
|
477
|
+
box->zmax = (box->zmax > tmp->zmax) ? box->zmax : tmp->zmax;
|
|
478
|
+
|
|
479
|
+
LWDEBUGF(4, "circularstring %d x=(%.16f,%.16f) y=(%.16f,%.16f) z=(%.16f,%.16f)", i/2, box->xmin, box->xmax, box->ymin, box->ymax, box->zmin, box->zmax);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
return box;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
int
|
|
487
|
+
lwcircstring_compute_box2d_p(LWCIRCSTRING *curve, BOX2DFLOAT4 *result)
|
|
488
|
+
{
|
|
489
|
+
BOX3D *box = lwcircstring_compute_box3d(curve);
|
|
490
|
+
LWDEBUG(2, "lwcircstring_compute_box2d_p called.");
|
|
491
|
+
|
|
492
|
+
if(box == NULL) return 0;
|
|
493
|
+
box3d_to_box2df_p(box, result);
|
|
494
|
+
return 1;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
void lwcircstring_free(LWCIRCSTRING *curve)
|
|
498
|
+
{
|
|
499
|
+
lwfree(curve->points);
|
|
500
|
+
lwfree(curve);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/* find length of this serialized curve */
|
|
504
|
+
size_t
|
|
505
|
+
lwgeom_size_circstring(const uchar *serialized_curve)
|
|
506
|
+
{
|
|
507
|
+
int type = (uchar)serialized_curve[0];
|
|
508
|
+
uint32 result = 1; /* type */
|
|
509
|
+
const uchar *loc;
|
|
510
|
+
uint32 npoints;
|
|
511
|
+
|
|
512
|
+
LWDEBUG(2, "lwgeom_size_circstring called");
|
|
513
|
+
|
|
514
|
+
if(lwgeom_getType(type) != CIRCSTRINGTYPE)
|
|
515
|
+
lwerror("lwgeom_size_circstring::attempt to find the length of a non-circularstring");
|
|
516
|
+
|
|
517
|
+
loc = serialized_curve + 1;
|
|
518
|
+
if(lwgeom_hasBBOX(type))
|
|
519
|
+
{
|
|
520
|
+
loc += sizeof(BOX2DFLOAT4);
|
|
521
|
+
result += sizeof(BOX2DFLOAT4);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if(lwgeom_hasSRID(type))
|
|
525
|
+
{
|
|
526
|
+
loc += 4; /* type + SRID */
|
|
527
|
+
result += 4;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/* we've read the type (1 byte) and SRID (4 bytes, if present) */
|
|
531
|
+
npoints = lw_get_uint32(loc);
|
|
532
|
+
result += sizeof(uint32); /* npoints */
|
|
533
|
+
|
|
534
|
+
result += TYPE_NDIMS(type) * sizeof(double) * npoints;
|
|
535
|
+
|
|
536
|
+
LWDEBUGF(3, "lwgeom_size_circstring returning %d", result);
|
|
537
|
+
|
|
538
|
+
return result;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
void printLWCIRCSTRING(LWCIRCSTRING *curve)
|
|
542
|
+
{
|
|
543
|
+
lwnotice("LWCIRCSTRING {");
|
|
544
|
+
lwnotice(" ndims = %i", (int)TYPE_NDIMS(curve->type));
|
|
545
|
+
lwnotice(" SRID = %i", (int)curve->SRID);
|
|
546
|
+
printPA(curve->points);
|
|
547
|
+
lwnotice("}");
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/* Clone LWCIRCSTRING object. POINTARRAY is not copied. */
|
|
551
|
+
LWCIRCSTRING *
|
|
552
|
+
lwcircstring_clone(const LWCIRCSTRING *g)
|
|
553
|
+
{
|
|
554
|
+
LWCIRCSTRING *ret = lwalloc(sizeof(LWCIRCSTRING));
|
|
555
|
+
memcpy(ret, g, sizeof(LWCIRCSTRING));
|
|
556
|
+
if(g->bbox) ret->bbox = box2d_clone(g->bbox);
|
|
557
|
+
return ret;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/*
|
|
561
|
+
* Add 'what' to this curve at position 'where'.
|
|
562
|
+
* where=0 == prepend
|
|
563
|
+
* where=-1 == append
|
|
564
|
+
* Returns a MULTICURVE or a GEOMETRYCOLLECTION
|
|
565
|
+
*/
|
|
566
|
+
LWGEOM *
|
|
567
|
+
lwcircstring_add(const LWCIRCSTRING *to, uint32 where, const LWGEOM *what)
|
|
568
|
+
{
|
|
569
|
+
LWCOLLECTION *col;
|
|
570
|
+
LWGEOM **geoms;
|
|
571
|
+
int newtype;
|
|
572
|
+
|
|
573
|
+
if(where != -1 && where != 0)
|
|
574
|
+
{
|
|
575
|
+
lwerror("lwcurve_add only supports 0 or -1 as second argument %d", where);
|
|
576
|
+
return NULL;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/* dimensions compatibility are checked by caller */
|
|
580
|
+
|
|
581
|
+
/* Construct geoms array */
|
|
582
|
+
geoms = lwalloc(sizeof(LWGEOM *)*2);
|
|
583
|
+
if(where == -1) /* append */
|
|
584
|
+
{
|
|
585
|
+
geoms[0] = lwgeom_clone((LWGEOM *)to);
|
|
586
|
+
geoms[1] = lwgeom_clone(what);
|
|
587
|
+
}
|
|
588
|
+
else /* prepend */
|
|
589
|
+
{
|
|
590
|
+
geoms[0] = lwgeom_clone(what);
|
|
591
|
+
geoms[1] = lwgeom_clone((LWGEOM *)to);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/* reset SRID and wantbbox flag from component types */
|
|
595
|
+
geoms[0]->SRID = geoms[1]->SRID = -1;
|
|
596
|
+
TYPE_SETHASSRID(geoms[0]->type, 0);
|
|
597
|
+
TYPE_SETHASSRID(geoms[1]->type, 0);
|
|
598
|
+
TYPE_SETHASBBOX(geoms[0]->type, 0);
|
|
599
|
+
TYPE_SETHASBBOX(geoms[1]->type, 0);
|
|
600
|
+
|
|
601
|
+
/* Find appropriate geom type */
|
|
602
|
+
if(TYPE_GETTYPE(what->type) == CIRCSTRINGTYPE || TYPE_GETTYPE(what->type) == LINETYPE) newtype = MULTICURVETYPE;
|
|
603
|
+
else newtype = COLLECTIONTYPE;
|
|
604
|
+
|
|
605
|
+
col = lwcollection_construct(newtype,
|
|
606
|
+
to->SRID, NULL,
|
|
607
|
+
2, geoms);
|
|
608
|
+
|
|
609
|
+
return (LWGEOM *)col;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
void lwcircstring_reverse(LWCIRCSTRING *curve)
|
|
613
|
+
{
|
|
614
|
+
ptarray_reverse(curve->points);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/*
|
|
618
|
+
* TODO: Invalid segmentization. This should accomodate the curvature.
|
|
619
|
+
*/
|
|
620
|
+
LWCIRCSTRING *
|
|
621
|
+
lwcircstring_segmentize2d(LWCIRCSTRING *curve, double dist)
|
|
622
|
+
{
|
|
623
|
+
return lwcircstring_construct(curve->SRID, NULL,
|
|
624
|
+
ptarray_segmentize2d(curve->points, dist));
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/* check coordinate equality */
|
|
628
|
+
char
|
|
629
|
+
lwcircstring_same(const LWCIRCSTRING *me, const LWCIRCSTRING *you)
|
|
630
|
+
{
|
|
631
|
+
return ptarray_same(me->points, you->points);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/*
|
|
635
|
+
* Construct a LWCIRCSTRING from an array of LWPOINTs
|
|
636
|
+
* LWCIRCSTRING dimensions are large enough to host all input dimensions.
|
|
637
|
+
*/
|
|
638
|
+
LWCIRCSTRING *
|
|
639
|
+
lwcircstring_from_lwpointarray(int SRID, unsigned int npoints, LWPOINT **points)
|
|
640
|
+
{
|
|
641
|
+
int zmflag=0;
|
|
642
|
+
unsigned int i;
|
|
643
|
+
POINTARRAY *pa;
|
|
644
|
+
uchar *newpoints, *ptr;
|
|
645
|
+
size_t ptsize, size;
|
|
646
|
+
|
|
647
|
+
/*
|
|
648
|
+
* Find output dimensions, check integrity
|
|
649
|
+
*/
|
|
650
|
+
for(i = 0; i < npoints; i++)
|
|
651
|
+
{
|
|
652
|
+
if(TYPE_GETTYPE(points[i]->type) != POINTTYPE)
|
|
653
|
+
{
|
|
654
|
+
lwerror("lwcurve_from_lwpointarray: invalid input type: %s",
|
|
655
|
+
lwgeom_typename(TYPE_GETTYPE(points[i]->type)));
|
|
656
|
+
return NULL;
|
|
657
|
+
}
|
|
658
|
+
if(TYPE_HASZ(points[i]->type)) zmflag |= 2;
|
|
659
|
+
if(TYPE_HASM(points[i]->type)) zmflag |=1;
|
|
660
|
+
if(zmflag == 3) break;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
if(zmflag == 0) ptsize = 2 * sizeof(double);
|
|
664
|
+
else if(zmflag == 3) ptsize = 4 * sizeof(double);
|
|
665
|
+
else ptsize = 3 * sizeof(double);
|
|
666
|
+
|
|
667
|
+
/*
|
|
668
|
+
* Allocate output points array
|
|
669
|
+
*/
|
|
670
|
+
size = ptsize * npoints;
|
|
671
|
+
newpoints = lwalloc(size);
|
|
672
|
+
memset(newpoints, 0, size);
|
|
673
|
+
|
|
674
|
+
ptr = newpoints;
|
|
675
|
+
for(i = 0; i < npoints; i++)
|
|
676
|
+
{
|
|
677
|
+
size = pointArray_ptsize(points[i]->point);
|
|
678
|
+
memcpy(ptr, getPoint_internal(points[i]->point, 0), size);
|
|
679
|
+
ptr += ptsize;
|
|
680
|
+
}
|
|
681
|
+
pa = pointArray_construct(newpoints, zmflag&2, zmflag&1, npoints);
|
|
682
|
+
|
|
683
|
+
return lwcircstring_construct(SRID, NULL, pa);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
/*
|
|
687
|
+
* Construct a LWCIRCSTRING from a LWMPOINT
|
|
688
|
+
*/
|
|
689
|
+
LWCIRCSTRING *
|
|
690
|
+
lwcircstring_from_lwmpoint(int SRID, LWMPOINT *mpoint)
|
|
691
|
+
{
|
|
692
|
+
unsigned int i;
|
|
693
|
+
POINTARRAY *pa;
|
|
694
|
+
char zmflag = TYPE_GETZM(mpoint->type);
|
|
695
|
+
size_t ptsize, size;
|
|
696
|
+
uchar *newpoints, *ptr;
|
|
697
|
+
|
|
698
|
+
if(zmflag == 0) ptsize = 2 * sizeof(double);
|
|
699
|
+
else if(zmflag == 3) ptsize = 4 * sizeof(double);
|
|
700
|
+
else ptsize = 3 * sizeof(double);
|
|
701
|
+
|
|
702
|
+
/* Allocate space for output points */
|
|
703
|
+
size = ptsize * mpoint->ngeoms;
|
|
704
|
+
newpoints = lwalloc(size);
|
|
705
|
+
memset(newpoints, 0, size);
|
|
706
|
+
|
|
707
|
+
ptr = newpoints;
|
|
708
|
+
for(i = 0; i < mpoint->ngeoms; i++)
|
|
709
|
+
{
|
|
710
|
+
memcpy(ptr,
|
|
711
|
+
getPoint_internal(mpoint->geoms[i]->point, 0),
|
|
712
|
+
ptsize);
|
|
713
|
+
ptr += ptsize;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
pa = pointArray_construct(newpoints, zmflag&2, zmflag&1,
|
|
717
|
+
mpoint->ngeoms);
|
|
718
|
+
|
|
719
|
+
LWDEBUGF(3, "lwcurve_from_lwmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
|
|
720
|
+
|
|
721
|
+
return lwcircstring_construct(SRID, NULL, pa);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
LWCIRCSTRING *
|
|
725
|
+
lwcircstring_addpoint(LWCIRCSTRING *curve, LWPOINT *point, unsigned int where)
|
|
726
|
+
{
|
|
727
|
+
POINTARRAY *newpa;
|
|
728
|
+
LWCIRCSTRING *ret;
|
|
729
|
+
|
|
730
|
+
newpa = ptarray_addPoint(curve->points,
|
|
731
|
+
getPoint_internal(point->point, 0),
|
|
732
|
+
TYPE_NDIMS(point->type), where);
|
|
733
|
+
ret = lwcircstring_construct(curve->SRID, NULL, newpa);
|
|
734
|
+
|
|
735
|
+
return ret;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
LWCIRCSTRING *
|
|
739
|
+
lwcircstring_removepoint(LWCIRCSTRING *curve, unsigned int index)
|
|
740
|
+
{
|
|
741
|
+
POINTARRAY *newpa;
|
|
742
|
+
LWCIRCSTRING *ret;
|
|
743
|
+
|
|
744
|
+
newpa = ptarray_removePoint(curve->points, index);
|
|
745
|
+
ret = lwcircstring_construct(curve->SRID, NULL, newpa);
|
|
746
|
+
|
|
747
|
+
return ret;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/*
|
|
751
|
+
* Note: input will be changed, make sure you have permissions for this.
|
|
752
|
+
* */
|
|
753
|
+
void
|
|
754
|
+
lwcircstring_setPoint4d(LWCIRCSTRING *curve, unsigned int index, POINT4D *newpoint)
|
|
755
|
+
{
|
|
756
|
+
setPoint4d(curve->points, index, newpoint);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
|