Skip to content

Instantly share code, notes, and snippets.

@shimizu
Last active May 22, 2021 16:32
Show Gist options
  • Save shimizu/1f8c1f44e29f93a34a2be3be1db5829d to your computer and use it in GitHub Desktop.
Save shimizu/1f8c1f44e29f93a34a2be3be1db5829d to your computer and use it in GitHub Desktop.
D3 v4 - Voronoi diagram on Google Maps
license: mit

高崎市 燃料給油所(GS) ボロノイ図

D3 ver.4を使ったGoogleMap上でのボロノイ図描画サンプル。

燃料給油所のデータは国土数値情報より。

Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
html, body {
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
}
#map {
width:980px;
height: 500px;
}
.SvgOverlay {
position: relative;
width: 900px;
height: 600px;
}
.SvgOverlay svg {
position: absolute;
top: -4000px;
left: -4000px;
width: 8000px;
height: 8000px;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script src="//unpkg.com/d3@4.12.2/build/d3.min.js"></script>
<script>
d3.json('gasStation.geojson', main);
function main(pointjson) {
//Google Map 初期化
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 11,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: new google.maps.LatLng(36.322356, 139.013057),
});
const overlay = new google.maps.OverlayView(); //OverLayオブジェクトの作成
//オーバレイ追加
overlay.onAdd = function () {
const layer = d3.select(this.getPanes().overlayLayer).append("div").attr("class", "SvgOverlay");
const svg = layer.append("svg");
const svgOverlay = svg.append("g").attr("class", "AdminDivisions");
const pointLayer = svgOverlay.append("g");
const voronoiLayer = svgOverlay.append("g");
const markerOverlay = this;
const overlayProjection = markerOverlay.getProjection();
//Google Mapの投影法設定
const googleMapProjection = coordinates => {
const googleCoordinates = new google.maps.LatLng(coordinates[1], coordinates[0]);
const pixelCoordinates = overlayProjection.fromLatLngToDivPixel(googleCoordinates);
return [pixelCoordinates.x + 4000, pixelCoordinates.y + 4000];
}
//再描画時に呼ばれるコールバック
overlay.draw = function () {
const width = svg.node().clientWidth;
const height = svg.node().clientHeight;
//母点位置情報
const pointdata = pointjson.features;
//ピクセルポジション情報
const positions = [];
pointdata.forEach(d => {
positions.push(googleMapProjection(d.geometry.coordinates)); //位置情報→ピクセル
});
//母点表示
const updatePoint = pointLayer.selectAll(".point").data(positions)
const enterPoint = updatePoint.enter()
.append("circle")
.attr("class", "point")
.attr("r", 2);
const point = updatePoint.merge(enterPoint)
.attr("transform", d => `translate(${d[0]}, ${d[1]})` )
//ボロノイ変換関数
const voronoi = d3.voronoi()
.extent([[-1, -1],[width+1, height+1]]);
//ボロノイ境界ポリゴンデータを生成する
const polygons = voronoi(positions).polygons();
//境界表示
voronoiLayer.selectAll(".cell").remove(); //一旦全消しして際appendする方がスムーズに地図が動いた。
voronoiLayer.selectAll(".cell").data(polygons)
.enter()
.append("path")
.attr("class", "cell")
.attr("fill", "none")
.attr("stroke", "red")
.attr("d", d => {
if(!d) return null
return "M" + d.filter( df => df != null ).join("L") + "Z"
})
};
};
//作成したSVGを地図にオーバーレイする
overlay.setMap(map);
};
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment