Open Data and Projections

13 Jan

I am not a geographer, nor am I a math wiz. So for me, projections have been a constant source of pain and suffering. I have opened my mouth and said that WGS84 should be the default for all GIS data. It didn’t go over well – mostly because I think the old school GIS folks have just always done things a certain way and will not stop. Apparently, I am not the only person that hates projections. Calvin Metcalf hates projections too. In the real world, we are the minority and are stuck dealing with them. So in this article I will show you how the ESRI REST API makes it much simpler.

The Open Data

I will start by connection to some Albuquerque Open Data. In this example, I will query the Parks REST service. First, open the link for the parks service and notice that the spatial reference is 102100  (3857). This is WGS 1984 Web Mercator. If you query where 1=1, you can see coordinates like [-1.1855471312199999E7, 4173947.5449]. I want to use WGS84 (4326) so I need coordinates like [35.10418, -106.62987]. We could use a library like Proj4js to convert, but the API already has the functionality we need built right in. On the query form, add 4326 to the output spatial reference field and now you (-1.xx , 417.xxx) becomes [-106.xxx, 35.xxx]. This is what we need.

When you query, you may also want to pass in coordinates from a different spatial reference. You can do this by changing the input spatial reference to 4326. The server will handle the conversion and return the correct feature for you.

An Example

I will start by creating a simple Leaflet.js map that returns coordinates in 4326 on a map click.

<html>
<head><title>Projections</title>
<link rel=”stylesheet” href=”http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css&#8221; />
<style>
html, body, #map {
padding: 0;
margin: 0;
height: 100%;}

</style>
</head>
<body>
<script src=”http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js”></script&gt;
<div id=”map”></div>
<script>
var map = L.map(‘map’,
{center: [35.10418, -106.62987],
zoom:15 });
L.tileLayer(‘http://{s}.tile.osm.org/{z}/{x}/{y}.png’).addTo(map);
map.on(“click”,function(e){
alert(e.latlng);
});
</script>
</body>
</html>

To make a query, we need to replace the alert() function. I will use an AJAX query to the Parks REST endpoint.

First, we need to capture the (lat,lng) in a format we can use. You could split the e.latlng string but that is too much trouble. I will create a marker when the user clicks. I will not add the marker to the map, but rather, I will convert it to GeoJSON. Then I will create a parameter string from several other strings.

var marker=L.marker(e.latlng);
coords=marker.toGeoJSON();
q1=”inSR=4326&outSR=4326&f=json&geometryType=esriGeometryPoint&geometry=”;
q2=String(coords.geometry.coordinates[0]);
q3=”,”;
q4=String(coords.geometry.coordinates[1]);
var params=q1.concat(q2,q3,q4);

In the above code, I grabbed the click e.latlng and passed it to create a marker. The coords variable holds a GeoJSON representation of the marker.

The variable q1 holds my parameters:

  1. inSR = 4326 – this is the projection I want to use
  2. outSR = 4326 – I want the server to give me back the same, not 3857
  3. f=json – I want json, not the HTML
  4. geometryType = esriGeometryPoint – I am taking a point and want the polygon (park) it is in

The last parameter is the geometry.  I specified a point so the server expects two coordinates. I use coords.geometry.coordinates[0] and coords.geometry.coordinates[1] – These are the values for longitude and latitude from the GeoJSON representation of the marker.

Now, I will make the AJAX call and close the map.on function.

var params=q1.concat(q2,q3,q4);
var url = “http://coagisweb.cabq.gov/arcgis/rest/services/public/recreation/MapServer/0/query?&#8221;;
http=new XMLHttpRequest();
http.open(“POST”, url, true);
http.setRequestHeader(“Content-type”, “application/x-www-form-urlencoded”);
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
theGeom= JSON.parse(http.responseText);
console.log(theGeom.features[0].attributes.PARKNAME);
console.log(JSON.stringify(theGeom.features[0].geometry.rings));
}
}
http.send(params);
}); // close map.on

Now you should have a map that waits for a click, then queries the REST endpoint passing a point in 4326 and gets back a park name with coordinates in 4326.

I zoomed in to Robinson Park.

I zoomed in to Robinson Park.

Clicking Robinson Park gave me the screenshot below.

Robinson Park with Rings

Robinson Park with Rings

You do not have to be an expert on projections, just use the tools provided and pass what you want to input and what you want sent back to you as parameters in your queries.

Advertisements

One Response to “Open Data and Projections”

  1. ~Felicia~ January 18, 2015 at 2:11 am #

    I want to learn to do all this! ~~~F

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: