Skip to content

Instantly share code, notes, and snippets.

@tbuckl
Last active May 27, 2017 11:35
Show Gist options
  • Select an option

  • Save tbuckl/63781e614c3673c18fbd4405da973df0 to your computer and use it in GitHub Desktop.

Select an option

Save tbuckl/63781e614c3673c18fbd4405da973df0 to your computer and use it in GitHub Desktop.
Foursquare Neighborhood Estimation

Flickr Photos and Derived Neighborhood Boundaries

Washington, D.C.

This is an attempt at displaying the different neighborhoods in which photographs from Flickr are tagged, and the boundaries which can be aggregated from these individual points. Approximately 250,000 photographs are represented by the map. They were downloaded from the Flickr API and aggregated to "neighborhoods" using Betashapes.

Differences in point colors represent different neighborhood tags for the photograph. Pan around and zoom in and out to inspect the relationship between Flickr photos and the neighborhoods generated for them by Betashapes.

Data from Flickr< Based on this gist

d3.geo.tile=function(){function t(){var t=Math.max(Math.log(n)/Math.LN2-8,0),h=Math.round(t+e),o=Math.pow(2,t-h+8),u=[(r[0]-n/2)/o,(r[1]-n/2)/o],l=[],c=d3.range(Math.max(0,Math.floor(-u[0])),Math.max(0,Math.ceil(a[0]/o-u[0]))),M=d3.range(Math.max(0,Math.floor(-u[1])),Math.max(0,Math.ceil(a[1]/o-u[1])));return M.forEach(function(t){c.forEach(function(a){l.push([a,t,h])})}),l.translate=u,l.scale=o,l}var a=[960,500],n=256,r=[a[0]/2,a[1]/2],e=0;return t.size=function(n){return arguments.length?(a=n,t):a},t.scale=function(a){return arguments.length?(n=a,t):n},t.translate=function(a){return arguments.length?(r=a,t):r},t.zoomDelta=function(a){return arguments.length?(e=+a,t):e},t};
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
margin: 0;
}
.map {
position: relative;
overflow: hidden;
}
.layer {
position: absolute;
}
.tile {
pointer-events: none;
position: absolute;
width: 256px;
height: 256px;
}
.info {
position: absolute;
bottom: 10px;
left: 10px;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="d3.geo.tile.min.js"></script>
<script>
var width = Math.max(960, window.innerWidth),
height = Math.max(500, window.innerHeight),
prefix = prefixMatch(["webkit", "ms", "Moz", "O"]);
var tile = d3.geo.tile()
.size([width, height]);
var projection = d3.geo.mercator();
var zoom = d3.behavior.zoom()
.scale(1 << 12)
.scaleExtent([1 << 9, 1 << 23])
.translate([width / 2, height / 2])
.on("zoom", zoomed);
var map = d3.select("body").append("div")
.attr("class", "map")
.style("width", width + "px")
.style("height", height + "px")
.call(zoom)
.on("mousemove", mousemoved);
var layer = map.append("div")
.attr("class", "layer");
var info = map.append("div")
.attr("class", "info");
zoomed();
function zoomed() {
var tiles = tile
.scale(zoom.scale())
.translate(zoom.translate())
();
projection
.scale(zoom.scale() / 2 / Math.PI)
.translate(zoom.translate());
var image = layer
.style(prefix + "transform", matrix3d(tiles.scale, tiles.translate))
.selectAll(".tile")
.data(tiles, function(d) { return d; });
image.exit()
.remove();
image.enter().append("img")
.attr("class", "tile")
.attr("src", function(d) { return "https://" + ["a", "b", "c"][Math.random() * 3 | 0] + "s3-eu-west-1.amazonaws.com/dcflickr/" + d[2] + "/" + d[0] + "/" + d[1] + ".png"; })
.style("left", function(d) { return (d[0] << 8) + "px"; })
.style("top", function(d) { return (d[1] << 8) + "px"; });
}
function mousemoved() {
info.text(formatLocation(projection.invert(d3.mouse(this)), zoom.scale()));
}
function matrix3d(scale, translate) {
var k = scale / 256, r = scale % 1 ? Number : Math.round;
return "matrix3d(" + [k, 0, 0, 0, 0, k, 0, 0, 0, 0, k, 0, r(translate[0] * scale), r(translate[1] * scale), 0, 1 ] + ")";
}
function prefixMatch(p) {
var i = -1, n = p.length, s = document.body.style;
while (++i < n) if (p[i] + "Transform" in s) return "-" + p[i].toLowerCase() + "-";
return "";
}
function formatLocation(p, k) {
var format = d3.format("." + Math.floor(Math.log(k) / 2 - 2) + "f");
return (p[1] < 0 ? format(-p[1]) + "°S" : format(p[1]) + "°N") + " "
+ (p[0] < 0 ? format(-p[0]) + "°W" : format(p[0]) + "°E");
}
</script>
var map=null;
var center = new google.maps.LatLng(38.9013,-77.036);
function fetch_tile(coord, zoom) {
return "https://s3-eu-west-1.amazonaws.com/dcflickr/" + zoom + "/" + coord.x + "/" + coord.y + ".png";
}
$(document).ready(function() {
flickr_demo_options = {
getTileUrl: fetch_tile,
tileSize: new google.maps.Size(256, 256),
isPng: true
}
flickr_demo = new google.maps.ImageMapType(flickr_demo_options);
map_options = {
minZoom: 14,
maxZoom: 18,
zoom: 16,
center: center,
mapTypeControl: false,
mapTypeId: "simple"
};
backdrop_styles = [
{
featureType: "all",
stylers: [
{ saturation: 0 },
{ lightness: 50 }
]
},{
featureType: "administrative",
elementType: "labels",
stylers: [
{ lightness: 0 }
]
},{
featureType: "poi",
elementType: "labels",
stylers: [
{ visibility: "on" }
]
},{
featureType: "poi.park",
elementType: "geometry",
stylers: [
{ visibility: "off" }
]
},{
featureType: "road",
elementType: "geometry",
stylers: [
{ visibility: "simplified" },
{ saturation: 0 },
{ lightness: 0 }
]
},{
featureType: "road.arterial",
elementType: "labels",
stylers: [
{ gamma: 5 }
]
}
];
layer = new google.maps.FusionTablesLayer({
heatmap: { enabled: false },
query: {
select: "col0",
from: "1njehV_-TDWyGBe4R6ZvtykNiEkYylCtv6fKOiW8",
where: ""
},
options: {
styleId: 2,
templateId: 2
}
});
var ctaLayer = new google.maps.KmlLayer({
url: 'https://s3-eu-west-1.amazonaws.com/dcflickr/BetaShapesClippedDC2.kml'
});
simple = new google.maps.StyledMapType(backdrop_styles, { name: "Flickr Backdrop" });
map = new google.maps.Map(document.getElementById("map_canvas"), map_options);
map.mapTypes.set("simple", simple);
map.overlayMapTypes.push(flickr_demo);
ctaLayer.setMap(map);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment