File Coverage

blib/lib/Geo/Approx.pm
Criterion Covered Total %
statement 56 57 98.2
branch 5 6 83.3
condition 3 9 33.3
subroutine 15 15 100.0
pod 2 3 66.6
total 81 90 90.0


line stmt bran cond sub pod time code
1             package Geo::Approx;
2 1     1   21097 use strict;
  1         3  
  1         68  
3 1     1   5 use Carp;
  1         1  
  1         101  
4 1     1   1905 use Math::Trig;
  1         24917  
  1         171  
5 1     1   9 use vars qw ( $VERSION );
  1         1  
  1         91  
6             $^W = 1;
7              
8             $VERSION = 0.8;
9              
10             my %mask;
11             BEGIN
12             {
13 1     1   5 for(my $i=0;$i<=32;$i++){
14 33         965 $mask{$i} = pack("B32",('0'x(32-$i) . '1'x$i));
15             }
16             }
17              
18             sub new
19             {
20 2     2 0 915 my ($caller,$precision) = @_;
21 2   33     16 my $class = ref($caller) || $caller;
22 2 100       7 if(defined $precision){
23 1 50 33     19 unless(($precision =~ /^(\d+)$/)&&($1>=0)&&($1<=32))
      33        
24             {
25 0         0 croak("optional argument to Geo::Aprox constructor must be a precision between zero and 32");
26             }
27             } else {
28 1         3 $precision = 32;
29             }
30 2         13 bless \$precision,$class;
31             }
32              
33             sub latlon2int
34             {
35 102     102 1 1468 my $prec = ${$_[0]};
  102         187  
36 102         224 my $result = _intint2int(_lat2int($_[1]),_lon2int($_[2]));
37 102         194 $result = _setPrecision($prec,$result);
38 102         488 return $result;
39             }
40              
41             sub int2latlon
42             {
43 100     100 1 66791 my $mask = \$_[0];
44 100         671 my ($lat_int,$lon_int) = _int2intint($_[1]);
45 100         187 my $lat = _int2lat($lat_int);
46 100         1649 my $lon = _int2lon($lon_int);
47 100         274 return ($lat,$lon);
48             }
49              
50             sub _setPrecision
51             {
52 102     102   166 my ($prec,$num) = @_;
53 102         340 return unpack("N",pack("N",$num)&$mask{$prec});
54             }
55              
56             sub _int2lat # 0 to 65535
57             {
58 100     100   481 return rad2deg(asin(($_[0]+0.5)/32768-1.0));
59             }
60              
61             sub _lat2int # -90 to 90 inclusive
62             {
63 102     102   248 my $result = int((sin(deg2rad($_[0]))+1.0)*32768);
64 102 100       1090 $result = 65535 if ($result==65536); # special case for lat==90.000
65 102         266 return int($result);
66             } # 0 to 65535
67              
68             sub _lon2int # -180 to 180 inclusive
69             {
70 102     102   185 my $result = int(($_[0]/360 + 0.5)*65536);
71 102         141 $result %= 65536; # wrap-around
72 102         202 return $result;
73             } # 0 to 65535 inclusive
74              
75             sub _int2lon # 0 to 65535 inclusive
76             {
77 100     100   218 return ($_[0]/65536 - 0.5)*360;
78             } # -180 to <180
79              
80             sub _intint2int # two 16-bit numbers
81             {
82 102     102   353 my $bina = substr(unpack("B32",pack("N",$_[0])),-16);
83 102         410 my $binb = substr(unpack("B32",pack("N",$_[1])),-16);
84 102         130 my $bbiinnab;
85 102         265 for(my $i=0;$i<16;$i++){
86 1632         1965 $bbiinnab .= substr($bina,$i,1);
87 1632         4078 $bbiinnab .= substr($binb,$i,1);
88             }
89 102         237 my $dec = unpack("V",pack("B32",$bbiinnab));
90 102         554 return $dec;
91             } # one 32-bit number
92              
93             sub _int2intint # one 32-bit number
94             {
95 100     100   479 my $bbiinnab = substr(unpack("B32",pack("V",$_[0])),-32);
96 100         212 my ($bina,$binb) = ('0000000000000000','0000000000000000');
97 100         273 for(my $i=0;$i<32;$i+=2){
98 1600         2388 $bina .= substr($bbiinnab,$i,1);
99 1600         4183 $binb .= substr($bbiinnab,$i+1,1);
100             }
101 100         289 my $deca = unpack("N",pack("B32",$bina));
102 100         229 my $decb = unpack("N",pack("B32",$binb));
103 100         255 return ($deca,$decb);
104             } # two 16-bit numbers
105              
106             1;
107              
108             __END__