canvas实现DBSCAN聚类算法可视化过程代码

代码语言:html

所属分类:其他

代码描述:canvas实现DBSCAN聚类算法可视化过程代码

代码标签: 聚类 算法 可视化 过程

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!doctype html>
<html  lang="en-us">
<head>
	<meta charset="utf-8">


</head>
<body>



<div class="center">
	<article>
		<div class="social">
    
</div>
		<h1 class="title">DBSCAN</h1>
		

		<div class="content"><div>
  <p>A visualization of a <a href="http://en.wikipedia.org/wiki/DBSCAN">DBSCAN algorithm</a>.</p>
<style>
    .post {
        max-width: none;
        width: 640px;
        padding: 0;
    }
</style>
<header>
	<nav id="menu"></nav>
	<div class="clear"></div>
</header>
<p><canvas id="canvas" ></canvas></p>
<script>
    
Math.TAU = Math.PI*2;

function $P(x,y){ return new Point(x,y);}
function Point(x,y){
	this.x = x;
	this.y = y;
}

Point.prototype = {
	toString : function(){ 
		return "<" + this.x.toFixed(2) + ";" + this.y.toFixed(2) + ">"; 
	}
};

function $R(left, top, right, bottom){
	return new Rect(left, top, right, bottom);
}

function Rect(left, top, right, bottom){
	this.left = left;
	this.top = top;
	this.right = right;
	this.bottom = bottom;
}

Rect.prototype = {
	get width(){ return Math.abs(this.right - this.left); },
	get height(){ return Math.abs(this.bottom - this.top); },

	get dx(){ return this.right - this.left; },
	get dy(){ return this.bottom - this.top; },

	get topLeft(){ return new Point(this.left, this.top); },
	get bottomRight(){ return new Point(this.right, this.bottom); },

	intersect : function(rect){
		var left = this.left > other.left ? this.left : other.left,
			top = this.top > other.top ? this.top : other.top,
			right = this.right < other.right ? this.right : other.right,
			bottom = this.bottom < other.bottom ? this.bottom : other.bottom;
		return new Rect(left, top, right, bottom);
	}
};

function sortRange(zero, from, to, delta){
	if (from < to) {
		return {from:from, to:to, delta:Math.abs(delta)};
	} else {
		return {from:to, to:from, delta:Math.abs(delta)};
	}
}
</script>
<script >
    
function clone(obj){
	if(typeof(obj) != "object")
		return obj;
	var result = {};
	for(var i in obj)
		result[i] = clone(obj[i]);
	return result;
}

function foreach(obj, f){
	if(obj instanceof Array){
		for(var i = 0; i < obj.length; i += 1){
			f(obj[i], i, obj);
		};
	} else {
		for(var name in obj){
			if(!obj.hasOwnProperty(name)) continue;
			f(obj[name], name, obj);
		};
	}
}
</script>
<script >
    function $(id){ return document.getElementById(id); }
main = {
	canvas : $("canvas"),
	draw : null,
	nav  : $("menu"),
	size : {x: 480, y:480},
	
	updateTimer: 0,
	drawTimer: 0,
	history: [],

	tick : 0,
	updateRate: 1000,
	drawRate : 33,

	running : false,

	state : null,
	updates : function(state){},
	render : function(draw, size, state){},
	
	runRendering: function(){
		this.drawTimer = window.setInterval($render, this.drawRate);
	},
	stopRendering: function(){
		window.clearInterval(this.drawTimer);
	},
	
	run : function(){ 
		this.stop();
		this.running = true;
		this.updateTimer = window.setInterval($update, this.updateRate);
	},
	stop : function(){ 
		this.running = false;
		window.clearInterval(this.updateTimer);
	},
	reset : function(){
		this.stop();
		this.tick = 0;
		this.history = [];
		this.state = {};
		this.resetState(this.draw, this.size, this.state);
		this.render(this.draw, this.size, this.state);
	},

	log : function(data){
		this.history.unshift(data);
	},
	
	update : function(){
		this.tick += 1;
		this.updates(this.state);
	},
	updateDisplay : function(){
		this.render(this.draw, this.size, this.state);
	},
	setSize : function(w,h){
		this.size = {x:w, y:h};
		this.canvas.width = this.size.x;
		this.canvas.height = this.size.y;
	},

	mouse : $P(0,0)
};

