PHP Extension to handle common geospatial functions.

Overview

geospatial - PHP Geospatial Extension

https://travis-ci.org/php-geospatial/geospatial.svg?branch=master https://codecov.io/gh/php-geospatial/geospatial/branch/master/graphs/badge.svg?branch=master

PHP Extension to handle common geospatial functions. The extension currently has implementations of the Haversine and Vincenty's formulas for calculating distances, an initial bearing calculation function, a Helmert transformation function to transfer between different supported datums, conversions between polar and Cartesian coordinates, conversions between Degree/Minute/Seconds and decimal degrees, a method to simplify linear geometries, as well as a method to calculate intermediate points on a LineString.

Instalation

git clone [email protected]:php-geospatial/geospatial.git
cd geospatial
phpize
./configure --enable-geospatial
make
sudo make install

Then add the extension to an ini file e.g. /etc/php.ini:

extension = geospatial.so

Usage

The extension makes use of the GeoJSON standard format for specifying points as co-ordinates. One important thing to note about this format is that points are specified longitude first i.e. longitude, latitude.

e.g.:

$greenwichObservatory = array(
    'type' => 'Point',
    'coordinates' => array( -0.001483 , 51.477917);
);

Haversine

$from = array(
    'type' => 'Point',
    'coordinates' => array( -104.88544, 39.06546 )
);
$to = array(
    'type' => 'Point',
    'coordinates' => array( -104.80, 39.06546 )
);
var_dump(haversine($to, $from));

Vincenty's Formula

Vincenty's formula attempts to provide a more accurate distance between two points than the Haversine formula. Whereas the Haversine formula assumes a spherical earth the Vincenty method models the earth as an ellipsoid:

$flinders = array(
    'type' => 'Point',
    'coordinates' => array(144.42486788889, -37.951033416667 )
);
$buninyong = array(
    'type' => 'Point',
    'coordinates' => array(143.92649552778, -37.652821138889 )
);
var_dump(vincenty($flinders, $buninyong));

Helmert Transformation

The Helmert transformation allows for the transformation of points between different datums. It can for instance be used to convert between the WGS84 ellipsoid (GEO_WGS84) used by GPS systems and OSGB36 (GEO_AIRY_1830) used by Ordnance Survey in the UK:

$greenwichObservatory = array(
    'type' => 'Point',
    'coordinates' => array(-0.0014833333333333 , 51.477916666667)
);

$greenwichObservatoryWGS84 = transform_datum($greenwichObservatory, GEO_WGS84, GEO_AIRY_1830);

var_dump($greenwichObservatoryWGS84);

Calculating Initial Bearing

The initial_bearing function calculates the initial bearing to go from the first to the second point, as expressed in a GeoJSON wrapper:

$from = array(
        'type' => 'Point',
        'coordinates' => array( 2.351, 48.857 )
);
$to = array(
        'type' => 'Point',
        'coordinates' => array( 0.119, 52.205 )
);
var_dump(initial_bearing($from, $to));

The range of the resulting heading is 0° to +360°.

Converting between polar and Cartesian Coordinates

These two functions calculate between Polar and Cartesian Coordinates, with results depending on which ellipsoid you use.

From Polar to Cartesian:

$lat = 53.38361111111;
$long = 1.4669444444;

var_dump(polar_to_cartesian($lat, $long, GEO_AIRY_1830));

And back:

$x = 3810891.6734396;
$y = 97591.624686311;
$z = 5095766.3939034;

$polar = cartesian_to_polar($x, $y, $z, GEO_AIRY_1830);
echo round($polar['lat'], 6), PHP_EOL;
echo round($polar['long'], 6), PHP_EOL;
echo round($polar['height'], 3), PHP_EOL;

Converting between Degree/Min/Sec and Decimal coordinates

From decimal to dms. The second argument is either "longitude" or "latitude":

$dms = decimal_to_dms(-1.034291666667, 'longitude');
var_dump($dms);

Which outputs:

array(4) {
  ["degrees"]=> int(1)
  ["minutes"]=> int(2)
  ["seconds"]=> float(3.4500000011994)
  ["direction"]=> string(1) "W"
}

