タイリング・パターン
/**
* Copyright Aquioux ( http://wonderfl.net/user/Aquioux )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/si4b
*/
package {
//import aquioux.display.colorUtil.CycleRGB;
import com.bit101.components.HSlider;
import com.bit101.components.HUISlider;
import com.bit101.components.PushButton;
import com.bit101.components.UISlider;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
[SWF(width = "465", height = "465", frameRate = "60", backgroundColor = "#F0F0F0")]
/**
* タイリング・パターン
* z = b * (sin(x * a) + sin(y * a)) >> 0;
* if (z % c = 0) dotPlot;
*
* @see http://aquioux.net/blog/?p=1835
* @see 「コンピュータ・カオス・フラクタル―見えない世界のグラフィックス」クリフォード・A・ピックオーバー著 白揚社 P317より
* http://www.amazon.co.jp/gp/product/482690052X/ref=as_li_tf_tl?ie=UTF8&tag=laxcomplex-22
* @author Aquioux(Yoshida, Akio)
*/
public class Main extends Sprite {
// Calculator で必要とする変数
private const KEYS:Array = ["a", "b", "c"];
// プリセットパターン
private const VALUES:Array = [
// a の値, b の値, c の値
11, 10, 16,
12, 10, 5,
75, 35, 18,
111, 25, 2,
121, 54, 20,
133, 10, 7,
142, 50, 10,
168, 17, 8,
179, 18, 2
];
// スライダー
private var sliders_:Dictionary;
private const SLIDER_PARAMS:Array = [
10, 200, 88, // slider a の最小値, a の最小値, a の初期値
10, 100, 62, // slider b 〃
2, 25, 2 // slider c 〃
];
// ボタン
private var buttons_:Dictionary;
private const DELIMITTER:String = " ";
// 描画計算
private var calculator_:Calculator;
// 表示
private var viewer_:Bitmap;
// 描画色用変数
private var angle:Number = 0;
// 各種定数
private var OFFSET_X:uint = 40;
private var W:int = stage.stageWidth - OFFSET_X * 2;
private var H:int = stage.stageHeight - OFFSET_X * 2;
private const RECT:Rectangle = new Rectangle(0, 0, W, H);
public function Main():void {
// スライダー
sliders_ = new Dictionary();
var sliderWidth:int = stage.stageWidth;
var sliderHeight:int = 15;
var sliderX:int = 10;
var len:int = KEYS.length;
for (var i:int = 0; i < len; i++) {
var label:String = KEYS[i];
var slider:HUISlider = new HUISlider(this, sliderX, sliderHeight * i, label, sliderHandler);
slider.width = sliderWidth;
slider.height = sliderHeight;
slider.labelPrecision = 0;
slider.setSliderParams(SLIDER_PARAMS[i * 3], SLIDER_PARAMS[i * 3 + 1], SLIDER_PARAMS[i * 3 + 2]);
sliders_[label] = slider;
}
// 表示
viewer_ = new Bitmap(new BitmapData(W, H, false, 0x0));
viewer_.x = OFFSET_X;
viewer_.y = sliderHeight * 3.5 >> 0;
addChild(viewer_);
// ボタン
buttons_ = new Dictionary();
var buttonWidth:Number = 51.5;
var buttonHeight:int = 20;
var buttonY:int = stage.stageHeight - buttonHeight;
var numOfButtons:int = VALUES.length / 3;
for (var j:int = 0; j < numOfButtons; j++) {
var button:PushButton = new PushButton(this, buttonWidth * j, buttonY, "pattern" +DELIMITTER + String(j + 1), buttonHandler);
button.width = buttonWidth;
buttons_[j] = button;
}
// 描画計算
calculator_ = new Calculator(RECT);
// calclator の各変数を初期値する
for each (var item:* in sliders_) {
slider = HUISlider(item);
label = slider.label;
calculator_[label] = slider.value;
}
// 最初の描画
draw();
}
// スライダーハンドラ
private function sliderHandler(e:Event):void {
var slider:HUISlider = HUISlider(e.target);
var label:String = slider.label;
calculator_[label] = (label=="c") ? slider.value >> 0 : slider.value;
draw();
}
// ボタンハンドラ
private function buttonHandler(e:MouseEvent):void {
var button:PushButton = PushButton(e.target);
var label:String = button.label.split(DELIMITTER)[1];
var idx:int = int(label) - 1;
var degree:int = KEYS.length;
calculator_.a = sliders_["a"].value = VALUES[idx * degree];
calculator_.b = sliders_["b"].value = VALUES[idx * degree + 1];
calculator_.c = sliders_["c"].value = VALUES[idx * degree + 2];
draw();
}
// Viewer に描画
private function draw():void {
angle += 5;
angle % 360;
calculator_.color = CycleRGB.getColor(angle);
calculator_.update();
viewer_.bitmapData.setVector(RECT, calculator_.data);
}
}
}
//package {
import flash.geom.Rectangle;
/**
* タイリングパターン描画計算
* @author YOSHIDA, Akio (Aquioux)
*/
/*public*/ class Calculator {
// タイリングパターン計算用変数
public function set a(value:Number):void { _a = value; }
private var _a:Number;
public function set b(value:Number):void { _b = value; }
private var _b:Number;
public function set c(value:Number):void { _c = value; }
private var _c:Number;
// 計算結果データ
public function get data():Vector.<uint> { return data_; }
private var data_:Vector.<uint>;
// 描画色
public function set color(value:uint):void { _color = value; }
private var _color:uint;
// 描画領域
private var width_:int; // 幅
private var height_:int; // 高
// 地色
private var BG_COLOR:uint = 0x000000;
public function Calculator(rect:Rectangle) {
width_ = rect.width;
height_ = rect.height;
data_ = new Vector.<uint>(width_ * height_, true);
}
public function update():void {
for (var y:int = 0; y < height_; y++) {
for (var x:int = 0; x < width_; x++) {
var c:int = _b * (Math.sin(x * _a) + Math.sin(y * _a)) >> 0;
data[width_ * y + x] = (c % _c == 0) ? _color : BG_COLOR;
}
}
}
}
//}
//package aquioux.display.colorUtil {
/**
* コサインカーブで色相環的な RGB を計算
* @author Aquioux(YOSHIDA, Akio)
*/
/*public*/ class CycleRGB {
/**
* 32bit カラーのためのアルファ値(0~255)
*/
static public function get alpha():uint { return _alpha; }
static public function set alpha(value:uint):void {
_alpha = (value > 0xFF) ? 0xFF : value;
}
private static var _alpha:uint = 0xFF;
private static const PI:Number = Math.PI; // 円周率
private static const DEGREE120:Number = PI * 2 / 3; // 120度(弧度法形式)
/**
* 角度に応じた RGB を得る
* @param angle HSV のように角度(度数法)を指定
* @return 色(0xNNNNNN)
*/
public static function getColor(angle:Number):uint {
var radian:Number = angle * PI / 180;
var r:uint = (Math.cos(radian) + 1) * 0xFF >> 1;
var g:uint = (Math.cos(radian + DEGREE120) + 1) * 0xFF >> 1;
var b:uint = (Math.cos(radian - DEGREE120) + 1) * 0xFF >> 1;
return r << 16 | g << 8 | b;
}
/**
* 角度に応じた RGB を得る(32bit カラー)
* @param angle HSV のように角度(度数法)を指定
* @return 色(0xNNNNNNNN)
*/
public static function getColor32(angle:Number):uint {
return _alpha << 24 | getColor(angle);
}
}
//}