Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [geomesa-users] International date line dilemma for non-point geometries, possible bug?

Beau,

We are on the same page. I think we want to support wrapping for every kind of Geometry.

Upon further examination I found this in the docs of spatial4j:

http://spatial4j.github.io/spatial4j/apidocs/index.html?com/spatial4j/core/context/jts/JtsSpatialContext.html

MakeShape

"dateline180Check - if both this is true and SpatialContext.isGeo(), then JtsGeometry will check for adjacent coordinates greater than 180 degrees longitude apart, and it will do tricks to make that line segment (and the shape as a whole) cross the dateline even though JTS doesn't have geodetic support."

So it looks like this lib doesn't support what we both have in mind and we may roll our own.

Hunter

In case you may be interested, I've included the tests I have written and which pass within my feature branch.

It is scala format for creating a Map of String to Tuple(String, String, String).

key -> (geometryToTest, point s.th. transformed geometry.contains = true, point s.th. transformed geometry.constains = false)

"[LINE] no span" -> ("LINESTRING(50 50, 60 60)", "POINT(55 55)", "POINT(30 30)"),
    "[LINE] span" -> ("LINESTRING(-200 50, -160 60)", "POINT(170 52.5)", "POINT(30 30)"),
    "[POLYGON] span" -> ("POLYGON((-170 80, -190 80, -190 70, -170 70, -170 80))", "POINT(175 75)", "POINT(165 75)"),
    "[POLYGON] span transform right" -> ("POLYGON((190 80, 170 80, 170 70, 190 70, 190 80))", "POINT(-175 75)", "POINT(165 75)"),
    "[POLYGON] no span" -> ("POLYGON((-170 80, 170 80, 170 70, -170 70, -170 80))", "POINT(165 75)", "POINT(175 75)"),
    "[MULTILINE] span" -> ("MULTILINESTRING((-190 40, -170 40),(40 50, 45 55))", "POINT(175 40)", "POINT(165 40)"),
    "[MULTIPOLYGON] span" -> ("MULTIPOLYGON(((-170 80, -190 80, -190 70, -170 70, -170 80)),((30 30, 30 40, 40 40, 40 30, 30 30)))", "POINT(175 75)", "POINT(30 25)"),
    "[MULTIPOINT] span" -> ("MULTIPOINT(-200 50, 40 20)", "POINT(160 50)", "POINT(159 60)"),
    "[MULTIPOINT] no span" -> ("MULTIPOINT(80 50, 40 20)", "POINT(80 50)", "POINT(159 60)"),
    "[MULTIPOINT] no span2" -> ("MULTIPOINT(80 50, 40 20)", "POINT(40 20)", "POINT(159 60)"),
    "[POINT] point no span" -> ("POINT(-190 40)", "POINT(170 40)", "POINT(40 40)"),
    "[POLYGON] antarctica" -> ("POLYGON((-179.99900834195893 -89.99982838943765, -179.99900834195893 -84.35288625138337, -164.16219722595443 -78.99626230923768, -158.26351334731075 -77.08619801855957, -158.2192008065469 -77.0736923216127, -55.37731278554597 -61.07063812275956, -45.934374960003026 -60.524831644861884, -45.7198660894195 -60.51625335736412, 135.3432939050984 -66.10066701248235, 135.4887113859158 -66.11100229913357, 143.50863529466415 -66.84460093230936, 153.878803345093 -68.27893198676848, 167.70100874912129 -70.79128509537779, 170.26488326045944 -71.29213307737697, 170.28265995306788 -71.29874766015023, 170.8138936774078 -71.69965342205771, 170.88500044784155 -71.75887461315726, 170.96623579935533 -71.83452891065282, 180.001 -84.35286778378045, 180.001 -89.99982838943765, -179.99900834195893 -89.99982838943765))", "POINT(-179.999999 -89.99)", "POINT(40 50)")
On 07/01/2014 02:10 PM, Beau Lalonde wrote:
Hunter,

Thanks for the update.

You are correct in that I would expect LINESTRING (-200 50, -160 60) to be equivalent to two linestrings (-180 55, -160 60) (160 50 180 55).

I will mention that in different parts of my code I am using LINESTRING geometries and in other parts of my code I am using POLYGONS (usually just a rectangle).  Given the location of the data, the LINESTRING or POLYGON geometries could cross the international date line and have longitudinal values that break out of the [-180, 180] region.  I allow the longitudinal values to "unwrap" so that there is no ambiguity in the Geometry.  That being said, it would be great if you somehow create a generic enough implementation such that you can handle any geometry that crosses the international date line.  In the generic sense, that could mean having to split a single geometry into N>=1 geometries that live in the [-180, 180] longitudinal space (concave polygons could be tricky).

It sounds like you are moving toward the exact implementation that I would find desirable:
 - an implementation in which I can index features with unwrapped geometries
 - an implementation in which my queries can remain in the [-180, 180] longitudinal space (meaning I don't have to query outside of [-180, 180] in order to get results for geometries that were indexed with longitudes that went beyond the [-180, 180] space.
 -- for example, if I index LINESTRING (-200 50, -160 60), and then query (160 50 180 55), I should get results.

Let me know if we are on the same page.  I believe we are.

Thanks,
Beau

-----Original Message-----
From: Hunter Provyn [mailto:fhp@xxxxxxxx] 
Sent: Tuesday, July 01, 2014 1:19 PM
To: Beau Lalonde; hunter@xxxxxxxx; Geomesa User discussions
Subject: Re: [geomesa-users] International date line dilemma for non-point geometries, possible bug?

Beau,

Yes, the ticket is Geomesa-150.

https://geomesa.atlassian.net/browse/GEOMESA-150

I've got a PR up that handles part of this issue. We expect it to be resolved soon.
I was just looking into using spatial4j rather than the transformations that I have written.
However, spatial4j JtsGeometry turns LINESTRING (-200 50, -160 60) into LINESTRING (-180 55, -160 60).  So it fails the test I created that should turn that into two linestrings (-180 55, -160 60) (160 50 180 55). This (result of my test) is what you would be expecting, right?

thanks,
Hunter


On 07/01/2014 12:48 PM, Beau Lalonde wrote:
Hunter,

Any update about this issue?

Thanks,

Beau

-----Original Message-----
From: geomesa-users-bounces@xxxxxxxxxxxxxxxx 
[mailto:geomesa-users-bounces@xxxxxxxxxxxxxxxx] On Behalf Of Hunter 
Provyn
Sent: Monday, June 23, 2014 9:45 AM
To: geomesa-users@xxxxxxxxxxxxxxxx
Subject: Re: [geomesa-users] International date line dilemma for non-point geometries, possible bug?

Beau,

Good catch. We are looking into this now.
I'll get back to you with some guidance and, if this turns out to be a bug, a JIRA tracking ticket.

thanks,
Hunter
On 06/20/2014 02:17 PM, Beau Lalonde wrote:
Hi,

I currently use GeoMesa to index non-point geometries (e.g. LineString, Polygon, MultiPoint), and I have recently switched from using a January version of GeoMesa to using a version that is current (as of the last week or so).

In the January version of GeoMesa, I had implemented an international date line solution for non-point geometries as follows:
- When indexing a non-point geometry (e.g. Polygon) that overlapped the international date line, I would make sure all of the longitudinal values were unwrapped.  In my implementation, this had the consequence of having my indexed geometries span anywhere from -540 degrees longitude to 540 degrees longitude (with at least a portion of the geometry in the [-180, 180] region).
- When querying using GeoMesa, I would actually perform multiple queries in the appropriate redundant regions in space [-540, -180], [-180, 180], and [180, 540] to make sure I captured any geometries that spanned the international date line.


With the latest version of GeoMesa, I get the following exception when I try to index a non-point geometry (by unwrapping the longitude) that spans the international date line:
Exception in thread "main" java.lang.Exception: ERROR:  Could not find a suitable 0-bit MBR for the target geometry:  POLYGON ((179.31530746783775 -39.87427143505418, 179.31530746783775 -37.87427143505418, 181.31530746783775 -37.87427143505418, 181.31530746783775 -39.87427143505418, 179.31530746783775 -39.87427143505418))
	at geomesa.utils.geohash.GeohashUtils$.getMinimumBoundingGeohash(GeohashUtils.scala:241)
	at geomesa.utils.geohash.GeohashUtils$.decomposeGeometry_(GeohashUtils.scala:535)
	at geomesa.utils.geohash.GeohashUtils$.decomposeGeometry(GeohashUtils.scala:564)
	at geomesa.core.index.IndexEncoder.encode(IndexEntry.scala:70)
	at geomesa.core.index.IndexSchema.encode(IndexSchema.scala:84)
	at geomesa.core.data.AccumuloFeatureWriter.writeToAccumulo(AccumuloFeatureWriter.scala:104)
	at geomesa.core.data.AppendAccumuloFeatureWriter.write(AccumuloFeatureWriter.scala:130)
	at org.geotools.data.AbstractFeatureStore.addFeatures(AbstractFeatureStore.java:324)
	at
geomesa.core.data.AccumuloFeatureStore.addFeatures(AccumuloFeatureSto
r
e.scala:53)


When I try to query outside the [-180, 180] region I get the following exception (even if data does not exist outside of the [-180, 180] region:
Exception in thread "main" java.lang.IllegalStateException: getX called on empty Point
	at com.vividsolutions.jts.geom.Point.getX(Point.java:124)
	at geomesa.utils.geohash.GeohashUtils$.getCentroid(GeohashUtils.scala:256)
	at geomesa.utils.geohash.GeohashUtils$.getMinimumBoundingGeohash(GeohashUtils.scala:228)
	at geomesa.utils.geohash.GeohashUtils$.decomposeGeometry_(GeohashUtils.scala:535)
	at geomesa.utils.geohash.GeohashUtils$.decomposeGeometry(GeohashUtils.scala:564)
	at geomesa.utils.geohash.GeohashUtils$.getUniqueGeohashSubstringsInPolygon(GeohashUtils.scala:672)
	at geomesa.core.index.GeoHashPlanner$class.polyToGeoHashes(QueryPlanners.scala:275)
	at geomesa.core.inde I'll get back to you withx.GeoHashKeyPlanner.polyToGeoHashes(QueryPlanners.scala:308)
	at geomesa.core.index.GeoHashPlanner$class.polyToPlan(QueryPlanners.scala:280)
	at geomesa.core.index.GeoHashKeyPlanner.polyToPlan(QueryPlanners.scala:308)
	at geomesa.core.index.GeoHashPlanner$class.getKeyPlan(QueryPlanners.scala:302)
	at geomesa.core.index.GeoHashKeyPlanner.getKeyPlan(QueryPlanners.scala:308)
	at geomesa.core.index.GeoHashKeyPlanner.getKeyPlan(QueryPlanners.scala:309)
	at geomesa.core.index.CompositePlanner$$anonfun$9.apply(QueryPlanners.scala:396)
	at geomesa.core.index.CompositePlanner$$anonfun$9.apply(QueryPlanners.scala:396)
	at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
	at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
	at scala.collection.immutable.List.foreach(List.scala:318)
	at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
	at scala.collection.AbstractTraversable.map(Traversable.scala:105)
	at geomesa.core.index.CompositePlanner.getKeyPlan(QueryPlanners.scala:396)
	at geomesa.core.index.IndexQueryPlanner.planQuery(IndexQueryPlanner.scala:171)
	at geomesa.core.index.IndexQueryPlanner.getIterator(IndexQueryPlanner.scala:100)
	at geomesa.core.index.IndexSchema.query(IndexSchema.scala:98)
	at geomesa.core.data.AccumuloFeatureReader.<init>(AccumuloFeatureReader.scala:32)
	at geomesa.core.data.AccumuloDataStore.getFeatureReader(AccumuloDataStore.scala:294)
	at geomesa.core.data.AccumuloDataStore.getFeatureReader(AccumuloDataStore.scala:55)
	at org.geotools.data.AbstractDataStore.getFeatureReader(AbstractDataStore.java:369)
	at org.geotools.data.DefaultFeatureResults.reader(DefaultFeatureResults.java:215)
	at org.geotools.data.store.DataFeatureCollection.openIterator(DataFeatureCollection.java:231)
	at org.geotools.data.store.DataFeatureCollection.iterator(DataFeatureCollection.java:199)
	at org.geotools.data.store.DataFeatureCollection.features(DataFeatureCollection.java:188)
	at org.geotools.data.store.DataFeatureCollection.features(DataFeatureCollection.java:79)
	...


My questions are:
1) Is this behavior a bug?
2) if it's not a bug, what are some alternate approaches to indexing/querying non-point geometries that span the international date line?  Any direct guidance would be appreciated.


My ideal GeoMesa solution would be:
A) When I index geometries, I could provide GeoMesa unwrapped longitudes in order to remove ambiguity as to what the geometry represents in actual space (e.g. a small polygon crossing the international dateline vs. a large polygon covering almost the entire world).
B) When I query, I would prefer querying only the [-180, 180] longitudinal region and have GeoMesa/GeoTools be smart enough to detect overlaps with my unwrapped indexed geometries.

Thanks,
Beau
_______________________________________________
geomesa-users mailing list
geomesa-users@xxxxxxxxxxxxxxxx
http://www.locationtech.org/mailman/listinfo/geomesa-users
_______________________________________________
geomesa-users mailing list
geomesa-users@xxxxxxxxxxxxxxxx
http://www.locationtech.org/mailman/listinfo/geomesa-users

    


Back to the top