And back from DMS to decimal, where the fourth argument is either "N", "S", "E", or "W":

$decimal = dms_to_decimal(0, 6, 9, 'S');

Which outputs:

float(-0.1025)

Simplifying LineStrings

The rdp_simplify method implements RDP to simplify a LineString according to a certain accuracy (epsilon). As first argument it takes a GeoJSON LineString (in PHP variable format), and it outputs a similar structure but then simplified

Interpolation along a Greater Circle Line

The fraction_along_gc_line function can be used to calculate intermediate points along a Greater Circle Line. For example if you need to draw lines with more accuracy with for example Leaflet. The function takes the start and end coordinates (as GeoJson Point), and calculates the intermediate point along those line. To calculate the point 25% from the start point to the end point, you would use:

$point1 = [ 'type' => 'Point', 'coordinates' => [  5, 10 ] ];
$point2 = [ 'type' => 'Point', 'coordinates' => [ 15, 10 ] ];

var_dump(fraction_along_gc_line($point1, $point2, 0.25));

Geohashing

The geohash_encode function can be used to convert GeoJSON Point to a geohash of a specific length (in this case, 12):

$point = [ 'type' => 'Point', 'coordinates' => [ 16.4, 48.2 ] ];
echo geohash_encode( $point, 12 );

Which outputs:

u2edjnw17enr

Similarly, a hashed coordinates pair can be decoded using geohash_decode function:

