Graph draw (sin,cos,tan)
[SWF(width=465,height=465,frameRate=465, backgroundColor="#000000")]
...
@author Thi
/**
* Copyright Thy ( http://wonderfl.net/user/Thy )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/x17z
*/
package
{
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
//
//[SWF(width=465,height=465,frameRate=465, backgroundColor="#000000")]
/**
* ...
* @author Thi
*/
public class Main extends Sprite
{
// calculators storage (functions + TextField, expressions)
private var calculators:Vector.<Calculadora> = new Vector.<Calculadora>(1)
// libraly, i haven't really tested this
private var libraly:Array
// temp var calculadora
private var calc:Calculadora
// a option var
private var opt:Option
// a graph var
private var graph:Graph, g:Graphics
private var graphs:Vector.<Graph>
// the x,y line axis
private var axis:Axis
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// create the library. Variables who will be used in some calculator who uses that library
libraly = ["x", 1, "y", 2, "pi", Math.PI]
// create a calculator
calc = new Calculadora(libraly, "-.5 + sin ( x² ) + 5 * cos( x )", "y")//".1*x^3-x*4+.1x^2-(.0045*x^4)", "y")
calculators[0] = calc
// the x,y line axis
axis = new Axis(232, 232, 46.5, 10)
// the graph
graph = new Graph(libraly, "x", "y", scale)
g = graph.graphics
//
graphs = new Vector.<Graph>()
graphs[0] = graph
// the first init from calculator
stage.frameRate = 465
calc.convert()
calc.convert_to_rpn() // convert the expression for a way to calculate more easily
// create options
opt = new Option(libraly, graphs)
//
// childs
addChild(axis)
stage.addChild(graph)
stage.addChild(calc)
stage.addChild(opt)
// listener
stage.addEventListener(Event.ENTER_FRAME, ef)
}
private var i:int, j:int
private var range:Number = 10, scale:Number = (465*.5) / range, plus:Number = 2*range/465
private var X:Number = -range
private function ef(e:Event = null):void
{
if (calc.upd || opt.upd)
{
// changed expression
calc.upd = false
opt.upd = false
//
i = 0
while (i < graphs.length)
{
graphs[i].clear()
++i
}
X = -range
stage.frameRate = 465
//
calc.convert()
calc.convert_to_rpn() // convert the expression for a way to calculate more easily
//
libraly[1] = X
calc.rpn() // just calculate (+,-,*,/,^)
libraly[3] = calc.Return
//
i = 0
while (i < graphs.length)
{
graphs[i].move()
++i
}
} else if (calc.pos)
{
// changed the result text, so adjust the position
calc.pos = false
//
calc.position()
}
if (X < range)
{
libraly[1] = X
calc.rpn() // just calculate (+,-,*,/,^)
libraly[3] = calc.Return
i = 0
while (i < graphs.length)
{
graphs[i].line()
++i
}
//g.lineTo(X*scale + 232, 232 - libraly[3]*scale)
//g.lineTo(mouseX, mouseY)
X += plus
} else {
stage.frameRate = 5
}
}
}
}
//
//package
//{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TextEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
/**
* ...
* @author Thi
*/
/*public*/ class Calculadora extends Sprite
{
// public variables
public var TF:TextField
public var t:String
public var libraly:Array
public var Return:Number
//
public var upd:Boolean // updated the expression
public var pos:Boolean // updated the 'result text', then must update the position
// result TF
public var tf:TextField
public var r:String
// '=' text
private var eq:Sprite
// text stuff
private var format:TextFormat
public function Calculadora(libraly:Array = null, t:String = null, r:String = null)
{
this.libraly = libraly; // libraly, used for variables, example 'x = 0' or 'hello = 1'
this.t = t; // the input expression, when this calss is called
this.r = r; // the input result variable, when this calss is called. the result is put in this var
// init format
format = new TextFormat("Arial", 20)
// init text
TF = new TextField()
TF.defaultTextFormat = format
TF.autoSize = TextFieldAutoSize.LEFT
TF.type = "input"
TF.border = true
TF.text = t
//
tf = new TextField()
tf.defaultTextFormat = format
tf.autoSize = TextFieldAutoSize.LEFT
tf.type = "input"
tf.border = true
tf.text = r
//
eq = new Sprite()
var q:TextField = new TextField()
q.defaultTextFormat = format
q.autoSize = TextFieldAutoSize.LEFT
q.selectable = false
q.text = "="
eq.graphics.beginFill(0x09C0C0)
eq.graphics.drawRect(0, 0, q.width, q.height)
eq.graphics.endFill()
eq.addChild(q)
//
tf.x = 10
tf.y = 10
eq.x = tf.width + tf.x + 20
eq.y = 10
TF.x = eq.width + eq.x + 20
TF.y = 10
// add to Sprite content
this.addChild(TF)
this.addChild(tf)
this.addChild(eq)
// add text change listener
eq.addEventListener(MouseEvent.CLICK, click)
tf.addEventListener(TextEvent.TEXT_INPUT, changed)
TF.addEventListener(TextEvent.TEXT_INPUT, changed)
// sets 'updated' to false
upd = false
}
private function click(e:MouseEvent = null):void
{
// an concrete way to 'upd = true', so it will start calculating stuff
upd = true
}
private function changed(e:TextEvent):void
{
// this function actually happends when the TEXT has no been changed, but the key has been pressed
if (e.target == TF)
{
// changed the expression
upd = true
} else
{
// changed the 'result' text
pos = true
}
}
public function position():void
{
tf.x = 10
eq.x = tf.width + tf.x + 20
TF.x = eq.width + eq.x + 20
}
// storage the elements when converting
private var ele:Array
private var num:Array // used for sotage big numbers or words (so 'HI' wont be storage as 'H','I', but "HI")
// int for looping process
private var i:int, j:int
//
private var length:int
private var char:String, last:String
// function who convert 'strings' to 'expressions'
public function convert():void
{
// clear arrays and integers and errorPreventing (Parentesis stuff)
ele = []
num = []
i = j = 0
preventError = false
// setup length
t = TF.text
length = t.length
while (i < length)
{
char = t.charAt(i)
if (Number(char) || char == "0")
{
// lats char is equal to the last char from elements
last = ele[ele.length - 1]
if (last == ")")
{
// push an multiplication (* symbol)
ele.push("*")
}
//
j = i
while (Number(char) || char == "," || char == "." || char == "0")
{
num.push(char)
++j
char = t.charAt(j)
}
// so the '2 char or more' number has been 'built'
// add the 'big number' to the array
ele.push(num.join(""))
num = [] // clear
// the loop continues
i = j - 1
j = 0 // clear j
} else if (char == "*" || char == "+" || char == "-" || char == "/" || char == "^")
{
ele.push(char)
} else if (char == "." || char == ",")
{
// create a big number, for example: .2 -> 0.2
num.push("0")
num.push(".")
//
j = i
if (Number(char))
{
while (Number(char))
{
num.push(char)
++j
char = t.charAt(j)
}
// 'big number' ready
// make the array became a single 'number', then add it to elements
ele.push(num.join(""))
// keep looping..
i = j-1
// clear
num = []
j = 0
}
} else if (char == "(" || char == "[" || char == "{")
{
preventError = true
// take the last element
last = ele[ele.length-1]
if (last != "+" && last != "-" && last != "*" && last != "/" && last != "^" && last != "undefined" && last != null && last != "sin" && last != "cos" && last != "tan")
{
// add an multiplication
ele.push("*")
}
// then finnaly add the parentesis
ele.push("(")
} else if (char == "²")
{
ele.push("^")
ele.push("2")
} else if (char == "³")
{
ele.push("^")
ele.push("3")
} else if (char == ")" || char == "]" || char == "}")
{
ele.push(")")
// so.. convert every ([{}]) -> ((()))
} else if (char != " ")
{
last = ele[ele.length -1]
if (last != "+" && last != "-" && last != "*" && last != "/" && last != "^" && last != "undefined" && last != "(" && last != "[" && last != "{" && last != null && last != "²" && last != "³" )
{
// add an multiply
ele.push("*")
}
j = i
while (char != "," && char != "." && char != "+" && char != "-" && char != "*" && char != "/" && char != "^" && char != "(" && char != "[" && char != "{" && char != ")" && char != "]" && char != "}" && char != " " && char != null && char != "undefined" && char != "" && char != "²" && char != "³")
{
num.push(char)
++j;
char = t.charAt(j)
}
// so the 'big word' has been formed. and then pushed at elements.
// but before that see if its angle relactioned
var temp:String = num.join("")
if (temp == "sen" || temp == "seno")
{
temp = "sin"
} else if (temp == "cosseno")
{
temp = "cos"
} else if (temp == "tangent" || temp == "tangente" || temp == "tgt" || temp == "tg")
{
temp = "tan"
}
ele.push(temp)
// clear
num = []
temp = ""
// keep loopin'
i = j-1
}
++i
}
}
// so after this function, i have the expression more organized
// but still an array with strings, like: [1,+,1] or [1,-,VAR,+,20,*,(,aVALUE,)]
private var result:Array // store elements used on RPN calculation. It will last 1 element, the result
private var calculation:Array // store elements that relacionates to the 'right order'.. like '*' first than '+'
private var result2:Array // just a copy from result
public function convert_to_rpn():void
{
// clear stuff
result = []
calculation = []
i = j = 0
//
while (i < ele.length)
{
// its not really a single char. can be an word or large number
char = ele[i]
if (Number(char))
{
result.push(char)
} else if (char == "(")
{
calculation.push(char)
} else if (char == "+" || char == "-" || char == "*" || char == "/" || char == "^" || char == "sin" || char == "cos" || char == "tan")
{
calculation.push(char)
// call a function that organizes the order
Nopr()
} else if (char == ")")
{
calculation.push(char)
close_parentesis()
} else
{
result.push(char)
}
// loopin' 'chars'
++i
}
// now add 'calculation' array (reverse) to the result array
j = calculation.length
while (j > 0)
{
if (calculation[j - 1] != "")
{
result.push(calculation[j-1])
}
--j
}
// keep looping thought other 'chars'
result2 = result
}
private var level1:uint, level2:uint
private function Nopr():void
{
if (char == "+" || char == "-")
{
level1 = 1;
} else if (char == "*" || char == "/")
{
level1 = 2;
} else if (char == "^")
{
level1 = 4;
} else if (char == "sin" || char == "cos" || char == "tan")
{
level1 = 8
}
if (calculation[calculation.length - 2] == "+" || calculation[calculation.length - 2] == "-")
{
level2 = 1;
} else if (calculation[calculation.length - 2] == "*" || calculation[calculation.length - 2] == "/")
{
level2 = 2;
} else if (calculation[calculation.length - 2] == "^")
{
level2 = 3;
} else if (calculation[calculation.length - 2] == "sin" || calculation[calculation.length - 2] == "cos" || calculation[calculation.length - 2] == "tan")
{
level2 = 4;
} else
{
level2 = 0;
}
if (level1 <= level2)
{
result.push(calculation[calculation.length-2]);
calculation.splice(calculation.length - 2, 1);
// repeats
Nopr();
}
}
private var preventError:Boolean
private function close_parentesis():void
{
if (calculation[calculation.length - 2] != "(")
{
result.push(calculation[calculation.length - 2])
calculation.splice(calculation.length - 2, 1)
if (preventError)
{
close_parentesis()
}
} else
{
calculation.splice(calculation.length-2,2)
}
}
private var n0:Boolean, n1:Boolean // if vars are number
private var operator:Boolean
public function rpn():void
{
result = result2.concat()
i = 0
while (i < result.length)
{
char = result[i]
if (result.length > 1)
{
if (char == "+")
{
if (Number(result[i - 2]))
{
result[i] = Number(result[i - 2]) + Number(result[i - 1])
result.splice(i - 2, 2)
--i;
} else
{
result[i] = Number(result[i - 1])
result.splice(i - 1, 1)
}
--i;
} else if (char == "-")
{
if (Number(result[i - 2]))
{
result[i] = Number(result[i - 2]) - Number(result[i - 1])
result.splice(i - 2, 2)
--i;
} else
{
result[i] = - Number(result[i - 1])
result.splice(i - 1, 1)
}
--i;
} else if (char == "*")
{
result[i] = Number(result[i - 2]) * Number(result[i - 1])
result.splice(i - 2, 2)
--i; --i;
} else if (char == "/")
{
result[i] = Number(result[i - 2]) / Number(result[i - 1])
result.splice(i - 2, 2)
--i; --i;
} else if (char == "^")
{
result[i] = Math.pow(Number(result[i - 2]), Number(result[i - 1]))
result.splice(i - 2, 2)
--i; --i;
} else if (!Number(char))
{
if (char == "sin")
{
result[i] = Math.sin(Number(result[i - 1]))
result.splice(i - 1, 1)
--i
} else if (char == "cos")
{
result[i] = Math.cos(Number(result[i - 1]))
result.splice(i - 1, 1)
--i
} else if (char == "tan")
{
result[i] = Math.tan(Number(result[i - 1]))
result.splice(i - 1, 1)
--i
} else
{
// then char is a word, so now that word is search in the referenced libraly
j = 0
while (j < libraly.length)
{
if (char == libraly[j])
{
++j
result[i] = libraly[j]
--i
break;
}
++j; ++j;
}
// the index of the value has been found (j)
if (j == 0 && libraly[0] != char)
{
++i
}
}
}
} else if (!Number(char))
{
if (char == "sin")
{
result[i] = Math.sin(Number(result[i - 1]))
result.splice(i - 1, 1)
--i
} else if (char == "cos")
{
result[i] = Math.cos(Number(result[i - 1]))
result.splice(i - 1, 1)
--i
} else if (char == "tan")
{
result[i] = Math.tan(Number(result[i - 1]))
result.splice(i - 1, 1)
--i
} else {
// then char is a word, so now that word is search in the referenced libraly
j = 0
while (j < libraly.length)
{
if (char == libraly[j])
{
++j
result[i] = libraly[j]
--i
break;
}
++j; ++j;
}
// the index of the value has been found (j)
if (j == 0 && libraly[0] != char)
{
++i
}
}
}
++i
}
// the returnable result, in (:Number)
Return = Number(result[0])
// changed the result variable, like 'y = 1*2+1', It will set 'y' (from libraly) to 3 (:Number)
// then char is a word, so now that word is search in the referenced libraly
i = 0, j = 0
while (i < libraly.length)
{
if (tf.text == libraly[i])
{
++i
libraly[i] = Return
j = 1
break;
}
++i; ++i;
}
if (j == 0)
{
// this just means that the word doesnt really exist in the libraly, so we create it
libraly.push(tf.text)
libraly.push(Return)
}
// now yes, this calculation thing ends :)
}
}
//}
//
//package
//{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;
/**
* ...
* @author Thi
*/
/*public*/ class Option extends Sprite
{
// libraly used on this Option stuff
public var libraly:Array
public var upd:Boolean
// state sprites. min minimized, max maximized
private var min:Sprite
private var max:Sprite
// the 'options' or 'back' button
private var t:TextField
private var format:TextFormat // format
// temp graphics
private var g:Graphics
// state (mini at first)
private var mini:Boolean = true
private var TF:TextField
// each graph
private var graphs:Vector.<Graph>
public function Option(libraly:Array = null, graphs:Vector.<Graph> = null)
{
this.libraly = libraly
this.graphs = graphs
this.addEventListener(Event.ADDED_TO_STAGE, added)
}
private function added(e:Event = null):void
{
// crate backgrounds
min = new Sprite()
max = new Sprite()
format = new TextFormat("Arial", 17)
//
TF = new TextField()
TF.defaultTextFormat = format
TF.selectable = false
TF.autoSize = TextFieldAutoSize.LEFT
TF.x = 20
TF.y = 20
TF.text = "libraly"
max.addChild(TF)
//
TF = new TextField()
TF.defaultTextFormat = format
TF.selectable = false
TF.autoSize = TextFieldAutoSize.LEFT
TF.x = 245
TF.y = 20
TF.text = "graphs"
max.addChild(TF)
//
// min graphics
g = min.graphics
g.lineStyle(1, 0)
g.beginFill(0xFFFFFF)
g.drawRect(400, 440, 60, 19) // direita,baixo
g.endFill()
// max graphics
g = max.graphics
g.lineStyle(1, 0)
g.beginFill(0xFFFFFF)
g.drawRect(10, 10, 445, 445)
g.endFill()
//
g.drawRect(20, 41, 200, 200)
g.drawRect(245,41, 200, 200)
// add min (start) on stage
stage.addChild(min)
// new text (Options, Back)
t = new TextField()
t.defaultTextFormat = format
t.text = "Options"
t.selectable = false
t.x = 400
t.y = 440
min.addChild(t)
// menus, for the libraly itens and for the graph itens
lib = []
graph = []
temp = []
//
lib2 = []
/*graph2 = []*/
temp2 = []
// listener
min.addEventListener(MouseEvent.CLICK, minmax)
}
private function minmax(e:MouseEvent = null):void
{
if (mini)
{
t.text = "Back"
this.addChild(max)
newMax()
} else
{
t.text = "Options"
this.removeChild(max)
upd = true
// update the libraly
i = 4
while (i < lib.length)
{
libraly[i] = lib[i-4].text
max.removeChild(lib[i-4])
lib[i-4] = null
++i;
//
if (Number( lib[i-4].text ))
{
libraly[i] = Number( lib[i-4].text )
} else {
libraly[i] = 0
}
max.removeChild(lib[i-4])
lib[i-4] = null
++i
}
lib = []
//
i = 0
while (i < temp.length)
{
max.removeChild(temp[i])
temp[i] = null
++i
}
temp = []
// // -- // //
// update the graph data
i = 0
while (i < lib2.length)
{
trace(lib2[i].text, lib2[i + 1].text)
graphs[i].X = lib2[i].text
graphs[i].Y = lib2[i+1].text
max.removeChild(lib2[i])
max.removeChild(lib2[i+1])
lib2[i] = null
lib2[i+1] = null
++i;
++i
}
lib2 = []
//
i = 0
while (i < temp2.length)
{
max.removeChild(temp2[i])
temp2[i] = null
++i
}
temp2 = []
}
mini = !mini
}
//
private var lib:Array, graph:Array, temp:Array
private var lib2:Array, /*graph2:Array,*/ temp2:Array
private var i:int, j:int
private function newMax():void
{
i = 4
//g.drawRect(20, 41, 200, 200)
while (i < libraly.length)
{
TF = new TextField()
TF.defaultTextFormat = format
TF.autoSize = TextFieldAutoSize.LEFT
TF.type = "input"
TF.border = true
TF.width = 90
TF.autoSize = TextFieldAutoSize.NONE
TF.text = libraly[i]
TF.x = 20
TF.y = (i-4) * 10 + 41
lib.push(TF)
max.addChild(TF)
//
TF = new TextField()
TF.defaultTextFormat = format
TF.selectable = false
TF.width = 20
TF.text = "="
TF.x = 120
TF.y = (i-4) * 10 + 41
temp.push(TF)
max.addChild(TF)
//
TF = new TextField()
TF.defaultTextFormat = format
TF.autoSize = TextFieldAutoSize.LEFT
TF.type = "input"
TF.border = true
TF.width = 80
TF.autoSize = TextFieldAutoSize.NONE
TF.text = libraly[i+1]
TF.x = 140
TF.y = (i -5) * 10 + 51
lib.push(TF)
max.addChild(TF)
++i; ++i;
}
//g.drawRect(245,41, 200, 200)
i = 0
trace("HUM")
while (i < graphs.length)
{
trace("FEIZ")
TF = new TextField()
TF.defaultTextFormat = format
TF.autoSize = TextFieldAutoSize.LEFT
TF.type = "input"
TF.border = true
TF.width = 90
TF.autoSize = TextFieldAutoSize.NONE
TF.text = graphs[i].X
TF.x = 245
TF.y = i * 10 + 41
lib2.push(TF)
max.addChild(TF)
//
TF = new TextField()
TF.defaultTextFormat = format
TF.selectable = false
TF.width = 20
TF.text = ","
TF.x = 345
TF.y = i * 10 + 41
temp2.push(TF)
max.addChild(TF)
//
TF = new TextField()
TF.defaultTextFormat = format
TF.autoSize = TextFieldAutoSize.LEFT
TF.type = "input"
TF.border = true
TF.width = 80
TF.autoSize = TextFieldAutoSize.NONE
TF.text = graphs[i].Y
TF.x = 365
TF.y = (i - 1) * 10 + 51
lib2.push(TF)
max.addChild(TF)
++i; ++i;
}
}
}
//}
//
//package
//{
import flash.display.Graphics;
import flash.display.Sprite;
/**
* ...
* @author Thi
*/
/*public*/ class Axis extends Sprite
{
public var cx:Number, cy:Number, range:Number, number:Number
private var g:Graphics
public function Axis(cx:Number = 0, cy:Number = 0, range:Number = 0, number:Number = 0)
{
this.cx = cx
this.cy = cy
this.range = range
this.number = number
g = this.graphics
draw()
}
public function draw():void
{
g.clear()
g.lineStyle(1, 0)
//
g.moveTo(0, cy)
g.lineTo(cx * 2, cy)
g.moveTo(cx, 0)
g.lineTo(cx, cy * 2)
//
g.lineStyle(1, 0, .1)
var i:int = 0
while (i < 2 * number)
{
g.moveTo(i*range*.5, 0)
g.lineTo(i*range*.5,cy*2)
g.moveTo(0, i*range*.5)
g.lineTo(cx*2,i*range*.5)
++i
}
}
}
//}
//
//package
//{
import flash.display.Graphics;
import flash.display.Sprite;
/**
* ...
* @author Thi
*/
/*public*/ class Graph extends Sprite
{
public var g:Graphics, X:String, Y:String
private var libraly:Array
private var valueX:Number, valueY:Number, scale:Number
public function Graph(libraly:Array = null, X:String = "x", Y:String = "y", scale:Number = 10)
{
this.libraly = libraly
this.X = X
this.Y = Y
this.scale = scale
g = this.graphics
g.lineStyle(1, 0xFF0000)
g.moveTo( -40, 250)
}
public function clear():void
{
g.clear()
g.lineStyle(1, 0xFF0000)
g.moveTo( -40, 250)
}
private var i:int
public function line():void
{
if (!Number(X))
{
i = 0
while (i < libraly.length)
{
if (libraly[i] == X)
{
break;
}
++i; ++i
}
valueX = Number(libraly[++i])
} else
{
valueX = Number(X)
}
if (!Number(Y))
{
i = 0
while (i < libraly.length)
{
if (libraly[i] == Y)
{
break;
}
++i; ++i
}
valueY = Number(libraly[++i])
} else
{
valueY = Number(Y)
}
//
g.lineTo(valueX * scale + 232, 232 - valueY * scale)
//g.lineTo(mouseX, mouseY)
}
public function move():void
{
if (!Number(X))
{
i = 0
while (i < libraly.length)
{
if (libraly[i] == X)
{
break;
}
++i; ++i
}
valueX = Number(libraly[++i])
} else
{
valueX = Number(X)
}
if (!Number(Y))
{
i = 0
while (i < libraly.length)
{
if (libraly[i] == Y)
{
break;
}
++i; ++i
}
valueY = Number(libraly[++i])
} else
{
valueY = Number(Y)
}
//
g.moveTo(valueX * scale + 232, 232 - valueY * scale)
//g.lineTo(mouseX, mouseY)
}
}
//}
//