Geo-Index

 view release on metacpan or  search on metacpan

Index.xs  view on Meta::CPAN

273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
        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;

Index.xs  view on Meta::CPAN

304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
        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

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
    
  ($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

241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
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

3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
        $$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

3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
        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

5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
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 0.262 second using v1.01-cache-2.11-cpan-496ff517765 )