Box2DObject生成 + MouseGesture
now only support: rectangle, circle, triangle
* inspired by Mouse Gesture Recognition from bytearray.org
* 2010-01-26 19:18:00
/**
* Copyright civet ( http://wonderfl.net/user/civet )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/5IQf
*/
/**
* now only support: rectangle, circle, triangle
* inspired by Mouse Gesture Recognition from bytearray.org
* 2010-01-26 19:18:00
*/
package
{
import com.actionsnippet.qbox.QuickBox2D;
import flash.display.*;
import flash.events.*;
import flash.geom.Point;
import flash.utils.getTimer;
public class Main extends MovieClip
{
private var sim:QuickBox2D;
private var time:int;
private var source:BitmapData;
private var shape:Shape;
private var wayPoints:Array = [];
public function Main()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.frameRate = 60;
init();
}
private function init():void
{
sim = new QuickBox2D(this, {debug:true});
sim.createStageWalls();
sim.start();
sim.mouseDrag();
source = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xffffff);
shape = new Shape();
var canvas:Bitmap = new Bitmap(source);
canvas.alpha = 0.5;
this.addChild(canvas);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onMouseDown(e:MouseEvent):void
{
time = getTimer();
wayPoints.length = 0;
this.addEventListener(Event.ENTER_FRAME, onTracing);
}
private function onMouseUp(e:MouseEvent):void
{
this.removeEventListener(Event.ENTER_FRAME, onTracing);
source.fillRect(source.rect, 0xffffff);
if(wayPoints.length < 1) return;
var p:Array = simplify(wayPoints);
var v:Array = toVectors( p );
var s:String = serialize(v).toString().replace(/,/g, '');
var i:int = recognize(s);
createShape(i);
}
private function onTracing(e:Event):void
{
if((getTimer() - time) < 30) return;
time = getTimer();
wayPoints[wayPoints.length] = new Point(mouseX, mouseY);
drawWay(wayPoints);
}
private function drawWay(pts:Array):void
{
var g:Graphics = shape.graphics;
g.clear();
var len:int = pts.length;
for(var i:int=0; i < len; ++i) {
g.beginFill(0xff0000);
g.drawCircle(pts[i].x, pts[i].y, 3);
g.endFill();
}
source.fillRect(source.rect, 0xffffff);
source.draw(shape);
}
private var maxPoint:Number = 17;
private function simplify(points:Array):Array
{
var p:Array = points.slice();
if(p.length <= maxPoint) return p;
while(p.length > maxPoint) {
var dMin:Number = Number.POSITIVE_INFINITY;
var d:Number;
var iMarker:int;
for(var i:int=2; i<p.length-1; i++) {
d = Point.distance(p[i], p[i-1]);
if(d<dMin) {
dMin = d;
iMarker = i;
}
}
p[iMarker] = new Point((p[iMarker].x+p[iMarker-1].x)/2, (p[iMarker].y+p[iMarker-1].y)/2);
p.splice(iMarker-1, 1);
}
return p;
}
private function toVectors(points:Array):Array
{
var v:Array = new Array();
for(var i:int=1; i<points.length; i++) {
var vector:Point = new Point((points[i].x-points[i-1].x), (points[i].y-points[i-1].y));
vector.normalize(1);
vector.x = int( Math.round(vector.x) );
vector.y = int( Math.round(vector.y) );
v[i-1] = vector;
}
return v;
}
private var pattern:Array = [[7, 8, 9], [4, 5, 6], [1, 2, 3]];
private function serialize(points:Array):Array {
var s:Array = new Array();
for(var i:int=0; i < points.length; i++) {
var pt:Point = points[i];
s.push( pattern[1 + pt.y][1 + pt.x] );
}
return s;
}
private var gesture:Array = ["5555555555555555",
"6666666666666666",
"2222222222222222",
"4444444444444444",
"8888888888888888",
"3333333333333333",
"1111111111111111",
"7777777777777777",
"9999999999999999",
"6666222244448888",
"4444222266668888",
"4441223669887444",
"6663221447889666",
"1111166666677777",
"3333366666699999"
];
private function recognize(s:String):int
{
var dMin:Number = Number.POSITIVE_INFINITY;
var d:Number;
var iMarker:int;
for(var i:int=0; i < gesture.length; ++i) {
d = Distance.levenshtein(s, gesture[i]);
if(d < dMin) {
dMin = d;
iMarker = i;
}
}
trace("input: " + s);
trace("match : " + gesture[iMarker]);
trace("distance: " + dMin);
return iMarker;
}
private function createShape(type:int):void
{
switch(type) {
case 9:
case 10:
sim.addBox({x:10, y:2, width:2, height:2});
break;
case 11:
case 12:
sim.addCircle({x:10, y:2, radius:1});
break;
case 13:
case 14:
sim.addPoly({x:10, y:2, verts:[[0,0,2,2,0,2]]});
break;
}
}
}
}
class Distance {
/* Compute Levenshtein distance */
public static function levenshtein(s:String, t:String):uint {
var cost:uint;
// Step 1
var n:uint = s.length;
var m:uint = t.length;
if(n==0) return m;
if(m==0) return n;
// Step 2
var d:Array = getArray2D(n+1, m+1, 0);
for(var i:uint=0; i<=n; i++) { d[i][0] = i; }
for(var j:uint=0; j<=m; j++) { d[0][j] = j; }
// Step 3
for(i=1; i<=n; i++) {
var sChar:String = s.charAt(i-1);
// Step 4
for(j=1; j<=m; j++) {
var tChar:String = t.charAt(j-1);
// Step 5
if(sChar==tChar) cost = 0;
else cost = 1;
// Step 6
d[i][j] = Math.min(d[i-1][j]+1, d[i][j-1]+1, d[i-1][j-1]+cost);
}
}
// Step 7
return d[n][m];
}
/* get Filled 2D Table(Matrix) */
private static function getArray2D(n:uint, m:uint, element:*):Array {
var matrix:Array = new Array(n);
for (var i:uint=0; i<n; i++) {
matrix[i] = new Array(m);
for (var j:uint=0; j<m; j++) {
matrix[i][j] = element;
}
}
return matrix;
}
}