PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/mad-components/MadComponentsStage3D/src/asfiles/GraphPalette.as

http://mad-components.googlecode.com/
ActionScript | 1 lines | 1 code | 0 blank | 0 comment | 0 complexity | eb124bf4bf29a16027474cecc4cedb34 MD5 | raw file
  1. /** * <p>Original Author: Daniel Freeman</p> * * <p>Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions:</p> * * <p>The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software.</p> * * <p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS' OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE.</p> * * <p>Licensed under The MIT License</p> * <p>Redistributions of files must retain the above copyright notice.</p> */ package asfiles { import flash.display.Shape; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.filters.BevelFilter; import flash.filters.DropShadowFilter; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; import flash.utils.ByteArray; import flash.utils.Timer; import com.danielfreeman.madcomponents.Colour; public class GraphPalette extends SimplePalette { protected const SETTINGS:String='graphpalette.settings'; protected const BINS:String='graphpalette.bins'; protected static const DELAY:Timer=new Timer(5000,1); private const kcolours:Array =['0xff0000','0x00ff00','0x0000ff','0xffff00','0xff00ff','0x009999','0xff8000','0x0080ff','0x80ff00','0xff0080','0x00ff80','0x8000ff']; private const intervals:int=6; public const scalewidth:int=100; private const controlsheight:int=100; private const controlsmargin:int=20; private const enumlimit:int=30; public var colours:Array=new Array(); public var gridbe:Shape=new Shape(); public var grph:Sprite=new Sprite(); public var drawax:Shape=new Shape(); public var scale:Sprite=new Sprite(); // public var over:Sprite=new Sprite(); public var controls:Sprite = new Sprite(); private var allintegers:Boolean; private var possiblenumeration:Boolean; public var frequencybin:Array; private var enum:Array; public var ndatai:int,ndataj:int,nno:int; public var nmin:Number,nmax:Number,nactualmin:Number; public var enumerationmode:Boolean=false; public var frequencymode:Boolean=false; public var integermode:Boolean=false; public var colourmode:String=GraphSettings.RAINBOW; public var mydata:Packet; public var title:String=''; public var ss:*; public var datai:int,dataj:int,no:int; public var min:Number=0,max:Number=Number.MIN_VALUE; public var actualmin:Number=Number.MAX_VALUE; public var nminimum:Number,nmaximum:Number,nrange:Number; public var sminimum:Number,smaximum:Number,srange:Number; public var swdth:Number,sxoffset:Number; public var thick:Number=0; public var freq:Boolean=false; public var finterval:Number; public var freqmin:Number=0; public var freqbin:int; protected var _setfreqbin:int=-1; protected var _numberofbins:int; public var mywidth:int=wdth-frame,myheight:int=hght-frame; private var scl:Vector.<PrintAt>=new Vector.<PrintAt>(); private var gnumformat:String; private var dps:int=-1; private var pre:String=''; public var stack:Boolean=false; public var threed:Boolean=true; public var swap:Boolean=false; private var oldx:int,oldy:int; public var oldwdth:int,oldhght:int; public var iam:int; public var stcol:int=0; protected var _currencySymbol:String='$'; protected var _precision:int=2; protected var _scaleColour:uint=0x666666; protected var _scaleFormat:TextFormat=new TextFormat('Arial',11,_scaleColour); public var sintervals:int = 6; // number of calibrations public var shght:Number; // total height (graph) public var step:Number; // step size (value) public var soffset:Number = 0; // initial value protected var _recalculated:Boolean = false; static public function tint(c:uint,tnt:uint=0xffffff,strength:int=6):uint { var r:uint,g:uint,b:uint,mask:uint=Math.pow(2,strength)-1; r=(c & ((255-mask)<<16)) + (tnt & (mask<<16)); g=(c & ((255-mask)<<8)) + (tnt & (mask<<8)); b=(c & (255-mask)) + (tnt & mask); return r+g+b; } protected function recalculate():void { sminimum=Math.floor(nminimum/step)*step; sintervals=Math.ceil((max-sminimum)/(step*1.02)); if (sintervals>intervals) { sintervals=intervals; } smaximum=sminimum+step*sintervals; srange=smaximum-sminimum; if (srange==0) { shght=myheight; } else { shght=myheight/srange; } soffset=myheight+shght*sminimum; if (srange==0) { sxoffset=mywidth*(swdth=-sminimum); } else { sxoffset=mywidth*(swdth=-sminimum/srange); } } public function refresh():void { resize2(wdth, hght); } public function set increment(value:Number):void { step = value; recalculate(); _recalculated = true; } public function set minimum(value:Number):void { min = value; recalculate(); } public function set maximum(value:Number):void { max = value; recalculate(); } public function get increment():Number { return step; } public function get minimum():Number { return sminimum; } public function get maximum():Number { return smaximum; } public function GraphPalette(screen:Sprite,xx:int,yy:int,select:Packet,ss:*=null,freq:Boolean=false) { x=xx;y=yy;this.ss=ss;this.freq=freq; screen.addChild(this); if (ss==null) mydata=select; else mydata=new Packet(select); maxandmin(); addChild(gridbe); addChild(grph); addChild(drawax); addChild(scale); gpredraw(); super(screen,xx,yy); controls.addEventListener(GraphSettings.SELECTED,controlschanged); controls.addEventListener(GraphSettings.NEWMODE,newmode); controls.addEventListener(GraphSettings.START,startcolour); DELAY.addEventListener(TimerEvent.TIMER,darefresh); } public function get textColour():uint { return _scaleColour; } private function startcolour(ev:MyEvent):void { stcol=ev.parameters[0]; colours=new Array(); bgredraw(); } private function controlschanged(ev:MyEvent):void { var actn:String=ev.parameters[0]; if (actn==GraphSettings.THREED) threed=!threed; else if (actn==GraphSettings.SWAP) swap=!swap; else if (actn==GraphSettings.STACK) stack=!stack; drawaxis(); bgredraw(); gridbehind(); } public function formatit(valu:Number):String { if (numformat==Cell.PERCENT) return Math.round(valu*Math.pow(10,dps+2))/Math.pow(10,dps)+'%'; else return (valu<0 ? '-' : '')+pre+todps(Math.abs(valu)); } public function formatit2(valu:Number):String { if (numformat==Cell.PERCENT) return Math.round(valu*Math.pow(10,dps+2))/Math.pow(10,dps)+'%'; else return (valu<0 ? '-' : '')+pre+todps(Math.abs(valu),2); } private function todps(valu:Number,dps:int=-1):String { var l:int; var ret:String; if (dps<0) dps=this.dps; if (dps<0) return valu.toString(); else ret=String(Math.round(valu*Math.pow(10,dps))/Math.pow(10,dps)); if (ret.lastIndexOf('.')<0) {l=dps;ret+='.';} else l=dps-(ret.length-ret.lastIndexOf('.'))+1; for (var i:int=0;i<l;i++) ret+='0'; ret=ret.substr(0,int(ret).toString().length+3); return ret; } private function set numformat(nfrmt:String):void { gnumformat=nfrmt; if (nfrmt=='') numberformat(-1,''); else if (nfrmt==Cell.CURRENCY) numberformat(_precision,_currencySymbol); else if (nfrmt==Cell.TWODP) numberformat(_precision,''); else if (nfrmt==Cell.PERCENT) numberformat(2,''); else if (nfrmt==Cell.REAL) numberformat(-1,''); else numberformat(Number(nfrmt)); } private function get numformat():String { return gnumformat; } private function numberformat(dps:int=-2,pre:String='.'):void { if (dps!=-2) this.dps=dps; if (pre!='.') this.pre=pre; } public function maxandmin():void { var cell:Cell; var numf:String; datai=mydata.ito-mydata.ifrom+1; dataj=mydata.jto-mydata.jfrom+1; no=datai*dataj; min=0,max=Number.MIN_VALUE;actualmin=Number.MAX_VALUE; allintegers=true; possiblenumeration=true; if ((cell=readcell(0,0))==null) numf=Cell.REAL; else numf=cell.numformat; for (var i:int=0;i<datai;i++) for (var j:int=0;j<dataj;j++) if ((cell=readcell(i,j))!=null) { if (numf!=cell.numformat) numf=''; if (cell.value>max) max=cell.value; if (cell.value<min) min=cell.value; if (cell.value<actualmin) actualmin=cell.value; if (cell.value!=Math.round(cell.value)) allintegers=false; if (cell.isvalue) possiblenumeration=false; } else if (numf!=Cell.REAL) numf=''; numformat=numf; if (cell!=null) { _currencySymbol=cell.currencySymbol; if (numf==Cell.TWODP || numf==Cell.CURRENCY) pre=_currencySymbol; _precision=cell.precision; } if (freq) convertofrequency(); } private function convertofrequency():Boolean { ndatai=datai;ndataj=dataj;nno=no;nmin=min;nmax=max;nactualmin=actualmin; if (possiblenumeration) if (enumeration()) {enumerationmode=true;frequency();return true;} else return false; else {frequencymode=true;frequency();return true;} } protected function setnumberofbins(ev:MyEvent):void { _setfreqbin=ev.parameters[0] as int; darefresh(); } private function numberofbins():int { var sortit:Array=new Array(); var count:int=0; var cell:Cell; var total:Number=0,diff:Number,mean:Number,power:int,normalised:Number; for (var i:int=0;i<ndatai;i++) for (var j:int=0;j<ndataj;j++) if ((cell=readcell(i,j))!=null && cell.isvalue) sortit.push(cell.value); sortit.sort(); for (var k:int=0;k<sortit.length-1;k++) if ((diff=sortit[k+1]-sortit[k])>0) {total+=diff;count++;} if (count>0) { mean=total/count; power=Math.pow(10,Math.floor(Math.log(mean)/Math.LN10)); normalised=mean/power; if (normalised>5) finterval=5*power; else if (normalised>2) finterval=2*power; else finterval=1*power; if (finterval==0) finterval=0.1; freqmin=Math.floor(nactualmin/finterval)*finterval; if (isNaN(freqmin)) freqmin=0; freqbin=Math.ceil((nmax-freqmin)/finterval); return freqbin; } else return 1; } public function frequency():void { var i:int,j:int,k:int; if (frequencymode || enumerationmode) { min=0,max=Number.MIN_VALUE;actualmin=Number.MAX_VALUE; var n:int; var bin:int; if (_setfreqbin>0) {n=_setfreqbin;enumerationmode=integermode=false;frequencymode=true;finterval=(nmax-freqmin)/_setfreqbin;} else if (enumerationmode) n=enum.length; else if (integermode=(allintegers && nmax-nactualmin<=enumlimit)) n=nmax-nactualmin+1; else _numberofbins=n=numberofbins(); // controls.binsVisible=!integermode && !enumerationmode; frequencybin=new Array(); if (swap || dataj==1) { for (k=0;k<n;k++) frequencybin[k]=new Array(); for (j=0;j<ndataj;j++) { for (k=0;k<n;k++) frequencybin[k][j]=0; for (i=0;i<ndatai;i++) if ((bin=whatbin(readcell(i,j)))>=0) {frequencybin[bin][j]++;} // for (k=0;k<n;k++) trace('frequencybin['+k+']['+j+']='+frequencybin[k][j]); for (k=0;k<n;k++) { if (frequencybin[k][j]>max) max=frequencybin[k][j]; if (frequencybin[k][j]<min) min=frequencybin[k][j]; if (frequencybin[k][j]<actualmin) actualmin=frequencybin[k][j]; } } datai=n;dataj=ndataj;no=datai*dataj; // if (max==min) shght=myheight; else shght=myheight/(max-min); } else { for (i=0;i<ndatai;i++) { frequencybin[i]=new Array(); for (k=0;k<n;k++) frequencybin[i][k]=0; for (j=0;j<ndataj;j++) if ((bin=whatbin(readcell(i,j)))>=0) {frequencybin[i][bin]++;} // for (k=0;k<n;k++) trace('frequencybin['+i+']['+k+']='+frequencybin[i][k]); for (k=0;k<n;k++) { if (frequencybin[i][k]>max) max=frequencybin[i][k]; if (frequencybin[i][k]<min) min=frequencybin[i][k]; if (frequencybin[i][k]<actualmin) actualmin=frequencybin[i][k]; } } datai=ndatai;dataj=n;no=datai*dataj;trace('****frequency datai='+datai+' dataj='+dataj+' no='+no); } } } public function frequencylabel(n:int):String { if (enumerationmode) return enum[n]; else if (integermode) return String(n+nactualmin); else return formatit2(freqmin+n*finterval)+'->'+formatit2(freqmin+(n+1)*finterval); } private function addtoenum(cell:Cell):Boolean { if (cell==null || cell.string=='') return false; else { var found:Boolean=false; for (var p:int=0;p<enum.length && !found;p++) found=enum[p]==cell.string; if (!found) {enum.push(cell.string);return enum.length>enumlimit;} else return false; } } private function enumeration():Boolean { var i:int; enum=new Array(); var exit:Boolean=false; for (i=0;i<datai && !exit;i++) for (var j:int=0;j<dataj && !exit;j++) exit=addtoenum(readcell(i,j)); return !exit && enum.length>0; } private function whatbin(cell:Cell):int { if (cell==null || isNaN(cell.value)) return -1; else if (enumerationmode) { var found:Boolean=false; for (var p:int=0;p<enum.length && !(found=(enum[p]==cell.string));p++) {}; if (found) return p; else return -1; } else { if (integermode) return cell.value-nactualmin; else if (_setfreqbin>0) return Math.min(Math.floor((cell.value-freqmin)/finterval),_setfreqbin-1); else return Math.min(Math.floor((cell.value-freqmin)/finterval),freqbin-1); } } public function darefresh(ev:*=null):void { if (ev) { // trace('>>>>>>>>>ev.type='+ev.type+' _setfreqbin='+_setfreqbin+' _numberofbins='+_numberofbins); _numberofbins=_setfreqbin; } maxandmin(); scaleit(); drawscale(scale); mywidth=wdth-scaleoffset(wdth,hght)-frame; drawaxis(); scale.x=drawax.x=gridbe.x=grph.x=frame/2+scaleoffset(wdth,hght)-(scale.visible ? 6 : 0); bgredraw(); gridbehind(); } private function newmode(ev:MyEvent):void { colourmode=ev.parameters[0]; bgredraw(); } private function rndcol(i:int):uint { const lo:int=40; const hi:int=255; const sp:int=40; var ret:uint=lo+(i*sp)%(hi-lo); return ret; } private function rndgrey(i:int,invert:Boolean=false):uint { var col:int=rndcol(i); if (invert) col=255-col; return col*65536+col*256+col; } public function colour(idx:int,idx2:int=0,mde:String=null):uint { var col:Object,col2:Object; if (datai==1) {idx=idx2;idx2=0;} col=colours[idx%kcolours.length]; if (datai==1 || dataj==1) col2=col; else col2=colours[idx2%kcolours.length]; if (mde==null) mde=colourmode; if (mde==GraphSettings.RAINBOW) return tint(col!=null ? Number(col) : kcolours[(idx+stcol)%kcolours.length],rndgrey(idx2)); else if (mde==GraphSettings.GREYSCALE0) return tint(col!=null ? Number(col) : rndgrey(idx),rndgrey(idx2),4); else if (mde==GraphSettings.SUBTLE) return tint(col2!=null ? Number(col2) : kcolours[(idx2+stcol)%kcolours.length],rndgrey(idx)); else return tint(col2!=null ? Number(col2) : rndgrey(idx2,true),rndgrey(idx),4); } public function readcell(i:int,j:int):Cell { if (ss==null) return mydata.readlocal(i,j); else return ss.readcell(i+mydata.ifrom,j+mydata.jfrom); } public function scaleoffset(wdth:int,hght:int):int { return (scale.visible=wdth>scalewidth) ? scale.width : 0; } public function controlsoffset(wdth:int,hght:int):int { if (controls==null) return 0; else return (controls.visible=(wdth>scalewidth && hght>controlsheight)) ? controlsmargin : 0; } override public function resize(wdth:int,hght:int):void { myheight=hght-controlsoffset(wdth,hght)-frame; drawscale(scale); mywidth=wdth-scaleoffset(wdth,hght)-frame; scale.x=drawax.x=gridbe.x=grph.x=frame/2+scaleoffset(wdth,hght)-(scale.visible ? 6 : 0); scale.y=drawax.y=gridbe.y=grph.y=frame/2+controlsoffset(wdth,hght)+4; // if (freq) darefresh(); gpredraw();bgredraw();gridbehind(); extra=0; } public function resize2(wdth:int,hght:int):void { extra=0; this.wdth=wdth; this.hght=hght; drawscale(scale); redraw();bgredraw(); } public function bgredraw():void {} private function gpredraw():void { if (no>1 && !(max==0 && min==0)) { scaleit(); drawaxis(); drawscale(scale); } } private function fit(guess:Number,intervals:int):Number { var minimum:Number=Math.floor(nminimum/guess)*guess; var maximum:Number=minimum+intervals*guess; //may put a small threshold here - want a large value of this.nrange/(maximum-minimum) if (0.01+maximum<nmaximum || maximum<=0) return 0; else return nrange/(maximum-minimum); } private function scaleit():void { if (_recalculated) { recalculate(); return; } var intervals:int=Math.floor(hght/20); var f:Number,maxv:Number,maxi:Number,tempmax:Number; var range:Number,power:int,topower:Number; tempmax=max; if (max<0) max=0; range=max-min; if (range==0) {range=1;power=0;topower=1;nmaximum=max=1;nminimum=0;srange=step=sintervals=1;} else { power=Math.round(Math.log(range)/Math.LN10); topower=Math.pow(10,power); nmaximum=max/topower; nminimum=min/topower; nrange=range/(topower*intervals); maxv=fit(0.1,intervals);maxi=0.1; if ((f=fit(0.2,intervals))>maxv) {maxv=f;maxi=0.2;} if ((f=fit(0.5,intervals))>maxv) {maxv=f;maxi=0.5;} if ((f=fit(0.01,intervals))>maxv) {maxv=f;maxi=0.01;} if ((f=fit(0.02,intervals))>maxv) {maxv=f;maxi=0.02;} if ((f=fit(0.05,intervals))>maxv) {maxv=f;maxi=0.05;} if (maxv==0) { topower=topower*10; nminimum=nminimum/10; nrange=nrange/10; maxv=fit(0.1,intervals);maxi=0.1; if ((f=fit(0.2,intervals))>maxv) {maxv=f;maxi=0.2;} if ((f=fit(0.5,intervals))>maxv) {maxv=f;maxi=0.5;} if ((f=fit(0.01,intervals))>maxv) {maxv=f;maxi=0.01;} if ((f=fit(0.02,intervals))>maxv) {maxv=f;maxi=0.02;} if ((f=fit(0.05,intervals))>maxv) {maxv=f;maxi=0.05;} } step=topower*maxi; sminimum=topower*Math.floor(nminimum/maxi)*maxi; sintervals=Math.ceil((max-sminimum)/(step*1.02)); if (sintervals>intervals) sintervals=intervals; smaximum=sminimum+step*sintervals; srange=smaximum-sminimum; } if (srange==0) shght=myheight; else shght=myheight/srange; soffset=myheight+shght*sminimum; if (srange==0) sxoffset=mywidth*(swdth=-sminimum); else sxoffset=mywidth*(swdth=-sminimum/srange); // trace('myheight='+myheight+' soffset='+soffset); // trace('mywidth='+mywidth+' sxoffset='+sxoffset); // trace('scale goes from:'+sminimum+' to '+smaximum+' in steps of '+step+' shght='+shght); max=tempmax; } public function gridbehind():void { var yy:int; gridbe.graphics.clear(); gridbe.graphics.lineStyle(0,0xddddff); for (var i:int=0;i<=sintervals;i++) { yy=myheight-i*step*shght; gridbe.graphics.moveTo(0,yy); if (thick>0) { gridbe.graphics.lineTo(thick,yy-thick); gridbe.graphics.lineTo(mywidth+thick,yy-thick); } else gridbe.graphics.lineTo(mywidth,yy); } } public function drawaxis():void { var yy:int; drawax.graphics.clear(); drawax.graphics.lineStyle(2,_scaleColour); drawax.graphics.moveTo(0,0); drawax.graphics.lineTo(0,myheight); drawax.graphics.moveTo(0,soffset); drawax.graphics.lineTo(mywidth,soffset); scale.graphics.clear(); scale.graphics.lineStyle(2,_scaleColour); for (var i:int=0;i<=sintervals;i++) { yy=myheight-i*step*shght; scale.graphics.moveTo(0,yy); scale.graphics.lineTo(-2,yy); } } private function numbererror(n:Number):Number { return Math.round(n*1e6)/1e6; } public function drawscale(screen:Sprite):void { for (var j:int=0;j<scl.length;j++) screen.removeChild(scl[j]); scl=new Vector.<PrintAt>; for (var i:int=0;i<=sintervals;i++) { scl[i]=new PrintAt(screen,-2,myheight-i*step*shght,formatit(numbererror(sminimum+i*step)),TextFieldAutoSize.RIGHT,_scaleFormat); scl[i].y-=scl[i].height/2; } } public function format():void { mouseChildren=mouseEnabled=false; filters=null; } public function thumbnail(xx:int,yy:int,sz:int):void { oldx=x;oldy=y;oldwdth=wdth;oldhght=hght; x=xx;y=yy; mouseChildren=mouseEnabled=false; resize(sz,sz);graphics.clear();edge.visible=false; filters=nullfilters=null; } public function restore(partial:Boolean=false):void { grph.filters=null; if (partial) {x=y=0;resize(oldwdth,oldhght);} else { x=oldx;y=oldy; mouseChildren=mouseEnabled=edge.visible=true; resize(oldwdth,oldhght); } redraw(); } public function contained():void { graphics.clear(); edge.visible=hitArea.visible=false; mouseEnabled=false; mouseChildren=true; filters=nullfilters=null; customcolours(0,uint.MAX_VALUE,uint.MAX_VALUE); } override public function destructor():void { controls.removeEventListener(GraphSettings.SELECTED,controlschanged); controls.removeEventListener(GraphSettings.NEWMODE,newmode); controls.removeEventListener(GraphSettings.START,startcolour); super.destructor(); } } }