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

test_case09

ref 
Flash Math & Physics Design ActionScript 3.0による数学・物理学表現[実践編]
WaterVoronoiのコードの写経といろいろ実験
Get Adobe Flash player
by h_kamizono 06 Aug 2010

    Talk

    teltelbose at 27 Dec 2010 17:17
    h_kamizonoさんの影響でアカウント取りました。 面白そうなので、久しぶりにプログラムを書きたいと思います。

    Tags

    Embed
/**
 * Copyright h_kamizono ( http://wonderfl.net/user/h_kamizono )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/mnqm
 */

// forked from h_kamizono's test
// ref 
// Flash Math & Physics Design ActionScript 3.0による数学・物理学表現[実践編]
// WaterVoronoiのコードの写経といろいろ実験
package {
    import flash.display.MovieClip;
    import flash.utils.Timer;
    import flash.events.TimerEvent;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    public class WaterVoronoi extends MovieClip {
        private var pt:Array = new Array();
        private var dotNum:Number = 50;
        private var pigment:Number = 0;
        public function WaterVoronoi() {
            // write as3 code here..
            for (var i:Number = 0; i < dotNum; ++i) {
                pt.push(new PhysicalPoint(Math.random()*stage.stageWidth, Math.random()*stage.stageHeight));
            }
            
            var timer:Timer = new Timer(33);
            timer.addEventListener(TimerEvent.TIMER, loop);
            timer.start();
        }
        
        private function loop(event:TimerEvent) :void {
            pt[0].setKasokudo((mouseX - pt[0].x)*10, (mouseY - pt[0].y)*10);
            for (var i:Number = 0; i < pt.length; ++i) {
                for (var j:Number = 0; j < pt.length; ++j) {
                    if (i != j) {
                        var dist:Number = Point.distance(pt[j], pt[i]);
                        dist = Math.max(100 - dist, 0)/100;
                        var dire:Number = Math.atan2(pt[i].y - pt[j].y, pt[i].x - pt[j].x);
                        pt[i].setKasokudoByPolar(dist*2000, dire);
                    }
                }
                
                if (pt[i].x < 50) pt[i].setKasokudo(500, 0);
                if (pt[i].y < 50) pt[i].setKasokudo(0, 500);
                if (pt[i].x > stage.stageWidth - 50) pt[i].setKasokudo(-500, 0);
                if (pt[i].y > stage.stageHeight - 50) pt[i].setKasokudo(0, -500);
                
            }
            // Rectangleは画面の大きさ
            var areas:Array = Functions.getVoronoiAreas(pt, new Rectangle(0, 0, 
                              stage.stageWidth, stage.stageHeight));
            if (areas != null) {
                for (var m:Number = 0; m < areas.length; ++m) {
                    var cen:Point = Functions.getCentroid(areas[m]);
                    if (cen != null) {
                        for (var n:Number = 0; n < areas[m].length; ++n) {
                            areas[m][n].x += (cen.x - areas[m][n].x)*0.05;
                            areas[m][n].y += (cen.y - areas[m][n].y)*0.05;
                        }
                    }
                }
            }
            this.graphics.clear();
            pigment++;
            var col:uint = Functions.hsbToRgb(pigment, 1, 1);
            
            if (areas != null) {
                for (var k:Number = 0; k < areas.length; ++k) {
                    if (k == 0) {
                        this.graphics.lineStyle(2, 0x000000);
                        Functions.fillRing(areas[0], this, 0x000000);
                    } else {
                        this.graphics.lineStyle(2, 0x888888);
                        Functions.fillRing(areas[k], this, col);
                    }
                }

            }


        }

    }
}
import flash.geom.Rectangle;
import flash.display.Sprite;