var_dump(geohash_decode('u2edjnw17enr'));
array(2) {
  ["type"]=>
  string(5) "Point"
  ["coordinates"]=>
  array(2) {
        [0]=>
        float(16.40000006184)
        [1]=>
        float(48.199999993667)
  }
}
Comments
  • Add geohashing capabilities

    Add geohashing capabilities

    I'd like to propose two new functionalities to be added to geospatial extension:

    • geohash_encode
    • geohash_decode

    Geohash is a geocoding system invented by Gustavo Niemeyer. https://en.wikipedia.org/wiki/Geohash

    There is a significant performance gain from using this extension compared to user-land libraries.

    Source code is available at https://github.com/emirb/php-geohash-ext Rather than creating a standalone extension for the sole purpose of dealing with geohashes, a mutual agreement has been met concerning merging it to the existing geospatial PHP extension.

    opened by emirb 5
  • Add functions to convert between WGS-84 and OSGB36

    Add functions to convert between WGS-84 and OSGB36

    Using my rudimentary knowledge of C I have implemented the helmert transformation and some other functions to make it useful.

    This may be completely the wrong way to do it and I am happy to change any of it but just thought it would be good to get the functions in there.

    I based the calculations on the spreadsheet www.ordnancesurvey.co.uk/oswebsite/gps/docs/ProjectionandTransformationCalculations.xls which seemed to be a pretty accurate source.

    opened by natmchugh 5
  • Travis tests

    Travis tests

    • Added Travis tests (including upcoming PHP 7.2) so we can have matrix-based tests for all PHP versions.
    • Added codecov integration for generating code coverage
    opened by emirb 3
  • Helmert transformation

    Helmert transformation

    Using my rudimentary knowledge of C I have implemented the helmert transformation and some other functions to make it useful.

    This may be completely the wrong way to do it and I am happy to change any of it but just thought it would be good to get the functions in there.

    I based the calculations on the spreadsheet www.ordnancesurvey.co.uk/oswebsite/gps/docs/ProjectionandTransformationCalculations.xls which seemed to be a pretty accurate source.

    opened by natmchugh 3
  • make test errors

    make test errors

     make test
    /bin/bash /tmp/geospatial/libtool --mode=install cp ./geospatial.la /tmp/geospatial/modules
    libtool: install: cp ./.libs/geospatial.so /tmp/geospatial/modules/geospatial.so
    libtool: install: cp ./.libs/geospatial.lai /tmp/geospatial/modules/geospatial.la
    libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/sbin" ldconfig -n /tmp/geospatial/modules
    ----------------------------------------------------------------------
    Libraries have been installed in:
       /tmp/geospatial/modules
    
    If you ever happen to want to link against installed libraries
    in a given directory, LIBDIR, you must either use libtool, and
    specify the full pathname of the library, or use the '-LLIBDIR'
    flag during linking and do at least one of the following:
       - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
         during execution
       - add LIBDIR to the 'LD_RUN_PATH' environment variable
         during linking
       - use the '-Wl,-rpath -Wl,LIBDIR' linker flag
       - have your system administrator add LIBDIR to '/etc/ld.so.conf'
    
    See any operating system documentation about shared libraries for
    more information, such as the ld(1) and ld.so(8) manual pages.
    ----------------------------------------------------------------------
    
    Build complete.
    Don't forget to run 'make test'.
    
    
    =====================================================================
    PHP         : /usr/bin/php7.2 
    PHP_SAPI    : cli
    PHP_VERSION : 7.2.3-1ubuntu1
    ZEND_VERSION: 3.2.0
    PHP_OS      : Linux - Linux 746209f08f68 4.15.0-13-generic #14-Ubuntu SMP Sat Mar 17 13:44:27 UTC 2018 x86_64
    INI actual  : /tmp/geospatial/tmp-php.ini
    More .INIs  :   
    ---------------------------------------------------------------------
    PHP         : /usr/bin/phpdbg7.2 
    PHP_SAPI    : phpdbg
    PHP_VERSION : 7.2.3-1ubuntu1
    ZEND_VERSION: 3.2.0
    PHP_OS      : Linux - Linux 746209f08f68 4.15.0-13-generic #14-Ubuntu SMP Sat Mar 17 13:44:27 UTC 2018 x86_64
    INI actual  : /tmp/geospatial/tmp-php.ini
    More .INIs  : 
    ---------------------------------------------------------------------
    CWD         : /tmp/geospatial
    Extra dirs  : 
    VALGRIND    : Not used
    =====================================================================
    TIME START 2018-04-07 10:13:43
    =====================================================================
    PASS WGS84 to OSGB36 for Greenwich Observertory [tests/Greenwich.phpt] 
    PASS WGS84 to OSGB36 [tests/JodrellBank.phpt] 
    PASS OSGB36 to WGS84 [tests/OSGB36_to_WGS84.phpt] 
    PASS WGS84 to OSGB36 [tests/WGS84_to_OSGB36.phpt] 
    FAIL Test for issue #16: Segfault on rdp_simplify for GeoJSON [tests/bug0016.phpt] 
    PASS Test cartesian to polar [tests/cartesian_to_polar.phpt] 
    PASS degrees minutes seconds [tests/decimal_to_dms.phpt] 
    PASS dms_to_decimal() [tests/dms_to_decimal.phpt] 
    PASS Test for "fraction_along_gc_line" #1 [tests/fraction_along-001.phpt] 
    PASS Test for "fraction_along_gc_line" #2 [tests/fraction_along-002.phpt] 
    PASS Test for "fraction_along_gc_line" #3 [tests/fraction_along-003.phpt] 
    PASS Test geohash_decode [tests/geohash_decode.phpt] 
    PASS Test geohash_encode [tests/geohash_encode.phpt] 
    PASS Check the haversine function returns the correct distance between London and Edinburgh. [tests/geospatial_haversine_london_edinburgh.phpt] 
    PASS Check the haversine function returns the correct distance between the North and South poles, using a custom radius. [tests/geospatial_haversine_polar_distance.phpt] 
    PASS haversine() function - basic test for haversine forumla [tests/haversine.phpt] 
    PASS helmert() function - basic test for helmert formula [tests/helmert.phpt] 
    PASS initial_bearing() function - basic test for initial_bearing forumla [tests/initial_bearing.phpt] 
    PASS Test polar to cartesian [tests/polar_to_cartesian.phpt] 
    PASS Test for "Vincenty" distance between FlindersPeak and Buninyong [tests/vincenty.phpt] 
    =====================================================================
    TIME END 2018-04-07 10:13:43
    
    =====================================================================
    TEST RESULT SUMMARY
    ---------------------------------------------------------------------
    Exts skipped    :    0
    Exts tested     :   15
    ---------------------------------------------------------------------
    
    Number of tests :   20                20
    Tests skipped   :    0 (  0.0%) --------
    Tests warned    :    0 (  0.0%) (  0.0%)
    Tests failed    :    1 (  5.0%) (  5.0%)
    Expected fail   :    0 (  0.0%) (  0.0%)
    Tests passed    :   19 ( 95.0%) ( 95.0%)
    ---------------------------------------------------------------------
    Time taken      :    0 seconds
    =====================================================================
    
    =====================================================================
    FAILED TEST SUMMARY
    ---------------------------------------------------------------------
    Test for issue #16: Segfault on rdp_simplify for GeoJSON [tests/bug0016.phpt]
    =====================================================================
    
    
    opened by mhf-ir 2
  • Segfault on rdp_simplify for GeoJSON

    Segfault on rdp_simplify for GeoJSON

    rdp_simplify method segfaults when passing GeoJSON data as an array (returns NULL if object or a string). This works if you just pass the coordinate array, but this isn't as described in the documentation.

    To recreate:

    $geojson = json_decode('{"type":"LineString","coordinates":[[0,0],[1,0],[2,0],[2,1],[2,2],[1,2],[0,2],[0,1],[0,0]]}', true);
    
    var_dump(rdp_simplify($geojson, 1)); //segfault
    var_dump(rdp_simplify($geojson['coordinates'], 1)); //works
    
    bug 
    opened by rickogden 2
  • PHP 8 support

    PHP 8 support

    Is there any plan or timeline for supporting PHP 8? The current version fails to compile.

    I see there's a PR for adding support with the release candidate.

    opened by jaikdean 1
  • fixed the initial_bearing test

    fixed the initial_bearing test

    This test was failing, but the expected result was not matching other implementations of this algorithm. This has been updated with the correct result.

    opened by rickogden 1
  • Compile failure with PHP 5.6 on Windows (using VC11)

    Compile failure with PHP 5.6 on Windows (using VC11)

    The compilation fails on Windows with VC11 due to a mix of declarations and assignments in the code. VC11 does not support that (and neither does C!).

    opened by derickr 0
  • Vincenty

    Vincenty

    Been meaning to send in this for a while. Implemented vincenty inverse problem. Based it on http://en.wikipedia.org/wiki/Vincenty's_formulae and http://www.movable-type.co.uk/scripts/latlong-vincenty.html. Test case from http://www.ga.gov.au/geodesy/datums/vincenty_inverse.jsp.

    opened by natmchugh 0
  • Add Spherical Law Of Cosines method

    Add Spherical Law Of Cosines method

    Spherical Law Of Cosines is commonly used instead of Haversine due to better performance and very close results. Generally, if you need higher accuracy than SLOC, Haversine is probably too inaccurate as well.

    See here for an explaination of the quality aspect: http://gis.stackexchange.com/questions/4906/why-is-law-of-cosines-more-preferable-than-haversine-when-calculating-distance-b

    See here for documentation: https://en.wikipedia.org/wiki/Spherical_law_of_cosines

    If you want, I have PHP code for it, but it's pretty trivial to implement yourself.

    opened by vanderlee 3
Releases(RELEASE_0_1_0)
Owner
PHP Geospatial, putting the Elephpant on your globe
PHP Geospatial, putting the Elephpant on your globe
GeoSpatial integration on Laravel 5.2+ that supports MySQL and PostgreSQL.

Features GeoSpatial integration on Laravel 5.2+: Create geospatial columns using Schema and migrations Save and retrieve geospatial attributes using d

Eleven 47 Dec 22, 2022
Free database of geographic place names and corresponding geospatial data

FreeGeoDB Free database of geographic place names and corresponding geospatial data Entities airports cities countries (admin-0) lakes ports railroads

delight.im 1.6k Dec 15, 2022
IP2Location Yii extension enables the user to find the country, region, city, coordinates, zip code, time zone, ISP

IP2Location Yii extension enables the user to find the country, region, city, coordinates, zip code, time zone, ISP, domain name, connection type, area code, weather, MCC, MNC, mobile brand name, elevation, usage type, IP address type and IAB advertising category from IP address using IP2Location database. It has been optimized for speed and memory utilization. Developers can use the API to query all IP2Location BIN databases or web service for applications written using Yii.

IP2Location 7 May 21, 2022
GeoJSON implementation for PHP

GeoJson PHP Library This library implements the GeoJSON format specification. The GeoJson namespace includes classes for each data structure defined i

Jeremy Mikola 274 Dec 17, 2022
ESRI ShapeFile library for PHP

shapefile ShapeFile library for PHP Features Currently the 2D and 3D variants except MultiPatch of the ShapeFile format as defined in https://www.esri

phpMyAdmin 23 Jun 29, 2022
The most featured Geocoder library written in PHP.

Geocoder Important: You are browsing the documentation of Geocoder 4.x. Documentation for version 3.x is available here: Geocoder 3.x documentation. D

Geocoder 3.9k Jan 2, 2023
Simple Yet Powerful Geo Library for PHP

phpgeo - A Simple Geo Library for PHP phpgeo provides abstractions to geographical coordinates (including support for different ellipsoids) and allows

Marcus Jaschen 1.4k Dec 27, 2022
Geo-related tools PHP 5.4+ library built atop Geocoder and React libraries

Geotools Geotools is a PHP geo-related library, built atop Geocoder and React libraries. Features Batch geocode & reverse geocoding request(s) in seri

The League of Extraordinary Packages 1.3k Dec 27, 2022
PHP library to access the OpenCage geocoding API

OpenCage Geocoding API Library for PHP A PHP library to use the OpenCage geocoding API. Build Status / Code Quality Overview This library attempts to

OpenCage GmbH 29 Nov 15, 2022
PHP library for determining the physical location of binaries

Bin Locator Library for searching binary files in the operating system. Requirements PHP >= 7.4 Installation Library is available as composer reposito

PHP FFI 8 Jul 27, 2022
PHP library to easily get static image from French Cadastral Government map with markers and lines.

PHP French Cadastral Map Static API PHP library to easily get static image from French Cadastral Government map with markers and lines. Map source : c

Franck Alary 6 Nov 29, 2022
PHP library to easily get static image from OpenStreetMap (OSM) with markers and lines.

PHP OpenStreetMap Static API PHP library to easily get static image from OpenStreetMap with markers and lines. ✨ Supporting ⭐ Star this repository to

Franck Alary 34 Jan 2, 2023
Official PHP library for IPinfo (IP geolocation and other types of IP data)

This is the official PHP client library for the IPinfo.io IP address API, allowing you to lookup your own IP address,

IPinfo 171 Jan 2, 2023
Laravel package to work with geospatial data types and functions.

Laravel Spatial Laravel package to work with geospatial data types and functions. For now it supports only MySql Spatial Data Types and Functions. Sup

Tarfin 47 Oct 3, 2022
PHP extension for geospatial rendering with Mapnik

PHP7 Mapnik Introduction This project is an extension for PHP 7 that enables geospatial rendering with Mapnik. Create tile generation scripts, dynamic

Garrett Johnson 20 Dec 14, 2022
PHP Functional Programming library. Monads and common use functions.

Functional PHP PHP Functional Programming library. Monads and common use functions. Documentation Functions Monads Installation Composer $ composer re

Alexander Sv. 169 Dec 27, 2022
GeoSpatial integration on Laravel 5.2+ that supports MySQL and PostgreSQL.

Features GeoSpatial integration on Laravel 5.2+: Create geospatial columns using Schema and migrations Save and retrieve geospatial attributes using d

Eleven 47 Dec 22, 2022
Free database of geographic place names and corresponding geospatial data

FreeGeoDB Free database of geographic place names and corresponding geospatial data Entities airports cities countries (admin-0) lakes ports railroads

delight.im 1.6k Dec 15, 2022
Here is the top 100 PHP functions: it is the list of the most often used PHP native functions

Here is the top 100 PHP functions: it is the list of the most often used PHP native functions. If you are a PHP developer, you must know the Top 100 PHP Functions deeply.

Max Base 16 Dec 11, 2022
Simple MySQL library for PHP 5.4+ includes Query Builder, PDO Native functions, Helper functions for quick use.

Simple MySQL library for PHP 5.4+ includes Query Builder, PDO Native functions, Helper functions for quick use.

Kodols 9 Dec 22, 2022