Geo-Calc

 view release on metacpan or  search on metacpan

lib/Geo/Calc.pm  view on Meta::CPAN


    my ( $brng12, $brng21 );
    if( sin( $dlon ) > 0 ) {
        $brng12 = $brnga;
        $brng21 = pi2 - $brngb;
    } else {
        $brng12 = pi2 - $brnga;
        $brng21 = $brngb;
    }

    my $alpha1 = POSIX::fmod( $brng13 - $brng12 + ( pi * 3 ), pi2 ) - pi;
    my $alpha2 = POSIX::fmod( $brng21 - $brng23 + ( pi * 3 ), pi2 ) - pi;

    return undef if( ( sin( $alpha1 ) == 0 ) and ( sin( $alpha2 ) == 0 ) ); #infinite intersections
    return undef if( sin( $alpha1 ) * sin( $alpha2 ) < 0 ); #ambiguous intersection

    my $alpha3 = acos( -cos( $alpha1 ) * cos( $alpha2 ) + sin( $alpha1 ) * sin( $alpha2 ) * cos( $dist12 ) );
    my $dist13 = atan2( sin( $dist12 ) * sin( $alpha1 ) * sin( $alpha2 ), cos( $alpha2 ) + cos( $alpha1 ) * cos( $alpha3 ) );
    my $lat3 = asin( sin( $lat1 ) * cos( $dist13 ) + cos( $lat1 ) * sin( $dist13 ) * cos( $brng13 ) );
    my $dlon13 = atan2( sin( $brng13 ) * sin( $dist13 ) * cos( $lat1 ), cos( $dist13 ) - sin( $lat1 ) * sin( $lat3 ) );
    my $lon3 = POSIX::fmod( $lon1 + $dlon13 + ( pi * 3 ), pi2 ) - pi;

    return {
        lat => $self->_precision( Math::Trig::rad2deg($lat3), $precision ),
        lon => $self->_precision( Math::Trig::rad2deg($lon3), $precision ),
    };
}

=head2 distance_at

Returns the distance in meters for 1deg of latitude and longitude at the
specified latitude

 my $m_distance = $self->distance_at([$precision]);
 my $m_distance = $self->distance_at();
 # at lat 2 with precision -6 returns { m_lat => 110575.625009, m_lon => 111252.098718 }

=cut

method distance_at(Int $precision? = -6 ) returns (HashRef[Num]) {
    my $lat = deg2rad( $self->get_lat() );

    # Set up "Constants"
    my $m1 = 111132.92; # latitude calculation term 1
    my $m2 = -559.82;   # latitude calculation term 2
    my $m3 = 1.175;     # latitude calculation term 3
    my $m4 = -0.0023;   # latitude calculation term 4
    my $p1 = 111412.84; # longitude calculation term 1
    my $p2 = -93.5;     # longitude calculation term 2
    my $p3 = 0.118;     # longitude calculation term 3 

    return {
        m_lat => $self->_precision( $m1 + ($m2 * cos(2 * $lat)) + ($m3 * cos(4 * $lat)) + ( $m4 * cos(6 * $lat) ), $precision ),
        m_lon => $self->_precision( ( $p1 * cos($lat)) + ($p2 * cos(3 * $lat)) + ($p3 * cos(5 * $lat) ), $precision ),
    }
}

sub _precision {
    my ( $self, $number, $precision ) = @_;

    die "Error: Private method called" unless (caller)[0]->isa( ref($self) );

    my $mbf = Math::BigFloat->new( $number );
    $mbf->precision( $precision );

    return $mbf->bstr() + 0;
}

sub _ib_precision {
    my ( $self, $brng, $precision, $mul ) = @_;

    $mul ||= 1;

    die "Error: Private method called" unless (caller)[0]->isa( ref($self) );

    my $mbf = Math::BigFloat->new( POSIX::fmod( $mul * ( Math::Trig::rad2deg( $brng ) ) + 360, 360 ) );
    $mbf->precision( $precision );

    return $mbf->bstr() + 0;
}

sub _fb_precision {
    my ( $self, $brng, $precision ) = @_;

    die "Error: Private method called" unless (caller)[0]->isa( ref($self) );

    my $mbf = Math::BigFloat->new( POSIX::fmod( ( Math::Trig::rad2deg( $brng ) ) + 180, 360 ) );
    $mbf->precision( $precision );

    return $mbf->bstr() + 0;
}

no Moose;
__PACKAGE__->meta->make_immutable;

=head1 BUGS

All complex software has bugs lurking in it, and this module is no
exception.

Please report any bugs through the web interface at L<http://rt.cpan.org>.

=head1 AUTHOR

Sorin Alexandru Pop C<< <asp@cpan.org> >>

=head1 LICENSE

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

See L<http://www.perl.com/perl/misc/Artistic.html>

=cut

__END__

1;



( run in 3.150 seconds using v1.01-cache-2.11-cpan-302cb4679cc )