jillesvangurp / geogeometry

GeoGeometry is a set of algorithms and functions for manipulating geo hashes and geometric shapes with geo coordinates.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

polygonContains doesn't seem to work correctly

dalbrx opened this issue · comments

Hi,

I am calling com.jillesvangurp.geo.GeoGeometry.polygonContains(double latitude, double longitude, double[][][] polygonPoints)

params are:

latitude = 42.503615,
longitude = 1.641881
polygonPoints= [[[42.503320312499994, 1.7060546875], [42.4966796875, 1.678515625000017], [42.455957031249994, 1.58642578125], [42.441699218749996, 1.534082031250023], [42.434472656249994, 1.486230468750023], [42.437451171875, 1.448828125], [42.46132812499999, 1.428125], [42.497851562499996, 1.430273437500006], [42.530810546874996, 1.421972656250006], [42.548388671874996, 1.414843750000017], [42.5958984375, 1.428320312500006], [42.6216796875, 1.458886718750023], [42.642724609374994, 1.501367187500023], [42.635009765625, 1.568164062500017], [42.604443359375, 1.709863281250023], [42.575927734375, 1.739453125000011], [42.55673828125, 1.740234375], [42.525634765625, 1.713964843750006], [42.503320312499994, 1.7060546875]]]

the result is false shouldn't it be true?

Quickly created a test for this and it seems to work as expected for me (test passes).

public void issue5PolygonContainsDoesNotWorkCorrectly() {
    double[][][] polygon = new double[][][] { { { 42.503320312499994, 1.7060546875 }, { 42.4966796875, 1.678515625000017 },
            { 42.455957031249994, 1.58642578125 }, { 42.441699218749996, 1.534082031250023 }, { 42.434472656249994, 1.486230468750023 },
            { 42.437451171875, 1.448828125 }, { 42.46132812499999, 1.428125 }, { 42.497851562499996, 1.430273437500006 },
            { 42.530810546874996, 1.421972656250006 }, { 42.548388671874996, 1.414843750000017 }, { 42.5958984375, 1.428320312500006 },
            { 42.6216796875, 1.458886718750023 }, { 42.642724609374994, 1.501367187500023 }, { 42.635009765625, 1.568164062500017 },
            { 42.604443359375, 1.709863281250023 }, { 42.575927734375, 1.739453125000011 }, { 42.55673828125, 1.740234375 },
            { 42.525634765625, 1.713964843750006 }, { 42.503320312499994, 1.7060546875 } } };
    double[] point=new double[] {42.503615,1.641881};

    assertThat("should contain the point", GeoGeometry.polygonContains(point, polygon));
}

Hi I wrote the following code to test it again (scala but should be easy to understand):

def main(args: Array[String]) {
    println(GeoGeometry.polygonContains(getPoint(), getPolygon()))
    println(GeoGeometry.polygonContains(getPoint()(0),getPoint()(1), getPolygon()))
  }

  def getPolygon() = {
    Array(Array( Array(42.503320312499994, 1.7060546875), Array( 42.4966796875, 1.678515625000017 ),
    Array( 42.455957031249994, 1.58642578125 ), Array( 42.441699218749996, 1.534082031250023 ), Array( 42.434472656249994, 1.486230468750023 ),
    Array( 42.437451171875, 1.448828125 ), Array( 42.46132812499999, 1.428125 ), Array( 42.497851562499996, 1.430273437500006 ),
    Array( 42.530810546874996, 1.421972656250006 ), Array( 42.548388671874996, 1.414843750000017 ), Array( 42.5958984375, 1.428320312500006 ),
    Array( 42.6216796875, 1.458886718750023 ), Array( 42.642724609374994, 1.501367187500023 ), Array( 42.635009765625, 1.568164062500017 ),
    Array( 42.604443359375, 1.709863281250023 ), Array( 42.575927734375, 1.739453125000011 ), Array( 42.55673828125, 1.740234375 ),
    Array( 42.525634765625, 1.713964843750006 ), Array( 42.503320312499994, 1.7060546875 ) ) )
}

 def getPoint() = {
    Array(42.503615,1.641881)

}

the result is:

true
false

So the difference is in the two methods

public static boolean polygonContains(double[] point, double[][][] polygonPoints)

and

public static boolean polygonContains(double latitude, double longitude, double[][][] polygonPoints) 

The data I am using are actually latitude,longitude values.

Ah, the second call reverses the lat and lon, this actually intentional since that is the convention in a lot of places. Geojson does lon,lat (x,y). So you need to swap x and y and it should work.

Then the method signature of

public static boolean polygonContains(double latitude, double longitude, double[][][] polygonPoints) 

is wrong?

actually 42.503615 is the latitude value...

actually in geojson, the first double would be the longitude and the second one the latitude. http://terraformer.io/glossary/. In your polygon, you have the same.

Sorry but I still don't get it.
I know geojson but the data of the point and the polygon I am using in the example is always [lat,lng].

Point:
[lat,lng] => 
[42.503615, 1.641881]

Polygon:
[[ [lat,lng],  [lat,lng], [lat,lng], ... ]] =>
[[[42.503320312499994, 1.7060546875], [42.4966796875, 1.678515625000017],
[42.455957031249994, 1.58642578125], ... ]]

Do I have to reverse the order for the point and not for the polygon when calling the following method?

public static boolean polygonContains(double latitude, double longitude, double[][][] polygonPoints)

Shouldn't the signature be

public static boolean polygonContains(double longitude, double latitude, double[][][] polygonPoints)

then?

That might be what you intend, but geojson interprets it as lon,lat. So your point is middle of nowhere in Somalia (check on http://geojsonlint.com/). If you reverse it, you end up in Andorra, which I guess is what your polygon was intended to be?.

Yes it's a loc in Andorra and the polygon is actually (approximately) the border of Andorra. 👍

So when I understand it correctly the third param double[][][] polygonPoints should actually be geojson?

e.g. [[ [lng,lat], [lng, lat], ... ]]

Seems like I was confused by the comments of another method:

 /**
* Determine whether a point is contained in a polygon. Note, technically
* the points that make up the polygon are not contained by it.
*
* @param latitude latitude
* @param longitude longitude
* @param polygonPoints
* polygonPoints points that make up the polygon as arrays of
* [latitude,longitude]
* @return true if the polygon contains the coordinate
*/
public static boolean polygonContains(double latitude, double longitude, double[]... polygonPoints)

Where it says that the polygonPoints are arrays of [lat,lng]

Yes, the javadoc is wrong basically. Sorry about that. Need to fix that.

Great thx alot!

http://www.scoopmap.net performance will get better with GeoGeometry 👍

No problem, glad some people are using this. As you can see, the code has some rough edges. So, thanks for reporting.

Scoopmap looks cool BTW. Looks conceptually similar to Localstream, which is something I worked on last year. We did a news demo based on archives of the Guardian, trying to tie articles to locations at really finegrained level. We tried to geocode things in the articles to determine mentions of streets and neighborhoods to come up with a local new engine. Was pretty hard to get right in the end (lots of ambiguity) but I like your approach.

Sounds interesting. Closing this issue. Thx again.