class Functions {
    public static function hsbToRgb(h:Number,
                                    s:Number,
                                    b:Number) :uint {
        while (h < 0) {
            h+=360;
        }
        while (h >= 360) {
            h -= 360;
        }
        var h2:Number = Math.floor(h/60);
        var f:Number = h/60 - h2;
        var parFull:Number = 255;
        var parEmp:Number = 0;
        var parZoka:Number = 255*f;
        var parGensho:Number = 255*(1-f);
        var red:Number = 0;
        var green:Number = 0;
        var blue:Number = 0;
        
        switch (h2) {
          case 0:
            red = parFull; green = parZoka; blue = parEmp;
            break;
          case 1:
            red = parGensho; green = parFull; blue = parEmp;
            break;
          case 2:
            red = parEmp; green = parFull; blue = parZoka;
            break;
          case 3:
            red = parEmp; green = parGensho; blue = parFull;
            break;
          case 4:
            red = parZoka; green = parEmp; blue = parFull;
            break;
          case 5:
            red = parFull; green = parEmp; blue = parGensho;
            break;
        }
        var max:Number = Math.max(Math.max(red, green), blue);
        red = max - (max - red)*s;
        green = max - (max - green)*s;
        blue = max - (max - blue)*s;
        red *= b; green *= b; blue *= b;
        var ret:uint = int(red) << 16 | int(green) << 8 | int(blue);
        return ret; 
    }
    
    
    public static function getCentroid(pt:Array) :Point {
        if (pt != null) {
            if (pt.length == 0) {
                return new Point(0, 0);
            } else if (pt.length == 1) {
                return new Point(pt[0].x, pt[0].y);
            } else if (pt.length == 2) {
                return new Point((pt[0].x + pt[1].x)/2, (pt[0].y + pt[1].y)/2);
            } else {
                var ptSize:Number = pt.length;
                // area
                var s:Number = pt[0].x * (pt[1].y - pt[ptSize-1].y);
                // centroid
                var gx:Number = pt[0].y * (pt[ptSize-1].x - pt[1].x) * (pt[ptSize-1].x + pt[0].x + pt[1].x);
                var gy:Number = -pt[0].x * (pt[ptSize-1].y - pt[1].y) * (pt[ptSize-1].y + pt[0].y + pt[1].y);
                  
                for (var i:Number = 1; i < ptSize - 1; ++i) {
                    s += pt[i].x * (pt[i+1].y - pt[i-1].y);
                    
                    gx += pt[i].y * (pt[i-1].x - pt[i+1].x) * (pt[i-1].x + pt[i].x + pt[i+1].x);
                    gy += -pt[i].x * (pt[i-1].y - pt[i+1].y) * (pt[i-1].y + pt[i].y + pt[i+1].y);
                }
                s += pt[ptSize - 1].x * (pt[0].y - pt[ptSize - 2].y);
                s /= 2;
                
                gx += pt[ptSize-1].y * (pt[ptSize-2].x - pt[0].x) * (pt[ptSize-2].x + pt[ptSize-1].x + pt[0].x);
                gy += -pt[ptSize-1].x * (pt[ptSize-2].y - pt[0].y) * (pt[ptSize-2].y + pt[ptSize-1].y + pt[0].y);
                
                gx /= s*6; gy /= s*6;
                return new Point(gx, gy);
            }
        } else {
            return null;
        }
    }
    
    public static function fillRing(pt:Array, sp:Sprite, 
                                    col:uint = 0x000000, al:Number = 1) :void {
        if (pt.length >= 3) {
            sp.graphics.moveTo((pt[pt.length-1].x + pt[0].x)/2,
                                (pt[pt.length-1].y + pt[0].y)/2);
            sp.graphics.beginFill(col, al);
            for (var i:Number = 0; i < pt.length; ++i) {
                sp.graphics.curveTo(pt[i].x, pt[i].y,
                                    (pt[i].x + pt[(i+1)%pt.length].x)/2, (pt[i].y + pt[(i+1)%pt.length].y)/2);
            }
            sp.graphics.endFill();
        }
    }
    
    public static function drawPolygon(pt:Array, sp:Sprite) :void {
        if (pt.length >= 3) {
            sp.graphics.moveTo(pt[0].x, pt[0].y);
            for (var i:Number = 0; i < pt.length; ++i) {
                sp.graphics.lineTo(pt[i].x, pt[i].y);
            }
            sp.graphics.lineTo(pt[0].x, pt[0].y);
        }
    }
    
    public static function drawCircle(pt:Array, sp:Sprite,
                                      col:uint = 0x000000, al:Number = 1) :void {
        if (pt.length >= 3) {
            sp.graphics.beginFill(col, al);
            for (var i:Number = 0; i < pt.length; ++i) {
                //sp.graphics.lineTo(pt[i].x, pt[i].y);
                sp.graphics.drawCircle(pt[i].x, pt[i].y, 1);
            }
            //sp.graphics.lineTo(pt[0].x, pt[0].y);
            sp.graphics.endFill();
        }
    }
    
    public static function outerProduct(p0:Point, p1:Point, pt:Point) :Number {
        var ret:Number;
        var ax:Number = pt.x - p0.x; 
        var ay:Number = pt.y - p0.y;
        var bx:Number = p1.x - p0.x;
        var by:Number = p1.y - p0.y;
        // Z値だけ返す、p0-p1よりp0-ptが左ならminus,右ならplus
        ret = ax*by - bx*ay;
        return ret;
    }
    
    public static function perpendicularBisector(p0:Point, p1:Point) :Array {
        var ret:Array = new Array();
        if (p0 != null && p1 != null) {
            if (p0.y == p1.y) {
                ret.push((p0.x + p1.x)/2);
                return ret;
            } else {
                var slant:Number = -(p1.x - p0.x) / (p1.y - p0.y);
                //var cp:Point = new Point((p0.x + p1.x)/2 , (p0.y + p1.y)/2);
                //var y:Number = cp.y - slant*cp.x;
                
                var y:Number =  (p0.y + p1.y) - slant*(p0.x + p1.x);
                y >>= 1;
                
                ret.push(slant); ret.push(y);
                return ret;
            }
        }
        return null;        
    }
    
    public static function calcIntersectionPoint(p0:Point, p1:Point, line:Array) :Point {
        if (line != null) {
            if (line.length == 1) {
                if (p0.x == p1.x) {
                    if (p0.y == p1.y && line[0] == p0.x) {
                        return new Point(p0.x, p0.y);
                    } else {
                        return null;
                    }
                } else {
                    var slant:Number = (p1.y - p0.y) / (p1.x - p0.x);
                    var y:Number = p0.y - slant*p0.x;
                    var ix:Number = line[0];
                    var iy:Number = slant*ix + y;
                    if (iy <= Math.max(p0.y, p1.y) && iy >= Math.min(p0.y, p1.y)) {
                        return new Point(ix, iy);
                    } else {
                        return null;
                    }
                }
            } else {
                if (p0.x == p1.x) {
                    var jx:Number = p0.x; var jy:Number = line[0]*jx + line[1];
                    if (jy <= Math.max(p0.y, p1.y) && jy >= Math.min(p0.y, p1.y)) {
                        return new Point(jx, jy);
                    } else {
                        return null;
                    }
                } else {
                    var slant2:Number = (p1.y - p0.y) / (p1.x - p0.x);
                    var y2:Number = p0.y - slant2*p0.x;
                    //
                    if (slant2 == line[0]) {
                        return null;
                    } else {
                        var kx:Number = (line[1] - y2) / (slant2 - line[0]);
                        var ky:Number = slant2*kx + y2;
                        
                        if (kx <= Math.max(p0.x, p1.x) && kx >= Math.min(p0.x, p1.x)) {
                            return new Point(kx, ky);
                        } else {
                            return null;
                        }
                    }
                }
            }
        }
        return null;
    }

