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 <cdb.h> |
5 | #include <math.h> |
6 | |
6 | |
7 | #include "perlmulticore.h" |
7 | #include "perlmulticore.h" |
8 | |
8 | |
|
|
9 | #if EMBED_CDB |
|
|
10 | #include "cdb-embedded.c" |
|
|
11 | #else |
|
|
12 | #include <cdb.h> |
|
|
13 | #endif |
|
|
14 | |
|
|
15 | #define TORAD(r) ((r) * (M_PI / 180.)) |
|
|
16 | |
9 | 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 | } |
10 | |
43 | |
11 | MODULE = Geo::LatLon2Place PACKAGE = Geo::LatLon2Place |
44 | MODULE = Geo::LatLon2Place PACKAGE = Geo::LatLon2Place |
12 | |
45 | |
13 | PROTOTYPES: ENABLE |
46 | PROTOTYPES: ENABLE |
14 | |
47 | |
15 | int |
48 | SV * |
16 | cdb_make_start (int fd) |
49 | lookup_ext_ (SV *cdb, int km, int boxes, NV lat, NV lon, int r0, int r1, int flags) |
17 | CODE: |
|
|
18 | RETVAL = cdb_make_start (&make, fd); |
|
|
19 | OUTPUT: RETVAL |
|
|
20 | |
|
|
21 | int |
|
|
22 | cdb_make_add (SV *k, SV *v) |
|
|
23 | CODE: |
50 | CODE: |
24 | { |
51 | { |
25 | STRLEN klen; const char *kp = SvPVbyte (k, klen); |
52 | struct cdb *db = (struct cdb *)SvPVX (cdb); |
26 | STRLEN vlen; const char *vp = SvPVbyte (v, vlen); |
53 | |
27 | 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 | rx, rx >> 8, |
|
|
88 | y, y >> 8, |
|
|
89 | }; |
|
|
90 | |
|
|
91 | //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)); |
|
|
92 | |
|
|
93 | if (cdb_find (db, key, sizeof (key)) <= 0) |
|
|
94 | continue; |
|
|
95 | |
|
|
96 | int len = cdb_datalen (db); |
|
|
97 | const U8 *ptr = cdb_get (db, len, cdb_datapos (db)); |
|
|
98 | |
|
|
99 | while (len > 0) |
|
|
100 | { |
|
|
101 | int datalen = ptr[5]; |
|
|
102 | |
|
|
103 | double plat = get_u16 (ptr + 0) * ( 90. / 32767.); |
|
|
104 | double plon = get_u16 (ptr + 2) * (180. / 32767.); |
|
|
105 | int w = ptr[4]; |
|
|
106 | |
|
|
107 | double dx = TORAD (lon - plon) * coslat; |
|
|
108 | double dy = TORAD (lat - plat); |
|
|
109 | double d2 = (dx * dx + dy * dy) * w; |
|
|
110 | //printf ("%g,%g %g %.*s\n", plat,plon,d2, datalen,ptr+6); |
|
|
111 | |
|
|
112 | if (d2 < mind) |
|
|
113 | { |
|
|
114 | mind = d2; |
|
|
115 | resptr = ptr; |
|
|
116 | reslen = datalen; |
|
|
117 | } |
|
|
118 | |
|
|
119 | len -= datalen + 6; |
|
|
120 | ptr += datalen + 6; |
|
|
121 | } |
|
|
122 | } |
|
|
123 | } |
|
|
124 | |
|
|
125 | if (!reslen) |
|
|
126 | XSRETURN_EMPTY; |
|
|
127 | |
|
|
128 | RETVAL = newSVpvn (resptr + 6, reslen); |
28 | } |
129 | } |
29 | OUTPUT: RETVAL |
130 | OUTPUT: RETVAL |
30 | |
131 | |
31 | int |
132 | ############################################################################# |
32 | cdb_make_finish () |
|
|
33 | CODE: |
|
|
34 | RETVAL = cdb_make_finish (&make); |
|
|
35 | OUTPUT: RETVAL |
|
|
36 | |
133 | |
37 | int |
134 | int |
38 | cdb_init (SV *self, int fd) |
135 | cdb_init (SV *self, int fd) |
39 | CODE: |
136 | CODE: |
40 | sv_upgrade (self, SVt_PV); |
137 | sv_upgrade (self, SVt_PV); |
|
|
138 | sv_grow (self, sizeof (struct cdb)); |
41 | SvCUR_set (self, sizeof (struct cdb)); |
139 | SvCUR_set (self, sizeof (struct cdb)); |
42 | SvPOK_only (self); |
140 | SvPOK_only (self); |
43 | RETVAL = cdb_init ((struct cdb *)SvPVX (self), fd); |
141 | RETVAL = cdb_init ((struct cdb *)SvPVX (self), fd); |
44 | OUTPUT: RETVAL |
142 | OUTPUT: RETVAL |
45 | |
143 | |
… | |
… | |
64 | l = cdb_datalen (db); |
162 | l = cdb_datalen (db); |
65 | RETVAL = newSVpvn (cdb_get (db, l, p), l); |
163 | RETVAL = newSVpvn (cdb_get (db, l, p), l); |
66 | } |
164 | } |
67 | OUTPUT: RETVAL |
165 | OUTPUT: RETVAL |
68 | |
166 | |
|
|
167 | ############################################################################# |
|
|
168 | |
|
|
169 | int |
|
|
170 | cdb_make_start (int fd) |
|
|
171 | CODE: |
|
|
172 | RETVAL = cdb_make_start (&make, fd); |
|
|
173 | OUTPUT: RETVAL |
|
|
174 | |
|
|
175 | int |
|
|
176 | cdb_make_add (SV *k, SV *v) |
|
|
177 | CODE: |
|
|
178 | { |
|
|
179 | STRLEN klen; const char *kp = SvPVbyte (k, klen); |
|
|
180 | STRLEN vlen; const char *vp = SvPVbyte (v, vlen); |
|
|
181 | RETVAL = cdb_make_add (&make, kp, klen, vp, vlen); |
|
|
182 | } |
|
|
183 | OUTPUT: RETVAL |
|
|
184 | |
|
|
185 | int |
|
|
186 | cdb_make_finish () |
|
|
187 | CODE: |
|
|
188 | RETVAL = cdb_make_finish (&make); |
|
|
189 | OUTPUT: RETVAL |
|
|
190 | |