フラクタル曲線のコントロール

by gaziya
赤いポイントをドラックすると、フラクタル曲線のパターンを変えられる。
まだマウスイベント周辺の操作が理解できてません。
♥0 | Line 183 | Modified 2011-11-07 23:04:04 | MIT License
play

ActionScript3 source code

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

package {    
    import flash.text.TextField
    import flash.display.Sprite
    import flash.geom.Point
    import flash.events.Event
    import flash.events.MouseEvent
    import flash.utils.setInterval
    [SWF(width=465,height=465,frameRate=30)]
    
    public class FlashTest extends Sprite {
        public function FlashTest() {
            var cornarPoints:Vector.<Point> = new Vector.<Point>()
            cornarPoints.push(new Point(1/3,0))
            cornarPoints.push(new Point(1/2,-Math.sqrt(3) / 6))
            cornarPoints.push(new Point(2/3,0))
            
            var koch:KochShape = new KochShape(cornarPoints)
            koch.x = stage.stageWidth/2
            koch.y = stage.stageHeight/2
            koch.mouseChildren = false
            addChild(koch)
            setInterval(function():void {koch.update()},800)
            
            var lineLength:int = 250
            var lineOffset:Point = new Point(Math.round((stage.stageWidth - lineLength)/2),Math.round(stage.stageHeight/2))
            var kochLine:Sprite = new Sprite
            kochLine.mouseChildren = false
            addChild(kochLine)
            
            var points:Vector.<Sprite> = new Vector.<Sprite>()
            var textXs:Vector.<TextField> = new Vector.<TextField>()
            var textYs:Vector.<TextField> = new Vector.<TextField>()
            for (var i:int = 0; i < cornarPoints.length; i++) {
                points.push(new Sprite)
                points[i].buttonMode = true
                points[i].graphics.beginFill(0xFF0000)
                points[i].graphics.drawCircle(0,0,6)                
                points[i].x = lineLength*cornarPoints[i].x + lineOffset.x
                points[i].y = lineOffset.y - lineLength*cornarPoints[i].y                   
                addChild(points[i])
                textXs.push(new TextField)
                textXs[i].autoSize = "left"
                textXs[i].textColor = 0xFF0000
                addChild(textXs[i])
                textYs.push(new TextField)
                textYs[i].autoSize = "left"
                textYs[i].textColor = 0xFF0000
                addChild(textYs[i])                
            }
            update()                  
                    
            stage.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void
            {
                if (e.target == points[0] || e.target == points[1] || e.target == points[2]) e.target.startDrag();
                stage.addEventListener(Event.ENTER_FRAME, update)
            })
            
            stage.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void {
                e.target.stopDrag()                
                stage.removeEventListener(Event.ENTER_FRAME, update)
                koch.setCornarPoints(cornarPoints)                
            }) 
            
            function update():void{
               kochLine.graphics.clear()
               kochLine.graphics.lineStyle(2,0xff0000)
               kochLine.graphics.moveTo(lineOffset.x, lineOffset.y)
               for (var i:int = 0; i < cornarPoints.length; i++) {
                   cornarPoints[i].x = (points[i].x - lineOffset.x) / lineLength
                   cornarPoints[i].y = -(points[i].y - lineOffset.y) / lineLength
                   kochLine.graphics.lineTo(points[i].x,points[i].y)
                   if (cornarPoints[i].x < 0) {
                       textXs[i].htmlText = "<font size='+10'>x = -0."+Math.round(-cornarPoints[i].x*100).toString()+"</font>"
                   }else{
                       textXs[i].htmlText = "<font size='+10'>x = 0."+Math.round(cornarPoints[i].x*100).toString()+"</font>"
                   }
                   textXs[i].x = points[i].x - 20
                   textXs[i].y = points[i].y
                   if (cornarPoints[i].y < 0) {
                       textYs[i].htmlText = "<font size='+10'>y = -0."+Math.round(-cornarPoints[i].y*100).toString()+"</font>"
                   }else{
                       textYs[i].htmlText = "<font size='+10'>y = 0."+Math.round(cornarPoints[i].y*100).toString()+"</font>"
                   }
                   textYs[i].x = points[i].x - 20
                   textYs[i].y = points[i].y + 20               
                }
                kochLine.graphics.lineTo(lineOffset.x+lineLength, lineOffset.y)                
            }            
        }
    }
}


