ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Geo-LatLon2Place/LatLon2Place.pm
(Generate patch)

Comparing Geo-LatLon2Place/LatLon2Place.pm (file contents):
Revision 1.5 by root, Tue Mar 15 07:33:40 2022 UTC vs.
Revision 1.6 by root, Thu Mar 17 00:32:54 2022 UTC

72use common::sense; 72use common::sense;
73 73
74use Carp (); 74use Carp ();
75 75
76BEGIN { 76BEGIN {
77 our $VERSION = 0.01; 77 our $VERSION = 0.9;
78 78
79 require XSLoader; 79 require XSLoader;
80 XSLoader::load (__PACKAGE__, $VERSION); 80 XSLoader::load (__PACKAGE__, $VERSION);
81 81
82 eval 'sub TORAD() { ' . ((atan2 1,0) / 90) . ' }'; 82 eval 'sub TORAD() { ' . ((atan2 1,0) / 90) . ' }';
128you usually do not specify this parameter. 128you usually do not specify this parameter.
129 129
130If something is found, the associated data blob (always a binary string) 130If something is found, the associated data blob (always a binary string)
131is returned, otherwise you receive C<undef>. 131is returned, otherwise you receive C<undef>.
132 132
133Unless you specify a cusotrm format, the data blob is actually a UTF-8 133Unless you specify a custom format/extractor when building your database,
134string, so you might want to call C<utf8::decode> on it to get a unicode 134the data blob is actually a UTF-8 string, so you might want to call
135astring. 135C<utf8::decode> on it to get a unicode string:
136 136
137At the moment, the implementation is in pure perl, but will eventually 137 my $res = $db->lookup (47, 37); # near mariupol, UA
138move to C. 138 if (defined $res) {
139 utf8::decode $res;
140 # $res now contains the unicode result
141 }
139 142
140=cut 143=cut
141
142sub lookup_xs {
143 my ($self, $lat, $lon, $radius) = @_;
144
145 lookup_ext_ $self->[1], $self->[2], $self->[3], $lat, $lon, 0, $radius, 0
146}
147 144
148sub lookup { 145sub lookup {
149 my ($self, $lat, $lon, $radius) = @_; 146 my ($self, $lat, $lon, $radius) = @_;
150 147
151 $radius ||= $self->[2]; 148 lookup_ext_ $self->[1], $self->[2], $self->[3], $lat, $lon, 0, $radius, 0
152 $radius = int +($radius + $self->[2] - 1) / $self->[2];
153
154 my $coslat = cos $lat * TORAD;
155
156 my $blat = int $self->[3] * $coslat;
157 my $cx = int (($lon + 180) * $blat / 360);
158 my $cy = int (($lat + 90) * $self->[3] / 180);
159
160 my ($min, $res) = (1e00);
161
162 for my $y ($cy - $radius .. $cy + $radius) {
163 for my $x ($cx - $radius .. $cx + $radius) {
164 warn unpack "H*", pack "s< s<", $x, $y;
165 warn $blat;
166 for (unpack "(C/a*)*", cdb_get $self->[1], pack "s< s<", $x, $y) {
167 my ($plat, $plon, $w, $data) = unpack "s< s< C a*";
168 $plat = $plat * ( 90 / 32767);
169 $plon = $plon * (180 / 32767);
170
171 my $dx = ($lon - $plon) * TORAD * $coslat;
172 my $dy = ($lat - $plat) * TORAD;
173 my $d2 = ($dx * $dx + $dy * $dy) * $w;
174
175 $d2 >= $min
176 or ($min, $res) = ($d2, $data);
177 }
178 }
179 }
180
181 $res
182} 149}
183 150
184=back 151=back
185 152
186=head1 ALGORITHM 153=head1 ALGORITHM
198 165
199It will then calculate the (squared) distance to the search coordinate 166It will then calculate the (squared) distance to the search coordinate
200using an approximate euclidean distance on an equireactangular 167using an approximate euclidean distance on an equireactangular
201projection. The squared distance is multiplied with a weight (1..25 for 168projection. The squared distance is multiplied with a weight (1..25 for
202the geonames database, based on population and adminstrative status, 169the geonames database, based on population and adminstrative status,
203always 1 for postcal codes), and the minimum distance wins. 170always 1 for postal codes), and the minimum distance wins.
204 171
205Binning should not introduce errors, but bigger bins can slow down lookup 172Binning should not introduce errors, but bigger bins can slow down lookup
206times due to having to look at more places. The lookup assumes a spherical 173times due to having to look at more places. The lookup assumes a spherical
207shape for the earth, the equirectangular projection stretches distances 174shape for the earth, the equirectangular projection stretches distances
208unevenly and the euclidean distance calculation introduces further 175unevenly and the euclidean distance calculation introduces further
209errors. For typical distance (<< 100km) and the intended usage, these 176errors. For typical distance (<< 100km) and the intended usage, these
210errors should be considered negligible. 177errors should be considered negligible.
211 178
212=head1 SPEED 179=head1 SPEED
213 180
214The current implementation is written in pure perl, and on my machine, 181On my machine, C<lookup> typically does more than a million lookups per
215typically does 10000-200000 lookups per second. The goal for version 1.0 182second - performance varies depending on result density and number of
216is to move the lookup to C. 183indexed points.
217 184
218=head1 TENTATIVE ROADMAP 185=head1 TENTATIVE ROADMAP
219 186
220The database writer should be accessible via a module, so you cna easily 187The database writer should be accessible via a module, so you can easily
221generate your own databases without having to run an external command. 188generate your own databases without having to run an external command.
222 189
223The api might be extended to allow for multiple returns, or nearest 190The API might be extended to allow for multiple lookups, multiple
224neighbour search, or more return values (distance, coordinates). 191returns, or nearest neighbour search, or more return values (distance,
192coordinates).
193
194Longer lookups will take advantage of perlmulticore.
225 195
226=head1 PERL MULTICORE SUPPORT 196=head1 PERL MULTICORE SUPPORT
197
198This is not yet implemented:
227 199
228This module supports the perl multicore specification 200This module supports the perl multicore specification
229(L<http://perlmulticore.schmorp.de/>) when doing lookups. 201(L<http://perlmulticore.schmorp.de/>) when doing lookups.
230 202
231=head1 SEE ALSO 203=head1 SEE ALSO

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines