Simple Yet Powerful Geo Library for PHP

Last update: Jul 29, 2022

phpgeo - A Simple Geo Library for PHP

phpgeo provides abstractions to geographical coordinates (including support for different ellipsoids) and allows you to calculate geographical distances between coordinates with high precision.

Latest Stable Version Total Downloads phpgeo Tests Scrutinizer Code Quality License

Table of Contents

Requirements

Minimum required PHP version is 7.2. phpgeo fully supports PHP 8.0.

The 2.x releases require PHP >= 7.0 but don't get feature updates any longer. Bugfixes will be backported.

The 1.x release line has support for PHP >= 5.4. Bugfixes won't be backported.

Documentation

The documentation is available at https://phpgeo.marcusjaschen.de/

API documentation is available as well: https://phpgeo.marcusjaschen.de/api/

Installation

Using Composer, just add it to your composer.json by running:

composer require mjaschen/phpgeo

License

Starting with version 2.0.0 phpgeo is licensed under the MIT license. Older versions were GPL-licensed.

Features

Info: Please visit the documentation site for complete and up-to-date documentation with many examples!

phpgeo provides the following features (follow the links for examples):

Examples/Usage

This list is incomplete, please visit the documentation site for the full monty of documentation and examples!

Distance between two coordinates (Vincenty's Formula)

Use the calculator object directly:

<?php

use Location\Coordinate;
use Location\Distance\Vincenty;

$coordinate1 = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit
$coordinate2 = new Coordinate(20.709722, -156.253333); // Haleakala Summit

$calculator = new Vincenty();

echo $calculator->getDistance($coordinate1, $coordinate2); // returns 128130.850 (meters; ≈128 kilometers)

or call the getDistance() method of a Coordinate object by injecting a calculator object:

<?php

use Location\Coordinate;
use Location\Distance\Vincenty;

$coordinate1 = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit
$coordinate2 = new Coordinate(20.709722, -156.253333); // Haleakala Summit

echo $coordinate1->getDistance($coordinate2, new Vincenty()); // returns 128130.850 (meters; ≈128 kilometers)

Simplifying a polyline

Polylines can be simplified to save storage space or bandwidth. Simplification is done with the Ramer–Douglas–Peucker algorithm (AKA Douglas-Peucker algorithm).

<?php

use Location\Coordinate;
use Location\Polyline;
use Location\Distance\Vincenty;

$polyline = new Polyline();
$polyline->addPoint(new Coordinate(10.0, 10.0));
$polyline->addPoint(new Coordinate(20.0, 20.0));
$polyline->addPoint(new Coordinate(30.0, 10.0));

$processor = new Simplify($polyline);

// remove all points which perpendicular distance is less
// than 1500 km from the surrounding points.
$simplified = $processor->simplify(1500000);

// simplified is the polyline without the second point (which
// perpendicular distance is ~1046 km and therefore below
// the simplification threshold)

Polygon contains a point (e.g. "GPS geofence")

phpgeo has a polygon implementation which can be used to determinate if a point is contained in it or not. A polygon consists of at least three points. Points are instances of the Coordinate class.

Warning: The calculation gives wrong results if the polygons has points on both sides of the 180/-180 degrees meridian.

<?php

use Location\Coordinate;
use Location\Polygon;

$geofence = new Polygon();

$geofence->addPoint(new Coordinate(-12.085870,-77.016261));
$geofence->addPoint(new Coordinate(-12.086373,-77.033813));
$geofence->addPoint(new Coordinate(-12.102823,-77.030938));
$geofence->addPoint(new Coordinate(-12.098669,-77.006476));

$outsidePoint = new Coordinate(-12.075452, -76.985079);
$insidePoint = new Coordinate(-12.092542, -77.021540);

var_dump($geofence->contains($outsidePoint)); // returns bool(false) the point is outside the polygon
var_dump($geofence->contains($insidePoint)); // returns bool(true) the point is inside the polygon

Formatted output of coordinates

You can format a coordinate in different styles.

Decimal Degrees

<?php

use Location\Coordinate;
use Location\Formatter\Coordinate\DecimalDegrees;

$coordinate = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit

echo $coordinate->format(new DecimalDegrees());

Degrees/Minutes/Seconds (DMS)

<?php

use Location\Coordinate;
use Location\Formatter\Coordinate\DMS;

$coordinate = new Coordinate(18.911306, -155.678268); // South Point, HI, USA

$formatter = new DMS();

echo $coordinate->format($formatter); // 18° 54′ 41″ -155° 40′ 42″

$formatter->setSeparator(", ")
    ->useCardinalLetters(true)
    ->setUnits(DMS::UNITS_ASCII);

echo $coordinate->format($formatter); // 18° 54' 41" N, 155° 40' 42" W

GeoJSON

<?php

use Location\Coordinate;
use Location\Formatter\Coordinate\GeoJSON;

$coordinate = new Coordinate(18.911306, -155.678268); // South Point, HI, USA

echo $coordinate->format(new GeoJSON()); // { "type" : "point" , "coordinates" : [ -155.678268, 18.911306 ] }

Development

Run Tests

Before submitting a pull request, please be sure to run all checks and tests and ensure everything is green.

  • lint PHP files for syntax errors: composer ci:lint
  • run static analysis with Psalm and report errors: composer ci:psalm
  • run unit tests with PHPUnit: composer ci:tests

To run all checks and tests at once, just use composer ci.

Of course, it's possible to use the test runners directly, e.g. for PHPUnit:

./vendor/bin/phpunit

Psalm:

./vendor/bin/psalm

Miscellaneous

@clemdesign created a TypeScript port of phpgeo.

Credits

GitHub

https://github.com/mjaschen/phpgeo
Comments
  • 1. Perpendicular distance between point and line segment

    This library can calculate perpendicular distance between point and great circle passing trough two points.

    It can calculate distance between two points.

    What about a line segment? Perpendicular distance may not exists between point and line segment on great circle -> how to check that?

    That can be useful when calculating minimum distance between point and line.

    Thanks.

    Reviewed by TheCelavi at 2017-03-10 11:44
  • 2. Calculation is wrong.

    I tried a straight actual GPS track from real device and calculated distance to be 128Km and by processing each coordinate individually using polyline method it comes out to be 97.2

    Reviewed by v920749 at 2015-03-26 08:08
  • 3. Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Latitude value must be numeric -90.0 .. +90.0'

    Hi. i using phpgeo for get nearby locations and everything works fine on my local. but on my server it returns this error: Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Latitude value must be numeric -90.0 .. +90.0' in /home/jaajim/public/public/plugins/jaajim-api/Location/Coordinate.php on line 56 ... $ php -v PHP 5.5.9-1ubuntu4.5 ... you can see the full error in this api call: https://jaajim.com/api/v1/nearby_locations?lat=35.7001673&lng=51.4056248&radius=2000

    thanks for your great job

    Reviewed by alijmlzd at 2014-12-17 13:23
  • 4. Point-to-line distance is incorrect sometimes

    Version of phpgeo: 4.1.0

    $ll1 = array (
        'lat' => 55.98467000751469413444283418357372283935546875,
        'lon' => 13.544430000324179985682349069975316524505615234375,
    );
    $ll2 = array (
        'lat' => 55.98461833972562118333371472544968128204345703125,
        'lon' => 13.54429500218709137016048771329224109649658203125,
    );
    $p = array (
        'lat' => 55.97609299999999876717993174679577350616455078125,
        'lon' => 13.5475989999999999469082467840053141117095947265625,
    );
    
    $dist = $pointToLineDistanceCalculator->getDistance(
        new Coordinate($p['lat'], $p['lon']), 
        new Line(
            new Coordinate($ll1['lat'], $ll1['lon']), 
            new Coordinate($ll2['lat'], $ll2['lon'])
        )
    );
    

    Result

    898.46032179829 meters
    

    But multiple other tools and formulas give a different result, around 971 meters, differing almost 100 meters!

    I've seen similar differences on other line segments and coordinates too, but the above one is a really big difference. Any ideas what's going on here? Which one is correct??

    Reviewed by magnuswikhog at 2022-07-22 13:25
  • 5. composer error

    - The requested package mjaschen/phpgeo No version set (parsed as 1.0.0) is
    

    satisfiable by mjaschen/phpgeo[No version set (parsed as 1.0.0)] but these confl ict with your requirements or minimum-stability.

    Reviewed by tamer-dahdul at 2018-11-20 11:28
  • 6. Formatter returns too many decimals.

    I want to use PHPGeo for simplifying lines in geojson files.

    PHP has a precision set to 8 (Leaving 6 decimals for the coordinates)

    I add points to a new Polyline with addPoint and new Coordinate.

    $line = new Polyline; foreach ($feature['geometry']['coordinates'] as $coordA){ $line->addPoint(new Coordinate($coordA[1],$coordA[0])); }

    I.e. the first coordinates from $feature['geometry']['coordinates'] are Lng: 15.640289 Lat: 60.604169

    For debugging I'm outputting to my html with: $formatter = new GeoJSON; echo var_dump($line->getPoints()[0]).'<br>'; echo $line->format(new GeoJSON()).'<br>'; The var dump on the points shows that the Polyline does indeed only have 6 decimals. But the echo on the results from the format shows Lng and Lat with this amount of decimals: Lng: 15.6402892857124840020333067514002323150634765625 Lat: 60.6041694346744890253830817528069019317626953125

    Which defeats the whole purpose of my simplification goal. As I save more bandwidth by just removing decimals. I don't want precision on subatomic levels.

    Edit: Fixed some typos. Was in a hurry when I wrote it.

    Reviewed by WeeRuz at 2018-11-08 08:12
  • 7. "Longitude value must be numeric" bad exception

    I get Longitude value must be numeric -180.0 .. +180.0 (given: 180) and looks like I should be able to put 180, right?

    This is because in < instead of <= https://github.com/mjaschen/phpgeo/blob/3a03fe3df865cac5aa8a6383052b29eda2137098/src/Coordinate.php#L177

    Reviewed by jonyrock at 2020-07-11 06:32
  • 8. PerpendicularDistance reports 21k meters on a distance of about 192k

    If you look at this GeoJSON demonstration:

    http://geojson.io/#id=gist:acidjazz/8cd03298ddf9bf42168a9ded77577dcf&map=9/29.9216/-94.4000

    I have a line drawn near Lake Charles, and a point set near Kingwood, about 120 miles away.

    The following code results in 21,989 meters for those coordinates:

        $perp = new PerpendicularDistance();
        $line = new Line(
            new Coordinate(29.888044473729,-93.580916446874),
            new Coordinate(29.890583508738,-93.552272621677),
        );
    
        $point = new Coordinate(29.941561, -95.118365);
    
        dd($perp->getPerpendicularDistance($point, $line));
    

    This returns 21989.019190836

    Now doing a point distance results in 148k-151k, ex:

        dump($line->getPoint1()->getDistance($point, new Haversine()));
        dd($line->getPoint2()->getDistance($point, new Haversine()));
    

    this results in:

    148298.123

    151043.798

    Reviewed by acidjazz at 2019-12-16 20:53
  • 9. Given a point and a distance, is it possible to compute the corresponding extent ?

    Hello,

    I am trying to compute the extent ((latMin, latMax), (lngMin, lngMax)), from a point (Coordinate object) and a distance.

    Is there an easy way to do that ? I am not familiar with GPS coordinates yet.

    Thank for your time.

    Reviewed by felixveysseyre at 2017-06-29 18:00
  • 10. Polygon getArea method

    Hello,

    First thank you for this awesome library !

    I am trying to compute the area of a polygon. Looking at the implementation of you Polygon class, there is a getArea method. Looking at the annotation, the method is giving false results.

    It is still true ? Do you have any idea when it will be fixed ?

    Best,

    Reviewed by felixveysseyre at 2017-06-29 17:52
  • 11. More permissive license?

    Hi,

    I just want to first off say thanks for making such a nice library, I played around with it a bit and It's definitely I want to use. Unfortunately due to the GPL license it seems that including within our codebase at work will effectively cause us to be violation of the GPL unless we open source our codebase. Considering we are a tech startup, this isn't an option.

    I don't have any issues contributing any changes changes back to open source which LGPL enforces but forcing to open source our code base is a deal breaker for us.

    Reviewed by Shard at 2017-01-25 08:26
  • 12. Point directions

    This library provides a class to calculate relative directions between two points (cardinal direction). I don't know about the history of this feature but from a user point of view, it would be handy if this was an integrated method of a point (formerly coordinate):

    $point1->isNorthOf($point2); // returns true/false
    $point1->directionOf($point2); // returns 'north|south|west|east'
    
    Reviewed by nilshoerrmann at 2022-06-01 13:52
  • 13. Explanation of warning for non-geo wiz

    Can you please explain the line:

    Warning: The calculation gives wrong results if the polygons has points on both sides of the 180/-180 degrees meridian.

    Maybe you can give a visual example of when these results would be wrong? I'm looking to use this library for shipping calculations where "shipping zones" will be created and the shipping cost will be determined by which polygon the customer's current location falls within. So needless to say wrong results can result in incontinences for the store trying to explain that it was a mistake to customers.

    Currently I'm making use of the Google Maps API Geometry library for this: https://developers.google.com/maps/documentation/javascript/examples/poly-containsLocation but I'd like to use PHP instead if i can find a library which is suitable

    Reviewed by UVLabs at 2022-03-17 23:01
  • 14. [FEATURE] Compute center of a polygon

    It would be nice to have a method in the Polygon class, which computes and returns the center of all coordinates.

    Is this something you would be interested in? See http://tutorialspots.com/php-how-to-determine-the-center-of-a-polygon-637.html

    Reviewed by aarongerig at 2020-01-24 10:57
  • 15. Polyline / Simplification: add additional properties and/or keep original array keys?

    Want to Simplify a GPX track, which includes not only lat+lon but also timestamps and other properties. After simplification, I want to retain these additional properties (most likely only the timestamp, the others need to be recalculated).

    Looking at the documentation: https://phpgeo.marcusjaschen.de/Transformations_and_Processing/Simplifying_a_Polyline.html

    How can I create a Polyline to be used by Simplify, which includes not only lat+lon, but additional properties? A la

    $polyline->addPoint(new Coordinate($point['lat'], $point['lon']), $gpxDetails);
    

    Alternatively, can you make it possible to retain the original array keys of the Polyline? (e.g. $simplified->getPoints(): [ 0 => [...], 3 => [...], 9 => [...] ])

    PS. the Github example for Simplify does not work, the one in the documentation does.

    Reviewed by wivaku at 2019-12-30 15:33
  • 16. Enable wrap around?

    Would it make sense to loosen the checks for lat -90..90 and lng -180..180 by building a "enable-wrap" option?

    The world is round. It does not end at the dateline. However, most flat representations of the earth only extend up to 180 east and west longitude. This makes it difficult to visualize areas that span across the dateline, or routes that traverse the Pacific Ocean. It is possible to visualize a world map extending seamlessly beyond the dateline. By enabling wraparound on a map, the eastern and western hemispheres wrap around each other forming a continuous map, giving the impression that the map is endless. Panning a map becomes similar to spinning a globe.

    quote from https://developers.arcgis.com/android/10-2/guide/enable-wrap-around.htm

    Reviewed by wolframkriesing at 2019-02-06 08:46
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

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

Aug 9, 2022
PHP library to access the OpenCage geocoding API
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

Jun 20, 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

Jul 27, 2022
PHP library to easily get static image from French Cadastral Government map with markers and lines.
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

May 24, 2022
PHP library to easily get static image from OpenStreetMap (OSM) with markers and lines.
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

Jul 28, 2022
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,

Aug 14, 2022
Simple solution for converting excel rows into coordinates using Google Maps API

Package Usage Start by creating a new instance of ExcelToCoorindates class: $excel_to_cordinates = new ExcelToCoordinates(); Methods ->setEx

Oct 16, 2021
A simple wrapper for (reverse) geocoding

Geocode - A simple wrapper for (reverse) geocoding Installation composer require markuskooche/geocode Usage How to geocode use Illuminate\Support\Col

Jul 9, 2022
PHP extension for geospatial rendering with Mapnik
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

Dec 17, 2021
PHP Extension to handle common geospatial functions.

geospatial - PHP Geospatial Extension PHP Extension to handle common geospatial functions. The extension currently has implementations of the Haversin

Aug 11, 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

Aug 4, 2022
Simple yet powerful Excel manipulation library for PHP 5.4+

| | \ / \_/ __ /^\ __ ' `. \_/ ,' ` \/ \/ _,--./| |\.--._ _,' _.-\_/-._ `._ | / \ | |

Dec 20, 2021
ExcelAnt - Simple yet powerful Excel manipulation library for PHP 5.4+

ExcelAnt is an Excel manipulation library for PHP 5.4. It currently works on top of PHPExcel. If you want to add / use another library, feel free to fork and contribute !

Dec 20, 2021
Simple but yet powerful library for running almost all artisan commands.
Simple but yet powerful library for running almost all artisan commands.

:artisan gui Simple but yet powerful library for running some artisan commands. Requirements Laravel 8.* php ^7.3 Installation Just install package: c

Aug 2, 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

Aug 7, 2022
Geo-related tools PHP 7.3+ 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

Aug 7, 2022
A simple script i made that generate a valid http(s) proxy in json format with its geo-location info

Gev Proxy Generator GPG is a simple PHP script that generate a proxy using free services on the web, the proxy is HTTP(s) and it generate it in json f

Nov 15, 2021