インボリュート曲線とアルファチャンネルマスク

by tkinjo
インボリュート曲線

さりげなくマスク処理に手間かけてます。
簡単にアルファ値を反転する方法か、
アルファチャンネル以外で特定の部位にマスクをかける方法とかってないですかね?

--- 参考 ---

Wikipedia - インボリュート曲線
http://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%88%E6%9B%B2%E7%B7%9A

...
@author tkinjo
♥0 | Line 99 | Modified 2009-06-14 10:56:00 | MIT License
play

ActionScript3 source code

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

package  
{
	/**
	 * インボリュート曲線
	 * 
	 * さりげなくマスク処理に手間かけてます。
	 * 簡単にアルファ値を反転する方法か、
	 * アルファチャンネル以外で特定の部位にマスクをかける方法とかってないですかね?
	 * 
	 * --- 参考 ---
	 * 
	 * Wikipedia - インボリュート曲線
	 * http://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%88%E6%9B%B2%E7%B7%9A
	 */
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.ColorMatrixFilter;
	import flash.geom.Matrix;
	import flash.geom.Point;
	
	[SWF(width=465,height=465,frameRate=60,backgroundColor=0xeeeeff)]
	/**
	 * ...
	 * @author tkinjo
	 */
	public class Main extends Sprite
	{
		private const speed:Number = 5;
		private const a:Number = 30;
		
		private var canvas:Sprite;
		private var canvasMask:Bitmap;
		private var canvasMaskCanvas:Sprite;
		
		private var draw:Boolean = true;
		private var angle:Number = 0;
		
		
		/**
		 * ラジアン角に対するインボリュート曲線の x 座標を返します。
		 * 
		 * @param	a
		 * @param	radian
		 * @return
		 */
		private function involuteX( radian:Number, a:Number = 1 ):Number {
			
			return a * ( Math.cos( radian) + radian * Math.sin( radian ) );
		}
		
		/**
		 * ラジアン角に対するインボリュート曲線の y 座標を返します。
		 * 
		 * @param	a
		 * @param	radian
		 * @return
		 */
		private function involuteY( radian:Number, a:Number = 1 ):Number {
			
			return a * ( Math.sin( radian ) - radian * Math.cos( radian) );
		}
		
		/**
		 * 以下演出処理
		 */
		
		/**
		 * 
		 */
		public function Main() 
		{
			canvas = new Sprite();
			canvas.x = stage.stageWidth / 2;
			canvas.y = stage.stageHeight / 2;
			canvas.cacheAsBitmap = true;
			canvas.scaleY = -1;
			
			canvasMask = new Bitmap();
			canvasMask.y = stage.stageHeight;
			canvasMask.cacheAsBitmap = true;
			canvasMask.scaleY = -1;
			
			canvasMaskCanvas = new Sprite();
			canvasMaskCanvas.cacheAsBitmap = true;
			
			
			addEventListener( Event.ENTER_FRAME, drawEnterFrameHandler );
			
			addChild( canvas );
			addChild( canvasMask );
		}
		
		private function drawEnterFrameHandler( event:Event ):void {
			
			var radian:Number = angleToRadian( angle );
			
			if ( draw ) {
				
				if ( angle == 0 ) {
					
					canvas.graphics.lineStyle( 1 );
					canvas.graphics.moveTo( 0, 0 );
				}
				
				canvas.graphics.lineTo( involuteX( radian, a ), involuteY( radian, a ) );
				
			} else {
				
				if ( angle == 0 ) {
					
					canvasMaskCanvas.graphics.lineStyle( 3 );
					canvasMaskCanvas.graphics.moveTo( 0, 0 );
					
					canvas.mask = canvasMask;
				}
				
				canvasMaskCanvas.graphics.lineTo( involuteX( radian, a ), involuteY( radian, a ) );
				var bitmapData:BitmapData = new BitmapData( stage.stageWidth, stage.stageHeight, true );
				bitmapData.draw( canvasMaskCanvas, new Matrix( 1, 0, 0, 1, stage.stageWidth / 2, stage.stageHeight / 2 ) );
				bitmapData = inversion( bitmapData );
				bitmapData = brightnessToAlpha( bitmapData );
				canvasMask.bitmapData = bitmapData;
			}
			
			angle += speed;
			
			if ( 360 < angle ) {
				
				if ( !draw ) {
					
					canvas.graphics.clear();
					canvas.mask = null;
					canvasMask.bitmapData = null;
					canvasMaskCanvas.graphics.clear();
				}
				
				angle = 0;
				draw = !draw;
			}
		}
		
		/**
		 * 
		 * @param	angle
		 * @return
		 */
		private function angleToRadian( angle:Number ):Number {
			
			return angle * Math.PI / 180;
		}
		
		/**
		 * 反転
		 * 
		 * @param	bitmapData
		 * @return
		 */
		private function inversion( bitmapData:BitmapData ):BitmapData {
			
			bitmapData.applyFilter( bitmapData, bitmapData.rect, new Point(), new ColorMatrixFilter( [
					-1,         0,         0,            0,            255, 
					0,         -1,         0,            0,            255, 
					0,         0,         -1,         0,            255, 
					0,         0,         0,         1,         0
				] ) );
			
			return bitmapData;
		}
		
		/**
		 * 明度アルファ変換?
		 * 
		 * @param	bitmapData
		 * @return
		 */
		private function brightnessToAlpha( bitmapData:BitmapData ):BitmapData {
			
			bitmapData.applyFilter( bitmapData, bitmapData.rect, new Point(), new ColorMatrixFilter( [
					-1,         0,         0,            0,            0, 
					0,         -1,         0,            0,            0, 
					0,         0,         -1,         0,            0, 
					-0.33,     -0.33,     -0.33,     1,         0
				] ) );
			
			return bitmapData;
		}
	}
	
}