Coder Social home page Coder Social logo

mjaschen / phpgeo Goto Github PK

View Code? Open in Web Editor NEW
1.5K 79.0 235.0 922 KB

Simple Yet Powerful Geo Library for PHP

Home Page: https://phpgeo.marcusjaschen.de

License: MIT License

PHP 99.59% Makefile 0.41%
php vincenty polyline area-calculator coordinates geofence distance-calculation gps simplify douglas-peucker

phpgeo's People

Contributors

andrewdawes avatar arsonik avatar clemdesign avatar dependabot[bot] avatar felixveysseyre avatar iamskey avatar jonathanmh avatar leovie avatar luismulinari avatar m7rc7ry avatar majebry avatar micaelmendes-flymaster avatar mjaschen avatar nilshoerrmann avatar paulvl avatar peter279k avatar r-barnes avatar sdennler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

phpgeo's Issues

ErrorException in Simplify.php line 148: Division by zero

Hello @mjaschen great work! I've been getting an ErrorException in line 148 of the Simplify.php file (when using the simplify method for a polyline object); Im making sure i'm only adding valid coordinates to the polyline and making sure no points are sent repeatedly.

Trying to search for a possible solution on the Simplify.php file, the error seems to happen when the function getPerpendicularDistance tries to find a length for two points on a line (the line provided as a parameter for the function contains two identical set of coordinates, even when the points provided for the Polyline were all different coordinates).

I've provided a set of coordinates that will trigger this exception; it won't happen if the parameter on the simplify method is a value higher than 2 (but this would be no solution as a different set of points could trigger it for a higher value). If you remove the last point from the array the exception will not be triggered.

$arr = [
    [20.6579781231, -103.422906054] ,
    [20.6580106449, -103.422897337] ,
    [20.6580357067, -103.422887027] ,
    [20.6580530573, -103.422873113] ,
    [20.6580754789, -103.422858864] ,
    [20.6581169274, -103.422843861] ,
    [20.6581701944, -103.422823409] ,
    [20.6582261855, -103.422804549] ,
    [20.6582879601, -103.422781583] ,
    [20.6583917403, -103.422747897] ,
    [20.6584564535, -103.422721072] ,
    [20.6585244273, -103.422692896] ,
    [20.6586065208, -103.422658867] ,
    [20.6586790699, -103.422628794] ,
    [20.6587552535, -103.422597214] ,
    [20.6588130308, -103.422573891] ,
    [20.6588720341, -103.42255021] ,
    [20.6589324369, -103.422525967] ,
    [20.6590027634, -103.422497741] ,
    [20.6590702995, -103.422468988] ,
    [20.6591201277, -103.422444292] ,
    [20.6591365207, -103.422436166] ,
    [20.6591257477, -103.422441506] ,
    [20.6591381119, -103.422435378] ,
    [20.6592482509, -103.42239942] ,
    [20.6592598032, -103.422395672] ,
    [20.6592684096, -103.42239288] ,
    [20.659233168, -103.422404313] ,
    [20.6592154847, -103.42241005] ,
    [20.6592024446, -103.422414281] ,
    [20.6592397671, -103.422538089] ,
    [20.6592234224, -103.422524845] ,
    [20.6592450058, -103.422512105] ,
    [20.6592722051, -103.422502633] ,
    [20.6594071957, -103.422540268] ,
    [20.6594734127, -103.42251244] ,
    [20.6596607482, -103.422478996] ,
    [20.6597573077, -103.42242334] ,
    [20.6598714693, -103.422378581] ,
    [20.6600107346, -103.422340276] ,
    [20.6601370663, -103.422289965] ,
    [20.6602900948, -103.422230188] ,
    [20.6604063622, -103.422165179] ,
    [20.660509254, -103.422112257] ,
    [20.6606362708, -103.422059897] ,
    [20.6607423011, -103.42200584] ,
    [20.660834149, -103.421968132] ,
    [20.6608913904, -103.421965255] ,
    [20.660888676, -103.421957729] ,
    [20.6608924298, -103.421968137] ,
    [20.6608892495, -103.421959319] ,
    [20.6608915012, -103.421965562] ,
    [20.6608967866, -103.421980217] ,
    [20.6608905586, -103.421962949] ,
    [20.6608862009, -103.421950866] ,
    [20.6608818429, -103.421938783] ,
    [20.6608846513, -103.421946569] ,
    [20.6608818429, -103.421938783] ,
    [20.6610598314, -103.421866543] ,
    [20.6610790881, -103.421889792]
];

$polyline = new Polyline();
foreach($arr as $point){
    $polyline->addPoint(new Coordinate($point[0], $point[1]));
}
$processor = new \Location\Processor\Polyline\Simplify($polyline);
$simplified = $processor->simplify(2);

Thank you in advance for your help.

pixel distance

If we simplify a line, we usually do it for plotting the line on a map. This means that ideally, we would like to express the tolerance in terms of pixels on the map, not in kilometers. Since maps usually use the Mercator projection, there is not a simply linear correlation between the two.

So if accuracy is a concern, we would add a pixel-distance calculation. Otherwise, we could simply use the degrees to calculate a 'degrees distance' (perhaps with a crude cos(lattitude) correction, as to speed things up.

[Feature] Calculate Bounds from a center point

I like to calculate Bounds from a center point + distance to edge.

A pull request is made: #60
The CI fails but I think it failed before my changes as well because Phive requires PHP 7.1 and PHP 7.0 is tested.

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.

Calculate cardinal direction distances between two coordinates

Given you have two Coordinates:

  • Point1 at (51.049531, 13.720699)
  • Point2 at (51.069706, 13.775459)

you'd like to know the shortest possible right angle to reach the Point2 from Point1
grafik

This would be possible by determining the point in the NorthWest corner (Point3) and calculate the distances Point1<->Point3 and Point2<->Point3.

As the sortest possible distances should be calculated, there has to be a check before: If Point1 is in NorthWest of Point2, the shortest directions are to go south and east.

Point1 in reference to Point2 Directions
North South
East West
South North
West East
NorthWest South, East
NorthEast South, West
SouthWest North, East
SouthEast North, West

The only real new logic would be this determination.
The determining of Point3 could be done via the class Bounds, the calculation of the distances via the class Coordinate.

What do you think about this feature? If something is unclear, please ask me. :)

Move to PHP7

What do you think about to move the code to PHP7? If it seems legit, we will need create a v2.x.

Library Use

Please what can I use this library for in real life scenario.

I know I can use it to get distance of coordinate from a point... But I need to know more I can use it for...

Thanks...

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.

Add functionality to move Coordinates

It would be nice to see some sort of function with which a coordinate could be moved in a certain direction and distance, e.g.:

$point =new Coordinate(19.820664, -155.468066);
$point->move(45, 5000); // Move $point to the east over 5 km

Test suite fails on HHVM

A fmod() calculation fails on HHVM. Probably it's a floating point problem, we need to investigate.

Travis build page: https://travis-ci.org/mjaschen/phpgeo/jobs/115529491

 There was 1 failure:

1) Location\Bearing\BearingSphericalTest::testIfCalculateFinalBearingNorthernWorksAsExpected

Failed asserting that 360 matches expected 0.0.

/home/travis/build/mjaschen/phpgeo/tests/Location/Bearing/BearingSphericalTest.php:96

Calculate the similarity of two polylines

An algorithm for calculating the similarity between two given polylines should be implemented.

Idea:

  • create a corridor area around the first polyline (with configurable corridor width); a polygon instance can be used for this (check: what happens if the polyline crosses itself?)
  • check how much of the second polyline is located within the corridor
  • the result is a floating point number between 0 and 1; 0 means that no parts of the second polyline are located within the corridor and 1 means that the second line ist located entirely within the corridor
  • additionally provide a check if the directions of both polylines are the same

Sounds reasonable?

Distance calculation

Sorry for the newbee question but when i am using the Distance calculation it provides me some false values. Went through the documentation but could not find some hint.

this is the function call:
$p1 = new \Location\Coordinate($point1_lat,$point1_long);
$p2 = new \Location\Coordinate($point2_lat,$point2_long);
$meters = $p1->getDistance($p2, new \Location\Distance\Vincenty());

and the result (sorry for the json encapsulation) is:

"distance": "4597208.7 Location\Coordinate Object\n(\n [lat:protected] => 16.1398995\n [lng:protected] => 48.0313793\n [ellipsoid:protected] => Location\Ellipsoid Object\n (\n [name:protected] => World Geodetic System 1984\n [a:protected] => 6378137\n [f:protected] => 298.257223563\n )\n\n)\n Location\Coordinate Object\n(\n [lat:protected] => 48.4664936\n [lng:protected] => 16.3988242\n [ellipsoid:protected] => Location\Ellipsoid Object\n (\n [name:protected] => World Geodetic System 1984\n [a:protected] => 6378137\n [f:protected] => 298.257223563\n )\n\n)\n"

is it a bug or is there a need to set unit system or is it just "stupid me"

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

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!

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.

Multiple Simplifications

Hi there,

I haven't studied the Douglas-Peucker algorithm in details, but if I execute the simplification algorithm multiple times, the polyline reduces/smoothes more and more, although the algorithm tolerance is still unchanged.

// 1 meter tolerance
$processor = new SimplifyDouglasPeucker(1);

$polyline = $processor->simplify($polyline);
echo sizeof($polyline->getPoints());

echo "<br>";

$polyline = $processor->simplify($polyline);
echo sizeof($polyline->getPoints());

echo "<br>";

$polyline = $processor->simplify($polyline);
echo sizeof($polyline->getPoints());

Shouldn't it be constant?

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.

No license?

I don't see the LICENSE file on your project, although composer.json indicates it's MIT. Please add it.

I see that you credit GPL licensed software, so maybe the license should be GPL.

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

Add support for PHP 8.1

  • verifiy it's supported in composer.json
  • run all tests
  • adjust text matrix in Github workflow definition
  • update README and change log

Error: Call to a member function

Good afternoon.
Put through composer require mjaschen/phpgeo (php 7.2).
I try to use an example from the description

`<?php
use Location\Bearing\BearingEllipsoidal;
use Location\Bearing\BearingSpherical;
use Location\Coordinate;
use Location\Formatter\Coordinate\DecimalDegrees;

$berlin = new Coordinate(52.5, 13.5);

$bearingSpherical = new BearingSpherical();
$bearingEllipsoidal = new BearingEllipsoidal();

$destination1 = $BearingSpherical->calculateDestination($berlin, 153, 56100);
$destination2 = $bearingEllipsoidal->calculateDestination($berlin, 153, 56100);

echo "Spherical: " . $destination1->format(new DecimalDegrees()) . PHP_EOL;
echo "Ellipsoidal: " . $destination2->format(new DecimalDegrees()) . PHP_EOL;
`

I receive an error.
Uncaught Error: Call to a member function calculateDestination() on null in ...

But all other functions work.
What could be wrong?
Thanks.

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.

[FEATURE] Integration with GEOS

Have you ever considered to integrate https://trac.osgeo.org/geos like https://geophp.net/geos.html did?

Geophp seams very obsolete, with poor Composer and OOP support, while GEOS have a lot of useful methods, like touches, intersects, crosses, etc...

Circle is missing, though, but circle can be solved easily in terms of calculating distance, or checking weather circle touches/intersects/crosses/etc... some other geo object...

What do you think?

Fatal error: Class 'Location\Coordinate' not found

Hi. Thanks for project. Very nice and powerfull instrument! But i have some trouble:

