aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--resources/data.js9
-rw-r--r--resources/map.js526
2 files changed, 275 insertions, 260 deletions
diff --git a/resources/data.js b/resources/data.js
index 85a77c2..e69de29 100644
--- a/resources/data.js
+++ b/resources/data.js
@@ -1,9 +0,0 @@
-function getVillages(area, zoom) {
- var poly = "12.3 -12.3 12.4 -12.3 12.48 -12.25 12.35 -12.19";
- var query = 'data=[out:json];(node(poly:"' + poly + '");<;);out;';
-
- converter = new op2geojson();
- converter.fetch("http://overpass-api.de/api/interpreter", query, zoom, function(data) {
-
- });
-}
diff --git a/resources/map.js b/resources/map.js
index 3369656..8159514 100644
--- a/resources/map.js
+++ b/resources/map.js
@@ -48,6 +48,78 @@ function getDataURIForRegion(self, region) {
return dataURI;
}
+function catchmentAreaProperties(catchmentArea, healthPost) {
+ var settlements = catchmentArea.settlements;
+
+ var format = new OpenLayers.Format.GeoJSON;
+ var openLayersGeo = format.parseGeometry(catchmentArea.geometry);
+
+ var sumOfDistances = 0;
+ var maxDistance = 0;
+
+ var Geographic = new OpenLayers.Projection("EPSG:4326");
+ var Mercator = new OpenLayers.Projection("EPSG:900913");
+
+ var healthPostPoint = format.parseGeometry(healthPost.geometry);
+ if (healthPost.geometry.type == "Point") {
+ //amenityPoint = new OpenLayers.Geometry.Point(amenity.geometry.coordinates[0], amenity.geometry.coordinates[1]).transform(Geographic, Mercator);
+ } else { // Its a polygon
+ healthPostPoint = healthPostPoint.getCentroid();
+ }
+
+ _.each(catchmentArea.settlements, function (settlement) {
+ var settlementGeo = format.parseGeometry(settlement.geometry);
+
+ var distance = settlementGeo.distanceTo(healthPostPoint);
+ sumOfDistances += distance;
+ if (distance > maxDistance)
+ maxDistance = distance;
+ });
+
+ var areaInSquareMeters = openLayersGeo.getGeodesicArea();
+ var areaString = areaInSquareMeters.toFixed(2) + "m" + "2".sup();
+ if (areaInSquareMeters > 1000000) {
+ areaString = (areaInSquareMeters / 1000000).toFixed(2) + "km" + "2".sup();
+ }
+
+ var areaProperties;
+ if (typeof settlements == "undefined") {
+ areaProperties = { area: areaString,
+ number_of_settlements: "Unknown",
+ population: "Unknown",
+ greatest_settlement_dist: "Unknown",
+ average_settlement_dist: "Unknown"
+ }
+ } else {
+ var population = 0;
+ var numberOfSettlementsWithoutPopulation = 0;
+
+ _.each(settlements, function(settlement) {
+ if (typeof settlement.properties.population != "undefined") {
+ population += parseInt(settlement.properties.population);
+ } else {
+ numberOfSettlementsWithoutPopulation++;
+ }});
+
+ if (numberOfSettlementsWithoutPopulation != 0) {
+ if (numberOfSettlementsWithoutPopulation == 1) {
+ population = population + " (but " + numberOfSettlementsWithoutPopulation + " settlement has no population set)";
+ } else {
+ population = population + " (but " + numberOfSettlementsWithoutPopulation + " settlements have no population set)";
+ }
+ }
+
+ areaProperties = { area: areaString,
+ number_of_settlements: settlements.length,
+ population: population,
+ greatest_settlement_dist: maxDistance,
+ average_settlement_dist: (sumOfDistances/catchmentArea.settlements.length)
+ }
+ }
+
+ return areaProperties;
+}
+
function initMap(self) {
self.tileLayer = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
@@ -60,87 +132,23 @@ function initMap(self) {
layers: [self.tileLayer],
}).setView([12.4822, -11.9463], 11);
- self.amenitiesShown = ["hospital", "doctors", "dentist"];
+ self.amenitiesShown = ["hospital"];
self.amenities = {};
self.amenityLayers = {}; // contains the layers for each amenity type
+ self.catchmentAreaSettlementsLayers = {}; // Settlement layers, addressed by catchmentArea.id
+ self.settlementsLayerGroup = L.layerGroup(); // A layer group for all the settlement layers, such that they can be treated as one layer in the control
self.catchmentAreas = {};
-
- // Create the settlement layer
- self.settlementLayer = L.geoJson({ type: "FeatureCollection", features: [] }, {
- style: function(feature) {
- return {fillColor: 'green',
- weight: 2,
- opacity: 1,
- color: 'black',
- dashArray: '3',
- fillOpacity: 0.1};
- },
- onEachFeature: function(feature, layer) {
- var center;
- if (feature.geometry.type === "Point") {
- center = feature.geometry.coordinates;
- } else {
- center = feature.geometry.coordinates[0];
- }
-
- var displayProperties = { name: feature.properties["name"], population: feature.properties["population"] };
- if (typeof displayProperties["name"] == "undefined")
- displayProperties["name"] = "Unknown";
- if (typeof displayProperties["population"] == "undefined")
- displayProperties["population"] = "Unknown";
-
- layer.bindPopup(self.settlementPopupTemplate({ properties: displayProperties, coordinate: center }));
- }
- });
- map.addLayer(self.settlementLayer);
+ self.healthPosts = {};
+ self.markers = {};
+ self.converter = new op2geojson();
// Layer controller
self.layersControl = L.control.layers().addTo(map);
- self.layersControl.addOverlay(self.settlementLayer, "Settlements");
-
- L.control.locate().addTo(map);
-
- // Legend
- var legend = L.control({position: 'bottomright'});
- legend.onAdd = function (map) {
- var div = L.DomUtil.create('div', 'info legend');
- div.innerHTML += '<img src="resources/img/hospital.png"> Hospital<br>';
- return div;
- };
- legend.addTo(map);
-
- return map;
-}
-
-function displayMap(self, map) {
-
- function createQueryData(bbox) {
- return "data=[out:json];(" +
- "(node[amenity=hospital]("+ bbox +");way[amenity=hospital]("+ bbox +");node(w););" +
- "(node[amenity=doctors]("+ bbox +");way[amenity=doctors]("+ bbox +");node(w););" +
- "(node[amenity=dentist]("+ bbox +");way[amenity=dentist]("+ bbox +");node(w););" +
- "(node(" + bbox + ");relation[type=boundary][boundary=catchment_area];way(r);node(w););" +
- ");out;";
- }
- function highlightFeature(e) {
- var layer = e.target;
+ map.addLayer(self.settlementsLayerGroup);
+ self.layersControl.addOverlay(self.settlementsLayerGroup, "Settlements");
- layer.setStyle({
- weight: 5,
- color: '#666',
- dashArray: '',
- fillOpacity: 0.1
- });
-
- if (!L.Browser.ie && !L.Browser.opera) {
- layer.bringToFront();
- }
- }
-
- function resetHighlight(e) {
- self.catchmentAreaLayer.resetStyle(e.target);
- }
+ var emptyFeatureCollection = { type: "FeatureCollection", features: [] };
var hospitalIcon = L.icon({
iconUrl: 'resources/img/hospital.png',
@@ -150,47 +158,48 @@ function displayMap(self, map) {
popupAnchor: [2, -9] // point to open the popup from relative to iconAnchor
});
- var zoom = map.getZoom();
- if (zoom < 10) {
- return;
- }
-
- // Make the bounding box string
- var bounds = map.getBounds();
- var sw = bounds.getSouthWest();
- var ne = bounds.getNorthEast();
- bbox = [sw.lat, sw.lng, ne.lat, ne.lng].join(',');
-
- self.converter = new op2geojson();
- var markers = {};
-
- function createCatchmentAreaLayer(data) {
- return L.geoJson(data, {
- style: function(feature) {
- return {fillColor: 'green',
- weight: 2,
- opacity: 1,
- color: 'black',
- dashArray: '3',
- fillOpacity: 0.1};
- },
- onEachFeature: function(feature, layer) {
- layer.on({
- mouseover: highlightFeature,
- mouseout: resetHighlight,
- click: function() {
- markers[feature.properties.subject].openPopup();
+ self.catchmentAreaLayer = L.geoJson(emptyFeatureCollection, {
+ style: function(feature) {
+ return {fillColor: 'green',
+ weight: 2,
+ opacity: 1,
+ color: 'black',
+ dashArray: '3',
+ fillOpacity: 0.1};
+ },
+ onEachFeature: function(feature, layer) {
+ layer.on({
+ mouseover: function(e) {
+ var layer = e.target;
+
+ layer.setStyle({
+ weight: 5,
+ color: '#666',
+ dashArray: '',
+ fillOpacity: 0.1
+ });
+
+ if (!L.Browser.ie && !L.Browser.opera) {
+ layer.bringToFront();
}
- });
- },
- filter: function(feature, layer) {
- return _.contains(_.values(feature.properties), "catchment_area");
- }
- });
- }
+ },
+ mouseout: function(e) {
+ self.catchmentAreaLayer.resetStyle(e.target);
+ },
+ click: function() {
+ self.markers[feature.properties.subject].openPopup();
+ }
+ });
+ },
+ filter: function(feature, layer) {
+ return _.contains(_.values(feature.properties), "catchment_area");
+ }
+ });
+ map.addLayer(self.catchmentAreaLayer);
+ self.layersControl.addOverlay(self.catchmentAreaLayer, "Catchment Areas");
- function createAmenityLayer(data, amenity) {
- return L.geoJson(data, {
+ function createAmenityLayer(amenity) {
+ return L.geoJson(emptyFeatureCollection, {
style: function(feature) {
return {color: 'red',
fillColor: 'red',
@@ -209,90 +218,69 @@ function displayMap(self, map) {
}
var catchmentArea = self.catchmentAreas[feature.id];
- var settlements = catchmentArea.settlements;
-
- var format = new OpenLayers.Format.GeoJSON;
- var openLayersGeo = format.parseGeometry(catchmentArea.geometry);
- var sumOfDistances = 0;
- var maxDistance = 0;
+ layer.bindPopup(self.editorTemplate({coordinate: center}) +
+ self.healthPostTemplate(feature.properties) +
+ '<div id="' + catchmentArea.id + '">' +
+ self.catchmentAreaTemplate(catchmentAreaProperties(catchmentArea, feature)) +
+ '</div>');
- var Geographic = new OpenLayers.Projection("EPSG:4326");
- var Mercator = new OpenLayers.Projection("EPSG:900913");
+ self.markers[feature.id] = layer;
+ },
+ filter: function(feature, layer) {
+ // TODO: Fix and make more efficient
+ return _.contains(_.values(feature.properties), amenity);
+ }
+ });
+ }
- var featurePoint = format.parseGeometry(feature.geometry);
- if (feature.geometry.type == "Point") {
- //amenityPoint = new OpenLayers.Geometry.Point(amenity.geometry.coordinates[0], amenity.geometry.coordinates[1]).transform(Geographic, Mercator);
- } else { // Its a polygon
- featurePoint = featurePoint.getCentroid();
- }
+ _.each(self.amenitiesShown, function(amenity, i) {
+ self.amenityLayers[amenity] = createAmenityLayer(amenity);
- _.each(catchmentArea.settlements, function (settlement) {
- var settlementGeo = format.parseGeometry(settlement.geometry);
+ map.addLayer(self.amenityLayers[amenity]);
+ self.layersControl.addOverlay(self.amenityLayers[amenity],
+ self.amenitiesShown[i].charAt(0).toUpperCase() + self.amenitiesShown[i].slice(1));
+ });
- var distance = settlementGeo.distanceTo(featurePoint);
- sumOfDistances += distance;
- if (distance > maxDistance)
- maxDistance = distance;
- });
+ L.control.locate().addTo(map);
- var areaInSquareMeters = openLayersGeo.getGeodesicArea();
- var areaString = areaInSquareMeters.toFixed(2) + "m" + "2".sup();
- if (areaInSquareMeters > 1000000) {
- areaString = (areaInSquareMeters / 1000000).toFixed(2) + "km" + "2".sup();
- }
+ // Legend
+ var legend = L.control({position: 'bottomright'});
+ legend.onAdd = function (map) {
+ var div = L.DomUtil.create('div', 'info legend');
+ div.innerHTML += '<img src="resources/img/hospital.png"> Hospital<br>';
+ return div;
+ };
+ legend.addTo(map);
- var areaProperties;
- if (typeof settlements == "undefined") {
- areaProperties = { area: areaString,
- number_of_settlements: "Unknown",
- population: "Unknown",
- greatest_settlement_dist: "Unknown",
- average_settlement_dist: "Unknown"
- }
- } else {
- var population = 0;
- var numberOfSettlementsWithoutPopulation = 0;
+ return map;
+}
- _.each(settlements, function(settlement) {
- if (typeof settlement.properties.population != "undefined") {
- population += parseInt(settlement.properties.population);
- } else {
- numberOfSettlementsWithoutPopulation++;
- }});
+function displayMap(self, map) {
- if (numberOfSettlementsWithoutPopulation != 0) {
- if (numberOfSettlementsWithoutPopulation == 1) {
- population = population + " (but " + numberOfSettlementsWithoutPopulation + " settlement has no population set)";
- } else {
- population = population + " (but " + numberOfSettlementsWithoutPopulation + " settlements have no population set)";
- }
- }
+ function createQueryData(bbox) {
+ return "data=[out:json];(" +
+ "(node[amenity=hospital]("+ bbox +");way[amenity=hospital]("+ bbox +");node(w););" +
+ //"(node[amenity=doctors]("+ bbox +");way[amenity=doctors]("+ bbox +");node(w););" +
+ //"(node[amenity=dentist]("+ bbox +");way[amenity=dentist]("+ bbox +");node(w););" +
+ "(node(" + bbox + ");relation[type=boundary][boundary=catchment_area];way(r);node(w););" +
+ ");out;";
+ }
- areaProperties = { area: areaString,
- number_of_settlements: settlements.length,
- population: population,
- greatest_settlement_dist: maxDistance,
- average_settlement_dist: (sumOfDistances/catchmentArea.settlements.length)
- }
- }
+ var zoom = map.getZoom();
+ if (zoom < 10) {
+ return;
+ }
- layer.bindPopup(self.popupTemplate({ properties: $.extend(feature.properties, areaProperties), coordinate: center }));
+ // Make the bounding box string
+ var bounds = map.getBounds();
+ var sw = bounds.getSouthWest();
+ var ne = bounds.getNorthEast();
+ bbox = [sw.lat, sw.lng, ne.lat, ne.lng].join(',');
- markers[feature.id] = layer;
- },
- filter: function(feature, layer) {
- // TODO: Fix and make more efficient
- return _.contains(_.values(feature.properties), amenity);
- }
- });
- }
+ self.converter = new op2geojson();
function addSettlementsForArea(catchmentArea) {
- if (typeof catchmentArea.settlements != 'undefined') {
- return;
- }
-
// Create the bounding polygon for the query
var poly = "";
_.each(catchmentArea.geometry.coordinates[0], function(coordinatePair) {
@@ -302,73 +290,111 @@ function displayMap(self, map) {
var query = 'data=[out:json];(node(poly:"' + poly + '");<;node(w););out;';
- // Fetch settlement data
- self.converter.fetch("http://overpass-api.de/api/interpreter", query, zoom, function(data) {
+ function processSettlements(data, catchmentArea) {
data.features = _.filter(data.features, function(feature) {
return _.contains(_.keys(feature.properties), "place") ||
feature.properties["landuse"] == "residential";
});
catchmentArea.settlements = data.features;
- self.settlementLayer.addData(data);
- });
+
+ if (catchmentArea.id in self.catchmentAreaSettlementsLayers) {
+ self.catchmentAreaSettlementsLayers[catchmentArea.id].clearLayers();
+ self.catchmentAreaSettlementsLayers[catchmentArea.id].addData(data);
+ } else {
+ self.catchmentAreaSettlementsLayers[catchmentArea.id] = L.geoJson(data, {
+ style: function(feature) {
+ return {fillColor: 'green',
+ weight: 2,
+ opacity: 1,
+ color: 'black',
+ dashArray: '3',
+ fillOpacity: 0.1};
+ },
+ onEachFeature: function(feature, layer) {
+ var center;
+ if (feature.geometry.type === "Point") {
+ center = feature.geometry.coordinates;
+ } else {
+ center = feature.geometry.coordinates[0];
+ }
+
+ var displayProperties = { name: feature.properties["name"], population: feature.properties["population"] };
+ if (typeof displayProperties["name"] == "undefined")
+ displayProperties["name"] = "Unknown";
+ if (typeof displayProperties["population"] == "undefined")
+ displayProperties["population"] = "Unknown";
+
+ layer.bindPopup(self.editorTemplate({coordinate: center}) + self.settlementTemplate(displayProperties));
+ }
+ });
+ self.settlementsLayerGroup.addLayer(self.catchmentAreaSettlementsLayers[catchmentArea.id]);
+
+ $('#' + catchmentArea.id).html(self.catchmentAreaTemplate(catchmentAreaProperties(catchmentArea, self.healthPosts[catchmentArea.properties["subject"]])));
+ }
+ }
+
+ // Fetch settlement data
+ self.converter.fetch("http://overpass-api.de/api/interpreter", query, zoom,
+ (function(catchmentArea) { return function (data) { processSettlements(data, catchmentArea); }; })(catchmentArea));
}
var query = createQueryData(bbox);
- if (typeof self.amenities != "undefined") {
- console.log(getDataURIForRegion(self, "region"));
- }
- self.amenities = {};
_.each(self.amenitiesShown, function(amenity) {
self.amenities[amenity] = [];
});
// Convert the data to GeoJSON
self.converter.fetch("http://overpass-api.de/api/interpreter", query, zoom, function(data) {
- if (jQuery.isEmptyObject(self.amenityLayers)) {
-
- // For each catchment area polygon
- _.each(
- _.filter(data.features,
- function(feature) {
- return _.contains(_.values(feature.properties), "catchment_area");
- }),
- function(catchmentArea) {
- // Add it to the associative array
- self.catchmentAreas[catchmentArea.properties["subject"]] = catchmentArea;
+ self.catchmentAreaLayer.clearLayers();
+ var oldCatchmentAreas = self.catchmentAreas;
+ self.catchmentAreas = {};
+ self.healthPosts = {};
+
+ // For each health post
+ _.each(
+ _.filter(data.features,
+ function(feature) {
+ return feature.properties["amenity"] == "hospital";
+ }),
+ function(healthPost) {
+ // Add it to the associative array
+ self.healthPosts[healthPost.id] = healthPost;
+ }
+ );
+
+ // For each catchment area polygon
+ _.each(
+ _.filter(data.features,
+ function(feature) {
+ return _.contains(_.values(feature.properties), "catchment_area");
+ }),
+ function(catchmentArea) {
+ // Add it to the associative array
+ var subjectId = catchmentArea.properties["subject"];
+
+ if (subjectId in oldCatchmentAreas) {
+ catchmentArea = oldCatchmentAreas[subjectId];
+ }
+
+ self.catchmentAreas[subjectId] = catchmentArea;
+
+ // If the settlements for this catchment area have already been fetched
+ if (typeof catchmentArea.settlements == 'undefined') {
addSettlementsForArea(catchmentArea);
- }
- );
-
- // Now deal with the catchment areas
- self.catchmentAreaLayer = createCatchmentAreaLayer(data);
-
- _.each(self.amenitiesShown, function(amenity, i) {
- self.amenityLayers[amenity] = createAmenityLayer(data, amenity);
-
- map.addLayer(self.amenityLayers[amenity]);
- self.layersControl.addOverlay(self.amenityLayers[amenity],
- self.amenitiesShown[i].charAt(0).toUpperCase() + self.amenitiesShown[i].slice(1));
- });
-
- map.addLayer(self.catchmentAreaLayer);
- self.layersControl.addOverlay(self.catchmentAreaLayer, "Catchment Areas");
- } else {
- self.catchmentAreaLayer.clearLayers();
- self.catchmentAreaLayer.addData(data);
-
- _.each(self.amenitiesShown, function(amenity, i) {
- // Update the data for each amenity layer
- self.amenityLayers[amenity].clearLayers();
- self.amenityLayers[amenity].addData(data);
- });
-
- _.each(self.catchmentAreas, function(catchmentArea, i) {
- // Update the data for each CatchmentAreaVillageLayer
- addSettlementsForArea(catchmentArea);
- });
- }
+ }
+ }
+ );
+
+ self.catchmentAreaLayer.clearLayers();
+ self.catchmentAreaLayer.addData(data);
+
+ _.each(self.amenitiesShown, function(amenity, i) {
+ // Update the data for each amenity layer
+ self.amenityLayers[amenity].clearLayers();
+ self.amenityLayers[amenity].addData(data);
+ });
});
}
@@ -376,32 +402,30 @@ $(document).ready(function() {
var self = this; // the HTMLDocument
- self.popupTemplate = _.template('<a href="http://www.openstreetmap.org/edit?editor=potlatch2&lat=<%= coordinate[1] %>&lon=<%= coordinate[0] %>&zoom=18">\
+ self.editorTemplate = _.template('<a href="http://www.openstreetmap.org/edit?editor=potlatch2&lat=<%= coordinate[1] %>&lon=<%= coordinate[0] %>&zoom=18">\
<img src="resources/img/potlatch.png"></a>\
<a href="http://www.openstreetmap.org/edit?editor=remote&lat=<%= coordinate[1] %>&lon=<%= coordinate[0] %>&zoom=18">\
-<img src="resources/img/josm.png"></a>\
-<h2>Hospital</h2>\
+<img src="resources/img/josm.png"></a>');
+
+ self.healthPostTemplate = _.template('<h2>Hospital</h2>\
<table width="100%">\
-<tr><td>Name</td><td align="right"><%= properties["name"] %></td></tr>\
-<tr><td>Emergency</td><td align="right" style="text-transform:capitalize;"><%= properties["emergency"] %></td></tr>\
-</table>\
-<h2>Catchment Area</h2>\
+<tr><td>Name</td><td align="right"><%= name %></td></tr>\
+<tr><td>Emergency</td><td align="right" style="text-transform:capitalize;"><%= emergency %></td></tr>\
+</table>');
+
+ self.catchmentAreaTemplate = _.template('<h2>Catchment Area</h2>\
<table>\
-<tr><td>Surface Area</td><td align="right"><%= properties["area"] %></td></tr>\
-<tr><td>Number of Settlements</td><td align="right"><%= properties["number_of_settlements"] %></td></tr>\
-<tr><td>Population</td><td align="right"><%= properties["population"] %></td></tr>\
-<tr><td>Furthest distance from settlement to health structure</td><td align="right"><%= properties["greatest_settlement_dist"] %></td></tr>\
-<tr><td>Average distance of all settlements from health structure</td><td align="right"><%= properties["average_settlement_dist"] %></td></tr>\
+<tr><td>Surface Area</td><td align="right"><%= area %></td></tr>\
+<tr><td>Number of Settlements</td><td align="right"><%= number_of_settlements %></td></tr>\
+<tr><td>Population</td><td align="right"><%= population %></td></tr>\
+<tr><td>Furthest distance from settlement to health structure</td><td align="right"><%= greatest_settlement_dist %></td></tr>\
+<tr><td>Average distance of all settlements from health structure</td><td align="right"><%= average_settlement_dist %></td></tr>\
</table>');
- self.settlementPopupTemplate= _.template('<a href="http://www.openstreetmap.org/edit?editor=potlatch2&lat=<%= coordinate[1] %>&lon=<%= coordinate[0] %>&zoom=18">\
-<img src="resources/img/potlatch.png"></a>\
-<a href="http://www.openstreetmap.org/edit?editor=remote&lat=<%= coordinate[1] %>&lon=<%= coordinate[0] %>&zoom=18">\
-<img src="resources/img/josm.png"></a>\
-<h3>Settlement</h3>\
+ self.settlementTemplate = _.template('<h3>Settlement</h3>\
<table width="100%">\
-<tr><td>Name</td><td align="right"><%= properties["name"] %></td></tr>\
-<tr><td>Population</td><td align="right"><%= properties["population"] %></td></tr>\
+<tr><td>Name</td><td align="right"><%= name %></td></tr>\
+<tr><td>Population</td><td align="right"><%= population %></td></tr>\
</table>');
var map = initMap(self);