import flash.display.Sprite
import flash.geom.Point
import flash.geom.Matrix

class KochShape extends Sprite {
    private var _radius:int = 150
    private var _pointBlocks:Array
    private var _idx:int = 2
    
    public function KochShape(cornarPoints:Vector.<Point>) {
        setCornarPoints(cornarPoints)
    }
    
    public function setCornarPoints(cornarPoints:Vector.<Point>):void {
        _pointBlocks = new Array
        var koch:Koch = new Koch(_radius)
        koch.setCornarPoints(cornarPoints)
        for (var i:int=3; i<6; i++) {           
            var polygon:RegularPolygon = new RegularPolygon(_radius)
            _pointBlocks.push(koch.shapePoints(polygon.points(i)))            
        }
        update()
    }
    
    public function update():void {
        graphics.clear()
        graphics.lineStyle(2,0x000000)
        graphics.beginFill(0x00c080)
        var points:Vector.<Point> = _pointBlocks[_idx]
        for(var i:int=0; i < points.length;i++){
            if (i==0){
                graphics.moveTo(points[i].x, points[i].y)
            }else{
                graphics.lineTo(points[i].x, points[i].y)                    
            }                
        }
        rotationX = (Math.random()-0.5)*90
        rotationY = (Math.random()-0.5)*90
        rotationZ = (Math.random()-0.5)*90        
        _idx++
        if (_idx > 2) _idx = 0        
    }
}


class Koch {
    private var _recursion:int = 4
    private var _radius:int
    private var _rate:Vector.<Number>, _theta:Vector.<Number>
    
    public function Koch(radius:int) {
        _radius = radius 
     }
     
     public function shapePoints(points:Vector.<Point>):Vector.<Point> {
         for (var i:int=0; i<_recursion; i++) {
             points = growPoints(points)
         }
         return points
     }
     
     public function setCornarPoints(cornarPoints:Vector.<Point>):void { 
         _rate = new Vector.<Number>
         _theta = new Vector.<Number>
         for each(var value:Point in cornarPoints){             
             _rate.push(Math.sqrt(value.x*value.x+value.y*value.y))            
             _theta.push(Math.atan2(value.y,value.x))
        }     
     }

     private function growPoints(points:Vector.<Point>):Vector.<Point> {         
        var bp:Point = null
        var ep:Point = null        
        var buf:Vector.<Point> = new Vector.<Point>()
        for each(var value:Point in points){
            bp = ep
            ep = value
            if (bp != null) {
                for (var i:int = 0; i < 3; i++) {
                    var matrix:Matrix = new Matrix()
                    matrix.translate(-bp.x,-bp.y)
                    matrix.scale(_rate[i], _rate[i])
                    matrix.rotate(_theta[i])
                    matrix.translate(bp.x,bp.y)
                    buf.push(matrix.transformPoint(ep))                      
                }
            }
            buf.push(ep)
        }
        return buf
    }       
}


class RegularPolygon {
    public var _radius:int
    
    public function RegularPolygon(radius:int) {
        _radius = radius      
    }
    
    public function points(cornar:int):Vector.<Point> {
        var buf:Vector.<Point> = new Vector.<Point>()        
        var theta:Number = Math.PI / 2
        var step:Number = Math.PI * 2 /cornar        
        for (var i:int; i < cornar; i++) {
            buf.push(new Point(_radius * Math.cos(theta), -_radius * Math.sin(theta)))
            theta += step
        }        
        buf.push(buf[0])        
        return buf
    }
}