getDistance($coordinate1, $coordinate2); ?>

GOT:
Fatal error: Class 'Location\Coordinate' not found in /var/www/html/phpgeo/vendor/index.php on line 8

PHP Version 5.6.21

douglas peucker implementation glitch

        if ($distanceMax > $this->tolerance) {
            $lineSplitFirst  = array_slice($line, 0, $index);
            $lineSplitSecond = array_slice($line, $index, $lineSize);
            $resultsSplit1 = $this->douglasPeucker($lineSplitFirst);
            $resultsSplit2 = $this->douglasPeucker($lineSplitSecond);
            array_pop($resultsSplit1);
            return array_merge($resultsSplit1, $resultsSplit2);
        }

I think $resultsSplit1's last point shouldn't be dropped because $lineSplitFirst already only contains [$line[0],..., $line[$index-1]] because array_slice's second argument isn't inclusive. array_pop causes loose the point whose index is $index-1.

Division by zero in Vincenty.php on line 86

Hello,

Thanks for this great library !

I'm facing this issue with version 1.3.5 and php cli version 5.5.9-1ubuntu4.14

$vincenty = new \Location\Distance\Vincenty();

$distance = $vincenty->getDistance(
    new \Location\Coordinate(0, 0),
    new \Location\Coordinate(0, 0.1)
);

PHP Warning: Division by zero in /home/.../vendor/mjaschen/phpgeo/src/Location/Distance/Vincenty.php on line 86

Any idea ?

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

Find all objects within specific Distance

Is it possible to find all the objects within a specified distance from a given location?

I've been using Haversine to do this with an old php 5 class. But I'm not sure how you'd do that with this library.

The examples show how to find distance between two specific locations. But I'd like to find all the locations within X miles or km, ordered by distance. Is that possible?

I already have a populated database table with all of the locations. They are postal codes with latitude and longitude columns.

Thanks for your help!

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

Remove support for PHP 7.2

  • remove from composer.json
  • remove from Github Workflows
  • adjust Composer dependencies (newer PHPUnit etc.)
  • update README and change log

Create tagged version

Hi, I was wondering if you could create a tagged version in git so that I can specify the version in my composer file?

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,

Vincenty results are wrong

It seems that Vincenty calculation are wrong.

Distance between theses two points return 0, it should return 1.255 meters

<?php
var_dump((new Vincenty())
    ->getDistance(
        new Coordinate(45.306833,5.887717), 
        new Coordinate(45.306833,5.887733)
)); // float(0)

Using some other lib, it return the correct value.

image

>>> point1 = (45.306833,5.887717)
>>> point2 = (45.306833,5.887733)
>>> vincenty(point1, point2) * 1000
1.2550000000000001

Extra space in Ellipsoid name

The preconfigured ellipsoid WGS-84 has a double space in its name:

World␣Geodetic␣System␣␣1984

Name should read:

World␣Geodetic␣System␣1984

Warning emitted for valid coordinates in CoordinateFactory

PHP version: 7.4.6
Library version: 3.0.0

Passing a set of non-decimal coordinates without seconds to CoordinateFactory::fromString() will emit the following PHP warning:

PHP Warning: A non-numeric value encountered in /home/../vendor/mjaschen/phpgeo/src/Factory/CoordinateFactory.php on line 177

Reproducible by the following code:

$coordinates = CoordinateFactory::fromString('11°17′N 15°50′W');

The coordinates are for an airport in Guinea-Bissau. It should be noted that the library still calculates the correct latitude and longitude, so it works, but the warning poses a problem for anyone who converts warnings, notices, etc. into exceptions automatically (typically done when using a framework).

The warning is not emitted if you add zero-filled seconds to the coordinates:

$coordinates = CoordinateFactory::fromString('11°17′00″N 15°50′00″W');

However the coordinates in question are of a valid format, so the library shouldn't be emitting the warning.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.