群馬県の小学校区とボロノイ図を重ね合わせてみた
以前紹介した「最適配置の数理」という本の中で、学校区の範囲とボロノイ分割区域とを比較して、そのズレを検討した研究事例というのが載っていたので群馬県の小学校の上にボロノイ図をオーバレイしてみました。
ざっと見た感じ中心地ではほとんど近似しているようなのですが、沼田市周辺で学区とボロノイ図がズレまくっていて気になったので調べてみたところ、いくつかの小学校が廃統合された結果、ちょっと歪な形になっているようです。
いろいろ調べてみると面白いことがわかるかもしれません。
小学校区ポリゴン表示
小学校区に関しては以前Google Maps上にKMLを読み込んで表示したことがあったので、今回はGeoJSONデータを使いました。元データは国土数値情報から、QGISを使ってGeoJSONに変換しています。
参考:ShapeファイルからGeoJsonファイルを作成する
Google Maps上に表示する方法は以下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//ポリゴンデータのスタイルを指定 var styleFeature = function(feature){ return { "strokeWeight": 2, "strokeColor": "green", "zIndex": 1, "fillColor": "lightgreen", "fillOpacity": 0.5, "visible": true }; } //小学校区データ読み込み d3.json("../../_geodata/SchoolDistrict.geojson", function(data) { //データレイヤーに追加 map.data.addGeoJson(data); //データレイヤのスタイルを指定 map.data.setStyle(styleFeature); }); |
詳細はこちらを。
ボロノイ図の表示
小学校の位置(母点)とボロノイ図はD3.jsで作成しGoogle Maps上にオーバレイしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
/*************************************************************************** * ボロノイ図表示 ***************************************************************************/ var overlay = new google.maps.OverlayView(); //OverLayオブジェクトの作成 //小学校位置データ読み込み d3.json("../../_geodata/PublicElementarySchool.geojson", function(pointjson) { //オーバレイ追加 overlay.onAdd = function () { var layer = d3.select(this.getPanes().overlayMouseTarget).append("div").attr("class", "SvgOverlay"); var svg = layer.append("svg"); var svgoverlay = svg.append("g").attr("class", "AdminDivisions"); var markerOverlay = this; var overlayProjection = markerOverlay.getProjection(); //Google Mapの投影法設定 var googleMapProjection = function (coordinates) { var googleCoordinates = new google.maps.LatLng(coordinates[1], coordinates[0]); var pixelCoordinates = overlayProjection.fromLatLngToDivPixel(googleCoordinates); return [pixelCoordinates.x + 4000, pixelCoordinates.y + 4000]; } //再描画時に呼ばれるコールバック overlay.draw = function () { //母点位置情報 var pointdata = pointjson.features; //ピクセルポジション情報 var positions = []; pointdata.forEach(function(d) { positions.push(googleMapProjection(d.geometry.coordinates)); //位置情報→ピクセル }); //ボロノイ変換関数 var polygons = d3.geom.voronoi(positions); var pathAttr = { "d":function(d, i) { return "M" + polygons[i].join("L") + "Z"}, "stroke":"blue", "stroke-width": 2, "fill":"white", "fill-opacity":0 }; //境界表示 svgoverlay.selectAll("path") .data(pointdata) .attr(pathAttr) .enter() .append("svg:path") .attr("class", "cell") .attr(pathAttr) .append("title") .text(function(d, i){console.log(d); return d.properties.A27_003 +"区"; }); var circleAttr = { "cx":function(d, i) { return positions[i][0]; }, "cy":function(d, i) { return positions[i][1]; }, "r":4, "fill":"red" } //母点表示 svgoverlay.selectAll("circle") .data(pointdata) .attr(circleAttr) .enter() .append("svg:circle") .attr(circleAttr); }; }; //作成したSVGを地図にオーバーレイする overlay.setMap(map); }); |