|
<html> |
|
<head> |
|
<style> |
|
.point { |
|
fill: rgba(240, 66, 15, .75); |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.20/topojson.min.js"></script> |
|
<script src="//api.tiles.mapbox.com/mapbox.js/plugins/turf/v2.0.0/turf.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.7.0/lodash.min.js"></script> |
|
<script> |
|
var width = 600, |
|
height = 600; |
|
|
|
var area = d3.scale.linear().range([0, 800]); |
|
|
|
var projection = d3.geo.conicConformal() |
|
.rotate([90, 0]) |
|
.center([0.2, 44.75]) |
|
.parallels([29.5, 45.5]) |
|
.scale(6000) |
|
.translate([width/2, height/2]) |
|
.precision(.1); |
|
|
|
var path = d3.geo.path() |
|
.projection(projection); |
|
|
|
var map = d3.select("body").append("svg") |
|
.attr("class", "map") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
// add "loading" message |
|
map.append("text") |
|
.attr("x", width/2) |
|
.attr("y", height/2) |
|
.style("text-anchor", "middle") |
|
.text("Loading... (this might take a bit)"); |
|
|
|
d3.json("wi.json", ready); |
|
|
|
function ready(error, wi) { |
|
if (error) throw error; |
|
|
|
var countyFeatures = topojson.feature(wi, wi.objects.wi).features; |
|
var pointFeatures = turf.pointGrid([-93.5, 42.3, -86.49, 47.3], 20, "miles").features |
|
.map(function(pointFeature) { |
|
// get buffer of a point |
|
var bufferedPointFeature = turf.buffer(pointFeature, 20, "miles").features[0]; |
|
|
|
// get info on counties that intersect this point buffer |
|
var intersectingCountiesData = countyFeatures |
|
.map(function(countyFeature) { |
|
// if county intersects get the area within the point buffer |
|
// and return data on that county |
|
var intersection = turf.intersect(bufferedPointFeature, countyFeature); |
|
if (intersection !== undefined) { |
|
var area = turf.area(intersection); |
|
var countyProperties = _.clone(countyFeature.properties); |
|
countyProperties.areaWithinBuffer = area; |
|
return countyProperties; |
|
} |
|
else { return null; } |
|
}) |
|
.filter(function(d) { return d !== null; }); |
|
|
|
// estimate population within a point buffer by taking a |
|
// geo-weighted average of the counties that intersect with it |
|
var totalArea = d3.sum(intersectingCountiesData, function(d) { return d.areaWithinBuffer; }); |
|
var population = intersectingCountiesData |
|
.map(function(intersectingCountyData) { |
|
var areaShare = intersectingCountyData.areaWithinBuffer / totalArea; |
|
return { |
|
weight: areaShare, |
|
population: +intersectingCountyData["wi-data__1"] |
|
}; |
|
}) |
|
.reduce(function(a, b) { |
|
return a + b.population * b.weight; |
|
}, 0); |
|
|
|
pointFeature.properties.population = population; |
|
|
|
return pointFeature; |
|
}); |
|
|
|
// remove "loading" message |
|
map.select("text").remove(); |
|
|
|
area.domain([0, d3.max(pointFeatures, function(d) { return d.properties.population; })]); |
|
|
|
var points = map.selectAll(".point").data(pointFeatures) |
|
.enter().append("circle") |
|
.attr("class", "point") |
|
.attr("cx", function(feature) { |
|
return projection(feature.geometry.coordinates)[0]; |
|
}) |
|
.attr("cy", function(feature) { |
|
return projection(feature.geometry.coordinates)[1]; |
|
}) |
|
.attr("r", function(feature) { |
|
var A = area(feature.properties.population); |
|
return Math.sqrt(A / Math.PI); |
|
}); |
|
} |
|
|
|
d3.select(self.frameElement) |
|
.style("width", width + "px") |
|
.style("height", height + "px"); |
|
</script> |
|
</body> |
|
</html> |