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

Spline Text

だめだ・・
Get Adobe Flash player
by uwi 25 Apr 2009
    Embed
package {
    import flash.display.Sprite;
    import flash.text.*;
    import flash.display.*;
    import flash.geom.*;
    import flash.filters.*;
    import flash.events.*;
    
    // だめだ・・
    public class SplineText extends Sprite {
        private var splines : Array;
        private var tf : TextField;
        private var start : Number;
        
        public function SplineText()
        {
            tf = new TextField();
            tf.height = 450;
            tf.width = 450;
            addChild(tf);
            
            init();
            start = 0.0;
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
        
        private function onEnterFrame(e : Event) : void
        {
            if(start >= 10)return;
            // splineを描く
            graphics.clear();
            graphics.lineStyle(1, 0);
            var step : Number = 0.05;
            for each(var spline : Object in splines){
//                var len : int = co.x.a.length;
//                tf.appendText(len.toString() + "\n");
                graphics.moveTo(
                    Spline.calc(spline.co.x, start) * 2,
                    Spline.calc(spline.co.y, start) * 2
                    );
                for(var t : Number = start + step;t < start + spline.len;t+=step){
                    graphics.lineTo(
                        Spline.calc(spline.co.x, t) * 2, 
                        Spline.calc(spline.co.y, t) * 2
                    );
                }
            }
            start += 0.02;
        }
        
        private function init() : void
        {
            var tfmt : TextFormat = new TextFormat("Verdana", 130);
            var bmd : BitmapData = getTextBitMap("か", tfmt);
            var rect : Rectangle = bmd.getColorBoundsRect(0xffffff, 0x000000, true);
            
            // エッジ抽出
            var cf : ConvolutionFilter = new ConvolutionFilter(3, 3, [0, -1, 0, -1, 4, -1, 0, -1, 0]);
            bmd.applyFilter(bmd, bmd.rect, new Point(), cf);
            
            // 輪郭線追跡
            var pathes : Array = [];
            for(var x : int = 0;x < bmd.width;x++){
                for(var y : int = 0;y < bmd.height;y++){
                    if(bmd.getPixel(x, y) == 0xffffff){
                        pathes.push(tracePath(bmd, x, y));
                    }
                }
            }
            
            var newpathes : Array = [];
            for each(var path : Array in pathes){
                newpathes = newpathes.concat(findIndifferentiable(path));
            }
            
            splines = [];
            var i : int;
            
            // 適当にポイントを水増し
            var step : int = 80;
            for each(path in newpathes){
                var conti : Array = [];
//                if(path.length < 3)continue;
                for(i = 0;i < path.length - 3;i+=3){
                    conti.push(path[i]);
                }
                conti.push(path.pop());
                
                if(conti.length < 2)continue;
                var pc : Point = conti[conti.length - 2];
                var pl : Point = conti[conti.length - 1];
                var l : int = conti.length;
                
                var p0 : Point = new Point(2 * pl.x - pc.x, 2 * pl.y - pc.y);
                conti.push(p0);
                var p1 : Point = new Point(2 * p0.x - pl.x, 2 * p0.y - pl.y);
                conti.push(p1);
                conti = conti.reverse();
                
                tf.appendText(path.length.toString() + "\n");
                /*
                tf.appendText(conti[0].toString());
                tf.appendText(conti[1].toString());
                tf.appendText(conti[2].toString() + "\n");
                */
                
                var start : Number = conti[0].x + step;
                
                for(i = 0;i < 8;i++){
                    conti.unshift(new Point(start + step * i, Math.random() * 450 - 150));
                }
                splines.push({co : calc2D(conti), len : l});
            }
        }
        
        private static function tracePath(bmd : BitmapData, x : int, y : int) : Array
        {
            var pp : Point = new Point(x, y);
            var ret : Array = [pp];
            while(true){
                bmd.setPixel(pp.x, pp.y, 0x000000);
                var p : Point = survive(bmd, pp.x, pp.y);
                if(p == null)break;
                ret.push(p);
                pp = p;
            }
            return ret;
        }
        
        private static function survive(bmd : BitmapData, x : int, y : int) : Point
        {
            if(bmd.getPixel(x - 1, y - 1) != 0x000000)return new Point(x - 1, y - 1);
            if(bmd.getPixel(x - 1, y) != 0x000000)return new Point(x - 1, y);
            if(bmd.getPixel(x - 1, y + 1) != 0x000000)return new Point(x - 1, y + 1);
            if(bmd.getPixel(x, y + 1) != 0x000000)return new Point(x, y + 1);
            if(bmd.getPixel(x + 1, y + 1) != 0x000000)return new Point(x + 1, y + 1);
            if(bmd.getPixel(x + 1, y) != 0x000000)return new Point(x + 1, y);
            if(bmd.getPixel(x + 1, y - 1) != 0x000000)return new Point(x + 1, y - 1);
            if(bmd.getPixel(x, y - 1) != 0x000000)return new Point(x, y - 1);
            return null;
        }
        
        // テキストをBitmapDataに変換
        private static function getTextBitMap(text : String, tfmt : TextFormat) : BitmapData {
            var tf : TextField = new TextField();
            tf.autoSize = TextFieldAutoSize.LEFT;
            tf.defaultTextFormat = tfmt;
            tf.text = text;

            var ret : BitmapData = new BitmapData(tf.width, tf.height, false, 0xffffff);
            ret.draw(tf);
            return ret;
        }
    
        public static function calc2D(a : Array) : Object
        {
            var xs : Vector.<Number> = new Vector.<Number>();
            var ys : Vector.<Number> = new Vector.<Number>();
            for each(var p : Point in a){
                xs.push(p.x);
                ys.push(p.y);
            }
            return {x : Spline.calcCoordinate(xs), y : Spline.calcCoordinate(ys)};
        }
        
        // 微分不可能点のようなものをみつける
        public function findIndifferentiable(path : Array) : Array
        {
            var ret : Array = [];
            var dis : int = 5;
            var prev : int = 0;
            for(var i : int = dis;i < path.length - dis;i++){
                var p0 : Point = path[i - dis];
                var p1 : Point = path[i];
                var p2 : Point = path[i + dis];
                var ip : Number = (p2.x - p1.x) * (p1.x - p0.x) + (p2.y - p1.y) * (p1.y - p0.y);
                ip /= (Point.distance(p0, p1) * Point.distance(p1, p2));
                if(ip < 0.7){
                    ret.push(path.slice(prev, i));
                    prev = i;
                    i++;
                }
            }
            ret.push(path.slice(prev));
            return ret;
        }
    }
}

// @see http://www5d.biglobe.ne.jp/~stssk/maze/spline.html
class Spline {
    public static function calc(cs : Object, t : Number) : Number
    {
        var p : int = t >> 0;
        if(p >= cs.a.length)p--;
        if(p < 0)p = 0;
        var dt : Number = t - p;
        return cs.a[p] + (cs.b[p] + (cs.c[p] + cs.d[p] * dt) * dt) * dt;
    }
    
    public static function calcCoordinate(a : Vector.<Number>) : Object
    {
        var n : int = a.length;

        var b : Vector.<Number> = new Vector.<Number>();
        var c : Vector.<Number> = new Vector.<Number>();
        var d : Vector.<Number> = new Vector.<Number>();
        var w : Vector.<Number> = new Vector.<Number>();

        var i : int;

        c.push(0);
        for(i = 1;i < n - 1;i++){
            c.push(3 * (a[i + 1] - 2 * a[i] + a[i - 1]));
        }
        c.push(0);

        w.push(0);

        for(i = 1;i < n - 1;i++){
            var l : Number = 4.0 - w[i - 1];
            c[i] = (c[i] - c[i - 1]) / l;
            w.push(1.0 / l);
        }
        for(i = n - 2;i > 0;i--){
            c[i] -= c[i + 1] * w[i];
        }


        for(i = 0;i < n - 1;i++){
            d.push((c[i + 1] - c[i]) / 3.0);
            b.push(a[i + 1] - a[i] - c[i] - d[i]);
        }
        b.push(0);
        d.push(0);
            
        return {a : a, b : b, c : c, d : d};
    }
}