Colorsクラス

ちょっとは実際に使えるクラス
画像は上がColorsクラスを使って色補完したもの
下がFlashに元々あるColor.interpolateColor()を使って色補完したもの
Flashに元々あるColor.interpolateColor()を使って色補完すると
鮮やかな色同士でも補完は濁ったカンジの色になりますが
このColorsクラスは一度色をHSBに解釈してから色補完をするため
鮮やかな色同士の補完は鮮やかな色で補完します
/*
■使い方
色数値の配列のクラスです
配列の数を伸縮したり、中間値を取得するメソッドの他に
色数値の配列を生成するstaticなメソッドを持ちます
■パブリックプロパティ
■パブリックメソッド
expand(新しい要素数)
divide(分割数)
getValueAt(位置)
fromArray(数配列)
fromHSB(H配列、S配列、B配列)
interpolate(数配列1、数配列2、進捗)
linear(開始値、終了値、要素数)
ease(開始値、終了値、要素数、イージング)
rough(開始値、終了値、要素数、ランダム幅)
*/
package simplizer.graphic{
public dynamic class Colors extends Array{
public function Colors(...args) {
super()
for each(var item in args){
this.push(item)
}
}
public function expand(newLen:uint){
var Hlist:Numbers=new Numbers()
var Slist:Numbers=new Numbers()
var Blist:Numbers=new Numbers()
for(var i=0;i<this.length;i++){
var hsb:Object=Calc.RGBtoHSB(this[i])
Hlist.push(hsb.H)
Slist.push(hsb.S)
Blist.push(hsb.B)
}
for(i=1;i<Hlist.length;i++){
while(Hlist[i]-Hlist[i-1]>180)Hlist[i]-=360
while(Hlist[i]-Hlist[i-1]<-180)Hlist[i]+=360
}
Hlist=Hlist.expand(newLen)
Slist=Slist.expand(newLen)
Blist=Blist.expand(newLen)
var rtn:Colors=new Colors()
for(i=0;i<newLen;i++){
rtn.push(Calc.HSBtoRGB(Hlist[i]%360,Slist[i],Blist[i]))
}
return rtn
}
public function divide(div:uint){
var Hlist:Numbers=new Numbers()
var Slist:Numbers=new Numbers()
var Blist:Numbers=new Numbers()
for(var i=0;i<this.length;i++){
var hsb:Object=Calc.RGBtoHSB(this[i])
Hlist.push(hsb.H)
Slist.push(hsb.S)
Blist.push(hsb.B)
}
for(i=1;i<Hlist.length;i++){
while(Hlist[i]-Hlist[i-1]>180)Hlist[i]-=360
while(Hlist[i]-Hlist[i-1]<-180)Hlist[i]+=360
}
Hlist=Hlist.divide(div)
Slist=Slist.divide(div)
Blist=Blist.divide(div)
var rtn:Colors=new Colors()
for(i=0;i<Hlist.length;i++){
rtn.push(Calc.HSBtoRGB(Hlist[i]%360,Slist[i],Blist[i]))
}
return rtn
}
public function getValueAt(t:Number){
var Hlist:Numbers=new Numbers()
var Slist:Numbers=new Numbers()
var Blist:Numbers=new Numbers()
for(var i=0;i<this.length;i++){
var hsb:Object=Calc.RGBtoHSB(this[i])
Hlist.push(hsb.H)
Slist.push(hsb.S)
Blist.push(hsb.B)
}
for(i=1;i<Hlist.length;i++){
while(Hlist[i]-Hlist[i-1]>180)Hlist[i]-=360
while(Hlist[i]-Hlist[i-1]<-180)Hlist[i]+=360
}
return Calc.HSBtoRGB(Hlist.getValueAt(t)%360,Slist.getValueAt(t),Blist.getValueAt(t))
}
public static function fromArray(arr:Array):Colors{
var rtn:Colors=new Colors()
for each(var item in arr){
rtn.push(item)
}
return rtn
}
public static function fromHSB(Hlist:Array,Slist:Array,Blist:Array):Colors{
var rtn:Colors=new Colors()
Hlist=Numbers.fromArray(Hlist)
Slist=Numbers.fromArray(Slist)
Blist=Numbers.fromArray(Blist)
var len=Calc.getComMul(Calc.getComMul(Hlist.length,Slist.length),Blist.length)
for(var i=1;i<Hlist.length;i++){
while(Hlist[i]-Hlist[i-1]>180)Hlist[i]-=360
while(Hlist[i]-Hlist[i-1]<-180)Hlist[i]+=360
}
Hlist=Hlist.expand(len)
Slist=Slist.expand(len)
Blist=Blist.expand(len)
for(i=0;i<len;i++){
rtn.push(Calc.HSBtoRGB(Hlist[i],Slist[i],Blist[i]))
}
return rtn
}
public static function interpolate(clrs1:Array,clrs2:Array,prog:Number=0.5):Colors{
var rtn:Colors=new Colors()
var tmp:Colors=new Colors(0,0)
for(var i=0;i<Math.min(clrs1.length,clrs2.length);i++){
tmp[0]=clrs1[i]
tmp[1]=clrs2[i]
rtn.push(tmp.getValueAt(prog))
}
return rtn
}
public static function linear(startVal:Number,endVal:Number,len:uint):Colors{
var rtn:Colors=new Colors()
var tmp:Colors=new Colors(startVal,endVal)
for(var i=0;i<len;i++){
rtn.push(tmp.getValueAt(i/(len-1)))
}
return rtn
}
public static function ease(startVal:Number,endVal:Number,len:uint,ease:Number):Colors{
var rtn:Colors=new Colors()
var tmp:Colors=new Colors(startVal,endVal)
for(var i=0;i<len;i++){
rtn.push(tmp.getValueAt(Calc.getBezVal(i/(len-1),[0,1/2+ease/200,1])))
}
return rtn
}
public static function rough(startVal:Number,endVal:Number,len:uint,w:Number):Colors{
var rtn:Colors=new Colors()
var tmp:Colors=new Colors(startVal,endVal)
for(var i=0;i<len;i++){
rtn.push(tmp.getValueAt(i/(len-1)))
for each(var item in [0xFF0000,0xFF00,0xFF]){
rtn[i]+=Math.max(Math.min(((w*Math.random()-w/2)*item/0xFF)%item,item-rtn[i]%item),-rtn[i]%item)
}
}
return rtn
}
}
}
これもCalcクラスが一緒にいるのが前提のクラスです
Numbersクラス
まだまだ下準備的なクラス
これもcore.mathにいれとけよってようなクラス
easeメソッドでCalcクラスが少しだけ登場
自分で言うのもなんですが、このクラスは要するに数の配列にすぎない
というシンプルなクラスな分結構使い道が広いと思います
とくにgraphics.beginGradientFill()とかでは役に立つんじゃないでしょうか
これもcore.mathにいれとけよってようなクラス
/*
■使い方
数値の配列のクラスです
配列の数を伸縮したり、中間値を取得するメソッドの他に
数値の配列を生成するstaticなメソッドを持ちます
■パブリックプロパティ
■パブリックメソッド
expand(新しい要素数)
divide(分割数)
getValueAt(位置)
fromArray(数配列)
interpolate(数配列1、数配列2、進捗)
linear(開始値、終了値、要素数)
ease(開始値、終了値、要素数、イージング)
rough(開始値、終了値、要素数、ランダム幅)
*/
package simplizer.graphic{
public dynamic class Numbers extends Array{
public function Numbers(...args) {
super()
for each(var item in args){
push(item)
}
}
public function expand(newLen:uint){
var rtn:Numbers=new Numbers()
for(var i=0;i<newLen;i++){
rtn.push(this.getValueAt(i/(newLen-1)))
}
return rtn
}
public function divide(div:uint){
var rtn:Numbers=new Numbers()
for(var i=0;i<this.length-1;i++){
for(var j=0;j<div;j++){
var prog:Number=j/div
rtn.push(this[i]*(1-prog)+this[i+1]*prog)
}
}
rtn.push(this[this.length-1])
return rtn
}
public function getValueAt(t:Number){
var t=Math.max(Math.min(1,t),0)
if(this.length<1){
return null;
return;
}
if((this.length==1)||(t==0)){
return this[0];
return;
}
var ind:uint=Math.floor(t*(this.length-1))
var prog:Number=(t*(this.length-1))%1
if(prog==0){
return this[ind]
}else{
return this[ind]*(1-prog)+this[ind+1]*prog
}
}
public static function fromArray(arr:Array):Numbers{
var rtn:Numbers=new Numbers()
for each(var item in arr){
rtn.push(item)
}
return rtn
}
public static function interpolate(nums1:Array,nums2:Array,prog:Number=0.5):Numbers{
var rtn:Numbers=new Numbers()
for(var i=0;i<Math.min(nums1.length,nums2.length);i++){
rtn.push(nums1[i]*prog,nums2[i]*(1-prog))
}
return rtn
}
public static function linear(startVal:Number,endVal:Number,len:uint){
var rtn:Numbers=new Numbers()
for(var i=0;i<len;i++){
var prog=i/(len-1)
rtn.push(startVal*(1-prog)+endVal*prog)
}
return rtn
}
public static function ease(startVal:Number,endVal:Number,len:uint,ease:Number):Numbers{
var rtn:Numbers=new Numbers()
var midVal:Number=startVal*(100-ease)/200+endVal*(100+ease)/200
for(var i=0;i<len;i++){
rtn.push(Calc.getBezVal(i/(len-1),[startVal,midVal,endVal]))
}
return rtn
}
public static function rough(startVal:Number,endVal:Number,len:uint,w:Number):Numbers{
var rtn:Numbers=new Numbers()
for(var i=0;i<len;i++){
var prog=i/(len-1)
rtn.push(startVal*(1-prog)+endVal*prog+w*Math.random()-w/2)
}
return rtn
}
}
}
easeメソッドでCalcクラスが少しだけ登場
自分で言うのもなんですが、このクラスは要するに数の配列にすぎない
というシンプルなクラスな分結構使い道が広いと思います
とくにgraphics.beginGradientFill()とかでは役に立つんじゃないでしょうか
Calcクラス
Pictクラスグループのコアになる計算機のクラス
core.mathにでも入れとくべきような内容なのだけど
あんまりフォルダを多くしたくないのでベタ置き
何気にN次ベジェの値を計算する関数作っておきました
まあ2次か3次しか使う事ないでしょうけども
core.mathにでも入れとくべきような内容なのだけど
あんまりフォルダを多くしたくないのでベタ置き
何気にN次ベジェの値を計算する関数作っておきました
まあ2次か3次しか使う事ないでしょうけども
/*
■使い方
数値や座標、色数値の計算に使います
メソッドは全てstaticです
■パブリックプロパティ
■パブリックメソッド
・数値
getBezVal(位置、数配列) ベジェの特定の位置での値を求めます、数配列の数で何次ベジェか判断します
getComDiv(数値1、数値2) 二つの数の公約数を求めます
getComMul(数値1、数値2) 二つの数の公倍数を求めます
・点
isCrs(線1、線2) 二つの点で定義された二つの線が交わるかのプール値を返します
getCrs(線1、線2) 二つの点で定義された二つの線の交点を求めます、なければnullを返します
getPlrCrs(点1、角度1、点2、角度2) 点と角度で定義された二つの直線の交点を求めます
・角度
getDrc(点1、点2) 点1と点2の角度を求めます
getAng(点1、点2、点3) 点1・2・3の成す角の内角を-π~πのラジアンで求めます
getExAng(点1、点2、点3) 点1・2・3の成す角の外角を-π~πのラジアンで求めます
・色
HSBtoRGB(色相,彩度,明度) HSBの値から色数値を返します、あくまで近似値
RGBtoHSB(色数値) H,S,Bの値を持つオブジェクトを返します、あくまで近似値
*/
package simplizer.graphic{
import flash.geom.*
public class Calc{
public var onFrame:Function=function(){}
//コンストラクタ
public function Calc() {
}
//数
public static function getBezVal(t:Number,lst:Array):Number{
var rtn:Number=0
var n=lst.length-1
rtn+=lst[0]*Math.pow((1-t),n)
for(var i=1;i<n;i++){
rtn+=lst[i]*Math.pow((1-t),n-i)*Math.pow(t,i)*n
}
rtn+=lst[n]*Math.pow(t,n)
return rtn
}
public static function getComDiv(A:int,B:int):int {
var a=Math.max(A,B);
var b=Math.min(A,B);
while (a%b!==0) {
var n=a%b;
a=b;
b=n;
}
return b;
}
public static function getComMul(A:int,B:int):int {
return A * B / getComDiv(A,B);
}
//点
public static function isCrs(lineA:Array,lineB:Array):Boolean{
var rtn:Boolean=true
if((getAng(lineA[0],lineB[0],lineA[1])>0)==(getAng(lineA[0],lineB[1],lineA[1])>0))rtn=false
if((getAng(lineB[0],lineA[0],lineB[1])>0)==(getAng(lineB[0],lineA[1],lineB[1])>0))rtn=false
return rtn
}
public static function getCrs(lineA:Array,lineB:Array):Point{
var rtn:Point
if(isCrs(lineA,lineB)){
var vecA=lineA[1].subtract(lineA[0])
var vecB=lineB[1].subtract(lineB[0])
var f
if(lineB[0].x==lineB[1].x){
f=(lineB[0].x-lineA[0].x)/(lineA[1].x-lineA[0].x)
}else{
var dst1=Point.interpolate(lineB[1],lineB[0],(lineA[0].x-lineB[0].x)/(lineB[1].x-lineB[0].x)).subtract(lineA[0]).length
var dst2=Point.interpolate(lineB[1],lineB[0],(lineA[1].x-lineB[0].x)/(lineB[1].x-lineB[0].x)).subtract(lineA[1]).length
f=dst1/(dst1+dst2)
}
rtn=Point.interpolate(lineA[1],lineA[0],f)
}
return rtn
}
public static function getPlrCrs(PntA:Point,RA:Number,PntB:Point,RB:Number):Point{
if(PntA.equals(PntB)){
return PntA.clone()
return;
}
if(RA%Math.PI==RB%Math.PI){
return null
return;
}
var vec:Point=PntB.subtract(PntA)
var R=Math.atan2(vec.y,vec.x)+Math.PI/2
var R1=R-RA
var R2=RB-R
return PntA.add(Point.polar(vec.length/(Math.tan(R1)+Math.tan(R2))/Math.cos(R1),RA))
}
//角度
public static function getDrc(Pnt1:Point,Pnt2:Point):Number{
Pnt1=Pnt1||new Point(0,0)
var vec=Pnt2.subtract(Pnt1)
var rtn:Number=Math.atan2(vec.y,vec.x)
while(rtn>Math.PI)rtn-=Math.PI*2
while(rtn<-Math.PI)rtn+=Math.PI*2
return rtn
}
public static function getAng(Pnt1:Point,Pnt2:Point,Pnt3:Point):Number {
if(Pnt1.equals(Pnt2)||Pnt3.equals(Pnt2)){
return 0;
return;
}
var rtn=Math.atan2(Pnt3.y - Pnt2.y,Pnt3.x - Pnt2.x) - Math.atan2(Pnt1.y - Pnt2.y,Pnt1.x - Pnt2.x);
while (rtn > Math.PI) {
rtn-= Math.PI * 2;
}
while (rtn < - Math.PI) {
rtn+= Math.PI * 2;
}
return rtn;
}
public static function getExAng(Pnt1:Point,Pnt2:Point,Pnt3:Point):Number {
if(Pnt1.equals(Pnt2)||Pnt3.equals(Pnt2)){
return 0;
return;
}
var rtn=Math.atan2(Pnt3.y - Pnt2.y,Pnt3.x - Pnt2.x) - Math.atan2(Pnt1.y - Pnt2.y,Pnt1.x - Pnt2.x)-Math.PI;
while (rtn > Math.PI) {
rtn-= Math.PI * 2;
}
while (rtn < - Math.PI) {
rtn+= Math.PI * 2;
}
return rtn;
}
//色
public static function HSBtoRGB(H:Number,S:Number,B:Number):int {
var H=Math.abs(H%360)/60;
var S=Math.min(Math.abs(S),100)/100
var B=Math.min(Math.abs(B),100)/100
var rtn:int=0x010101*Math.floor(B*(1-S)*255);
var c=255*S*B;
var r:int=0;
var g:int=0;
var b:int=0;
if (H<1) {
r=Math.floor(c);
g=Math.floor(c*H);
} else if (H<2) {
r=Math.floor(c*(1-H%1));
g=Math.floor(c);
} else if (H<3) {
g=Math.floor(c);
b=Math.floor(c*(H%1));
} else if (H<4) {
g=Math.floor(c*(1-H%1));
b=Math.floor(c);
} else if (H<5) {
b=Math.floor(c);
r=Math.floor(c*(H%1));
} else {
b=Math.floor(c*(1-H%1));
r=Math.floor(c);
}
rtn+=r*0x010000+g*0x0100+b;
return rtn;
}
public static function RGBtoHSB(clr:uint):Object{
var rtn:Object={H:0,S:0,B:0}
var r:uint=(clr&0xFF0000)/0x010000
var g:uint=(clr&0x00FF00)/0x0100
var b:uint=(clr&0x0000FF)/0x01
var min:Number=Math.min(r,g,b)
var max:Number=Math.max(r,g,b)
var mid:Number=r+g+b-min-max
var prog:Number=(mid-min)/(max-min)
rtn.B=max/0xFF*100
rtn.S=(max-min)/max*100
rtn.H=([r,g,b].indexOf(max)*120+360+(([r,g,b].lastIndexOf(mid)-[r,g,b].indexOf(max)+4)%3-1)*prog*60)%360
return rtn
}
}
}