Monthly Archives: April 2009

Fun With Simile

I want to send a shout out to anyone working on the Simile Timeline project.  Born out of the Semantic Interoperability of Metadata and Information in unLike Environments (SIMILE) project conducted by the MIT Libraries and MIT CSAIL, they are part of a suite of tools that enable visualization of seemingly massive datasets. We are implementing an in-house solution for planning, and the timeline is fast, slick, and solid.

I was rockin’ the maps with a version of timeline integrated with OpenLayers, appropriately named maptimeline. Abandoning all grasp of reality, I then added a Simile Timeplot to the interface, too.   I would have liked to be able to integrate the time plot and the timeline tighter, but at this point, that integration is still a bit clunky.

Coming back down to earth, I dropped the map and the timeplot, as they didn’t add value to an already cluttered interface. Nonetheless,  I am really impressed with how well all of these tools perform.

Distance? Math? What?

A few days ago, I became painfully aware that the distance equation we all learn in geometry class, while it works perfectly well on flat, local projections,  is woefully inadequate when we’re talking about global coordinate systems.

In the midst of implementing Google Maps in our up-coming Sajara sample application, I realized that the International Date Line was causing problems. Large problems. Whenever the IDL was in play, I never retrieved the correct results from our database. One large problem was how we defined our bounding box inside Sajara itself. Once that was fixed, however, I realized that something was still wrong. The Nearest-to-Farthest sort was not behaving quite right: it was really doing a Nearest-on-this-side-of-the-IDL-first sort! The IDL was acting like a wall for our distance sort.

distance

Example of linear distance with IDL in play. X = center of map

Here’s what we used before (in sql-speak):

RETURN sqrt(power(@FromX - @ToX,2) + power(@FromY - @ToY,2))

Your standard square-root of difference-squared plus difference-squared. This formula is fast and worked perfectly well so long as I operated under these two criteria:

1. a FLAT projection
2. POSITIVE numbers only

Once either of those things aren’t true anymore, I can’t use the basic distance formula. In my case, both things stopped being true at the same time! The solution? Something fairly math-magical to my mind, but accepted as THE formula to get at the distance between any two global coordinates: the Haversine Formula. Delving into descriptions of the formula brings up concepts such as spherical triangles, the planet’s elipticity, great circles and other things very important to navigation. It’s accurate down to about a meter, which is plenty for anything I’ll be doing with it.

Haversine Formula in Javascript:

var R = 6371; // radius of the earth
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
        Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var distance = R * c;

So here is the resulting SQL function that gives me the right distance between any two global coordinates.. basically a direct translation of the above javascript into T-SQL:

CREATE FUNCTION [dbo].[distance] (@FromX float, @FromY float, @ToX float, @ToY float)
RETURNS float AS BEGIN
DECLARE @R AS FLOAT;
SET @R = 6371;
DECLARE @DLAT AS FLOAT;
DECLARE @DLON AS FLOAT;
DECLARE @A AS FLOAT;
DECLARE @C AS FLOAT;
DECLARE @D AS FLOAT;
SET @DLAT = RADIANS(@ToY - @FromY);
SET @DLON = RADIANS(@ToX - @FromX);
SET @A =
SIN(@DLAT/2) * SIN(@DLAT/2) +
COS(RADIANS(@FromY)) * COS(RADIANS(@ToY)) * SIN(@DLON/2) * SIN(@DLON/2);
SET @C = 2 * ATN2(SQRT(@A), SQRT(1-@A));
SET @D = @R * @C;
RETURN @D
END


Tricks & Woes w/ WMS GetFeatureInfo

Here’s a trick that could be useful if you’re writing a simple map application in JavaScript that interacts with a WMS map service that you control, and your application needs information about a feature that the user has clicked on.   Did you know that you can cajole your WMS server to directly produce JSON (which is a very convenient way to receive data in a JS application) with feature information as a response to a WMS request?  I found this trick useful in a recent application as a simple approach, if one doesn’t mind wrangling with server configuration.  Unfortunately, it involves using an under-specified part of the WMS standard, so this recipe is also a good illustration of where the OGC WMS standard could be improved.

In the WMS specification, OGC defined an “optional” GetFeatureInfo request that returns feature information based on a pixel from a map.  It’s both useful and limiting that the request is based on the pixel — it’s useful in that you can just pass along the pixel that the user clicked on, but you don’t have a lot of control (without other trickery I won’t go into here).  But here’s the catch: the output format isn’t defined in the standard.  But here the problem becomes the opportunity — most WMS servers allow you can define your own output format, which includes JSON.

But again the problem returns to the fact that there isn’t a standard in place here:  different mapservers handle the output format definition differently.  MapServer has a very straightforward method — it will respond to a “text/html” request with three templates you can define: you can define a header template, a content template (that is repeated for each feature), and a footer template.  It will replace any attribute name surrounded with brackets with the value of the attribute.  So if you create a header.html file with a single left bracket (‘[') and a footer.html with a single right bracket (']‘) and then a template.html file that is something like:

{
id: “[id]“,
attribute: “[attribute]“
}

you’ll get responses to your GetFeatureInfo request in proper JSON, e.g.:

“[ { id: "123", attribute: "foo" }, { id: "456", attribute: "bar" } ]“

GeoServer has a different structure for its GetFeatureInfo templates, which is described here but the same basic approach works, with the major difference being that you create a single template with header and footer sections.  I’m not sure how it’s done with ArcGIS Server, but with ArcIMS there are XSL files for each output format, and you could create one that generates JSON without too much trouble if you are familiar with XSL.  If someone figures out how to do this with ArcGIS Server, I’ve love to know.

Of course, what would really be fantastic would be if the OGC standard was extended to include a standard output format — I won’t even dare to dream for a standard way to define the output format.

I knew March was a long month…

But this is ridiculous:

March 74, 2009

Found here: http://www.statsvn.org/

OpenLayers with ArcGIS or ArcIMS

OpenLayers, an open source web mapping library for browsers, is 99% web mapping goodness.  We took a look at the library, and found that we could almost use it in our projects to provide a robust mapping interface.  The extra 1% that we really needed was support for ArcIMS and ArcGIS Server.

So we fixed it.

Jeff added support for ArcGIS Server, and I added support for ArcIMS (in addition to a subset of ArcXML).  These are tickets in the OpenLayers tracking system, under the monickers #1749 and #213, respectively.  ArcGIS Server has made it into the trunk, and we are anxiously awaiting the incorporation of ArcIMS/ArcXML support.  It looks like they are both on track to make it into OpenLayers v2.8, so we are excited.

We’ve been running production applications with the patches we’ve provided to the OpenLayers community for months now, so it’ll be wonderful to make it ‘official’.