文字のShape化
ビットマップデータの2値化、
頂点の抽出、
リンクリストの作成、
リンクリストのVector化、
いらない頂点の消去
を順番に行っています。
/**
* Copyright shohei909 ( http://wonderfl.net/user/shohei909 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/nt3v
*/
package {
import flash.display.Graphics;
import flash.text.TextFormat;
import flash.display.Bitmap;
import flash.text.TextField;
import flash.display.BitmapData;
import flash.events.Event;
import flash.display.Sprite;
import flash.display.Shape;
import flash.utils.setInterval;
import flash.utils.getTimer;
public class FlashTest extends Sprite {
public const W:int = 155;
public const H:int = 60;
public var map:Vector.<Vector.<Anchor>> = new Vector.<Vector.<Anchor>>();
public var vec:Vector.<Anchor> = new Vector.<Anchor>();
public var paths:Vector.<Vector.<Anchor>> = new Vector.<Vector.<Anchor>>();
public var shape:Shape = new Shape();
public var guide:Shape = new Shape();
public var bitmapData:BitmapData = new BitmapData( W, H );
public function FlashTest() {
var text:TextField = new TextField()
text.defaultTextFormat = new TextFormat( "", 55 );
text.width = W;
text.height= H;
text.text = "Orz";
bitmapData.draw( text );
var bmp:Bitmap = new Bitmap( bitmapData );
shape.scaleX = shape.scaleY = guide.scaleX = guide.scaleY = bmp.scaleX = bmp.scaleY = 3;
addChild( bmp ).y = 0 ;
addChild( guide ).y = 150;
addChild( shape ).y = 300;
for( var i:int = 0; i < W+1; i++ ){
map[i] = new Vector.<Anchor>();
for( var j:int = 0; j < H+1; j++ ){
map[i][j] = null;
}
}
progress();
}
public function progress():void{
var time:int = getTimer();
var c:int = 0;
monoColor();
setVec();
setLink();
draw();
setPaths();
cutAnchors();
drawShape()
}
public function draw():void{
var g:Graphics = guide.graphics;
g.clear();
g.lineStyle( 0.5, 0xFF0000 );
for each( var a:Anchor in vec ){
g.drawCircle( a.x, a.y, 0.5 );
var nx:Anchor = a.next;
if( nx ){
g.moveTo( a.x, a.y );
g.lineTo( nx.x, nx.y );
}
}
}
public function drawShape():void{
var g:Graphics = shape.graphics;
g.clear();
g.lineStyle( 0.5, 0, 1 );
g.beginFill( 0xFF2222, 1 );
for each( var v:Vector.<Anchor> in paths ){
var l:int = v.length
var a1:Anchor = v[l-2];
var a2:Anchor = v[l-1];
var a3:Anchor = v[0];
g.moveTo( a2.x, a2.y )
for( var i:int = 1; i<l; i++ ){
a1 = a2;
a2 = a3;
a3 = v[i];
g.lineTo( a2.x, a2.y )
}
}
}
public function monoColor():void {
var b:BitmapData = this.bitmapData;
b.lock();
for( var x:int = 0; x < W; x++ ){
for( var y:int = 0; y < H; y++ ){
if( b.getPixel( x, y ) != 0xFFFFFF ){ b.setPixel( x, y, 0 ) }
}
}
b.unlock();
}
public function setVec():void {
var b:BitmapData = this.bitmapData;
for( var x2:int = 0; x2 < W; x2++ ){
for( var y2:int = 0; y2 < H; y2++ ){
var d:Array = [];
var dl:int = 0;
for( var dx:int = -1; dx < 1; dx++ ){
for( var dy:int = -1; dy < 1; dy++ ){
var x:int = x2 + dx;
var y:int = y2 + dy;
if( x < 0 || W+1 < x || y < 0 || H+1 < y || b.getPixel(x,y) != 0 ){ d.push( "0" ) }
else { d.push( "1" ); dl++ }
}
}
if( dl == 1 || dl == 3 ){
var dir:Array;
if( dl == 1 ){
dir = [ [0,-1],[-1,0],[1,0],[0,1] ][ d.indexOf("1") ]
}else{
dir = [ [-1,0],[0,1],[0,-1],[1,0] ][ d.indexOf("0") ]
}
var anc:Anchor = new Anchor( x2, y2, dir );
vec.push( anc );
map[x2][y2] = anc;
}
}
}
}
public function setLink():void{
for each( var a:Anchor in vec ){
var dx:int = a.dir[0];
var dy:int = a.dir[1];
var x:int = a.x;
var y:int = a.y;
while( true ){
x += dx; y += dy;
if( x < 0 || W < x || y < 0 || H < y ){ break }
if( map[x][y] != null ){ a.next = map[x][y]; break; }
}
}
}
public function setPaths():void{
while( vec.length > 0 ){
var first:Anchor = vec[0];
var a:Anchor = first;
var v:Vector.<Anchor> = new Vector.<Anchor>;
do{
v.push(a)
vec.splice( vec.indexOf(a), 1 );
a = a.next;
}while( first != a )
paths.push( v );
}
}
public function cutAnchors( size:Number = 0.7 ):void{
for each( var v:Vector.<Anchor> in paths ){
while( v.length > 3 ){
var l:int = v.length
var a1:Anchor = v[l-2];
var a2:Anchor = v[l-1];
var a3:Anchor = v[0];
var min:Number = getTriangleHeight( a1, a2, a3 );
var mp:int = l-1;
for( var i:int = 1; i<l; i++ ){
a1 = a2;
a2 = a3;
a3 = v[i];
var s:Number = getTriangleHeight( a1, a2, a3 );
if( s < min ){ min = s; mp = i-1; }
}
if( min < size ){
v.splice( mp, 1 );
}else{ break; }
}
}
}
private function getTriangleHeight( a1:Anchor, a2:Anchor, a3:Anchor ):Number{
var x:Number = a3.x - a1.x ; var y:Number = a3.y - a1.y ;
var s:Number = ( a2.x - a1.x ) * y - ( a2.y - a1.y ) * x ;
var l:Number = Math.sqrt(x*x + y*y)
return ( s > 0 ? s : -s ) / l / 2;
}
}
}
class Anchor{
public var x:Number;
public var y:Number;
public var dir:Array;
public var next:Anchor;
public var curve:Number = 0;
function Anchor(x:Number,y:Number,dir:Array){ this.x = x; this.y = y; this.dir = dir }
}