Geo-Index
view release on metacpan or search on metacpan
float sin_lat_diff_over_2 = sinf( ( lat_0 - f_lat_1 ) / 2.0 );
float sin_lon_diff_over_2 = sinf( ( lon_0 - f_lon_1 ) / 2.0 );
float n = ( sin_lat_diff_over_2 * sin_lat_diff_over_2 )
+ (
( sin_lon_diff_over_2 * sin_lon_diff_over_2 )
* f_cos_lat_1
* cosf( lat_0 )
);
/* The haversine formula may get messy around antipodal points so clip to the largest sane value. */
if ( n < 0.0 ) { n = 0.0; }
return f_diameter * asinf( sqrtf(n) );
}
/* Functions using doubles */
double d_diameter, d_lat_1, d_lon_1;
double sin_lat_diff_over_2 = sin( ( lat_0 - d_lat_1 ) / 2.0 );
double sin_lon_diff_over_2 = sin( ( lon_0 - d_lon_1 ) / 2.0 );
double n = ( sin_lat_diff_over_2 * sin_lat_diff_over_2 )
+ (
( sin_lon_diff_over_2 * sin_lon_diff_over_2 )
* d_cos_lat_1
* cos( lat_0 )
);
/* The haversine formula may get messy around antipodal points so clip to the largest sane value. */
if ( n < 0.0 ) { n = 0.0; }
return d_diameter * asin( sqrt(n) );
}
/* End of C code */
MODULE = Geo::Index PACKAGE = Geo::Index
PROTOTYPES: DISABLE
lib/Geo/Index.pm view on Meta::CPAN
($closest) = $index->Closest( [ -80, 20 ] );
print "$$closest{name}\n"; # Also prints 'South Pole'
($closest) = $index->Closest( $points[1], { post_condition=>'NONE' } );
print "$$closest{name}\n"; # Also prints 'South Pole'
($farthest) = $index->Farthest( [ 90, 0 ] );
print "$$farthest{name}\n"; # Also prints 'South Pole'
# Compute distance in meters between two points (using haversine formula)
$m = $index->Distance( { lat=>51.507222, lon=>-0.1275 }, [ -6.2, 106.816667 ] );
printf("London to Jakarta: %i km\n", $m / 1000);
$index->DistanceFrom( [ 90, 0 ] );
$m = $index->DistanceTo( $points[1] );
printf("Pole to pole: %i km\n", $m / 1000);
=head1 DESCRIPTION
lib/Geo/Index.pm view on Meta::CPAN
B<C<lon_rad>> - The point's longitude in radians [ -pi .. pi )
=item *
B<C<circumference>> - Circumference (in meters) of the circle of latitude
that the point falls on. This is computed from the body's equatorial
circumference assuming a spherical (not an oblate) body.
=item *
B<C<search_result_distance>> - Distance (in meters) of point from search
point of previous search. The distance computation assumes a spherical body
and is computed using a ruggedized version of the haversine formula. This
value is only generated when C<L<Search(...)|/Search( ... )>> is called with the C<radius>
or C<sort_results> option. See also C<L<Distance(...)|/Distance( ... )>>, C<L<DistanceFrom(...)|/DistanceFrom( ... )>>,
and C<L<DistanceTo(...)|/DistanceTo( ... )>>.
=item *
B<C<antipode_distance>> - Distance (in meters) of point from search
point's antipode as determined by a previous call to C<L<Farthest(...)|/Farthest( ... )>>.
This distance is computed using a ruggedized version of the haversine formula.
=back
As a convenience, most methods allow points to be specified using a shorthand
notation S<C<[ I<lat>, I<lon> ]>> or S<C<[ I<lat>, I<lon>, I<data> ]>>. Points
given in this notation will be converted to hash-based points. If a point
created using this notation is returned as a search result it will be as a
reference to the hash constructed by Geo::Index and not as a reference to the
original array. To access the data field of a point created using the shorthand
notation use C<$$point{'data'}> where C<$point> is a search result point.
lib/Geo/Index.pm view on Meta::CPAN
$$p1{lat_rad} = Math::Trig::deg2rad($$p1{lat}) unless ($$p1{lat_rad});
$$p1{lon_rad} = Math::Trig::deg2rad($$p1{lon}) unless ($$p1{lon_rad});
return HaversineDistance($$p1{lat_rad}, $$p1{lon_rad});
}
#. Distance functions
#.
#. Geo::Index uses the haversine formula to compute great circle distances
#. between points.
#.
#. Three versions are supported: a fallback version written in Perl (used if the
#. C versions fail to compile) and two accelerated versions written in C, one
#. using floats and the other using doubles. By default the C float version is
#. used; if it fails to compile then the Perl version is used. Use of a specific
#. version can also be requested with Geo::Index->SetDistanceFunctionType(...).
#.
#. The Perl version uses doubles. When using floats instead of doubles the loss
#. of precision is typically under a meter (about 2 meters in the worst case).
lib/Geo/Index.pm view on Meta::CPAN
my $sin_lat_diff_over_2 = sin( ( $lat_0 - $DistanceFrom_lat_1 ) / 2.0 );
my $sin_lon_diff_over_2 = sin( ( $lon_0 - $DistanceFrom_lon_1 ) / 2.0 );
my $n = ( $sin_lat_diff_over_2 * $sin_lat_diff_over_2 )
+ (
( $sin_lon_diff_over_2 * $sin_lon_diff_over_2 )
* $DistanceFrom_cos_lat_1
* cos( $lat_0 )
);
#. The haversine formula may get messy around antipodal points so clip to the largest sane value.
if ( $n < 0.0 ) { $n = 0.0; }
return $DistanceFrom_diameter * asin( sqrt($n) );
}
=head2 GetConfiguration( )
lib/Geo/Index.pm view on Meta::CPAN
This could be encountered in a number of ways. For example, a search using a
condition function that itself runs a search against the second index could be
problematic. This could be encountered even when using a single index. For
example, if code relies on the distances values from a search it should save a
copy of them before running subsearches against the same set of points. If this
is not done then the distance values from the first search may be overwritten by
those of the subsequent searches.
=item *
Geo::Index uses the spherical haversine formula to compute distances. While
quite fast, its accuracy over long distances is poor, with a worst case error
of about 0.1% (22 km). Since the module already has provision for changing the
backends used for the distance methods, adding a new backend to, for example,
compute accurate distances on e.g. a WGS-84 spheroid would be simple and
straight-forward.
=item *
In places the code can be repetitious or awkward in style. This was done
because, especially in the inner loops, speed has been favoured over clarity.
( run in 1.484 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )