Howdy all:
I've been investigating strategies for serving up polygons that straddle the anti-meridian (-180/180 longitude aka International Date Line aka IDL) and thought I would share what I've found so far and see if anyone else had differing recommendations before writing up a wiki entry.
I will try to be very explicit with my terminology so as to provide as much fodder as possible for search engines.
Cheers,
Ryan
ENVIRONMENT:
I am using PostgreSQL/PostGIS with GeoServer 1.6.4 and want to be able to perform some SQL-based geospatial analysis and serve up my data sets to the following clients:
ESRI ArcGIS 9.2SP5
Google Earth 4.3.7204.0836
OpenLayers 2.6
My data sets are at the global scale -- features across the Pacific are just as relevant as features across the Atlantic. I store all the features in unprojected coordinates -- WGS84 aka EPSG:4326.
The following discussion will assume single ring polygons, amenable to storage in a PostGIS POLYGON type, though there shouldn't be anything that precludes more complex features that by nature require a MULTIPOLYGON.
PAST APPROACH: split polygons at anti-meridian
In the past, for expediency, I had simply just split all my polygons along the anti-meridian, keeping all the polygon points within [-180, 180] longitude. However, this has the downside of vertical lines running down the polygons when they get rendered on a anti-meridian-centered map.
Further, Google Earth will make requests for data beyond +180 longitude (depending on the current viewing position); for example: [80, 210] longitude. So, if you used this approach and had a polygon that had points in the [-180, -160] range, GeoServer (and indirectly PostGIS) would not provide it to Google Earth in response to such a request, as neither product makes accommodation for wrap-around.
Also, with this data storage approach, certain geospatial queries in PostGIS have to be done twice. For example, intersection tests involving a buffer around a point and a polygon. If that point was at 179 longitude, the spatial query would have to be done once using 179 as as point and again using -181.
ALTERNATIVE APPROACH: duplicate and shift coordinate space of polygon
I am now about to migrate to a methodology that would store two variants of a polygon that spans the anti-meridian: one that is wholly contained in (-180, 540) longitude and one that is wholly contained in (-540, 180) longitude. Both polygon variants would be accessible from a single layer.
The edge case where the polygon circles the entire globe like a belt (from the perspective of the Mercator_1SP projection) would be stored as a single polygon, closed at -180 and 180.
Each polygon feature would have a row in a parent table that stores all of the polygon's meta-data and one ore more rows in a child table (with a foreign key dependency on the parent table) that stores the geometry. GeoServer would retrieve this data through a table view.
This approach works with the existing PostGIS DataStore and minimizes the BBOX of the PostGIS geometry.
The downsides of this approach:
- two variants of the polygon's geometry are stored on disk
- two variants of the polygon get sent to the client over the network and are not associated with each other
- table join required
- features have coordinates outside the [-180, 180] longitude space, which results in warnings (seemingly benign, at least for my data sets) in ESRI ArcMap
- depending on the client, map projection, zoom level, etc., features will be displayed overhanging the map edges
A variation of this approach would be to store MULTIPOLYGON geometries. This would:
- eliminate the table join
- enlarge the BBOX of the geometry significantly, reducing the effectiveness of the spatial index. For example a polygon that spanned [170,190] would have a corresponding MULTIPOLYGON containing two polygons: one ranging from [170,190] and one from [-190,-170], resulting in a MULTIPOLYGON with a BBOX spanning [-190,190].
For the buffer-around-point geospatial query example mentioned previously, only is one query would be necessary -- effectively trading two SQL queries for two polygon variants stored on disk.
CLIENT BEHAVIOR USING ABOVE APPROACH:
* Google Earth 4.3.7204.0836
Displays well if polygons are rendered by GeoServer and sent in the .kmz as a bitmap.
Displays less-than-well if polygons are sent as KML vector data. Google Earth does not support KML vector data that spans the anti-meridian. So, if you have a polygon that spans [170, 190] longitude, Google Earth will draw it clipped at 180. Alternatively, if you clipped the polygon into two polygons that each spanned [170,180] and [-180,-170], Google Earth will not draw the polygons directly adjacent, but clips them so there is a ~60km gap in between the two polygons.
* ESRI ArcGIS 9.2SP5
Aside from the usual frustrating behavior associated with its WFS implementation (see http://sourceforge.net/mailarchive/message.php?msg_id=47A075BB-81ED-45C5-81C5-9283EF2E2BEF%40gmail.com), ArcGIS (ArcMap) renders the WFS data well.
Both unprojected and projected maps work (well, at least Mercator), centered on the prime meridian and anti-meridian alike. In an unprojected map, polygons that span the meridian hang off the edges of a Greenwich-centered map.
Due to a GeoServer issue, data requested via WMS in certain projections will not render correctly. More details in GEOSERVER PROJECTION ISSUES section.
* OpenLayers 2.6
Displays well in both unprojected and _certain_ projected coordinate spaces via WMS & WFS, with the caveat that anti-meridian spanning polygons will usually hang off the edge of the map in the case of Greenwich-centered maps. (In my tests, the srsName parameter was explicitly added to OpenLayers WFS 1.0.0 layer config to request that GeoServer perform reprojection from the native EPSG:4326). More details in GEOSERVER PROJECTION ISSUES section.
GEOSERVER PROJECTION ISSUES:
Although slightly orthogonal to the whole issue of how anti-meridian straddling polygons are stored and how to make it work across multiple clients, I ran across a potential projection issue in GeoServer.
My initial tests indicate that GeoServer has problems transforming some global data sets to projections that do not use 0 as the value of central_meridian. For example EPSG:3349, which is a Mercator projection centered on -150 longitude. I have been using ESRI ArcMap against the same input sets to verify results (ArcMap works very well in this regard) -- however, in most cases it is clearly obvious from a visual inspection that the projection failed.
I am still trying to understand this behavior and will file a JIRA issue, but in the meantime if you are curious you can download and install the world borders dataset from:
http://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.2.zip
and request something along the lines of:
/geoserver/wms/reflect?layers=test:TM_WORLD_BORDERS_SIMPL&srs=EPSG:3349
and you'll see what I mean.