Geo-Index
view release on metacpan or search on metacpan
273274275276277278279280281282283284285286287288289290291292293
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;
304305306307308309310311312313314315316317318319320321322323324
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
168169170171172173174175176177178179180181182183184185186187
(
$closest
) =
$index
->Closest( [ -80, 20 ] );
"$$closest{name}\n"
;
# Also prints 'South Pole'
(
$closest
) =
$index
->Closest(
$points
[1], {
post_condition
=>
'NONE'
} );
"$$closest{name}\n"
;
# Also prints 'South Pole'
(
$farthest
) =
$index
->Farthest( [ 90, 0 ] );
"$$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
241242243244245246247248249250251252253254255256257258259260261262263264265266267268269B<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
380138023803380438053806380738083809381038113812381338143815381638173818381938203821
$$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
39783979398039813982398339843985398639873988398939903991399239933994399539963997
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
550055015502550355045505550655075508550955105511551255135514551555165517551855195520This 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 0.262 second using v1.01-cache-2.11-cpan-496ff517765 )