Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

geoPHP point in polygon

i need some help, google makes me sad

I got polygon http://geojson.io/#id=gist:anonymous/069b8a955897723ca256&map=4/58.75/48.03 And it covering a lot. And i got geoPHP library https://github.com/phayes/geoPHP Which got methods contains, covers, coveredBy...

And everything is normal, except that point like 74.224074, 96.428248 is always false for methods contains,coveredBy,covers, etc for this polygon. But it must be true.

Please, tell me why. I got a headache.

OR

Tell me please, how check that the lat lng is inside polygon. I tested about 3 libraries in perl and php, making my own code, etc... But the right results i got only from google containsLocation in javascript. But i have to use it on server side, not in browser. If there any chance to use containsLocation in nodejs it would be very nice.

Thank you

A little code for geoPHP:
$a='JSON FROM LINK';
$b=geoPHP::load("POINT(74.224074 96.428248)","wkt");
$a=geoPHP::load($a, 'json');
$result=$a->contains($b);

var_dump($result);

And it will be false

EDIT: I think i got it. GeoJson making coordinates in wrong way, longtitude, latitude. But it must be latitude, longtitude. Will try and then write here if it works

ANSWER:

Use this www.birdtheme.org/useful/v3tool.html to make polygon on maps. It making it in right way(latitude,longtitude)

Working code for geoPHP:

    include_once('geoPHP.inc');
$addr=file_get_contents('https://maps.googleapis.com/maps/api/geocode/json?address='.urlencode($_GET['address']).'&sensor=false');
foreach($addr->{results} as $addr1)
{
if(array_key_exists("geometry",$addr1)){
$lat=$addr1->{geometry}->{location}->{lat};
$lng=$addr1->{geometry}->{location}->{lng};



break;
}
}
$point1 = geoPHP::load("POINT($lat $lng)","wkt");

$ya200=geoPHP::load("POLYGON((41.51 12.3, 38.27 28.83, 32.55 41.84, 27.6 55.55, 29.54 71.37, 33.43 83.32, 36.6 94.92, 36.6 99.49, 35.17 111.45, 32.55 124.8, 35.17 130.78, 39.64 142.73, 43.58 152.58, 45.83 166.29, 56.17 163.83, 63.07 159.26, 68.66 154.69, 72.18 148.71, 75.93 140.63, 78.49 129.02, 80.3 114.26, 80.98 100.2, 81.2 87.54, 80.87 73.83, 79.62 59.41, 76.27 40.43, 71.07 28.13, 67.2 23.2, 63.55 20.04, 59.01 17.23, 54.16 15.12, 48.46 13.36,41.51 12.3))","wkt");


var_dump($ya200->contains($point1));
like image 794
user3461842 Avatar asked Mar 26 '14 00:03

user3461842


5 Answers

I am the maintainer of the geoPHP library (https://geophp.net). You have your latitude and longitude mixed up. WKT specifies that x comes first, then y, and then (optionally) z. This makes sense, as we usually do things in XYZ order.

It's conventional in mathematics for the horizontal axis to be X, and the vertical axis to be Y. If we think of a globe overlaid on a piece of graphing paper with X and Y axes specified, we can see that longitude is the horizontal axis, which corresponds to X, and the latitude is the vertical axis, which corresponds to Y. Therefore reading it as "longitude, latitude" makes perfect sense.

Regrettably, this sensical approach is backwards from the way mariners and other cartographers have described coordinates on the globe it throughout history. Historically it has often been described as "latitude, longitude".

This clash of history vs mathematical-convention is why you see different conventions in different systems. In Google Maps API its "latitude, longitude", while in OpenLayers it's "longitude, latitude".

In this particular case, you are using WKT, which is specified in "longitude, latitude" order.

like image 78
phayes Avatar answered Nov 17 '22 17:11

phayes


WKT format expects POINT(lon, lat), with lon being first. You mixed up the order. Corrected:

geoPHP::load("POINT($lon $lat)","wkt");
like image 37
Dmitry Avatar answered Nov 17 '22 17:11

Dmitry


I have answered almost the same question but don't know how to make a repost of it, so I just repeat it here (sorry)

If you use this PHP library (https://github.com/xopbatgh/sb-polygon-pointer), it may do all you need

(but first you need to convert GEOjson coordinates to lat/lng)

Plan to do:

  1. Insert the coordinates of your polygon into array

  2. Ask the library is the any point with lat/lng inside this polygon

$polygonBox = [
    [55.761515, 37.600375],
    [55.759428, 37.651156],
    [55.737112, 37.649566],
    [55.737649, 37.597301],
];

$sbPolygonEngine = new sbPolygonEngine($polygonBox);

$isCrosses = $sbPolygonEngine->isCrossesWith(55.746768, 37.625605);

// $isCrosses is boolean

like image 2
Viktor Semenov Avatar answered Nov 17 '22 16:11

Viktor Semenov


After hours of struggle, I could not get the contains method to work with geoPHP. It turns out, as pointed out from this SO response that the geos library needs to be installed manually (no composer), which I could not get working after sifting through documentation on archive.org.

As an alternative, I found the mjaschen/phpgeo to be simple to use to do polygon contains point calculations. Simply load in your lat lons to objects and call the contains method as outlined in the documentation:

$polygon = new Polygon();
$polygon->addPoint(new Coordinate(12.3, 41.51));
$polygon->addPoint(new Coordinate(28.83, 38.27));
$polygon->addPoint(new Coordinate(41.84, 32.55));

$point = new Coordinate(74.224074, 96.428248)

var_dump($polygon->contains($point))
like image 2
craastad Avatar answered Nov 17 '22 16:11

craastad


All advanced methods in geoPHP requires that GEOS is installed. If You are not able to install it but still want to use intersects test for point and polygon, then I have forked geoPHP and added Polygon->pointInPolygon and MultiPolygon->pointInPolygon methods for that purpose. Take a look: https://github.com/sookoll/geoPHP

$point = \geoPHP::load('POINT (x y)','wkt');
$polygon = \geoPHP::load('POLYGON ((x y...))','wkt');
$point_is_in_polygon = $polygon->pointInPolygon($point);
like image 1
mihkelo Avatar answered Nov 17 '22 15:11

mihkelo