File Coverage

blib/lib/Geo/Coordinates/Converter/Format/IArea.pm
Criterion Covered Total %
statement 97 100 97.0
branch 7 10 70.0
condition 2 5 40.0
subroutine 15 15 100.0
pod 4 6 66.6
total 125 136 91.9


line stmt bran cond sub pod time code
1             package Geo::Coordinates::Converter::Format::IArea;
2 3     3   52017 use strict;
  3         6  
  3         82  
3 3     3   14 use warnings;
  3         5  
  3         69  
4 3     3   14 use base 'Geo::Coordinates::Converter::Format';
  3         8  
  3         1044  
5             our $VERSION = '0.01';
6 3     3   2096 use File::ShareDir 'dist_file';
  3         12730  
  3         189  
7 3     3   1348 use CDB_File;
  3         1745  
  3         109  
8 3     3   984 use Geo::Coordinates::Converter::iArea;
  3         6  
  3         2753  
9              
10 7     7 1 1851 sub name { 'iarea' }
11              
12             sub detect {
13 2     2 1 138 my($self, $point) = @_;
14 2 50       5 return unless Geo::Coordinates::Converter::iArea->get_center( $point->areacode );
15 0         0 return $self->name;
16             }
17              
18             # other(e.g. wgs84) to iarea
19             sub from {
20 1     1 1 359 my ($self, $point) = @_;
21              
22 1         5 my @mesh = _calc_meshcode($point);
23 1 50       3 if (my $areacode = $self->_meshcode2areacode(@mesh)) {
24 1         4 $point->areacode($areacode);
25             }
26 1         4 $point;
27             }
28              
29             sub _meshcode2areacode {
30 1     1   2 my ($self, @mesh) = @_;
31              
32 1         3 my $file = dist_file('Geo-Coordinates-Converter-iArea', 'meshcode2areacode.cdb');
33 1         202 my $cdb = CDB_File->TIEHASH($file);
34 1         2 for my $meshcode (@mesh) {
35 5 100       58 if ($cdb->EXISTS($meshcode)) {
36 1         37 return $cdb->FETCH($meshcode);
37             }
38             }
39 0         0 return;
40             }
41              
42             sub _calc_meshcode {
43 1     1   1 my $point = shift;
44              
45             # normalize
46 1         2 $point = do {
47 1         3 my $geo = Geo::Coordinates::Converter->new(point => $point);
48 1         239 $geo->convert('degree', 'tokyo');
49             };
50              
51 1         2480 my ($lat,$lng) = map { int ($_ * 60 * 60 * 1000) } ($point->lat, $point->lng);
  2         11  
52              
53 1         17 my $mesh;
54             my @mesh;
55 1         3 my $ab = int($lat / 2400000);
56 1         2 my $cd = int($lng / 3600000) - 100;
57 1         1 my $x1 = ($cd +100) * 3600000;
58 1         2 my $y1 = $ab * 2400000;
59 1         2 my $e = int(($lat - $y1) / 300000);
60 1         1 my $f = int(($lng - $x1) / 450000);
61 1         3 $mesh = $ab.$cd.$e.$f;
62 1         2 push @mesh, $mesh;
63              
64 1         2 my $x2 = $x1 + $f * 450000;
65 1         1 my $y2 = $y1 + $e * 300000;
66 1         2 my $l3 = int(($lng - $x2) / 225000);
67 1         2 my $m3 = int(($lat - $y2) / 150000);
68 1         2 my $g = $l3 + $m3 * 2;
69 1         1 $mesh .= $g;
70 1         2 push @mesh, $mesh;
71              
72 1         1 my $x3 = $x2 + $l3 * 225000;
73 1         1 my $y3 = $y2 + $m3 * 150000;
74 1         2 my $l4 = int(($lng - $x3) / 112500);
75 1         2 my $m4 = int(($lat - $y3) / 75000);
76 1         1 my $h = $l4 + $m4 * 2;
77 1         2 $mesh .= $h;
78 1         2 push @mesh, $mesh;
79              
80 1         1 my $x4 = $x3 + $l4 * 112500;
81 1         2 my $y4 = $y3 + $m4 * 75000;
82 1         1 my $l5 = int(($lng - $x4) / 56250);
83 1         2 my $m5 = int(($lat - $y4) / 37500);
84 1         1 my $i = $l5 + $m5 * 2;
85 1         2 $mesh .= $i;
86 1         2 push @mesh, $mesh;
87              
88 1         2 my $x5 = $x4 + $l5 * 56250;
89 1         1 my $y5 = $y4 + $m5 * 37500;
90 1         1 my $l6 = int(($lng - $x5) / 28125);
91 1         3 my $m6 = int(($lat - $y5) / 18750);
92 1         2 my $j = $l6 + $m6 * 2;
93 1         2 $mesh .= $j;
94 1         1 push @mesh, $mesh;
95              
96 1         2 my $x6 = $x5 + $l6 * 28125;
97 1         2 my $y6 = $y5 + $m6 * 18750;
98 1         2 my $l7 = int(($lng - $x6) / 14062.5);
99 1         2 my $m7 = int(($lat - $y6) / 9375);
100 1         1 my $k = $l7 + $m7 * 2;
101 1         1 $mesh .= $k;
102 1         2 push @mesh, $mesh;
103              
104 1         5 @mesh;
105             }
106              
107             # iarea to other(e.g. wgs84)
108             sub to {
109 1     1 1 674 my($self, $point) = @_;
110              
111 1   50     3 my $area_geo = _get_center($point) || { lat => '0.000000', lng => '0.000000' };
112              
113 1         106 $point->lat($area_geo->{lat});
114 1         8 $point->lng($area_geo->{lng});
115 1         7 $point->datum('tokyo');
116              
117 1         6 $point;
118             }
119              
120             sub _get_center {
121 1     1   2 my $point = shift;
122 1         2 my $center = Geo::Coordinates::Converter::iArea->get_center( $point->areacode );
123 1         135 +{ lat => $center->lat, lng => $center->lng };
124             }
125              
126             sub Geo::Coordinates::Converter::Point::areacode {
127 9 100   9 0 33718 return $_[0]->{'areacode'} if @_ == 1;
128 1 50       5 return $_[0]->{'areacode'} = $_[1] if @_ == 2;
129 0         0 shift->{'areacode'} = \@_;
130             }
131              
132             sub Geo::Coordinates::Converter::areacode {
133 2     2 0 1176 my $self = shift;
134 2   33     15 my $point = shift || $self->current;
135 2         15 $point->areacode;
136             }
137              
138             1;
139             __END__