line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Geo::Distance; |
2
|
4
|
|
|
4
|
|
824986
|
use 5.008001; |
|
4
|
|
|
|
|
34
|
|
3
|
4
|
|
|
4
|
|
19
|
use strict; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
70
|
|
4
|
4
|
|
|
4
|
|
16
|
use warnings; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
162
|
|
5
|
|
|
|
|
|
|
our $VERSION = '0.25'; |
6
|
|
|
|
|
|
|
|
7
|
4
|
|
|
4
|
|
1731
|
use GIS::Distance; |
|
4
|
|
|
|
|
9605
|
|
|
4
|
|
|
|
|
128
|
|
8
|
4
|
|
|
4
|
|
1731
|
use GIS::Distance::Constants qw( :all ); |
|
4
|
|
|
|
|
68042
|
|
|
4
|
|
|
|
|
525
|
|
9
|
4
|
|
|
4
|
|
31
|
use Carp qw( croak ); |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
160
|
|
10
|
4
|
|
|
4
|
|
20
|
use Const::Fast; |
|
4
|
|
|
|
|
9
|
|
|
4
|
|
|
|
|
25
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
const our %GEO_TO_GIS_FORMULA_MAP => (qw( |
13
|
|
|
|
|
|
|
alt ALT |
14
|
|
|
|
|
|
|
cos Cosine |
15
|
|
|
|
|
|
|
gcd GreatCircle |
16
|
|
|
|
|
|
|
hsin Haversine |
17
|
|
|
|
|
|
|
mt MathTrig |
18
|
|
|
|
|
|
|
null Null |
19
|
|
|
|
|
|
|
polar Polar |
20
|
|
|
|
|
|
|
tv Vincenty |
21
|
|
|
|
|
|
|
)); |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
const our @FORMULAS => (keys %GEO_TO_GIS_FORMULA_MAP); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub new { |
26
|
4
|
|
|
4
|
0
|
365
|
my $class = shift; |
27
|
4
|
|
|
|
|
12
|
my $self = bless {}, $class; |
28
|
4
|
|
|
|
|
12
|
my %args = @_; |
29
|
|
|
|
|
|
|
|
30
|
4
|
|
|
|
|
21
|
$self->{formula} = 'hsin'; |
31
|
4
|
|
|
|
|
11
|
$self->{units} = {}; |
32
|
4
|
50
|
|
|
|
16
|
if(!$args{no_units}){ |
33
|
4
|
|
|
|
|
51
|
$self->reg_unit( $KILOMETER_RHO, 'kilometer' ); |
34
|
4
|
|
|
|
|
32
|
$self->reg_unit( 1000, 'meter', => 'kilometer' ); |
35
|
4
|
|
|
|
|
13
|
$self->reg_unit( 100, 'centimeter' => 'meter' ); |
36
|
4
|
|
|
|
|
12
|
$self->reg_unit( 10, 'millimeter' => 'centimeter' ); |
37
|
|
|
|
|
|
|
|
38
|
4
|
|
|
|
|
12
|
$self->reg_unit( 'kilometre' => 'kilometer' ); |
39
|
4
|
|
|
|
|
12
|
$self->reg_unit( 'metre' => 'meter' ); |
40
|
4
|
|
|
|
|
9
|
$self->reg_unit( 'centimetre' => 'centimeter' ); |
41
|
4
|
|
|
|
|
10
|
$self->reg_unit( 'millimetre' => 'millimeter' ); |
42
|
|
|
|
|
|
|
|
43
|
4
|
|
|
|
|
11
|
$self->reg_unit( 'mile' => 1609.344, 'meter' ); |
44
|
4
|
|
|
|
|
10
|
$self->reg_unit( 'nautical mile' => 1852, 'meter' ); |
45
|
4
|
|
|
|
|
10
|
$self->reg_unit( 'yard' => 0.9144, 'meter' ); |
46
|
4
|
|
|
|
|
9
|
$self->reg_unit( 3, 'foot' => 'yard' ); |
47
|
4
|
|
|
|
|
12
|
$self->reg_unit( 12, 'inch' => 'foot' ); |
48
|
4
|
|
|
|
|
16
|
$self->reg_unit( 'light second' => 299792458, 'meter' ); |
49
|
|
|
|
|
|
|
|
50
|
4
|
|
|
|
|
10
|
$self->reg_unit( 'poppy seed' => 2.11, 'millimeter' ); |
51
|
4
|
|
|
|
|
9
|
$self->reg_unit( 'barleycorn' => 8.467, 'millimeter' ); |
52
|
4
|
|
|
|
|
11
|
$self->reg_unit( 'rod' => 5.0292, 'meter' ); |
53
|
4
|
|
|
|
|
10
|
$self->reg_unit( 'pole' => 'rod' ); |
54
|
4
|
|
|
|
|
10
|
$self->reg_unit( 'perch' => 'rod' ); |
55
|
4
|
|
|
|
|
10
|
$self->reg_unit( 'chain' => 20.1168, 'meter' ); |
56
|
4
|
|
|
|
|
9
|
$self->reg_unit( 'furlong' => 201.168, 'meter' ); |
57
|
4
|
|
|
|
|
10
|
$self->reg_unit( 'league' => 4.828032, 'kilometer' ); |
58
|
4
|
|
|
|
|
8
|
$self->reg_unit( 1.8288, 'fathom' => 'meter' ); |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
4
|
|
|
|
|
11
|
return $self; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub formula { |
65
|
2
|
|
|
2
|
1
|
513
|
my $self = shift; |
66
|
|
|
|
|
|
|
|
67
|
2
|
50
|
|
|
|
6
|
return $self->{formula} if !$_[0]; |
68
|
2
|
|
|
|
|
5
|
my $formula = shift; |
69
|
|
|
|
|
|
|
|
70
|
2
|
|
|
|
|
6
|
my $gis_formula = $GEO_TO_GIS_FORMULA_MAP{ $formula }; |
71
|
|
|
|
|
|
|
|
72
|
2
|
50
|
|
|
|
6
|
croak( |
73
|
|
|
|
|
|
|
'Unknown formula (available formulas are ', |
74
|
|
|
|
|
|
|
join(', ', sort @FORMULAS), |
75
|
|
|
|
|
|
|
')', |
76
|
|
|
|
|
|
|
) if !$gis_formula; |
77
|
|
|
|
|
|
|
|
78
|
2
|
|
|
|
|
5
|
$self->{formula} = $formula; |
79
|
2
|
|
|
|
|
6
|
$self->{gis_formula} = $gis_formula; |
80
|
|
|
|
|
|
|
|
81
|
2
|
|
|
|
|
3
|
return $formula; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub distance { |
85
|
39
|
|
|
39
|
1
|
113
|
my ($self, $unit, $lon1, $lat1, $lon2, $lat2) = @_; |
86
|
|
|
|
|
|
|
|
87
|
39
|
|
|
|
|
63
|
my $unit_rho = $self->{units}->{$unit}; |
88
|
39
|
50
|
|
|
|
62
|
croak('Unkown unit type "' . $unit . '"') if !$unit_rho; |
89
|
|
|
|
|
|
|
|
90
|
39
|
|
|
|
|
145
|
my $gis = GIS::Distance->new( $self->{gis_formula} ); |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# Reverse lon/lat to lat/lon, the way GIS::Distance wants it. |
93
|
39
|
|
|
|
|
82979
|
my $km = $gis->{code}->( $lat1, $lon1, $lat2, $lon2 ); |
94
|
|
|
|
|
|
|
|
95
|
39
|
|
|
|
|
1299
|
return $km * ($unit_rho / $KILOMETER_RHO); |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
4
|
|
|
4
|
|
4492
|
use Math::Trig qw( acos asin atan deg2rad great_circle_distance pi tan ); |
|
4
|
|
|
|
|
47565
|
|
|
4
|
|
|
|
|
5469
|
|
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub old_distance { |
101
|
0
|
|
|
0
|
0
|
0
|
my($self,$unit,$lon1,$lat1,$lon2,$lat2) = @_; |
102
|
0
|
0
|
|
|
|
0
|
croak('Unkown unit type "'.$unit.'"') unless($unit = $self->{units}->{$unit}); |
103
|
|
|
|
|
|
|
|
104
|
0
|
0
|
|
|
|
0
|
return 0 if $self->{formula} eq 'null'; |
105
|
0
|
0
|
|
|
|
0
|
return 0 if $self->{formula} eq 'alt'; |
106
|
|
|
|
|
|
|
|
107
|
0
|
0
|
|
|
|
0
|
if($self->{formula} eq 'mt'){ |
108
|
0
|
|
|
|
|
0
|
return great_circle_distance( |
109
|
|
|
|
|
|
|
deg2rad($lon1), |
110
|
|
|
|
|
|
|
deg2rad(90 - $lat1), |
111
|
|
|
|
|
|
|
deg2rad($lon2), |
112
|
|
|
|
|
|
|
deg2rad(90 - $lat2), |
113
|
|
|
|
|
|
|
$unit |
114
|
|
|
|
|
|
|
); |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
0
|
|
|
|
|
0
|
$lon1 = deg2rad($lon1); $lat1 = deg2rad($lat1); |
|
0
|
|
|
|
|
0
|
|
118
|
0
|
|
|
|
|
0
|
$lon2 = deg2rad($lon2); $lat2 = deg2rad($lat2); |
|
0
|
|
|
|
|
0
|
|
119
|
0
|
|
|
|
|
0
|
my $c; |
120
|
0
|
0
|
|
|
|
0
|
if($self->{formula} eq 'cos'){ |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
121
|
0
|
|
|
|
|
0
|
my $a = sin($lat1) * sin($lat2); |
122
|
0
|
|
|
|
|
0
|
my $b = cos($lat1) * cos($lat2) * cos($lon2 - $lon1); |
123
|
0
|
|
|
|
|
0
|
$c = acos($a + $b); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
elsif($self->{formula} eq 'hsin'){ |
126
|
0
|
|
|
|
|
0
|
my $dlon = $lon2 - $lon1; |
127
|
0
|
|
|
|
|
0
|
my $dlat = $lat2 - $lat1; |
128
|
0
|
|
|
|
|
0
|
my $a = (sin($dlat/2)) ** 2 + cos($lat1) * cos($lat2) * (sin($dlon/2)) ** 2; |
129
|
0
|
|
|
|
|
0
|
$c = 2 * atan2(sqrt($a), sqrt(abs(1-$a))); |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
elsif($self->{formula} eq 'polar'){ |
132
|
0
|
|
|
|
|
0
|
my $a = pi/2 - $lat1; |
133
|
0
|
|
|
|
|
0
|
my $b = pi/2 - $lat2; |
134
|
0
|
|
|
|
|
0
|
$c = sqrt( $a ** 2 + $b ** 2 - 2 * $a * $b * cos($lon2 - $lon1) ); |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
elsif($self->{formula} eq 'gcd'){ |
137
|
0
|
|
|
|
|
0
|
$c = 2*asin( sqrt( |
138
|
|
|
|
|
|
|
( sin(($lat1-$lat2)/2) )**2 + |
139
|
|
|
|
|
|
|
cos($lat1) * cos($lat2) * |
140
|
|
|
|
|
|
|
( sin(($lon1-$lon2)/2) )**2 |
141
|
|
|
|
|
|
|
) ); |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# Eric Samuelson recommended this formula. |
144
|
|
|
|
|
|
|
# http://forums.devshed.com/t54655/sc3d021a264676b9b440ea7cbe1f775a1.html |
145
|
|
|
|
|
|
|
# http://williams.best.vwh.net/avform.htm |
146
|
|
|
|
|
|
|
# It seems to produce the same results at the hsin formula, so... |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
#my $dlon = $lon2 - $lon1; |
149
|
|
|
|
|
|
|
#my $dlat = $lat2 - $lat1; |
150
|
|
|
|
|
|
|
#my $a = (sin($dlat / 2)) ** 2 |
151
|
|
|
|
|
|
|
# + cos($lat1) * cos($lat2) * (sin($dlon / 2)) ** 2; |
152
|
|
|
|
|
|
|
#$c = 2 * atan2(sqrt($a), sqrt(1 - $a)); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
elsif($self->{formula} eq 'tv'){ |
155
|
0
|
|
|
|
|
0
|
my($a,$b,$f) = (6378137,6356752.3142,1/298.257223563); |
156
|
0
|
|
|
|
|
0
|
my $l = $lon2 - $lon1; |
157
|
0
|
|
|
|
|
0
|
my $u1 = atan((1-$f) * tan($lat1)); |
158
|
0
|
|
|
|
|
0
|
my $u2 = atan((1-$f) * tan($lat2)); |
159
|
0
|
|
|
|
|
0
|
my $sin_u1 = sin($u1); my $cos_u1 = cos($u1); |
|
0
|
|
|
|
|
0
|
|
160
|
0
|
|
|
|
|
0
|
my $sin_u2 = sin($u2); my $cos_u2 = cos($u2); |
|
0
|
|
|
|
|
0
|
|
161
|
0
|
|
|
|
|
0
|
my $lambda = $l; |
162
|
0
|
|
|
|
|
0
|
my $lambda_pi = 2 * pi; |
163
|
0
|
|
|
|
|
0
|
my $iter_limit = 20; |
164
|
0
|
|
|
|
|
0
|
my($cos_sq_alpha,$sin_sigma,$cos2sigma_m,$cos_sigma,$sigma); |
165
|
0
|
|
0
|
|
|
0
|
while( abs($lambda-$lambda_pi) > 1e-12 && --$iter_limit>0 ){ |
166
|
0
|
|
|
|
|
0
|
my $sin_lambda = sin($lambda); my $cos_lambda = cos($lambda); |
|
0
|
|
|
|
|
0
|
|
167
|
0
|
|
|
|
|
0
|
$sin_sigma = sqrt(($cos_u2*$sin_lambda) * ($cos_u2*$sin_lambda) + |
168
|
|
|
|
|
|
|
($cos_u1*$sin_u2-$sin_u1*$cos_u2*$cos_lambda) * ($cos_u1*$sin_u2-$sin_u1*$cos_u2*$cos_lambda)); |
169
|
0
|
|
|
|
|
0
|
$cos_sigma = $sin_u1*$sin_u2 + $cos_u1*$cos_u2*$cos_lambda; |
170
|
0
|
|
|
|
|
0
|
$sigma = atan2($sin_sigma, $cos_sigma); |
171
|
0
|
|
|
|
|
0
|
my $alpha = asin($cos_u1 * $cos_u2 * $sin_lambda / $sin_sigma); |
172
|
0
|
|
|
|
|
0
|
$cos_sq_alpha = cos($alpha) * cos($alpha); |
173
|
0
|
|
|
|
|
0
|
$cos2sigma_m = $cos_sigma - 2*$sin_u1*$sin_u2/$cos_sq_alpha; |
174
|
0
|
|
|
|
|
0
|
my $cc = $f/16*$cos_sq_alpha*(4+$f*(4-3*$cos_sq_alpha)); |
175
|
0
|
|
|
|
|
0
|
$lambda_pi = $lambda; |
176
|
0
|
|
|
|
|
0
|
$lambda = $l + (1-$cc) * $f * sin($alpha) * |
177
|
|
|
|
|
|
|
($sigma + $cc*$sin_sigma*($cos2sigma_m+$cc*$cos_sigma*(-1+2*$cos2sigma_m*$cos2sigma_m))); |
178
|
|
|
|
|
|
|
} |
179
|
0
|
0
|
|
|
|
0
|
undef if( $iter_limit==0 ); |
180
|
0
|
|
|
|
|
0
|
my $usq = $cos_sq_alpha*($a*$a-$b*$b)/($b*$b); |
181
|
0
|
|
|
|
|
0
|
my $aa = 1 + $usq/16384*(4096+$usq*(-768+$usq*(320-175*$usq))); |
182
|
0
|
|
|
|
|
0
|
my $bb = $usq/1024 * (256+$usq*(-128+$usq*(74-47*$usq))); |
183
|
0
|
|
|
|
|
0
|
my $delta_sigma = $bb*$sin_sigma*($cos2sigma_m+$bb/4*($cos_sigma*(-1+2*$cos2sigma_m*$cos2sigma_m)- |
184
|
|
|
|
|
|
|
$bb/6*$cos2sigma_m*(-3+4*$sin_sigma*$sin_sigma)*(-3+4*$cos2sigma_m*$cos2sigma_m))); |
185
|
0
|
|
|
|
|
0
|
$c = ( $b*$aa*($sigma-$delta_sigma) ) / $self->{units}->{meter}; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
else{ |
188
|
0
|
|
|
|
|
0
|
croak('Unkown distance formula "'.$self->{formula}.'"'); |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
0
|
|
|
|
|
0
|
return $unit * $c; |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub closest { |
195
|
4
|
|
|
4
|
1
|
9202
|
my $self = shift; |
196
|
4
|
|
|
|
|
33
|
my %args = @_; |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
# Set defaults and prepare. |
199
|
4
|
|
33
|
|
|
16
|
my $dbh = $args{dbh} || croak('You must supply a database handle'); |
200
|
4
|
50
|
|
|
|
28
|
$dbh->isa('DBI::db') || croak('The dbh must be a DBI database handle'); |
201
|
4
|
|
33
|
|
|
21
|
my $table = $args{table} || croak('You must supply a table name'); |
202
|
4
|
|
33
|
|
|
12
|
my $lon = $args{lon} || croak('You must supply a longitude'); |
203
|
4
|
|
33
|
|
|
7
|
my $lat = $args{lat} || croak('You must supply a latitude'); |
204
|
4
|
|
33
|
|
|
9
|
my $distance = $args{distance} || croak('You must supply a distance'); |
205
|
4
|
|
33
|
|
|
10
|
my $unit = $args{unit} || croak('You must specify a unit type'); |
206
|
4
|
|
33
|
|
|
16
|
my $unit_size = $self->{units}->{$unit} || croak('This unit type is not known'); |
207
|
4
|
|
|
|
|
22
|
my $degrees = $distance / ( $DEG_RATIO * $unit_size ); |
208
|
4
|
|
50
|
|
|
19
|
my $lon_field = $args{lon_field} || 'lon'; |
209
|
4
|
|
50
|
|
|
15
|
my $lat_field = $args{lat_field} || 'lat'; |
210
|
4
|
|
50
|
|
|
14
|
my $fields = $args{fields} || []; |
211
|
|
|
|
|
|
|
|
212
|
4
|
|
|
|
|
12
|
unshift @$fields, $lon_field, $lat_field; |
213
|
4
|
|
|
|
|
12
|
$fields = join( ',', @$fields ); |
214
|
4
|
|
100
|
|
|
16
|
my $count = $args{count} || 0; |
215
|
4
|
|
66
|
|
|
15
|
my $sort = $args{sort} || ( $count ? 1 : 0 ); |
216
|
4
|
|
|
|
|
13
|
my $where = qq{$lon_field >= ? AND $lat_field >= ? AND $lon_field <= ? AND $lat_field <= ?}; |
217
|
4
|
50
|
|
|
|
11
|
$where .= ( $args{where} ? " AND ($args{where})" : '' ); |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
my @bind = ( |
220
|
|
|
|
|
|
|
$lon-$degrees, $lat-$degrees, |
221
|
|
|
|
|
|
|
$lon+$degrees, $lat+$degrees, |
222
|
4
|
50
|
|
|
|
25
|
( $args{bind} ? @{$args{bind}} : () ) |
|
0
|
|
|
|
|
0
|
|
223
|
|
|
|
|
|
|
); |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
# Retrieve locations. |
226
|
4
|
|
|
|
|
59
|
my $sth = $dbh->prepare(qq{ |
227
|
|
|
|
|
|
|
SELECT $fields |
228
|
|
|
|
|
|
|
FROM $table |
229
|
|
|
|
|
|
|
WHERE $where |
230
|
|
|
|
|
|
|
}); |
231
|
4
|
|
|
|
|
628
|
$sth->execute( @bind ); |
232
|
4
|
|
|
|
|
12
|
my $locations = []; |
233
|
4
|
|
|
|
|
175
|
while(my $location = $sth->fetchrow_hashref){ |
234
|
35
|
|
|
|
|
354
|
push @$locations, $location; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
# Calculate distances. |
238
|
4
|
|
|
|
|
11
|
my $closest = []; |
239
|
4
|
|
|
|
|
8
|
foreach my $location (@$locations){ |
240
|
|
|
|
|
|
|
$location->{distance} = $self->distance( |
241
|
|
|
|
|
|
|
$unit, $lon, $lat, |
242
|
|
|
|
|
|
|
$location->{$lon_field}, |
243
|
35
|
|
|
|
|
86
|
$location->{$lat_field} |
244
|
|
|
|
|
|
|
); |
245
|
35
|
100
|
|
|
|
77
|
if( $location->{distance} <= $distance ){ |
246
|
32
|
|
|
|
|
55
|
push @$closest, $location; |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
} |
249
|
4
|
|
|
|
|
9
|
$locations = $closest; |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# Sort. |
252
|
4
|
100
|
|
|
|
10
|
if( $sort ){ |
253
|
1
|
|
|
|
|
9
|
@$locations = sort { $a->{distance} <=> $b->{distance} } @$locations; |
|
17
|
|
|
|
|
23
|
|
254
|
|
|
|
|
|
|
} |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# Split for count. |
257
|
4
|
100
|
66
|
|
|
19
|
if( $count and $count < @$locations ){ |
258
|
1
|
|
|
|
|
5
|
splice @$locations, $count; |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
|
261
|
4
|
|
|
|
|
103
|
return $locations; |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub reg_unit { |
265
|
92
|
|
|
92
|
1
|
103
|
my $self = shift; |
266
|
92
|
|
|
|
|
100
|
my $units = $self->{units}; |
267
|
92
|
|
|
|
|
111
|
my($count1,$key1,$count2,$key2); |
268
|
92
|
|
|
|
|
97
|
$count1 = shift; |
269
|
92
|
100
|
66
|
|
|
272
|
if($count1=~/[^\.0-9]/ or !@_){ $key1=$count1; $count1=1; } |
|
64
|
|
|
|
|
74
|
|
|
64
|
|
|
|
|
66
|
|
270
|
28
|
|
|
|
|
42
|
else{ $key1 = shift; } |
271
|
92
|
100
|
|
|
|
119
|
if(!@_){ |
272
|
4
|
|
|
|
|
12
|
$units->{$key1} = $count1; |
273
|
|
|
|
|
|
|
}else{ |
274
|
88
|
|
|
|
|
96
|
$count2 = shift; |
275
|
88
|
100
|
66
|
|
|
259
|
if($count2=~/[^\.0-9]/ or !@_){ $key2=$count2; $count2=1; } |
|
48
|
|
|
|
|
58
|
|
|
48
|
|
|
|
|
53
|
|
276
|
40
|
|
|
|
|
61
|
else{ $key2 = shift; } |
277
|
88
|
50
|
|
|
|
145
|
($key1,$key2) = ($key2,$key1) if( defined $units->{$key1} ); |
278
|
88
|
|
|
|
|
213
|
$units->{$key1} = ($units->{$key2}*$count1) / $count2; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
1; |
283
|
|
|
|
|
|
|
__END__ |