( function ( $ ) { op2geojson = function() { var instance = {}, geojson; instance.fetch = function(url, data, zoom, latitude, callback) { var postCallback = function(data) { // Add nodes and ways to the layer var features = []; // Process the data var nodes = {}; var ways = {}; var relations = {}; $.each(data.elements, function(i, item) { if (item.type === 'node') { nodes[item.id] = item; // As the nodes do not relate to other bits, // they can be added here if (item.tags != undefined) { features.push( instance.point(item) ); } } else if (item.type === 'way') { ways[item.id] = item; } else if (item.type === 'relation') { relations[item.id] = item; } }); var format = new OpenLayers.Format.GeoJSON; // circumference of the Earth * cos(latitude)/2^(zoom level +8) var latitudeInRadians = latitude * Math.PI/180; var metersPerPixel = (40075000 * Math.cos(latitudeInRadians))/(Math.pow(2, (zoom + 8))); $.each(ways, function(i, way) { if (!_.isUndefined(way.tags) && ( way.tags.amenity == "hospital" || !_.isUndefined(way.tags.place) || way.tags.landuse == "residential")) { var area = instance.wayToPolygon(way, nodes); var areaGeo = format.parseGeometry(area.geometry); var geodesicArea = areaGeo.getGeodesicArea(); var averageWidth = Math.sqrt(geodesicArea); var pixelsOfAverageWidth = averageWidth / metersPerPixel; if (pixelsOfAverageWidth < 10) { var node = nodes[way.nodes[0]]; var centroid = areaGeo.getCentroid(); var point = { type : "Feature", id : way.id, geometry : { type : "Point", coordinates : [centroid.x, centroid.y] }, properties : {} }; _.extend(point.properties, way.tags); features.push(point); } else { features.push(area); } } }); $.each(relations, function(i, relation) { if (relation.tags != undefined && relation.tags['type'] == 'boundary' && relation.tags['boundary'] == 'catchment_area') { var poly = instance.polygon(relation, ways, nodes); poly.id = relation.id; features.push(poly); } }); geojson = instance.featureCollection(features); callback(geojson); } $.post(url, data, postCallback, "json"); }; instance.point = function(node) { var point = { type : "Feature", geometry : { type : "Point", coordinates : [node.lon,node.lat] }, properties : {} }; _.extend(point.properties, node.tags); return point; } instance.lineString = function(way, nodeArray) { // Get the node coordinates from nodeArray var coordinates = []; for (id in way.nodes) { var node = nodeArray[way.nodes[id]]; coordinates.push([node.lon,node.lat]); } // Create the LineString var lineString = { type : "Feature", geometry : { type : "LineString", coordinates : coordinates }, properties : {} }; // Add the tags _.extend(lineString.properties, way.tags); return lineString; } instance.featureCollection = function(features) { collection = { type : "FeatureCollection", features : features }; return collection; } instance.polygon = function(relation, ways, nodes) { polyCoords = []; var firstCheck = true; var subject; $.each(relation.members, function(i, member) { if (member.role == "outer") { var way = ways[member.ref]; if (typeof way == 'undefined') return; var wayCoords = instance.lineString(way, nodes).geometry.coordinates; var numNodes = wayCoords.length // Need to ensure that the first way is in the correct direction, but this can // only be checked when looking at the second way if (firstCheck && polyCoords.length != 0) { firstCheck = false; if ((polyCoords[0][0] == wayCoords[0][0] && polyCoords[0][1] == wayCoords[0][1]) || (polyCoords[0][0] == wayCoords[numNodes - 1][0] && polyCoords[0][1] == wayCoords[numNodes - 1][1])) { polyCoords.reverse(); } } if (polyCoords.length != 0) { // If this way is backward if (polyCoords[polyCoords.length - 1][0] != wayCoords[0][0] || polyCoords[polyCoords.length - 1][1] != wayCoords[0][1]) { wayCoords.reverse(); } polyCoords.pop(); } polyCoords = polyCoords.concat( wayCoords ); } else if (member.role == "subject") { subject = member.ref; } }); var poly = { type : "Feature", geometry : { type : "Polygon", coordinates : [polyCoords] }, properties : {} }; // Add the tags _.extend(poly.properties, relation.tags); poly.properties["subject"] = subject; return poly; } instance.wayToPolygon = function(way, nodeArray) { // Get the node coordinates from nodeArray var coordinates = []; for (id in way.nodes) { var node = nodeArray[way.nodes[id]]; coordinates.push([node.lon,node.lat]); } // Create the LineString var poly = { type : "Feature", geometry : { type : "Polygon", coordinates : [coordinates] }, properties : {} }; // Add the tags _.extend(poly.properties, way.tags); return poly; } return instance; }; })( jQuery );