In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

k-means

nitoyon氏の記事から改変
http://d.hatena.ne.jp/nitoyon/20090409/kmeans_visualise
Get Adobe Flash player
by ototoi 11 Apr 2009
//nitoyon氏の記事から改変
//http://d.hatena.ne.jp/nitoyon/20090409/kmeans_visualise
//

package{
import flash.display.*;
import flash.events.Event;
import flash.utils.setTimeout;
//import sketchbook.colors.ColorSB;
import frocessing.color.ColorHSV;//こっちに
import caurina.transitions.Tweener;



[SWF(backgroundColor="#223344", width=400, height=400)]
public class KMeans extends Sprite{
	private var k:int;
	private var n:int;
	private var colors:Array;
	private var dots:Array;
	private var groups:Array;
	private var centers:Array;
	private var changed:Boolean;
	private var canvas:Sprite = new Sprite();

	private const WIDTH:int = 400;
	private const HEIGHT:int = 300;
	private const ANIMATE:Number = .2;

	public function KMeans():void{
		stage.scaleMode = "noScale";

		// init canvas
		canvas.graphics.beginFill(0x000000, 0);
		canvas.graphics.drawRect(0, 0, WIDTH, HEIGHT);
		canvas.graphics.endFill();
		canvas.useHandCursor = buttonMode = true;
		canvas.mouseChildren = false;
		addChild(canvas);

		var state:int = 0;
		canvas.addEventListener("click", function(event:Event):void{
			if(state == 0){
				moveCenter();
			}else{
				updateGroups();
			}
			state = (state + 1) % 2;
		});

		// init inputs
		var nInput:Input = new Input("N (the number of node):", "100");
		nInput.y = HEIGHT + 5;
		addChild(nInput);

		var kInput:Input = new Input("K (the number of cluster):", "5");
		kInput.y = nInput.y + nInput.height + 5;
		addChild(kInput);

		var nextButton:Button = new Button("Step");
		nextButton.y = kInput.y + kInput.height + 5;
		addChild(nextButton);
		nextButton.addEventListener("click", canvas.dispatchEvent);

		var resetButton:Button = new Button("Restart");
		resetButton.x = nextButton.width + 5;
		resetButton.y = nextButton.y;
		addChild(resetButton);
		resetButton.addEventListener("click", function(event:Event):void{
			changed = true;
			state = 0;

			k = kInput.value;
			n = nInput.value;
			init();
		});
		resetButton.dispatchEvent(new Event("click"));
	}
	
	// find the nearest group
        private function findGroup(x:Number, y:Number):int{
		var min:Number = Infinity;
		var group:int = -1;
		for(var i:int = 0; i < centers.length; i++){
			var center:Center = centers[i];
			if(!center) continue;

			var d:Number = Math.pow(center.x - x, 2) + Math.pow(center.y - y, 2);
			if(d < min){
			    min = d;
			    group = i;
			}
		}
		return group;
	}

	private function init():void{
		// remove previous sprites
		graphics.clear();
		for each(var dot:Dot in dots){
			canvas.removeChild(dot);
		}
		for each(var center:Center in centers){
			if(center) canvas.removeChild(center);
		}

		// init colors
		colors = [];
		for(var i:int = 0; i < k; i++){
			colors.push(new ColorHSV(i * 360 / k, 90, 100));//ここ改変
		}
		// init centers
		centers = [];
		for(var i:int = 0; i < k; i++){//重心の初期値はランダムに
			var center:Center = new Center(colors[i]);
			center.x = Math.random() * WIDTH; 
			center.y = Math.random() * HEIGHT;
			centers[i] = canvas.addChild(center);
		}
		// init dot
		dots = [];
		groups = [];
		for(var i:int = 0; i < n; i++){
			//var group:int = Math.floor(Math.random() * k);
			var x:Number = Math.random() * WIDTH;
			var y:Number = Math.random() * HEIGHT;
			//var group:int = findGroup(x,y);//先の重心から最近傍を見つける
			//if(colors[group]){
			    //var dot:Dot = new Dot(colors[group]);
                            var dot:Dot = new Dot(0xFFFFFF);//最初はどこにも属さない・・・とりあえず白
			    dot.x = x;
			    dot.y = y;
			    canvas.addChild(dot);
                            dots.push(dot);
			    //if(!groups[group]) groups[group] = [];
			    //groups[group].push(dot);
                        //}
		}
	}

	private function moveCenter():void{
		for each(var dot:Dot in dots) dot.glow = false;
		if(!changed) return;

		graphics.clear();
		var animated:Boolean = false;
		for(var i:int = 0; i < groups.length; i++){
			if(!groups[i] || !groups.length){
				continue;
			}

			// get center of gravity
			var x:Number = 0, y:Number = 0;
			for each(dot in groups[i]){
				x += dot.x;
				y += dot.y;
			}
			x /= groups[i].length;
			y /= groups[i].length;

			if(centers[i]){
				Tweener.addTween(centers[i], {
					x: x, y: y, time: ANIMATE
				});
				animated = true;
			}else{
				var center:Center = new Center(colors[i]);
				center.x = x; center.y = y;
				centers[i] = canvas.addChild(center);
			}
		}

		if(!animated) drawCenterLines();
		else setTimeout(drawCenterLines, ANIMATE * 1000);
	}

	private function drawCenterLines():void{
		graphics.clear();
		for(var i:int = 0; i < groups.length; i++){
			var center:Center = centers[i];
			if(!center) continue;
			for each(var dot:Dot in groups[i]){
				graphics.lineStyle(1, colors[i], .5);
				graphics.moveTo(center.x, center.y);
				graphics.lineTo(dot.x, dot.y);
				graphics.lineStyle();
			}
		}
	}

	private function updateGroups():void{
		changed = false;
		groups = [];
		for each(var dot:Dot in dots){
			var group:int = findGroup(dot.x,dot.y);

			// update group
			if(!groups[group]) groups[group] = [];
			groups[group].push(dot);
			if(dot.color != colors[group]){
				dot.color = colors[group];
				dot.glow = true;
				changed = true;
			}
		}

		drawCenterLines();
	}
}
}

