Simple Yet Powerful Geo Library for PHP

Overview

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

Comments
  • Perpendicular distance between point and line segment

    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.

    opened by TheCelavi 19
  • Calculation is wrong.

    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

    opened by v920749 7
  • Fatal error: Uncaught exception 'InvalidArgumentException' with message 'Latitude value must be numeric -90.0 .. +90.0'

    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

    opened by alijmlzd 7
  • Point-to-line distance is incorrect sometimes

    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??

    opened by magnuswikhog 6
  • composer error

    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.

    opened by tamer-dahdul 6
  • Formatter returns too many decimals.

    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.

    opened by WeeRuz 5
  • Coordinate class naming

    Coordinate class naming

    Hi, I was doing a little bit of domain research for a side project of mine, and I noticed your library: it looks nice! :) While reading the code, I noticed the "Coordinate" class and wondered if it shouldn't be named "Coordinates" (plural) as it represents a pair of coordinates(latitude and longitude, plus an ellipsoid). Sorry for opening an issue for a single character, but I thought it could've been a possible item for the next major release. Thanks!

    opened by omissis 5
  • "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

    opened by jonyrock 4
  • PerpendicularDistance reports 21k meters on a distance of about 192k

    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

    opened by acidjazz 4
  • Given a point and a distance, is it possible to compute the corresponding extent ?

    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.

    opened by felixveysseyre 4
  • Polygon getArea method

    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,

    opened by felixveysseyre 4
  • Line::intersectsLine() is buggy

    Line::intersectsLine() is buggy

    Hello, Unfortunately, the Line::intersectsLine() method doesn't always work correctly. Try this test:

    <?php
    declare(strict_types=1);
    require 'vendor/autoload.php';
    
    use Location\Coordinate;
    use Location\Line;
    
    $line1 = new Line(
        new Coordinate(0.0, 0.0),
        new Coordinate(0.0, 2.0)
    );
    $line2 = new Line(
        new Coordinate(2.0, 2.0),
        new Coordinate(0.0, 10.0)
    );
    if ($line1->intersectsLine($line2)) {
        echo 'Line::intersectsLine() is buggy!'.PHP_EOL;
    }
    
    opened by vlad-vinogradov 3
  • Merging multiple adjacent rectangles into one polygon

    Merging multiple adjacent rectangles into one polygon

    Hello.

    Is it possible to implement polygon merging as suggested by users on this page: https://stackoverflow.com/questions/13746284/merging-multiple-adjacent-rectangles-into-one-polygon

    Thank you.

    opened by rumano 0
  • Point directions

    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'
    
    opened by nilshoerrmann 0
  • Explanation of warning for non-geo wiz

    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

    opened by UVLabs 0
  • [FEATURE] Compute center of a polygon

    [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

    feature 
    opened by aarongerig 3
Releases(3.2.0)
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
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
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

Nikola Cirkovic 2 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

Markus Koch 2 Jul 9, 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 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

PHP Geospatial, putting the Elephpant on your globe 56 Dec 29, 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
Simple yet powerful Excel manipulation library for PHP 5.4+

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

Wisembly 68 Sep 20, 2022
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 !

Wisembly 68 Sep 20, 2022
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

null 324 Dec 28, 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
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

The League of Extraordinary Packages 1.3k Dec 27, 2022
🖥 Build beautiful PHP CLI menus. Simple yet Powerful. Expressive DSL.

Contents Minimum Requirements Installation Upgrading Usage Quick Setup Examples API Appearance Menu Title Colour Width Padding Margin Borders Exit But

PHP School 1.9k Dec 28, 2022
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.

Slim Framework Slim is a PHP micro-framework that helps you quickly write simple yet powerful web applications and APIs. Installation It's recommended

Slim Framework 11.5k Jan 4, 2023