Daily Archives: 05/08/2013

Shapefileをcanvasに描画する。

Shapefileをcanvasに描画する。

ShapefileをOpenLayersで表示する。[その2] に続いて、Shapefileを直接読み込んで、canvasに描画してみます。
元ネタは、shapefile-jsで公開されているJavaScriptを使いました。

開発環境は、Windows 7 32bit,Aptana Studio 3.4
Firefox 20.0とGoogle Chromeで確認しました。

必要なJavaScript

shapefile-jsからmasterのZIPをdownloadして、unzipします。 とりあえずDesktopでも大丈夫です。

kanagawa folderに表示させたいShapefile一式をcopy、その際にshp,shx、dbfの3つのファイルが必要になります。

canvasに描画してみる。

exampleのファイルを編集します。
HTML5で作成します。file名は、ol_simple.htmlol_simple.jsです。
codeは簡単です。元のcodeを参考にして若干手を加えています。

<!DOCTYPE html>
<html lang="ja">
	<head>
		<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
		<title>Javascript Shapefile and DBF Loader</title>
		<script type="text/javascript" src="lib/binaryajax.js"></script>
		<script type="text/javascript" src="src/binarywrapper.js"></script>
		<script type="text/javascript" src="src/shapefile.js"></script>
		<script type="text/javascript" src="src/dbf.js"></script>
		<!--[if IE]>
<script src="lib/excanvas.js"></script><![endif]-->
		<script type="text/javascript">
			//var shpURL = "thematicmapping/TM_WORLD_BORDERS_SIMPL-0.3.shp";
			//var dbfURL = "thematicmapping/TM_WORLD_BORDERS_SIMPL-0.3.dbf";
			var shpURL = "kanagawa/c14_region.shp";
			//表示したいShape file名
			var dbfURL = "kanagawa/c14_region.dbf";
			//表示したいdbf file名
 
			var shpFile;
			var dbfFile;
 
			window.onload = function() {
				var shpLoader = new BinaryAjax(shpURL, onShpComplete, onShpFail);
				var dbfLoader = new BinaryAjax(dbfURL, onDbfComplete, onDbfFail);
			}
			function onShpFail() {
				alert('failed to load ' + shpURL);
			}
 
			function onDbfFail() {
				alert('failed to load ' + dbfURL);
			}
 
			function onShpComplete(oHTTP) {
				var binFile = oHTTP.binaryResponse;
 
				if (window.console && window.console.log)
					console.log('got data, parsing shapefile');
 
				shpFile = new ShpFile(binFile);
 
				if (shpFile.header.shapeType != ShpType.SHAPE_POLYGON && shpFile.header.shapeType != ShpType.SHAPE_POLYLINE) {
					alert("Shapefile does not contain Polygon records (found type: " + shpFile.header.shapeType + ")");
				}
 
				//if (window.console && window.console.log) console.log(records);
				if (dbfFile) {
					render(shpFile.records, dbfFile.records);
				}
			}
 
			function onDbfComplete(oHTTP) {
				var binFile = oHTTP.binaryResponse;
 
				if (window.console && window.console.log)
					console.log('got data, parsing dbf file');
 
				dbfFile = new DbfFile(binFile);
 
				if (shpFile) {
					render(shpFile.records, dbfFile.records);
				}
			}
 
			function render(records, data) {
 
				if (window.console && window.console.log)
					console.log('creating canvas and rendering');
 
				var canvas = document.getElementById('map');
 
				if (window.G_vmlCanvasManager) {
					G_vmlCanvasManager.initElement(canvas);
				}
 
				var t1 = new Date().getTime();
				if (window.console && window.console.log)
					console.log('calculating bbox...');
 
				var box;
				for (var i = 0; i < records.length; i++) {
					var record = records[i];
					if (record.shapeType == ShpType.SHAPE_POLYGON || record.shapeType == ShpType.SHAPE_POLYLINE) {
						var shp = record.shape
						for (var j = 0; j < shp.rings.length; j++) {
							var ring = shp.rings[j];
							for (var k = 0; k < ring.length; k++) {
								if (!box) {
									box = {
										x : ring[k].x,
										y : ring[k].y,
										width : 0,
										height : 0
									};
								} else {
									var l = Math.min(box.x, ring[k].x);
									var t = Math.min(box.y, ring[k].y);
									var r = Math.max(box.x + box.width, ring[k].x);
									var b = Math.max(box.y + box.height, ring[k].y);
									box.x = l;
									box.y = t;
									box.width = r - l;
									box.height = b - t;
								}
							}
						}
					}
				}
 
				var t2 = new Date().getTime();
				if (window.console && window.console.log)
					console.log('found bbox in ' + (t2 - t1) + ' ms');
 
				t1 = new Date().getTime();
				if (window.console && window.console.log)
					console.log('starting rendering...');
 
				var ctx = canvas.getContext('2d');
 
				var sc = Math.min(600 / box.width, 400 / box.height);
 
				ctx.fillStyle = '#ccccff';
				ctx.fillRect(0, 0, 600, 400);
 
				ctx.lineWidth = 0.5;
				//ctx.strokeStyle = '#ffffff';
				ctx.strokeStyle = '#000000';
				for (var i = 0; i < records.length; i++) {
					var record = records[i];
					if (record.shapeType == ShpType.SHAPE_POLYGON || record.shapeType == ShpType.SHAPE_POLYLINE) {
						var shp = record.shape;
						for (var j = 0; j < shp.rings.length; j++) {
							var ring = shp.rings[j];
							if (ring.length < 1)
								continue;
							ctx.fillStyle = rndColor(0);
							ctx.beginPath();
							ctx.moveTo((ring[0].x - box.x) * sc, 400 - (ring[0].y - box.y) * sc);
							for (var k = 1; k < ring.length; k++) {
								ctx.lineTo((ring[k].x - box.x) * sc, 400 - (ring[k].y - box.y) * sc);
							}
							ctx.fill();
							ctx.stroke();
						}
					}
				}
				t2 = new Date().getTime();
				if (window.console && window.console.log)
					console.log('done rendering in ' + (t2 - t1) + ' ms');
			}
 
			function rndColor(start) {
				var base = 0;
				if (start == 1) {
					base = 40;
				} else {
					base = 127;
				}
				var r = base + Math.floor(128 * Math.random());
				var g = base + Math.floor(128 * Math.random());
				var b = base + Math.floor(128 * Math.random());
				return '#' + r.toString(16) + g.toString(16) + b.toString(16);
			}
 
		</script>
		<style type="text/css">
			body {
				background-color: #eeeeee;
				color: #000000;
				font: 12px sans-serif;
				margin: 20px;
			}
			canvas {
				background-color: #FFFFFF;
				padding: 10px;
			}
		</style>
	</head>
	<body>
		<h1>Javascript Shapefile and DBF Loader</h1>
		<h2>Shapefileを読み込んでcanvasに描画するサンプル (Firefox,Chrome)</h2>
		<p>
			Loading shapefile... uninformative errors may appear in the dark crevices of your browser.
		</p>
		<canvas id="map" width="600" height="400"></canvas>
		<p>
			See <a href="http://github.com/RandomEtc/shapefile-js">http://github.com/RandomEtc/shapefile-js</a> for more details.
		</p>
	</body>
</html>

FireFoxで実行させると、
blog.godo-tys.jp_wp-content_gallery_shapefile_3_image01.jpg

な感じで、Shapefileが表示されます。Good Job!!ですね。
ここでは、神奈川県の市区町村の行政界を表示しています。

これは、いろいろと使えますよね。
覚えておいて損はnice!!

1 / 3123

Social Widgets powered by AB-WebLog.com.