    public static function getVoronoiAreas(pt:Array, rect:Rectangle) :Array{
        for (var i:Number = 0; i < pt.length; ++i) {
            if (pt[i] is Point) {
            } else {
                return null;
            }
        }
        var ret:Array = new Array();
        for (var j:Number = 0; j < pt.length; ++j) {
            ret.push(new Array());
            ret[ret.length - 1].push(new Point(rect.left, rect.top));
            ret[ret.length - 1].push(new Point(rect.right, rect.top));
            ret[ret.length - 1].push(new Point(rect.right, rect.bottom));
            ret[ret.length - 1].push(new Point(rect.left, rect.bottom));
        }
        for (var m:Number = 0; m < pt.length; ++m) {
            for (var n:Number = 0; n < pt.length; ++n) {
                if (m != n) {
                    var p:Array = perpendicularBisector(pt[m], pt[n]);
                    var counter:Number = 0;
                    var isPt:Array = new Array();
                    var startPtNum:Array = new Array();
                    for (var k:Number = 0; k < ret[m].length; ++k) {
                        var pp:Point = calcIntersectionPoint(ret[m][k], ret[m][(k+1)%(ret[m].length)], p);
                        if (pp != null) {
                            ++counter;
                            isPt.push(pp);
                            startPtNum.push(k);
                        }
                    }
                    if (counter == 2) {
                        var temp0:Array = ret[m].slice(0, startPtNum[0] + 1);
                        var temp1:Array = ret[m].slice(startPtNum[0] + 1, startPtNum[1] + 1);
                        var temp2:Array = ret[m].slice(startPtNum[1] + 1);
                        var temp:Array;
                        var g1:Number; var g2:Number;
                        
                        if (temp0 != null) {
                            if (temp0.length > 0) {
                                g1 = outerProduct(isPt[0], isPt[1], temp0[0]);
                                g2 = outerProduct(isPt[0], isPt[1], pt[m]);
                                if (g1*g2 >= 0) {
                                    temp = temp0.concat([isPt[0]]);
                                } else {
                                    temp = [isPt[0]];
                                }
                            }
                        }
                        
                        if (temp1 != null) {
                            if (temp1.length > 0) {
                                g1 = outerProduct(isPt[0], isPt[1], temp1[0]);
                                g2 = outerProduct(isPt[0], isPt[1], pt[m]);
                                if (g1*g2 >= 0) {
                                    temp = temp.concat(temp1, [isPt[1]]);
                                } else {
                                    temp = temp.concat([isPt[1]]);
                                }
                            }
                        }
                        
                        if (temp2 != null) {
                            if (temp2.length > 0) {
                                g1 = outerProduct(isPt[0], isPt[1], temp2[0]);
                                g2 = outerProduct(isPt[0], isPt[1], pt[m]);
                                if (g1*g2 >= 0) {
                                    temp = temp.concat(temp2);
                                } 
                            }
                        }
                        ret[m] = temp;
                    }
                }

            }
        }
        return ret;
    }

}
 

import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.geom.Point;
import flash.utils.Timer;
class PhysicalPoint extends Point {
    private var vx:Number, vy:Number;
    private var ax:Number, ay:Number;
    private var b:Number;
    private var preTime:Number;
    private var timer:Timer;
    
    private var preX:Number, preY:Number;
    
    public var kb:Number;
    public var angle:Number;
    public var preAngle:Number;
    public var kakusokudo:Number;
    public var kakukasokudo:Number;
    
    private var limitter:Number = 0.3;
    
    function PhysicalPoint(xx: Number = 0, yy:Number = 0, an:Number = 0) {
        x = xx; y = yy;
        preX = xx; preY = yy;
        b = 0.9;
        vx = 0; vy = 0;
        ax = 0; ay = 0;
        
        angle = an;
        preAngle = an;
        kb = 0.9;
        kakusokudo = 0;
        kakukasokudo = 0;
        
        preTime = new Date().getTime();
        timer = new Timer(33);
        timer.addEventListener(TimerEvent.TIMER, loop);
        timer.start();
        
    }
    
    public function loop(event:TimerEvent) :void {
        var nowTime:Number = new Date().getTime();
        var t:Number = (nowTime - preTime)/1000;
        
        if (t > limitter) t = limitter;
        
        preX = x;
        preY = y;
        
        x += (vx + 0.5*ax*t)*t;
        y += (vy + 0.5*ay*t)*t;
        
        vx += ax*t; vy += ay*t;
        vx *= b;    vy *= b;
        ax = 0;     ay = 0;
        preAngle = angle;
        angle += (kakusokudo + 0.5*kakukasokudo*t) *t;
        kakusokudo += kakukasokudo*t;
        
        kakusokudo *= kb;
        kakukasokudo = 0;
        preTime = nowTime;
    }
    
    public function setKasokudo(aax:Number = 0, aay:Number = 0) :void {
        ax += aax;
        ay += aay;
    }
    
    public function setKasokudoByPolar(r:Number=0, dire:Number = 0) :void {
        ax += r*Math.cos(dire);
        ay += r*Math.sin(dire);
    }
    
    public function setKakuKasokudo(aan:Number = 0) :void {
        kakukasokudo += aan;
    }
    
    public function setKakuKasokudo2(dire:Number, val:Number) :void {
        var aan:Number = val * Math.sin(dire - angle);
        setKakuKasokudo(aan);
    }

}