f8g

等高線を描く

基盤地図情報を使うと画像が公開できないので、普通の画像のRGBを標高値として等高線を描きます。
http://gyazo.com/c014bb18e03322b94cd4dff3ea07c75d.png
アルゴリズムが合ってんだか間違ってんだか分からん。(間違ってたのでコード修正しました)
簡単なアルゴリズムでは、画像を三角形に分割してその中で線を引いていきます。
http://media.tumblr.com/CAiSbEIuHf10vmvt7Gyxbunbo1_500.png
使用

// 点
function Point3D(x, y, z){
	if(!x) x = 0;
	if(!y) y = 0;
	if(!z) z = 0;

	this.x = x;
	this.y = y;
	this.z = z;
}

/**
 * 分割して線を引かせる部分
 * @boxInterval 三角形の大きさ
 * @conInterval 等高線を引く間隔
 */
ImageProcessing.prototype.drawContour = function(boxInterval, conInterval){
	var ps = [];
	var _x = 0, _y = 0;
	var canvas = this.clone().clear();  // 等高線を描くCanvas

	for(var x = 0; x < this.canvas.width; x += boxInterval){
		for(var y = 0; y < this.canvas.height; y += boxInterval){
			_x = x + boxInterval;
			_y = y + boxInterval;

			if(_x >= this.canvas.width)
				_x = this.canvas.width - 1;

			if(_y >= this.canvas.height)
				_y = this.canvas.height - 1;

			ps[0] = new Point3D(x,  y, this.getPixel(x,  y).g);
			ps[1] = new Point3D(x, _y, this.getPixel(x, _y).g);
			ps[2] = new Point3D(_x, y, this.getPixel(_x, y).g);

			this.drawContourLine(canvas, ps, conInterval);

			// 修正
			ps[0] = new Point3D(_x, _y, this.getPixel(_x,  _y).g);
			this.drawContourLine(canvas, ps, conInterval);

			// 間違い
/*			if(x - boxInterval < 0){
				ps[2] = new Point3D(x - boxInterval, _y, this.getPixel(x - boxInterval, _y).g);
				this.drawContourLine(canvas, ps, conInterval);
			}*/
		}
	}

	return canvas;
};

あとは線を引くだけです。簡単ですね。

/**
 * 実際に線を引く部分
 * @process  線を引くCanvas
 * @points   三角形の点たち
 * @interval 等高線の間隔
 */
ImageProcessing.prototype.drawContourLine = function(process, points, interval){
	// 点の中の最大と最小の標高値をintervalで丸めてます
	var contourL = parseInt(Math.min.apply(null, points.map(function(p){ return p.z; })) / interval) * interval;
	var contourH = parseInt(Math.max.apply(null, points.map(function(p){ return p.z; })) / interval) * interval;
	var flags = [];
	var ratio = 0;
	var x1 = 0, y1 = 0;
	var x2 = 0, y2 = 0;

	var drawLine = function(x1, y1, x2, y2){
		process.context.beginPath();
		process.context.moveTo(x1, y1);
		process.context.lineTo(x2, y2);
		process.context.closePath();
		process.context.stroke();
	};

	for(var h = contourL; h <= contourH; h += interval){
		// どこに線を引くか調べてます
		flags = [
			(points[0].z <= h && h <= points[1].z) || (points[1].z <= h && h <= points[0].z),
			(points[1].z <= h && h <= points[2].z) || (points[2].z <= h && h <= points[1].z),
			(points[2].z <= h && h <= points[0].z) || (points[0].z <= h && h <= points[2].z)
		];

		// 線引いてます
		if(flags[0] && flags[1] && points[1].z != points[0].z && points[2].z != points[1].z){
			ratio = (h - points[0].z) / (points[1].z - points[0].z);
			x1 = ratio * (points[1].x - points[0].x) + points[0].x;
			y1 = ratio * (points[1].y - points[0].y) + points[0].y;

			ratio = (h - points[1].z) / (points[2].z - points[1].z);
			x2 = ratio * (points[2].x - points[1].x) + points[1].x;
			y2 = ratio * (points[2].y - points[1].y) + points[1].y;

			drawLine(x1, y1, x2, y2);
		}

		if(flags[1] && flags[2] && points[2].z != points[1].z && points[2].z != points[0].z){
			ratio = (h - points[1].z) / (points[2].z - points[1].z);
			x1 = ratio * (points[2].x - points[1].x) + points[1].x;
			y1 = ratio * (points[2].y - points[1].y) + points[1].y;

			ratio = (h - points[2].z) / (points[0].z - points[2].z);
			x2 = ratio * (points[0].x - points[2].x) + points[2].x;
			y2 = ratio * (points[0].y - points[2].y) + points[2].y;

			drawLine(x1, y1, x2, y2);
		}

		if(flags[2] && flags[0] && points[0].z != points[2].z && points[1].z != points[0].z){
			ratio = (h - points[2].z) / (points[0].z - points[2].z);
			x1 = ratio * (points[0].x - points[2].x) + points[2].x;
			y1 = ratio * (points[0].y - points[2].y) + points[2].y;

			ratio = (h - points[0].z) / (points[1].z - points[0].z);
			x2 = ratio * (points[1].x - points[0].x) + points[0].x;
			y2 = ratio * (points[1].y - points[0].y) + points[0].y;

			drawLine(x1, y1, x2, y2);
		}
	}
};

三角形の大きさが大きいほど大雑把な感じです。楽しいですね。

分割サイズ
1 http://media.tumblr.com/CAiSbEIuHf1xq96gUrfu7WhTo1_500.png
5 http://data.tumblr.com/CAiSbEIuHf1xqqy10mM7asaWo1_500.png
10 http://data.tumblr.com/CAiSbEIuHf1xp80uxrix5OVHo1_500.png

等高線を引く間隔を変えると線の数が変わります。三角形って感じですね。

間隔
16 http://media.tumblr.com/CAiSbEIuHf1xsfpjn9D5kKO4o1_500.png
32 http://data.tumblr.com/CAiSbEIuHf1xqqy10mM7asaWo1_500.png
64 http://data.tumblr.com/CAiSbEIuHf1xtyfoP5HfDNV0o1_500.png