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