1 | #include "EXTERN.h" |
1 | #include "EXTERN.h" |
2 | #include "perl.h" |
2 | #include "perl.h" |
3 | #include "XSUB.h" |
3 | #include "XSUB.h" |
4 | |
4 | |
|
|
5 | #include <math.h> |
|
|
6 | |
|
|
7 | #include "perlmulticore.h" |
|
|
8 | |
|
|
9 | #if EMBED_CDB |
|
|
10 | #include "cdb-embedded.c" |
|
|
11 | #else |
5 | #include <cdb.h> |
12 | #include <cdb.h> |
|
|
13 | #endif |
|
|
14 | |
|
|
15 | #define TORAD(r) ((r) * (M_PI / 180.)) |
6 | |
16 | |
7 | static struct cdb_make make; |
17 | static struct cdb_make make; |
|
|
18 | |
|
|
19 | struct res |
|
|
20 | { |
|
|
21 | double mind; |
|
|
22 | unsigned int respos, reslen; |
|
|
23 | double x, y; |
|
|
24 | }; |
|
|
25 | |
|
|
26 | static inline int |
|
|
27 | intmin (int a, int b) |
|
|
28 | { |
|
|
29 | return a > b ? b : a; |
|
|
30 | } |
|
|
31 | |
|
|
32 | static inline int |
|
|
33 | intmax (int a, int b) |
|
|
34 | { |
|
|
35 | return a > b ? a : b; |
|
|
36 | } |
|
|
37 | |
|
|
38 | static inline int |
|
|
39 | get_u16 (const U8 *ptr) |
|
|
40 | { |
|
|
41 | return ptr[0] | (ptr[1] << 8); |
|
|
42 | } |
8 | |
43 | |
9 | MODULE = Geo::LatLon2Place PACKAGE = Geo::LatLon2Place |
44 | MODULE = Geo::LatLon2Place PACKAGE = Geo::LatLon2Place |
10 | |
45 | |
11 | PROTOTYPES: ENABLE |
46 | PROTOTYPES: ENABLE |
12 | |
47 | |
13 | int |
48 | SV * |
14 | cdb_make_start (int fd) |
49 | lookup_ext_ (SV *cdb, int km, int boxes, NV lat, NV lon, int r0, int r1, int flags) |
15 | CODE: |
|
|
16 | RETVAL = cdb_make_start (&make, fd); |
|
|
17 | OUTPUT: RETVAL |
|
|
18 | |
|
|
19 | int |
|
|
20 | cdb_make_add (SV *k, SV *v) |
|
|
21 | CODE: |
50 | CODE: |
22 | { |
51 | { |
23 | STRLEN klen; const char *kp = SvPVbyte (k, klen); |
52 | struct cdb *db = (struct cdb *)SvPVX (cdb); |
24 | STRLEN vlen; const char *vp = SvPVbyte (v, vlen); |
53 | |
25 | RETVAL = cdb_make_add (&make, kp, klen, vp, vlen); |
54 | if (!r1) |
|
|
55 | r1 = km; |
|
|
56 | |
|
|
57 | r0 = r0 / km; |
|
|
58 | r1 = (r1 + km - 1) / km; |
|
|
59 | double coslat = cos (TORAD (lat)); |
|
|
60 | int cy = (lat + 90.) * boxes * (1. / 180.); |
|
|
61 | int x, y; |
|
|
62 | |
|
|
63 | if (r1 < r0 || r0 < 0 || r1 < 0 || r0 >= boxes / 2 || r1 >= boxes / 2) |
|
|
64 | XSRETURN_EMPTY; |
|
|
65 | |
|
|
66 | if (lat < -90. || lat > 90. || lon < -180 || lon > 180.) |
|
|
67 | XSRETURN_EMPTY; |
|
|
68 | |
|
|
69 | double mind = 1e99; |
|
|
70 | const U8 *resptr; |
|
|
71 | int reslen = 0; |
|
|
72 | |
|
|
73 | for (y = intmax (0, cy - r1); y <= intmin (boxes - 1, cy + r1); ++y) |
|
|
74 | { |
|
|
75 | double glat = y * (180. / boxes) - 90.; |
|
|
76 | double coslat = cos (TORAD (glat)); |
|
|
77 | int blat = boxes * coslat; /* can be zero */ |
|
|
78 | int cx = (lon + 180.) * blat * (1. / 360.); |
|
|
79 | |
|
|
80 | for (x = cx - r1; x <= cx + r1; ++x) |
|
|
81 | { |
|
|
82 | int rx = x; |
|
|
83 | rx += rx < 0 ? blat : 0; |
|
|
84 | rx -= rx >= blat ? blat : 0; |
|
|
85 | |
|
|
86 | unsigned char key[4]; |
|
|
87 | key[0] = rx; |
|
|
88 | key[1] = rx >> 8; |
|
|
89 | key[2] = y; |
|
|
90 | key[3] = y >> 8; |
|
|
91 | |
|
|
92 | //printf ("x,y %4d,%4d blat %d %d %g %02x%02x%02x%02x %d\n", rx, y, blat, (int)glat, TORAD(glat), key[0],key[1],key[2],key[3], sizeof(key)); |
|
|
93 | |
|
|
94 | if (cdb_find (db, key, sizeof (key)) <= 0) |
|
|
95 | continue; |
|
|
96 | |
|
|
97 | int len = cdb_datalen (db); |
|
|
98 | const U8 *ptr = (const U8 *)cdb_get (db, len, cdb_datapos (db)); |
|
|
99 | |
|
|
100 | while (len > 0) |
|
|
101 | { |
|
|
102 | int datalen = ptr[5]; |
|
|
103 | |
|
|
104 | double plat = get_u16 (ptr + 0) * ( 90. / 32767.); |
|
|
105 | double plon = get_u16 (ptr + 2) * (180. / 32767.); |
|
|
106 | int w = ptr[4]; |
|
|
107 | |
|
|
108 | double dx = TORAD (lon - plon) * coslat; |
|
|
109 | double dy = TORAD (lat - plat); |
|
|
110 | double d2 = (dx * dx + dy * dy) * w; |
|
|
111 | //printf ("%g,%g %g %.*s\n", plat,plon,d2, datalen,ptr+6); |
|
|
112 | |
|
|
113 | if (d2 < mind) |
|
|
114 | { |
|
|
115 | mind = d2; |
|
|
116 | resptr = ptr; |
|
|
117 | reslen = datalen; |
|
|
118 | } |
|
|
119 | |
|
|
120 | len -= datalen + 6; |
|
|
121 | ptr += datalen + 6; |
|
|
122 | } |
|
|
123 | } |
|
|
124 | } |
|
|
125 | |
|
|
126 | if (!reslen) |
|
|
127 | XSRETURN_EMPTY; |
|
|
128 | |
|
|
129 | RETVAL = newSVpvn ((const char *)resptr + 6, reslen); |
26 | } |
130 | } |
27 | OUTPUT: RETVAL |
131 | OUTPUT: RETVAL |
28 | |
132 | |
29 | int |
133 | ############################################################################# |
30 | cdb_make_finish () |
|
|
31 | CODE: |
|
|
32 | RETVAL = cdb_make_finish (&make); |
|
|
33 | OUTPUT: RETVAL |
|
|
34 | |
134 | |
35 | int |
135 | int |
36 | cdb_init (SV *self, int fd) |
136 | cdb_init (SV *self, int fd) |
37 | CODE: |
137 | CODE: |
38 | sv_upgrade (self, SVt_PV); |
138 | sv_upgrade (self, SVt_PV); |
|
|
139 | sv_grow (self, sizeof (struct cdb)); |
39 | SvCUR_set (self, sizeof (struct cdb)); |
140 | SvCUR_set (self, sizeof (struct cdb)); |
40 | SvPOK_only (self); |
141 | SvPOK_only (self); |
41 | RETVAL = cdb_init ((struct cdb *)SvPVX (self), fd); |
142 | RETVAL = cdb_init ((struct cdb *)SvPVX (self), fd); |
42 | OUTPUT: RETVAL |
143 | OUTPUT: RETVAL |
43 | |
144 | |
… | |
… | |
58 | if (cdb_find (db, s, l) <= 0) |
159 | if (cdb_find (db, s, l) <= 0) |
59 | XSRETURN_UNDEF; |
160 | XSRETURN_UNDEF; |
60 | |
161 | |
61 | p = cdb_datapos (db); |
162 | p = cdb_datapos (db); |
62 | l = cdb_datalen (db); |
163 | l = cdb_datalen (db); |
63 | RETVAL = newSVpvn (cdb_get (db, l, p), l); |
164 | RETVAL = newSVpvn ((const char *)cdb_get (db, l, p), l); |
64 | } |
165 | } |
65 | OUTPUT: RETVAL |
166 | OUTPUT: RETVAL |
66 | |
167 | |
|
|
168 | ############################################################################# |
|
|
169 | |
|
|
170 | int |
|
|
171 | cdb_make_start (int fd) |
|
|
172 | CODE: |
|
|
173 | RETVAL = cdb_make_start (&make, fd); |
|
|
174 | OUTPUT: RETVAL |
|
|
175 | |
|
|
176 | int |
|
|
177 | cdb_make_add (SV *k, SV *v) |
|
|
178 | CODE: |
|
|
179 | { |
|
|
180 | STRLEN klen; const char *kp = SvPVbyte (k, klen); |
|
|
181 | STRLEN vlen; const char *vp = SvPVbyte (v, vlen); |
|
|
182 | RETVAL = cdb_make_add (&make, kp, klen, vp, vlen); |
|
|
183 | } |
|
|
184 | OUTPUT: RETVAL |
|
|
185 | |
|
|
186 | int |
|
|
187 | cdb_make_finish () |
|
|
188 | CODE: |
|
|
189 | RETVAL = cdb_make_finish (&make); |
|
|
190 | OUTPUT: RETVAL |
|
|
191 | |