import flash.display.*;
import flash.text.*;
import flash.filters.GlowFilter;

class Dot extends Sprite{
	private var _color:uint;
	public function get color():uint{return _color;}
	public function set color(v:uint):void{
		_color = v;
		draw();
	}

	public function set glow(v:Boolean):void{
		if(v) filters = [new GlowFilter(0xffffff, 1, 5, 5)];
		else filters = [];
	}

	public function Dot(col:uint){
		color = col;
	}

	private function draw():void{
		graphics.clear();
		graphics.beginFill(_color);
		graphics.drawCircle(0, 0, 5);
		graphics.endFill();
	}
}

class Center extends Sprite{
	public function Center(col:uint){
		graphics.lineStyle(3, 0xffffff);
		draw();
		graphics.endFill();

		graphics.lineStyle(2, col);
		draw();
		graphics.endFill();
	}

	private function draw():void{
		graphics.moveTo(-5, -5);
		graphics.lineTo(5, 5);
		graphics.moveTo(5, -5);
		graphics.lineTo(-5, 5);
	}
}

class Button extends Sprite{
	public function Button(label:String){
		useHandCursor = buttonMode = true;
		mouseChildren = false;

		var t:TextField = new TextField();
		t.text = label;
		t.autoSize = "left";
		t.selectable = false;
		t.x = t.y = 5
		addChild(t);

		graphics.beginFill(0xcccccc);
		graphics.drawRect(0, 0, t.width + 10, t.height + 10);
		graphics.endFill();
	}
}

class Input extends Sprite{
	private var input:TextField;

	public function get value():int{
		return parseInt(input.text, 10);
	}

	public function Input(labelStr:String, valueStr:String):void{
		var tf:TextFormat = new TextFormat();
		tf.size = 20;

		var label:TextField = new TextField();
		input = new TextField();
		input.textColor = label.textColor = 0xffffff;
		input.defaultTextFormat = label.defaultTextFormat = tf;

		label.text = labelStr;
		label.autoSize = "left";
		addChild(label);

		input.border = true;
		input.borderColor = 0x999999;
		input.type = "input";
		input.text = valueStr;
		input.height = 22;
		addChild(input).x = 220;
	}
}