aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/Geo/Coordinates/CH1903.pm
blob: 6121821529a263222f1fbe74d953508ee207c90b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/usr/bin/perl
#
# Geo::Coordinates::CH1903
# Conversion between WGS84 and Swiss CH1903.
#
# Copyright (c) 2012 UK Citizens Online Democracy. This module is free
# software; you can redistribute it and/or modify it under the same terms as
# Perl itself.
#
# WWW: http://www.mysociety.org/

package Geo::Coordinates::CH1903;

$Geo::Coordinates::CH1903::VERSION = '1.00';

use strict;

=head1 NAME

Geo::Coordinates::CH1903

=head1 VERSION

1.00

=head1 SYNOPSIS

    use Geo::Coordinates::CH1903;

    my ($lat, $lon) = ...;
    my ($e, $n) = Geo::Coordinates::CH1903::from_latlon($lat, $lon);
    my ($lat, $lon) = Geo::Coordinates::CH1903::to_latlon($e, $n);

=head1 FUNCTIONS

=over 4

=cut

sub from_latlon($$) {
    my ($lat, $lon) = @_;

    $lat *= 3600;
    $lon *= 3600;

    my $lat_aux = ($lat - 169028.66) / 10000;
    my $lon_aux = ($lon - 26782.5) / 10000;

    my $x = 600072.37
        + (211455.93 * $lon_aux)
        - (10938.51 * $lon_aux * $lat_aux)
        - (0.36 * $lon_aux * $lat_aux**2)
        - (44.54 * $lon_aux**3);

    my $y = 200147.07
        + (308807.95 * $lat_aux)
        + (3745.25 * $lon_aux**2)
        + (76.63 * $lat_aux**2)
        - (194.56 * $lon_aux**2 * $lat_aux)
        + (119.79 * $lat_aux**3);

    return ($x, $y);
}

sub to_latlon($$) {
    my ($x, $y) = @_;

    my $x_aux = ($x - 600000) / 1000000;
    my $y_aux = ($y - 200000) / 1000000;

    my $lat = 16.9023892
        + (3.238272 * $y_aux)
        - (0.270978 * $x_aux**2)
        - (0.002528 * $y_aux**2)
        - (0.0447 * $x_aux**2 * $y_aux)
        - (0.0140 * $y_aux**3);

    my $lon = 2.6779094
        + (4.728982 * $x_aux)
        + (0.791484 * $x_aux * $y_aux)
        + (0.1306 * $x_aux * $y_aux**2)
        - (0.0436 * $x_aux**3);

    $lat = $lat * 100 / 36;
    $lon = $lon * 100 / 36;

    return ($lat, $lon);
}

=head1 AUTHOR AND COPYRIGHT

Maths courtesy of the Swiss Federal Office of Topography:
http://www.swisstopo.admin.ch/internet/swisstopo/en/home/products/software/products/skripts.html

Written by Matthew Somerville

Copyright (c) UK Citizens Online Democracy.

This module is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=cut

1;