Skip to content

Instantly share code, notes, and snippets.

@michalskop
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save michalskop/9246304 to your computer and use it in GitHub Desktop.
Save michalskop/9246304 to your computer and use it in GitHub Desktop.
SK: Spatial distribution of presidential candidates 2014
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 12px sans-serif;
}
.point {
fill: #1F77B4;
stroke: #1F77B4;
fill-opacity: .3;
stroke-width: 1.5px;
stroke-opacity: 1;
}
g.active .point {
fill-opacity: .9;
}
g.active .name {
font-weight: bold;
}
.line-text {
font: 10px sans-serif;
}
g.active .line-text {
font-weight: bold;
cursor: default;
}
g.active line {
stroke-width: 4
}
.name {
fill: blue;
font-family: sans-serif;
cursor: default;
}
line {
stroke:gray;
stroke-width:2;
opacity: .15;
}
.quality-1 line {
stroke-dasharray:10,10
}
.area {
visibility: hidden;
}
g.active .area {
opacity: .15;
visibility: visible;
}
g.active .yes {
fill: green;
}
g.active .no {
fill: red;
}
g.yes circle {
stroke: green;
}
g.no circle {
stroke: red;
}
</style>
<div id="chart"></div>
<script src="http://d3js.org/d3.v3.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>
var margin = {top: 20, right: 30, bottom: 30, left: 30},
width = 500 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width])
.domain([-2.5,2.5]);
var y = d3.scale.linear()
.range([height, 0])
.domain([-2.5,2.5]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.csv("wpca_candidates.csv", function(error, data) {
limits = {"x": [-2.5,2.5],"y": [-2.5,2.5]};
lines = [{
'a':0,
'b':-1.06,
'd1':-2.053,
'd2':-1.93,
'id': 1,
'description':'Možnosť vyhlásiť amnestiu'},
{
'a': 0.145,
'b': -0.177,
'd1':0.37,
'd2':2.07,
'description':'Imunita prezidenta'},
{
'a': 0.335,
'b': 2.7665358349,
'd1': 1.54,
'd2': -0.56,
'description':'Zákaz interupcií'},
{
'a': -1.019,
'b': 2.142,
'd1':-2.1,
'd2':0.98,
'description':'Registrované partnerstvo'},
{
'a': 3.99,
'b': -2.87,
'd1':-0.85,
'd2':-0.3,
'description':'Kotleba pozývaný ako iní župani'},
{
'a': -0.27,
'b': -0.21,
'd1':0.33,
'd2':1.6,
'description':'Obch. vzťahy x ľudská práva'},
{
'a': 2.6613760408,
'b': -2.5781557199,
'd1':-0.16,
'd2':-0.06,
'description':'Rómčina',
'quality':1 },
{
'a': 6.38,
'b': -3.16,
'd1':-0.33,
'd2':-0.1,
'description':'Voľby cez internet'},
{
'a': -2.5817095387,
'b': 21.1590242094,
'd1':-0.49199217,
'd2':0.02325212,
'description':'Maďarčina - stejné postavenie',
'quality': 1
},
];
for (k in lines) {
ps = linecross(lines[k],limits);
if (ps.length == 2) {
lines[k].x1 = ps[0][0];
lines[k].y1 = ps[0][1];
lines[k].x2 = ps[1][0];
lines[k].y2 = ps[1][1];
}
way = get_sign(lines[k].b,lines[k].d1,lines[k].d2);
lines[k].path =[corners(lines[k],limits,way),corners(lines[k],limits,-1*way)];
}
var line = svg.selectAll ('g')
.data(lines)
.enter().append('g')
.attr("class",function(d) {if (d.quality == 1) return "line quality-1"; else return "line";})
.attr("id", function (d, i) {return "q-" + i;})
.on("mouseover", function (d, i) {
d3.select(this).classed({"active":true});
highlight_persons(data,i);
})
.on("mouseout",function (d,i) {
d3.select(this).classed({"active":false});
dehighlight_persons(i);
})
line.append("line")
.attr("x1",function(d) {return x(d.x1)})
.attr("y1",function(d) {return y(d.y1)})
.attr("x2",function(d) {return x(d.x2)})
.attr("y2",function(d) {return y(d.y2)});
line.append("text")
.attr("text-anchor", "middle")
.attr("class","line-text")
.text(function (d, i) {
return d.description;
})
.attr("x", function(d, i) {
if (d.x1 > d.x2)
return x(d.x2);
else
return x(d.x1);
})
.attr("y", function(d, i) {
if (d.x1 > d.x2)
return y(d.y1);
else
return y(d.y2);
})
.style("text-anchor", "start")
.attr("transform", function(d, i) {
rot=-Math.atan(d.b)/2/Math.PI*360; //d.slope;
if (d.x1 > d.x2){
xx = x(d.x1);
yy = y(d.y1);
} else {
xx = x(d.x2);
yy = y(d.y2);
}
return "rotate(" + rot +"," +xx + "," + yy +")"});
//explanation: http://code.hazzens.com/d3tut/lesson_3.html
var area = d3.svg.line()
.x(function(d) {return x(d.x);})
.y(function(d) {return y(d.y);});
var areas = line.selectAll("path.area")
.data(function(d) {
return d.path;
}).enter()
.append("path")
.attr("class",function(d, i) {if (i == 0) return "area yes"; else return "area no";})
.attr("d",area);
var point = svg.selectAll ('.candidate')
.data(data)
.enter().append("g")
.attr("class","candidate")
.attr("id", function (d, i) {return "p-" + i;})
.on("mouseover", function (d, i) {
d3.select(this).attr("class","candidate active");
})
.on("mouseout",function (d,i) {
d3.select(this).attr("class","candidate");
})
point.append('circle')
.attr("cx", function(d) {
return x(d.d1)
})
.attr("cy", function(d) {return y(d.d2) })
.attr("r", 10)
.attr("class", "point")
point.append('text')
.text(function (d, i) {return d.name; })
.attr("x", function(d) {return x(d.d1) })
.attr("y", function(d) {return y(d.d2) })
.attr("r", 10)
.attr("class", "name")
.style("text-anchor","middle")
})
function highlight_persons(values,index) {
//cannot use jQuery addClass with svg !
//http://stackoverflow.com/questions/8638621/jquery-svg-why-cant-i-addclass
$(".candidate").each(function(i,e) {
$(this).attr('class',function() {
if (parseInt(values[i]['q'+index]) == 1) return 'candidate yes';
if (parseInt(values[i]['q'+index]) == -1) return 'candidate no';
return;
});
});
}
function dehighlight_persons(index) {
$(".candidate").attr('class','candidate');
}
function corners(l,e,o) {
//l = {"a":0,"b":1} //line, a and slope, i.e., y=a+bx
//e = {"x": [-10,10], "y": [-10,10]} //limits
//o = 1 //orientation -1 or 1
//crossing x0, x1
//crossing y0, y1
outp = linecross (l,e);
out = [];
//vertices
for (i=0;i<=1;i++){
for (j=0;j<=1;j++){
if (o*(l.a+l.b*e.x[i]-e.y[j]) > 0)
outp.push([e.x[i],e.y[j]]);
}
}
//sort the outps, anticlockwise
if (outp.length > 0) {
mid = [0,0];
for (i in outp) {
mid[0] += outp[i][0];
mid[1] += outp[i][1];
}
mid[0] = mid[0] / outp.length;
mid[1] = mid[1] / outp.length;
for (i in outp) {
p = outp[i][1] - mid[1];
q = outp[i][0] - mid[0];
if (q != 0)
outp[i][2] = Math.atan(p/q) + (q<0 ? Math.PI : 0);
else
outp[i][2] = Math.PI/2 + Math.PI*sign(p);
}
outp = outp.sort(function(w,z) {
return w[2] > z[2];
});
for (i in outp) {
outp[i].splice(2,1);
out.push({"x":outp[i][0],"y":outp[i][1]});
}
}
return out;
}
function linecross (l,e) {
out = [];
//crossing x0, x1
for (i=0;i<=1;i++){
Y = l.a + l.b*e.x[i];
if ((Y > e.y[0]) && (Y < e.y[1]))
out.push([e.x[i],Y]);
}
//crossing y0, y1
for (j=0;j<=1;j++){
if (l.b != 0) {
X = (e.y[j] - l.a)/l.b;
if ((X > e.x[0]) && (X < e.x[1]))
out.push([X,e.y[j]]);
}
}
return out;
}
function get_sign(b,d1,d2) {
t = b*d1-d2;
if (t > 0) return 1;
if (t < 0) return -1;
return 0;
}
function sign(x) {
return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN;
}
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-8592359-13', 'ocks.org');
ga('send', 'pageview');
</script>
name d1 d2 q0 q1 q2 q3 q4 q5 q6 q7 q8
Melník 1.07849065 -0.1191408 -1 -1 1 -1 1 1 0 1 -1
Martinčko -1.99039949 0.745852 1 1 0 1 1 1 1 1 1
Šimko -1.57697495 -1.2902898 1 -1 -1 1 1 -1 1 1 1
Čarnogurský 0.03047429 -1.9369032 1 -1 1 -1 1 -1 1 1 -1
Kiska -1.01942107 2.3123596 -1 1 -1 1 1 1 1 1 -1
Procházka 0.81328076 0.7885653 -1 1 1 0 1 1 0 1 -1
Hrušovský 2.39481329 0.6917826 -1 1 1 -1 -1 1 1 -1 -1
Bárdos 1.73643192 0.6233822 -1 1 1 -1 -1 1 1 1 1
Mezenská 0.32224881 -2.1949306 1 -1 1 -1 1 -1 1 1 -1
Kňažko -1.78894421 0.3793228 1 0 -1 1 1 1 1 1 -1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment