spline1
昔NHKのどっかの番組で見たやつ
別に不変じゃなくてもいいのは小文字
// 昔NHKのどっかの番組で見たやつ
// 別に不変じゃなくてもいいのは小文字
package {
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.filters.*;
import flash.geom.*;
[SWF(width=465,height=465,frameRate=30,backgroundColor=0xffffff)]
public class Outliner extends Sprite {
private const N : int = 1000;
private const str : String = "あこるでぃおん"; // 空白文字入れちゃダメデスヨー
private const tfmt : TextFormat = new TextFormat("MS 明朝", 100);
private const step : Number = 0.02;
private const scale : Number = 5;
private var t : Number = -1; // 停止時間を設けるため余裕を持たせてある
private var xcvec : Vector.<Object> = new Vector.<Object>();
private var ycvec : Vector.<Object> = new Vector.<Object>();
public function Outliner() {
var i : int;
var pvec : Vector.<Vector.<Point>> = new Vector.<Vector.<Point>>();
var vec : Vector.<Point>;
var cf : ConvolutionFilter = new ConvolutionFilter(3, 3, [0, -1, 0, -1, 4, -1, 0, -1, 0]);
for(i = 0;i < str.length;i++){
var bmd : BitmapData = getTextBitMap(str.charAt(i), tfmt);
// エッジ抽出
bmd.applyFilter(bmd, bmd.rect, new Point(), cf);
// 輪郭上の点を得る
vec = new Vector.<Point>();
var offset : Point = new Point(stage.stageWidth / 2 - bmd.width / 2, stage.stageHeight / 2 - bmd.height / 2);
while(vec.length < N){
var p : Point = new Point(Math.random() * bmd.width, Math.random() * bmd.height);
if(bmd.getPixel(p.x, p.y) == 0xffffff){
vec.push(p.add(offset));
}
}
pvec.push(vec);
}
// 各点についてB-splineの係数を求めておく
for(i = 0;i < N;i++){
var xvec : Vector.<Number> = new Vector.<Number>();
var yvec : Vector.<Number> = new Vector.<Number>();
for each(vec in pvec){
xvec.push(vec[i].x);
yvec.push(vec[i].y);
}
xcvec.push(Spline.calcCoordinate(xvec));
ycvec.push(Spline.calcCoordinate(yvec));
}
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(e : Event) : void
{
graphics.clear();
graphics.beginFill(0x000000);
graphics.lineStyle(0);
var ut : Number = t;
if(ut < 0)ut = 0;
if(ut > str.length)ut = str.length;
var i : int;
for(i = 0;i < N;i++){
// 補間計算
var x : Number = Spline.calc(xcvec[i], ut);
var y : Number = Spline.calc(ycvec[i], ut);
// 中央に関してscale倍
x = (x - stage.stageWidth / 2) * scale + stage.stageWidth / 2;
y = (y - stage.stageHeight / 2) * scale + stage.stageHeight / 2;
// graphics.drawCircle(x, y, 1);
graphics.drawRect(x - 1, y - 1, 2, 2);
}
graphics.endFill();
t += step;
if(t > str.length + 1)t = -1;
}
private function tr(s : String) : void
{
var tf : TextField = new TextField();
tf.autoSize = TextFieldAutoSize.LEFT;
tf.text = s;
addChild(tf);
}
// テキストを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, true, 0xffffffff);
ret.draw(tf);
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 = Math.floor(t);
if(p >= cs.a.length)p--;
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};
}
}