ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Geo-LatLon2Place/LatLon2Place.xs
Revision: 1.6
Committed: Thu Mar 17 22:55:34 2022 UTC (2 years, 1 month ago) by root
Branch: MAIN
CVS Tags: rel-1_0, HEAD
Changes since 1.5: +8 -7 lines
Log Message:
convert to c++

File Contents

# User Rev Content
1 root 1.1 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5 root 1.4 #include <math.h>
6    
7 root 1.3 #include "perlmulticore.h"
8 root 1.1
9 root 1.3 #if EMBED_CDB
10     #include "cdb-embedded.c"
11     #else
12     #include <cdb.h>
13     #endif
14 root 1.2
15 root 1.4 #define TORAD(r) ((r) * (M_PI / 180.))
16    
17 root 1.1 static struct cdb_make make;
18    
19 root 1.4 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 root 1.5 static inline int
39     get_u16 (const U8 *ptr)
40     {
41     return ptr[0] | (ptr[1] << 8);
42     }
43    
44 root 1.1 MODULE = Geo::LatLon2Place PACKAGE = Geo::LatLon2Place
45    
46     PROTOTYPES: ENABLE
47    
48 root 1.4 SV *
49     lookup_ext_ (SV *cdb, int km, int boxes, NV lat, NV lon, int r0, int r1, int flags)
50 root 1.1 CODE:
51 root 1.4 {
52     struct cdb *db = (struct cdb *)SvPVX (cdb);
53    
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 root 1.6 unsigned char key[4];
87     key[0] = rx;
88     key[1] = rx >> 8;
89     key[2] = y;
90     key[3] = y >> 8;
91 root 1.4
92 root 1.5 //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 root 1.4
94     if (cdb_find (db, key, sizeof (key)) <= 0)
95     continue;
96    
97     int len = cdb_datalen (db);
98 root 1.6 const U8 *ptr = (const U8 *)cdb_get (db, len, cdb_datapos (db));
99 root 1.4
100     while (len > 0)
101     {
102     int datalen = ptr[5];
103    
104 root 1.5 double plat = get_u16 (ptr + 0) * ( 90. / 32767.);
105     double plon = get_u16 (ptr + 2) * (180. / 32767.);
106 root 1.4 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 root 1.5 //printf ("%g,%g %g %.*s\n", plat,plon,d2, datalen,ptr+6);
112 root 1.4
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 root 1.1
129 root 1.6 RETVAL = newSVpvn ((const char *)resptr + 6, reslen);
130 root 1.1 }
131 root 1.4 OUTPUT: RETVAL
132 root 1.1
133 root 1.4 #############################################################################
134 root 1.1
135     int
136     cdb_init (SV *self, int fd)
137     CODE:
138     sv_upgrade (self, SVt_PV);
139 root 1.5 sv_grow (self, sizeof (struct cdb));
140 root 1.1 SvCUR_set (self, sizeof (struct cdb));
141     SvPOK_only (self);
142     RETVAL = cdb_init ((struct cdb *)SvPVX (self), fd);
143     OUTPUT: RETVAL
144    
145     void
146     cdb_free (SV *self)
147     CODE:
148     cdb_free ((struct cdb *)SvPVX (self));
149    
150     SV *
151     cdb_get (SV *self, SV *key)
152     CODE:
153     {
154     unsigned int p;
155     STRLEN l;
156     const char *s = SvPVbyte (key, l);
157     struct cdb *db = (struct cdb *)SvPVX (self);
158    
159     if (cdb_find (db, s, l) <= 0)
160     XSRETURN_UNDEF;
161    
162     p = cdb_datapos (db);
163     l = cdb_datalen (db);
164 root 1.6 RETVAL = newSVpvn ((const char *)cdb_get (db, l, p), l);
165 root 1.1 }
166     OUTPUT: RETVAL
167    
168 root 1.4 #############################################################################
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