Voronoi diagram of Barcelona's metro stations, a follow up of a previous block.
I was struggling to find a clear example of drawing a Voronoi on Canvas, so I just put a SVG overlay on top of the map (the points are also SVG).
license: mit | |
border: none | |
height: 650 |
lng | lat | type | line | name | |
---|---|---|---|---|---|
2.099720795414203 | 41.363669310300054 | METRO | L1 | RAMBLA JUST OLIVERAS | |
2.1026719363069075 | 41.35741392583299 | METRO | L1 | AVINGUDA CARRILET | |
2.103237123448869 | 41.367656549619376 | METRO | L1 | CAN SERRA | |
2.1064115174131994 | 41.344729421498144 | METRO | L1 | HOSPITAL DE BELLVITGE | |
2.10990044394329 | 41.351536228563305 | METRO | L1 | BELLVITGE | |
2.1103983831445907 | 41.36788261034843 | METRO | L1 | FLORIDA | |
2.1164925058226514 | 41.368751409095154 | METRO | L1 | TORRASSA | |
2.1287002494876877 | 41.3684523810948 | METRO | L1 | SANTA EULÀLIA | |
2.1340337698879637 | 41.37355257505901 | METRO | L1 | MERCAT NOU | |
2.138495928519069 | 41.37555171489993 | METRO | L1 | PLAÇA DE SANTS | |
2.143993685883448 | 41.375301030654065 | METRO | L1 | HOSTAFRANCS | |
2.1488031586172593 | 41.37538914994662 | METRO | L1 | ESPANYA | |
2.154458829202931 | 41.37915867062781 | METRO | L1 | ROCAFORT | |
2.1590005563069985 | 41.38246663059239 | METRO | L1 | URGELL | |
2.1641652947081313 | 41.38556031873351 | METRO | L1 | UNIVERSITAT | |
2.169509918633687 | 41.38763432574223 | METRO | L1 | CATALUNYA | |
2.1730926890619284 | 41.389529267238245 | METRO | L1 | URQUINAONA | |
2.180063901543007 | 41.39239609836004 | METRO | L1 | ARC DE TRIOMF | |
2.183326561055759 | 41.43046839524972 | METRO | L1 | FABRA I PUIG | |
2.186844744919792 | 41.39558333863722 | METRO | L1 | MARINA | |
2.1870883768969276 | 41.416165104455565 | METRO | L1 | NAVAS | |
2.187200971395667 | 41.42250112654303 | METRO | L1 | LA SAGRERA | |
2.1875152217557448 | 41.402707913413394 | METRO | L1 | GLÒRIES | |
2.187533054468753 | 41.41122717519894 | METRO | L1 | CLOT | |
2.190667803928558 | 41.44381638759569 | METRO | L1 | TORRAS I BAGES | |
2.190749818863545 | 41.437333832738396 | METRO | L1 | SANT ANDREU | |
2.1943862258757627 | 41.44954813770742 | METRO | L1 | TRINITAT VELLA | |
2.1996659250064075 | 41.44990541011909 | METRO | L1 | BARÓ DE VIVER | |
2.2071631887081646 | 41.451453481445995 | METRO | L1 | SANTA COLOMA | |
2.2170668923426136 | 41.45177007057777 | METRO | L1 | FONDO | |
2.2172458603128633 | 41.44148501697861 | METRO | L10 | LLEFIÀ | |
2.224026747506055 | 41.44235584998528 | METRO | L10 | LA SALUT | |
2.171580937086336 | 41.46274730921614 | METRO | L11 | CAN CUIÀS | |
2.179852354840731 | 41.45941835937983 | METRO | L11 | TORRE BARÓ VALLBONA | |
2.1630177408853455 | 41.37996245817153 | METRO | L2 | SANT ANTONI | |
2.1632543432475972 | 41.38502492641775 | METRO | L2 | UNIVERSITAT | |
2.167581431967113 | 41.37510069226224 | METRO | L2 | PARAL·LEL | |
2.168332839441089 | 41.38954251126039 | METRO | L2 | PASSEIG DE GRÀCIA | |
2.1745933931711248 | 41.39463370568517 | METRO | L2 | TETUAN | |
2.1763176709301346 | 41.40426618952202 | METRO | L2 | SAGRADA FAMÍLIA | |
2.180039956117605 | 41.40009650219717 | METRO | L2 | MONUMENTAL | |
2.1825600197345625 | 41.40734770486102 | METRO | L2 | ENCANTS | |
2.1865570036639186 | 41.41010979393296 | METRO | L2 | CLOT | |
2.195015157318397 | 41.415292090006915 | METRO | L2 | BAC DE RODA | |
2.200603658506352 | 41.41931557842177 | METRO | L2 | SANT MARTÍ | |
2.2066916481415157 | 41.42383621252897 | METRO | L2 | LA PAU | |
2.209634905525907 | 41.430308879013694 | METRO | L2 | VERNEDA | |
2.2168050533555337 | 41.43388850425456 | METRO | L2 | ARTIGUES SANT ADRIÀ | |
2.227786668411125 | 41.43552559216171 | METRO | L2 | SANT ROC | |
2.234042998554947 | 41.44064853055381 | METRO | L2 | GORG | |
2.2382125520174 | 41.44460061147726 | METRO | L2 | PEP VENTURA | |
2.244211818226918 | 41.449141712039626 | METRO | L2 | BADALONA POMPEU FABRA | |
2.1104031737139852 | 41.384147922010435 | METRO | L3 | ZONA UNIVERSITÀRIA | |
2.117875123660265 | 41.385915071565016 | METRO | L3 | PALAU REIAL | |
2.1263065758989725 | 41.388213725159154 | METRO | L3 | MARIA CRISTINA | |
2.131391760117895 | 41.38455431707076 | METRO | L3 | LES CORTS | |
2.136551764900411 | 41.382682015868646 | METRO | L3 | PLAÇA DEL CENTRE | |
2.140753188840037 | 41.417972883448336 | METRO | L3 | PENITENTS | |
2.141514699632166 | 41.381531496532865 | METRO | L3 | SANTS ESTACIÓ | |
2.142550072131155 | 41.42527136641748 | METRO | L3 | VALL D'HEBRON | |
2.145480927013976 | 41.378574276732564 | METRO | L3 | TARRAGONA | |
2.1450871167771655 | 41.41141065269198 | METRO | L3 | VALLCARCA | |
2.1451932507807494 | 41.43085599996142 | METRO | L3 | MONTBAU | |
2.1474981252125285 | 41.43524449995925 | METRO | L3 | MUNDET | |
2.150303460441094 | 41.37516939610728 | METRO | L3 | ESPANYA | |
2.1503938921607877 | 41.406608814442 | METRO | L3 | LESSEPS | |
2.1528175240534986 | 41.402306537691636 | METRO | L3 | FONTANA | |
2.1563943196784856 | 41.43758000314695 | METRO | L3 | VALLDAURA | |
2.1598821534098223 | 41.37515626684299 | METRO | L3 | POBLE SEC | |
2.1604759471277823 | 41.395764316362495 | METRO | L3 | DIAGONAL | |
2.1645726715556175 | 41.39290495682759 | METRO | L3 | PASSEIG DE GRÀCIA | |
2.1660807544409315 | 41.44203344492591 | METRO | L3 | CANYELLES | |
2.1703461620148445 | 41.38629523602731 | METRO | L3 | CATALUNYA | |
2.1707203725813993 | 41.37508872346003 | METRO | L3 | PARAL·LEL | |
2.173532548351183 | 41.380674972043785 | METRO | L3 | LICEU | |
2.176287229606268 | 41.376826871126674 | METRO | L3 | DRASSANES | |
2.176254779954988 | 41.447403374180524 | METRO | L3 | ROQUETES | |
2.184163514077928 | 41.449523666247266 | METRO | L3 | TRINITAT NOVA | |
2.163317374199931 | 41.40653235534556 | METRO | L4 | JOANIC | |
2.166164602312385 | 41.41178453962263 | METRO | L4 | ALFONS X | |
2.1676841883839923 | 41.38962447222799 | METRO | L4 | PASSEIG DE GRÀCIA | |
2.168594148441782 | 41.400179270035494 | METRO | L4 | VERDAGUER | |
2.1714083904377612 | 41.395269362308014 | METRO | L4 | GIRONA | |
2.17310643256742 | 41.388490000516946 | METRO | L4 | URQUINAONA | |
2.1734865679333395 | 41.43722392256478 | METRO | L4 | LLUCMAJOR | |
2.1745378621934788 | 41.41600549114402 | METRO | L4 | HOSPITAL DE SANT PAU GUINARDÓ | |
2.1776967871616826 | 41.42427869934448 | METRO | L4 | MARAGALL | |
2.1791278067023616 | 41.38399370053206 | METRO | L4 | JAUME I | |
2.1789090368322053 | 41.4439377665293 | METRO | L4 | VIA JÚLIA | |
2.185662749803024 | 41.38268381550357 | METRO | L4 | BARCELONETA | |
2.191501407647297 | 41.395310497250755 | METRO | L4 | BOGATELL | |
2.1927155650801113 | 41.388156091702456 | METRO | L4 | CIUTADELLA VILA OLIMPICA | |
2.1972499657101796 | 41.399266493450845 | METRO | L4 | LLACUNA | |
2.203214796536219 | 41.40344975781985 | METRO | L4 | POBLENOU | |
2.2064741602425126 | 41.42397067884454 | METRO | L4 | LA PAU | |
2.2099614685905697 | 41.40816428586267 | METRO | L4 | SELVA DE MAR | |
2.2103191688956847 | 41.42030091503714 | METRO | L4 | BESÒS | |
2.215690271272993 | 41.41501639312016 | METRO | L4 | BESÒS MAR | |
2.2169712691499632 | 41.411972055412306 | METRO | L4 | EL MARESME FÒRUM | |
2.182306 | 41.449190 | METRO | L4 | TRINITAT NOVA | |
2.182477258739901 | 41.449294852157976 | METRO | L11 | TRINITAT NOVA | |
2.0724067661737378 | 41.35615999645653 | METRO | L5 | CORNELLÀ CENTRE | |
2.0789068774410495 | 41.35771684646395 | METRO | L5 | GAVARRA | |
2.0839967889094053 | 41.36276206663678 | METRO | L5 | SANT ILDEFONS | |
2.090784291351685 | 41.36606486634577 | METRO | L5 | CAN BOIXERES | |
2.099240967351308 | 41.37132765786166 | METRO | L5 | CAN VIDALET | |
2.106777531680029 | 41.3735674280285 | METRO | L5 | PUBILLA CASES | |
2.1182995517532675 | 41.37580085050986 | METRO | L5 | COLLBLANC | |
2.1273153732529346 | 41.375614247963625 | METRO | L5 | BADAL | |
2.13548286616069 | 41.375453895709 | METRO | L5 | PLAÇA DE SANTS | |
2.1392963774276814 | 41.37970846893678 | METRO | L5 | SANTS ESTACIÓ | |
2.1414471870688554 | 41.425075923207665 | METRO | L5 | VALL D'HEBRON | |
2.145608274327709 | 41.38446375839175 | METRO | L5 | ENTENÇA | |
2.148523208344578 | 41.421983451652196 | METRO | L5 | EL COLL / LA TEIXONERA | |
2.1509870318883597 | 41.3890420103404 | METRO | L5 | HOSPITAL CLÍNIC | |
2.155128243797118 | 41.42460608993648 | METRO | L5 | EL CARMEL | |
2.1591623950839596 | 41.39489649034533 | METRO | L5 | DIAGONAL | |
2.1611806614505316 | 41.429771662434995 | METRO | L5 | HORTA | |
2.1667308339824998 | 41.3987780118665 | METRO | L5 | VERDAGUER | |
2.167762650306863 | 41.430833117745024 | METRO | L5 | VILAPICINA | |
2.173879547089167 | 41.40412620833251 | METRO | L5 | SAGRADA FAMÍLIA | |
2.1748775943420657 | 41.42974107538966 | METRO | L5 | VIRREI AMAT | |
2.176327038602659 | 41.41103033525497 | METRO | L5 | SANT PAU DOS DE MAIG | |
2.17647712858496 | 41.42587827513347 | METRO | L5 | MARAGALL | |
2.180941086984177 | 41.415008841253716 | METRO | L5 | CAMP DE L'ARPA | |
2.1816117427727684 | 41.423537197914634 | METRO | L5 | CONGRÉS | |
2.1868993989719283 | 41.42156549000137 | METRO | L5 | LA SAGRERA | |
2.1190009106752585 | 41.398976579596095 | FGC | L6 | REINA ELISENDA | |
2.1245255889061707 | 41.39935933772658 | FGC | L6 | SARRIÀ | |
2.130078121166356 | 41.398163424813525 | FGC | L6 | LES TRES TORRES | |
2.1351164320298426 | 41.39790443496872 | FGC | L6 | LA BONANOVA | |
2.1427563324952112 | 41.39864032692878 | FGC | L6 | MUNTANER | |
2.1470185420816703 | 41.40138136404616 | FGC | L6 | SANT GERVASI | |
2.152198 | 41.399717 | FGC | L6 | GRÀCIA | |
2.15250923148883 | 41.39956388602904 | FGC | L7 | GRÀCIA | |
2.158109 | 41.392780 | FGC | L6 | PROVENÇA | |
2.1579581721713352 | 41.392918251216386 | FGC | L7 | PROVENÇA | |
2.169742 | 41.385733 | FGC | L6 | CATALUNYA | |
2.1695056074604198 | 41.38571653459682 | FGC | L7 | CATALUNYA | |
2.137175722793227 | 41.41023638088421 | FGC | L7 | AVINGUDA DEL TIBIDABO | |
2.1392505813696796 | 41.40573995755271 | FGC | L7 | EL PUTXET | |
2.1426196698759385 | 41.40360519780606 | FGC | L7 | PADUA | |
2.147575544374719 | 41.40141289263426 | FGC | L7 | PLAÇA MOLINA | |
2.0346916335822876 | 41.357720085191204 | FGC | L8 | MOLÍ NOU CIUTAT COOPERATIVA | |
2.043261796054973 | 41.34815454728118 | FGC | L8 | SANT BOI | |
2.0684300990271516 | 41.35185495274866 | FGC | L8 | CORNELLÀ:RIERA | |
2.0867482896013736 | 41.353019993807926 | FGC | L8 | ALMEDA | |
2.1034244390799004 | 41.35780312987073 | FGC | L8 | L'HOSPITALET:AV. CARRILET | |
2.1116828152823457 | 41.361280437841245 | FGC | L8 | SANT JOSEP | |
2.117533256890129 | 41.355369396581125 | FGC | L8 | GORNAL | |
2.125371225579467 | 41.357014411290756 | FGC | L8 | EUROPA / FIRA | |
2.13046532981709 | 41.36140020802612 | FGC | L8 | ILDEFONS CERDÀ | |
2.1393603383592086 | 41.368237277520066 | FGC | L8 | MAGÒRIA LA CAMPANA | |
2.1486307346232185 | 41.37455640763753 | FGC | L8 | ESPANYA | |
2.198552832214578 | 41.45726270429347 | METRO | L9 | CAN ZAM | |
2.205782844559455 | 41.45937552702093 | METRO | L9 | SINGUERLÍN | |
2.210133119463337 | 41.44425515640065 | METRO | L9 | CAN PEIXAUET | |
2.2124152143832982 | 41.45451214006403 | METRO | L9 | ESGLÉSIA MAJOR | |
2.215910830603854 | 41.44669333746421 | METRO | L9 | SANTA ROSA | |
2.186309 | 41.420784 | METRO | L9 | LA SAGRERA | |
2.1862448671866446 | 41.42096945635101 | METRO | L10 | LA SAGRERA | |
2.193403 | 41.429742 | METRO | L9 | ONZE DE SETEMBRE | |
2.1931351396301815 | 41.429757841253334 | METRO | L10 | ONZE DE SETEMBRE | |
2.205065 | 41.436122 | METRO | L9 | BON PASTOR | |
2.204796554485712 | 41.436074039264945 | METRO | L10 | BON PASTOR |
<!DOCTYPE html> | |
<meta charset="utf-8" /> | |
<style> | |
canvas { | |
background: rgb(218, 233, 234) | |
} | |
.voronoi { | |
stroke: #2074A0; | |
pointer-events: all; | |
stroke-opacity: 0.5; | |
fill: none; | |
} | |
.voronoi path:hover { | |
fill: none; | |
stroke: #000; | |
stroke-opacity: 1; | |
stroke-width: 2px; | |
} | |
</style> | |
<body> | |
<script src="https://d3js.org/d3.v3.min.js"></script> | |
<script src="https://d3js.org/topojson.v1.min.js"></script> | |
<script src="https://d3js.org/queue.v1.min.js"></script> | |
<script src="https://unpkg.com/rbush@1.4.3/rbush.js"></script> | |
<script src="https://unpkg.com/spamjs@1.1.0/spam.min.js"></script> | |
<script type='text/javascript'> | |
var margin = { top: 0, right: 0, bottom: 0, left: 0 }, | |
width = 960 - margin.left - margin.right, | |
height = 650 - margin.top - margin.bottom | |
var svg = d3.select('body').append('svg') | |
.attr('width', width + margin.left + margin.right) | |
.attr('height', height + margin.top + margin.bottom) | |
.style("position", "absolute") | |
.append('g') | |
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') | |
var color = d3.scale.ordinal() | |
.domain(["L1", "L2", "L3", "L4", "L5", "L6", "L7", "L8", "L9", "L10", "L11"]) | |
.range(["rgb(225, 57, 62)", "rgb(156, 69, 154)", "rgb(83, 185, 85)", "rgb(254, 189, 16)", "rgb(49, 123, 200)", "rgb(132, 125, 198)", "rgb(174, 97, 24)", "rgb(230, 89, 180)", "rgb(246, 132, 41)", "rgb(0, 173, 239)", "rgb(168, 209, 100)"]) | |
queue() | |
.defer(d3.json, "bcn.json") | |
.defer(d3.csv, "data.csv") | |
.await(ready) | |
function ready(error, bcn, data) { | |
if (error) throw error | |
topojson.presimplify(bcn) | |
data.forEach(function(d) { | |
d.lng = +d.lng | |
d.lat = +d.lat | |
return d | |
}) | |
var map = new StaticCanvasMap({ | |
element: "body", | |
projection: d3.geo.mercator() | |
.center([29.6, 30.47]) | |
.scale(250000) | |
.rotate([0,0,-37.6]), | |
width: 960, | |
height: 650, | |
data: [{ | |
features: topojson.feature(bcn, bcn.objects["metro"]), | |
static: { | |
paintfeature: function(parameters, d) { | |
parameters.context.lineWidth = 0.5 | |
parameters.context.fillStyle = "rgb(250, 250, 250)" | |
parameters.context.strokeStyle = "rgb(200, 200, 200)" | |
parameters.context.fill() | |
parameters.context.stroke() | |
} | |
} | |
}, | |
{ | |
features: topojson.feature(bcn, bcn.objects["seccio-censal"]), | |
static: { | |
paintfeature: function(parameters, d) { | |
parameters.context.strokeStyle = "rgb(130, 170, 170)" | |
parameters.context.fillStyle = "rgb(255, 255, 255)" | |
parameters.context.stroke() | |
parameters.context.fill() | |
}, | |
postpaint: function(parameters) { | |
svg.append("g") | |
.attr("class", "circles") | |
.selectAll("circle") | |
.data(data) | |
.enter() | |
.append("circle") | |
.attr("cx", function (d) { | |
return parameters.map.settings().projection([d.lng, d.lat])[0] | |
}) | |
.attr("cy", function (d) { | |
return parameters.map.settings().projection([d.lng, d.lat])[1] | |
}) | |
.attr("r", "3px") | |
.attr("fill", function(d) { | |
return color(d.line) | |
}) | |
var voronoi = d3.geom.voronoi() | |
.x(function(d) { return parameters.map.settings().projection([d.lng, d.lat])[0] }) | |
.y(function(d) { return parameters.map.settings().projection([d.lng, d.lat])[1] }) | |
.clipExtent([[0, 0], [width, height]]); | |
var voronoiGroup = svg.append("g") | |
.attr("class", "voronoi") | |
voronoiGroup.selectAll("path") | |
.data(voronoi(data)) | |
.enter() | |
.append("path") | |
.attr("d", function(d) { return "M" + d.join("L") + "Z" }) | |
.datum(function(d) { return d.point }) | |
} | |
} | |
}] | |
}) | |
map.init() | |
} | |
</script> |