Skip to content

Instantly share code, notes, and snippets.

@veltman
Last active May 26, 2021 20:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save veltman/949ce9c1b6f3e54c6e18 to your computer and use it in GitHub Desktop.
Save veltman/949ce9c1b6f3e54c6e18 to your computer and use it in GitHub Desktop.
Redistricting

Old vs. new proposed North Carolina congressional districts, data via WRAL.

Polygons were pre-processed for gentler animation as follows:

  1. For each district, find the difference n in the number of vertices between the old and new district.
  2. Add n vertices to whichever one has fewer, evenly spaced along the existing polyline, so the old and new shape each have the same number of vertices (not great for performance).
  3. For each pair of old/new district, wind the old district around to minimize the sum of the squared distances between point index i in the old district and point index i in the new district.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
path {
stroke-width: 1px;
stroke: #444;
}
text {
font: bold 64px sans-serif;
text-anchor: middle;
text-transform: uppercase;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script>
<script>
var width = 960,
height = 500;
var colors = d3.scale.category20().range();
d3.shuffle(colors);
var svg = d3.select("body").append("svg")
.attr("width",width)
.attr("height",height);
var projection = d3.geo.conicConformal()
.parallels([34 + 20 / 60, 36 + 10 / 60])
.rotate([79, -33 - 45 / 60])
.scale(6102.002295938357)
.translate([570.5880508434078,431.7927213940179]);
var path = d3.geo.path().projection(projection);
queue()
.defer(d3.json,"old.geojson")
.defer(d3.json,"new.geojson")
.await(function(err,oldDistricts,newDistricts){
var combined = oldDistricts.features.map(function(d,i){
return [d,newDistricts.features[i]].map(path);
});
var districts = svg.selectAll("path")
.data(combined)
.enter()
.append("path")
.attr("d",next)
.style("fill",function(d,i){
return colors[i];
});
var label = svg.append("text")
.datum(["Old","New"])
.text(next)
.attr("x",300)
.attr("y",400);
morph();
function morph() {
districts.transition()
.duration(3200)
.attr("d",next)
.each("end",function(d,i){
if (i === combined.length - 1) {
morph();
}
});
label.transition()
.duration(0)
.delay(3200 / 2)
.each("end",function(){
label.text(next);
});
}
});
function next(d) {
return d.reverse()[1];
}
</script>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment