{"id":13475974,"url":"https://github.com/mjaschen/phpgeo","last_synced_at":"2025-05-14T03:05:39.478Z","repository":{"id":443708,"uuid":"8156875","full_name":"mjaschen/phpgeo","owner":"mjaschen","description":"Simple Yet Powerful Geo Library for PHP","archived":false,"fork":false,"pushed_at":"2024-07-01T08:06:12.000Z","size":924,"stargazers_count":1557,"open_issues_count":19,"forks_count":195,"subscribers_count":80,"default_branch":"main","last_synced_at":"2024-10-29T15:08:06.445Z","etag":null,"topics":["area-calculator","coordinates","distance-calculation","douglas-peucker","ellipsoid","geofence","gps","location","php","polyline","simplify","tracks","vincenty"],"latest_commit_sha":null,"homepage":"https://phpgeo.marcusjaschen.de","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mjaschen.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"mjaschen","custom":"https://www.paypal.com/paypalme/mjaschen"}},"created_at":"2013-02-12T10:35:37.000Z","updated_at":"2024-10-28T13:44:32.000Z","dependencies_parsed_at":"2024-01-16T12:46:27.067Z","dependency_job_id":"96e63d99-7c3d-4eca-b8b5-2d402e8c0070","html_url":"https://github.com/mjaschen/phpgeo","commit_stats":{"total_commits":460,"total_committers":21,"mean_commits":"21.904761904761905","dds":0.07608695652173914,"last_synced_commit":"727109c04bc6984551a6fd77aa69b6df9c27a698"},"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjaschen%2Fphpgeo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjaschen%2Fphpgeo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjaschen%2Fphpgeo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjaschen%2Fphpgeo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mjaschen","download_url":"https://codeload.github.com/mjaschen/phpgeo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254059496,"owners_count":22007768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["area-calculator","coordinates","distance-calculation","douglas-peucker","ellipsoid","geofence","gps","location","php","polyline","simplify","tracks","vincenty"],"created_at":"2024-07-31T16:01:25.268Z","updated_at":"2025-05-14T03:05:39.437Z","avatar_url":"https://github.com/mjaschen.png","language":"PHP","readme":"# phpgeo - A Simple Geo Library for PHP\n\nphpgeo provides abstractions to geographical coordinates (including support for different ellipsoids) and allows you to\ncalculate geographical distances between coordinates with high precision.\n\n[![Latest Stable Version](https://poser.pugx.org/mjaschen/phpgeo/v)](//packagist.org/packages/mjaschen/phpgeo)\n[![Total Downloads](https://poser.pugx.org/mjaschen/phpgeo/downloads)](//packagist.org/packages/mjaschen/phpgeo)\n[![phpgeo Tests](https://github.com/mjaschen/phpgeo/actions/workflows/ci.yml/badge.svg)](https://github.com/mjaschen/phpgeo/actions/workflows/ci.yml)\n[![Documentation Status](https://github.com/mjaschen/phpgeo/actions/workflows/docs.yml/badge.svg)](https://github.com/mjaschen/phpgeo/actions/workflows/docs.yml)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/mjaschen/phpgeo/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/mjaschen/phpgeo/?branch=master)\n[![License](https://poser.pugx.org/mjaschen/phpgeo/license)](//packagist.org/packages/mjaschen/phpgeo)\n\n## Requirements\n\nMinimum required PHP version is 8.2. *phpgeo* is tested up to PHP 8.4.\n\nNew features will only go into the main branch and won't be backported.\n\nIt's possible to install older versions of *phpgeo* for older PHP versions.\nPlease refer to the following table for the compatibility matrix:\n\n| PHP Version | phpgeo Version |  Support Status  | Composer Install                        |\n|:-----------:|:--------------:|:----------------:|-----------------------------------------|\n|     8.4     |      6.x       |     ✅ active     | `composer require mjaschen/phpgeo`      |\n|     8.3     |      6.x       |     ✅ active     | `composer require mjaschen/phpgeo`      |\n|     8.2     |      6.x       |     ✅ active     | `composer require mjaschen/phpgeo`      |\n|     8.1     |      5.x       | ⚠️ security only | `composer require mjaschen/phpgeo:^5.0` |\n|     8.0     |      4.x       | ⚠️ security only | `composer require mjaschen/phpgeo:^4.0` |\n|     7.4     |      4.x       | ⚠️ security only | `composer require mjaschen/phpgeo:^4.0` |\n|     7.3     |      4.x       | ⚠️ security only | `composer require mjaschen/phpgeo:^4.0` |\n|     7.2     |      3.x       |  ❌ end of life   | `composer require mjaschen/phpgeo:^3.0` |\n|     7.1     |      2.x       |  ❌ end of life   | `composer require mjaschen/phpgeo:^2.0` |\n|     7.0     |      2.x       |  ❌ end of life   | `composer require mjaschen/phpgeo:^2.0` |\n|     5.6     |      1.x       |  ❌ end of life   | `composer require mjaschen/phpgeo:^1.0` |\n|     5.5     |      1.x       |  ❌ end of life   | `composer require mjaschen/phpgeo:^1.0` |\n|     5.4     |      1.x       |  ❌ end of life   | `composer require mjaschen/phpgeo:^1.0` |\n\n## Documentation\n\nThe documentation is available at [phpgeo.marcusjaschen.de](https://phpgeo.marcusjaschen.de/).\n\n## Installation\n\nUsing [Composer](https://getcomposer.org), just add it to your `composer.json` by running:\n\n```\ncomposer require mjaschen/phpgeo\n```\n\n## Upgrading\n\nUpdate the version constraint in the project's `composer.json` and\nrun `composer update` or require the new version by running:\n\n```shell\ncomposer require mjaschen/phpgeo:^6.0\n```\n\n### Upgrading to 6.x\n\n*phpgeo* has some breaking changes in the 6.x release line. Please refer to the following list to see what has changed\nand what you need to do to upgrade your code.\n\n| Change                                                                         | Description                                                   | Action                                                                            |\n|--------------------------------------------------------------------------------|---------------------------------------------------------------|-----------------------------------------------------------------------------------|\n| `Line`, `Polygon`, and `Polyline` classes are now implementing a new interface | `GeometryLinesInterface` provides the `getSegments()` method. | There's no need to change anything if you don't extend those classes.             |\n| `getBounds()` method was added to `GeometryInterface`                          |                                                               | Ensure your class has a `getBounds()` method if you implement `GeometryInterface` |\n| removed support for PHP 8.1                                                    | Older PHP versions are no longer supported.                   | Upgrade to at least PHP 8.2 or keep using phpgeo 5.x                              |\n\n### Upgrading to 5.x\n\n*phpgeo* has some breaking changes in the 5.x release line. Please refer to the following list to see what has changed\nand what you need to do to upgrade your code.\n\n| Change                                                      | Description                                 | Action                                                  |\n|-------------------------------------------------------------|---------------------------------------------|---------------------------------------------------------|\n| `setPoint1()` and `setPoint2()` methods removed from `Line` | The `Line` class now is immutable.          | Use the constructor to create a new instance of `Line`. |\n| removed support for PHP 7.3, 7.4 and 8.0                    | Older PHP versions are no longer supported. | Upgrade to at least PHP 8.1.                            |\n\n## License\n\nStarting with version 2.0.0 phpgeo is licensed under the MIT license. Older versions were GPL-licensed.\n\n## Features\n\n**Info:** Please visit the **[documentation site](https://phpgeo.marcusjaschen.de/)** for complete and up-to-date\ndocumentation with many examples!\n\nphpgeo provides the following features (follow the links for examples):\n\n- abstractions of several geometry\n  objects ([coordinate/point](https://phpgeo.marcusjaschen.de/Geometries/Coordinate.html),\n  [line](https://phpgeo.marcusjaschen.de/Geometries/Line.html),\n  [polyline/GPS track](https://phpgeo.marcusjaschen.de/Geometries/Polyline.html),\n  [polygon](https://phpgeo.marcusjaschen.de/Geometries/Polygon.html)\n- support for different [ellipsoids](https://phpgeo.marcusjaschen.de/Geometries/Ellipsoid.html), e.g. WGS-84\n- [length/distance/perimeter calculations](https://phpgeo.marcusjaschen.de/Calculations/Distance_and_Length.html)\n  with different implementations (Haversine, Vincenty)\n- [Geofence](https://phpgeo.marcusjaschen.de/Calculations/Geofence.html) calculation,\n  i.e. answering the question \"Is this point contained in that area/polygon?\" and\n  other [intersection](https://phpgeo.marcusjaschen.de/Comparisons/Intersections.html) checks between different\n  geometries\n- [formatting and output](https://phpgeo.marcusjaschen.de/Formatting_and_Output/index.html) of geometry objects\n  (GeoJSON, nice strings, e. g. `18° 54′ 41″ -155° 40′ 42″`)\n- calculation\n  of [bearing angle between two points](https://phpgeo.marcusjaschen.de/Calculations/Bearing_and_Destination.html#page_Bearing-between-two-points)\n  (spherical or with Vincenty's formula)\n- calculation of\n  a [destination point for a given starting point](https://phpgeo.marcusjaschen.de/Calculations/Bearing_and_Destination.html#page_Destination-point-for-given-bearing-and-distance),\n  bearing angle, and distance (spherical or with Vincenty's formula)\n- calculation of\n  the [perpendicular distance between a point and a line](https://phpgeo.marcusjaschen.de/Calculations/Perpendicular_Distance.html)\n- calculation of\n  the [Cardinal Distances between two points](https://phpgeo.marcusjaschen.de/Calculations/Cardinal_Distance.html)\n- getting segments of a [polyline](https://phpgeo.marcusjaschen.de/Geometries/Polyline.html#page_Segments)\n  /[polygon](https://phpgeo.marcusjaschen.de/Geometries/Polygon.html#page_Segments),\n- [reversing direction](https://phpgeo.marcusjaschen.de/Geometries/Polygon.html#page_Reverse-Direction)\n  of polyline/polygon\n\n## Examples/Usage\n\nThis list is incomplete, please visit the **[documentation site](https://phpgeo.marcusjaschen.de/)**\nfor the full monty of documentation and examples!\n\n### Distance between two coordinates (Vincenty's Formula)\n\nUse the calculator object directly:\n\n```php\n\u003c?php\n\nuse Location\\Coordinate;\nuse Location\\Distance\\Vincenty;\n\n$coordinate1 = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit\n$coordinate2 = new Coordinate(20.709722, -156.253333); // Haleakala Summit\n\n$calculator = new Vincenty();\n\necho $calculator-\u003egetDistance($coordinate1, $coordinate2); // returns 128130.850 (meters; ≈128 kilometers)\n```\n\nor call the `getDistance()` method of a Coordinate object by injecting a calculator object:\n\n```php\n\u003c?php\n\nuse Location\\Coordinate;\nuse Location\\Distance\\Vincenty;\n\n$coordinate1 = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit\n$coordinate2 = new Coordinate(20.709722, -156.253333); // Haleakala Summit\n\necho $coordinate1-\u003egetDistance($coordinate2, new Vincenty()); // returns 128130.850 (meters; ≈128 kilometers)\n```\n\n### Simplifying a polyline\n\nPolylines can be simplified to save storage space or bandwidth. Simplification is done with\nthe [Ramer–Douglas–Peucker algorithm](https://en.wikipedia.org/wiki/Ramer–Douglas–Peucker_algorithm) (AKA\nDouglas-Peucker algorithm).\n\n```php\n\u003c?php\n\nuse Location\\Coordinate;\nuse Location\\Polyline;\nuse Location\\Distance\\Vincenty;\n\n$polyline = new Polyline();\n$polyline-\u003eaddPoint(new Coordinate(10.0, 10.0));\n$polyline-\u003eaddPoint(new Coordinate(20.0, 20.0));\n$polyline-\u003eaddPoint(new Coordinate(30.0, 10.0));\n\n$processor = new Simplify($polyline);\n\n// remove all points which perpendicular distance is less\n// than 1500 km from the surrounding points.\n$simplified = $processor-\u003esimplify(1500000);\n\n// simplified is the polyline without the second point (which\n// perpendicular distance is ~1046 km and therefore below\n// the simplification threshold)\n```\n\n### Polygon contains a point (e.g. \"GPS geofence\")\n\nphpgeo has a polygon implementation which can be used to determinate if a point is contained in it or not.\nA polygon consists of at least three points. Points are instances of the `Coordinate` class.\n\n**Warning:** The calculation gives wrong results if the polygons has points on both sides of the 180/-180 degrees\nmeridian.\n\n```php\n\u003c?php\n\nuse Location\\Coordinate;\nuse Location\\Polygon;\n\n$geofence = new Polygon();\n\n$geofence-\u003eaddPoint(new Coordinate(-12.085870,-77.016261));\n$geofence-\u003eaddPoint(new Coordinate(-12.086373,-77.033813));\n$geofence-\u003eaddPoint(new Coordinate(-12.102823,-77.030938));\n$geofence-\u003eaddPoint(new Coordinate(-12.098669,-77.006476));\n\n$outsidePoint = new Coordinate(-12.075452, -76.985079);\n$insidePoint = new Coordinate(-12.092542, -77.021540);\n\nvar_dump($geofence-\u003econtains($outsidePoint)); // returns bool(false) the point is outside the polygon\nvar_dump($geofence-\u003econtains($insidePoint)); // returns bool(true) the point is inside the polygon\n```\n\n### Formatted output of coordinates\n\nYou can format a coordinate in different styles.\n\n#### Decimal Degrees\n\n```php\n\u003c?php\n\nuse Location\\Coordinate;\nuse Location\\Formatter\\Coordinate\\DecimalDegrees;\n\n$coordinate = new Coordinate(19.820664, -155.468066); // Mauna Kea Summit\n\necho $coordinate-\u003eformat(new DecimalDegrees());\n```\n\n#### Degrees/Minutes/Seconds (DMS)\n\n```php\n\u003c?php\n\nuse Location\\Coordinate;\nuse Location\\Formatter\\Coordinate\\DMS;\n\n$coordinate = new Coordinate(18.911306, -155.678268); // South Point, HI, USA\n\n$formatter = new DMS();\n\necho $coordinate-\u003eformat($formatter); // 18° 54′ 41″ -155° 40′ 42″\n\n$formatter-\u003esetSeparator(\", \")\n    -\u003euseCardinalLetters(true)\n    -\u003esetUnits(DMS::UNITS_ASCII);\n\necho $coordinate-\u003eformat($formatter); // 18° 54' 41\" N, 155° 40' 42\" W\n```\n\n#### GeoJSON\n\n```php\n\u003c?php\n\nuse Location\\Coordinate;\nuse Location\\Formatter\\Coordinate\\GeoJSON;\n\n$coordinate = new Coordinate(18.911306, -155.678268); // South Point, HI, USA\n\necho $coordinate-\u003eformat(new GeoJSON()); // { \"type\" : \"point\" , \"coordinates\" : [ -155.678268, 18.911306 ] }\n```\n\n## Development\n\n### Run Tests\n\nBefore submitting a pull request, please be sure to run all checks and tests and ensure everything is green.\n\n- lint PHP files for syntax errors: `composer ci:lint`\n- run static analysis with [Psalm][] and report errors: `composer ci:psalm`\n- run unit tests with PHPUnit: `composer ci:tests`\n\nTo run all checks and tests at once, just use `composer ci`.\n\nOf course, it's possible to use the test runners directly, e.g. for PHPUnit:\n\n```shell\n./vendor/bin/phpunit\n```\n\nPHPStan:\n\n```shell\n./vendor/bin/phpstan\n```\n\n### Running GitHub Actions locally\n\nIt's possible to run the whole CI test matrix locally with *[act](https://github.com/nektos/act)*:\n\n```shell\nact --rm -P ubuntu-latest=shivammathur/node:latest\n```\n\n## Credits\n\n* Marcus Jaschen \u003cmail@marcusjaschen.de\u003e and [all contributors](https://github.com/mjaschen/phpgeo/graphs/contributors)\n* [Chris Veness](http://www.movable-type.co.uk/scripts/latlong-vincenty.html) - JavaScript implementation of\n  the [Vincenty formula](http://en.wikipedia.org/wiki/Vincenty%27s_formulae) for distance calculation\n* Ersts,P.J., Horning, N., and M. Polin[Internet] Perpendicular Distance Calculator(version\n  1.2.2) [Documentation](http://biodiversityinformatics.amnh.org/open_source/pdc/documentation.php). American Museum of\n  Natural History, Center for Biodiversity and Conservation. Available\n  from http://biodiversityinformatics.amnh.org/open_source/pdc. Accessed on 2013-07-07.\n* W. Randolph Franklin, PNPOLY - Point Inclusion in Polygon\n  Test [Documentation](http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html)\n","funding_links":["https://github.com/sponsors/mjaschen","https://www.paypal.com/paypalme/mjaschen"],"categories":["PHP","地理位置","目录","Table of Contents","地理位置 Geolocation","Geolocation","地理定位( Geolocation )"],"sub_categories":["地理位置 Geolocation","Geolocation"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjaschen%2Fphpgeo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmjaschen%2Fphpgeo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjaschen%2Fphpgeo/lists"}