$update	= function(){main.update()};
$run	= function(){main.run()};
$stop	= function(){main.stop()};
$reset	= function(){main.reset()};
$render = function(){main.updateDisplay()};

main.draw = main.canvas.getContext("2d");

function button(caption, func){
	var elem = document.createElement("button");
	elem.innerHTML = caption;
	elem.addEventListener("click", func);
	main.nav.appendChild(elem);
	return elem;
}

function input(id, value){
	var elem = document.createElement("input");
	elem.id = id;
	elem.value = value;
	main.nav.appendChild(elem);
	return elem;
}

main.canvas.addEventListener("mousemove", function(e){
	main.mouse.x = e.pageX - main.canvas.offsetLeft;
	main.mouse.y = e.pageY - main.canvas.offsetTop;
});

</script>
<script >
    inputData = {
	A : {x : 2, y : 4 },
	B : {x : 7, y : 3 },
	C : {x : 3, y : 5 },
	D : {x : 5, y : 3 },
	E : {x : 7, y : 4 },
	F : {x : 6, y : 8 },
	G : {x : 6, y : 5 },
	H : {x : 8, y : 4 },
	I : {x : 2, y : 5 },
	J : {x : 3, y : 7 }
};
</script>
<script >
    
function Grid(rect, range){
	this._rect = rect;
	this._range = range;
	this.tick = $P(1.0,1.0);
	this.scale = $P(1.0,1.0);
	this.recalc();
}

Grid.prototype = {
	get range(){ return this._range; },
	set range(range){ this._range = range; this.recalc(); },

	get rect(){ return this._rect; },
	set rect(rect){ this._rect = rect; this.recalc(); },

	recalc : function(){
		this.scale.x = this.rect.dx / this.range.dx;
		this.scale.y = this.rect.dy / this.range.dy;
	},
	render : function(draw){
		var zero = this.toScreen($P(0.0,0.0)),
			one = this.toScreen(this.tick),
			dx = one.x - zero.x,
			dy = one.y - zero.y,

			topLeft = this.toScreen(this.range.topLeft),
			bottomRight = this.toScreen(this.range.bottomRight);

		draw.beginPath();
		
		var r = sortRange(zero.x, topLeft.x, bottomRight.x, dx),
			gx = this.range.left;

		for(var x = r.from; x <= r.to; x += r.delta){
			draw.moveTo(x, topLeft.y);
			draw.lineTo(x, bottomRight.y);

			draw.fillText(gx.toFixed(1), x+2, zero.y-2);
			gx += this.tick.x;
		}

		var r = sortRange(zero.y, topLeft.y, bottomRight.y, dy),
			gy = this.range.top;

		for(var y = r.from; y <= r.to; y += r.delta){
			draw.moveTo(topLeft.x, y);
			draw.lineTo(bottomRight.x, y);
			
			draw.fillText(gy.toFixed(1), zero.x+2, y-2);
			gy -= this.tick.y;
		}

		draw.stroke();
	},
	toScreen : function(p, r){
		r = r || new Point(0,0);
		r.x = (p.x - this._range.left) * this.scale.x + this._rect.left,
		r.y = (p.y - this._range.top) * this.scale.y + this._rect.top;
		return r;
	},
	fromScreen : function(p, r){
		r = r || new Point(0,0);
		r.x = (p.x - this._rect.left) / this.scale.x + this._range.left,
		r.y = (p.y - this._rect.top) / this.scale.y + this._range.top;
		return r;
	}
};
</script>
<script>

function loaded(){
	main.setSize(640, 640);

	button("Step",  $update);
	button("Run",   $run);
	button("Stop",  $stop);
	button("Reset", $reset);

	input("eps", 2);
	input("minPts", 2);

	main.reset();
	main.runRendering();
}

var conf = {
	main : {
		background : "#222",
		foreground : "#ddd",
	},
	data : {
		background : "#fff",
		foreground : "#222",
		radius : 15,
	},
	algorithm : {
		marking : 18,
	}
};

main.resetState = function(draw, size, state){
	state.data = clone(inputData);
	state.n.........完整代码请登录后点击上方下载按钮下载查看

网友评论0