File Coverage

blib/lib/Geo/Coordinates/Convert.pm
Criterion Covered Total %
statement 38 38 100.0
branch 1 2 50.0
condition n/a
subroutine 8 8 100.0
pod 0 3 0.0
total 47 51 92.1


line stmt bran cond sub pod time code
1             package Geo::Coordinates::Convert;
2              
3 1     1   10494 use 5.006;
  1         4  
  1         48  
4 1     1   6 use strict;
  1         2  
  1         35  
5 1     1   5 use warnings;
  1         6  
  1         40  
6              
7 1     1   4 use Exporter ();
  1         2  
  1         21  
8 1     1   5 use vars qw($VERSION @ISA @EXPORT);
  1         2  
  1         2022  
9              
10             @EXPORT = qw(
11             set_Mean_Longitude
12             geo2lII
13             lII2geo
14             );
15              
16             @ISA = qw(Exporter);
17              
18             $VERSION = '0.01';
19              
20             # some constants
21             my $PIsur4 = atan2(1, 1);
22             my $PIsur180 = $PIsur4 / 45;
23             my $PI = $PIsur4 * 4;
24             my $PIsur2 = $PIsur4 * 2;
25             my $precision = 0.001; # degrees
26              
27             # these "constants" are relative to France (see www.ign.fr)
28             my $N = 0.7289686274;
29             my $C = 11745793.39;
30             my $XS = 600000;
31             my $YS = 8199695.768; # Lambert II (6199695.768 for extended LambertII)
32             my $E = 0.08248325676;
33             my $Esur2 = $E / 2;
34              
35             # mean longitude. 2.3372 is the longitude of the meridian of Paris (degrees)
36             my $mean_longitude = 2.3372;
37              
38             sub set_Mean_Longitude {
39 6623     6623 0 33315 $mean_longitude = $_[0];
40             }
41              
42             sub geo2lII {
43             # Conversion from geographics coordinates (decimal degrees) to Lambert II coordinates (meters)
44             #
45             # list in (decimal degrees):
46             # (geographic longitude, geographic latitude, mean longitude)
47             # list out (meters):
48             # (lambert II longitude, lambert II latitude)
49             #
50             # longitudes from -180° west to +180° east
51             # latitudes from -90° (south) to +90° (north)
52              
53 6623     6623 0 16234 my ($l, $r, $gamma, $sinlat, $xl, $yl);
54             # arguments
55 6623         8773 my ($lon, $lat, $ml) = @_;
56 6623         17465 $sinlat = sin($lat * $PIsur180);
57 6623 50       11374 set_Mean_Latitude($ml) if $ml;
58              
59 6623         16299 $l = 0.5 * (
60             log (
61             (1 + $sinlat) / (1 - $sinlat)
62             )
63             - $E * log (
64             (1 + $E * $sinlat) / (1 - $E * $sinlat)
65             )
66             );
67              
68 6623         8941 $r = $C * exp(-$N * $l);
69              
70 6623         8356 $gamma = $N * ($lon - $mean_longitude) * $PIsur180;
71              
72 6623         8650 $xl = $XS + $r * sin($gamma);
73 6623         9974 $yl = $YS - $r * cos($gamma);
74              
75 6623         14864 return ($xl, $yl);
76             }
77              
78             sub lII2geo {
79             # Conversion from Lambert II coordinates (meters) to geographics coordinates (decimal degrees)
80             #
81             # list in (meters):
82             # (lambert II longitude, lambert II latitude)
83             # list out (decimal degrees):
84             # (geographic longitude, geographic latitude)
85             # conventions:
86             # - negatives western longitudes, positives eastern
87             # - negatives southern latitudes, positives northern
88              
89 6623     6623 0 15545 my ($el, $r, $gamma, $lon, $lat, $latp);
90              
91 6623         7634 my ($xl, $yl) = @_;
92              
93 6623         12316 $r = sqrt( ($xl - $XS) * ($xl - $XS) + ($yl - $YS) * ($yl - $YS) );
94 6623         9988 $gamma = atan2 ( ($xl - $XS) / ($YS - $yl), 1 );
95              
96 6623         8164 $lon = $mean_longitude * $PIsur180 + $gamma / $N;
97 6623         9936 $el = exp( - log ($r / $C) / $N );
98              
99 6623         7529 $lat = $PIsur4;
100 6623         6558 $latp = 0;
101 6623         14300 while (abs($latp - $lat) > $precision) {
102 17945         17389 $latp = $lat;
103 17945         59503 $lat = 2 * atan2( ((1 + $E * $latp) / (1 - $E * $latp) )** $Esur2 * $el, 1 ) - $PIsur2;
104             }
105              
106 6623         16159 return ($lon/$PIsur180, $lat/$PIsur180);
107             }
108              
109              
110             1;
111             __END__