import java.util.*;
import java.util.regex.*;
// http://www.superstable.net/interfascia/
import interfascia.*;
// http://sourceforge.net/projects/jep/
import org.nfunk.jep.evaluation.*;
import org.nfunk.jep.*;
import org.nfunk.jep.function.*;
import org.nfunk.jep.type.*;
float zooml = 1, zoomr = 1, h;
float offsetrx=0, offsetry=0, offsetlx=0, offsetly=0;
boolean drawing = false;
boolean numberPoints = false;
boolean drawNow = false;
boolean drawAxis = false; // Obselete
boolean drawAxisLines = true; // For preview picture purposes only xD
boolean showExamples = false;
int display = Display.Normal;
PFont font, calibri, calibri25, calibri14;
ComplexDelegate transform = new ComplexDelegate() { ComplexNumber Invoke(ComplexNumber cn) { return cn.Power(2); } };
ArrayDelegate input = new ArrayDelegate() { ArrayList[] Invoke() { return createGrid(-300, -300, 300, 300, 10, 10); } };
//ArrayDelegate input = new ArrayDelegate() { ArrayList[] Invoke() { return createCircle(0,0,1,1,1000,PI/128); } };
//ArrayDelegate input = new ArrayDelegate() { ArrayList[] Invoke() { return createFilledCircle(0,0,1,1,600,25,PI/100); } };
//ArrayDelegate input = new ArrayDelegate() { ArrayList[] Invoke() { return createLine(-300,-300,300,300,10); } };
//ArrayDelegate input = new ArrayDelegate() { ArrayList[] Invoke() { return createFormula("x^2/100",-100,100,1); } };
org.nfunk.jep.JEP parser = new org.nfunk.jep.JEP();
org.nfunk.jep.JEP inputParser = new org.nfunk.jep.JEP();
org.nfunk.jep.JEP fParser = new org.nfunk.jep.JEP();
ArrayList arr = new ArrayList();
ArrayList fills = new ArrayList();
ArrayList complexs = new ArrayList();
String inputTransOrig;
void setup()
{
size(900,550);
//size(1200,700); // For larger screens
h=height-100;
smooth();
background(255);
stroke(0);
noStroke();
fill(0);
//noFill();
font = loadFont("LucidaConsole-10.vlw");
calibri = loadFont("Calibri-30.vlw");
calibri14 = loadFont("Calibri-14.vlw");
calibri25 = loadFont("Calibri-25.vlw");
textFont(font);
drawNow = true;
InitialiseGUI();
parser.addComplex();
parser.addStandardConstants();
parser.addStandardFunctions();
parser.addFunction("root", new Root());
inputParser.addStandardConstants();
inputParser.addStandardFunctions();
inputParser.addFunction("grid", new Grid());
inputParser.addFunction("circle", new Circle());
inputParser.addFunction("ellipse", new Ellipse());
inputParser.addFunction("filledCircle", new FilledCircle());
inputParser.addFunction("filledEllipse", new FilledEllipse());
inputParser.addFunction("line", new Line());
inputParser.addFunction("func",new Circle());
fParser.addStandardConstants();
fParser.addStandardFunctions();
}
void draw()
{
if(display == Display.FunctionHelp)
{
background(255);
drawFunctionHelpGUI();
}
else if(display == Display.Examples)
{
background(255);
drawExamplesGUI();
}
else if(display == Display.Help)
{
background(255);
drawHelpGUI();
}
else
{
CheckCenterMouse();
if(drawNow)
{
drawGraphGUI();
drawNow = false;
}
fill(255);
rect(0,h,width,height-h);
}
}
void drawGraphGUI()
{
drawing = true;
fill(255);
rect(0,0,width,h);
textFont(font);
textSize(10);
textAlign(CENTER);
arr.clear();
fills.clear();
if(arr.size() == 0)
CalculateInitials();
for(int i = 0; i < arr.size(); i++)
{
noStroke();
ComplexNumber cn = (ComplexNumber)arr.get(i);
Color c = (Color)fills.get(i);
fill(c.getRed(), c.getGreen(), c.getBlue());
if(ClampChoose(-width/4,width/4,cn.real*zooml+offsetlx) && ClampChoose(-h/2 - 10, h/2 + 10, cn.imaginary*zooml-offsetly))
{
ellipse(width/4 + cn.real*zooml+offsetlx, h/2 - cn.imaginary*zooml+offsetly,4,4);
if(numberPoints)
text(i, width/4 + cn.real*zooml+offsetlx, h/2 - cn.imaginary*zooml+offsetly - 4);
}
}
if(complexs.size() == 0)
{
CalculateComplexs();
}
for(int i = 0; i < arr.size(); i++)
{
ComplexNumber cn = (ComplexNumber)complexs.get(i);
Color c = (Color)fills.get(i);
fill(c.getRed(), c.getGreen(), c.getBlue());
if(ClampChoose(-width/4,width/4,cn.real*zoomr+offsetrx) && ClampChoose(-h/2 - 10, h/2 + 10, cn.imaginary*zoomr-offsetry))
{
ellipse(width*3/4 + cn.real*zoomr+offsetrx, h/2 - cn.imaginary*zoomr+offsetry,4,4);
if(numberPoints)
{
text(i, width*3/4 + cn.real*zoomr+offsetrx, h/2 - cn.imaginary*zoomr+offsetry - 4);
}
}
}
stroke(0);
strokeWeight(3);
line(width/2,0,width/2,h);
line(0,h,width,h);
strokeWeight(1);
if(drawAxisLines)
{
if(width/4+offsetlx < width/2)
line(width/4+offsetlx,0,width/4+offsetlx,h);
if(width*3/4+offsetrx > width/2)
line(width*3/4+offsetrx,0,width*3/4+offsetrx,h);
line(0,h/2+offsetly,width/2,h/2+offsetly);
line(width/2,h/2+offsetry,width,h/2+offsetry);
}
fill(0);
if(drawAxis)
{
for(float i = width/4 + offsetlx; i > 0 ; i -= 50)
{
if(ClampChoose(0,width/4 + offsetlx,width/4 + offsetlx - i))
text("-" + Round(i/10/zooml,2),width/4 + offsetlx - i,h/2 + offsetly + 10);
}
for(float i = 0; i <= width/4 + offsetlx; i += 50)
{
if(ClampChoose(width/4 + offsetlx,width/2,width/4 + offsetlx + i))
text(Round(i/10/zooml,2),width/4 + offsetlx + i,h/2 + offsetly + 10);
}
}
labelsr[1].setLabel(zoomr + "x");
labelsr[3].setLabel(Float.toString(offsetrx));
labelsr[5].setLabel(Float.toString(offsetry));
labelsl[1].setLabel(zooml + "x");
labelsl[3].setLabel(Float.toString(offsetlx));
labelsl[5].setLabel(Float.toString(offsetly));
drawing = false;
}
String Round(float num, int decimals)
{
String str = Float.toString(round(pow(10,decimals)*num)/pow(10,decimals));
return str.substring(0,str.length());
}
void ChangeIntialDelegate(String change)
{
inputParser.parseExpression(change);
if((inputParser.getValue() == -1))
{
inputError.setValue("Error: incorrect syntax");
}
else if(Double.isNaN(inputParser.getValue()))
{
inputError.setValue("Error: expression cannot be solved.");
}
else
{
CalculateInitials();
}
}
void CalculateInitials()
{
ArrayList[] ret = input.Invoke();
arr = ret[0];
fills = ret[1];
}
ArrayList[] createGrid(float xs, float ys, float xe, float ye, float xstep, float ystep)
{
ArrayList[] ret = new ArrayList[2];
ret[0] = new ArrayList();
ret[1] = new ArrayList();
for(float i = xs; i < xe; i += xstep)
{
for(float j = ys; j <= ye; j += ystep)
{
Color c = new Color(0,100+(abs((int)i)%50)*3,100+(abs((int)j)%50)*3);
ComplexNumber cn = new ComplexNumber(i/10,j/10);
ret[0].add(cn);
ret[1].add(c);
}
}
return ret;
}
ArrayList[] createCircle(float x, float y, float xstrech, float ystrech, float r, float ang)
{
ArrayList[] ret = new ArrayList[2];
ret[0] = new ArrayList();
ret[1] = new ArrayList();
for(float i = 0; i < TWO_PI; i += ang)
{
Color c = new Color(0,100+(int)((i*1000)%100),150);
ComplexNumber cn = new ComplexNumber(xstrech*(x+r*cos(i))/10,ystrech*(y+r*sin(i))/10);
ret[0].add(cn);
ret[1].add(c);
}
return ret;
}
ArrayList[] createFilledCircle(float x, float y, float xstrech, float ystrech, float r, float gap, float ang)
{
ArrayList[] ret = new ArrayList[2];
ret[0] = new ArrayList();
ret[1] = new ArrayList();
for(float i = gap; i < r; i += gap)
{
for(float j = 0; j < TWO_PI; j += ang)
{
Color c = new Color(0,100+(int)(i%100),200-(int)(j%100));
ComplexNumber cn = new ComplexNumber(xstrech*(x+i*cos(j))/10,ystrech*(y+i*sin(j))/10);
ret[0].add(cn);
ret[1].add(c);
}
}
return ret;
}
ArrayList[] createLine(float xs, float ys, float xe, float ye, float gap)
{
ArrayList[] ret = new ArrayList[2];
ret[0] = new ArrayList();
ret[1] = new ArrayList();
if(xe-xs == 0)
{
for(float i = 0; i < abs(ye-ys); i += gap)
{
Color c = new Color(0,100+(int)(i%100),150);
ComplexNumber cn = new ComplexNumber(xs, ys + i);
ret[0].add(cn);
ret[1].add(c);
}
}
else
{
float gradient = (ye - ys)/(xe - xs);
for(float i = 0; i < abs(xe-xs); i += gap)
{
Color c = new Color(0,50+100*(int)(i/abs(xe-xs)),125);
ComplexNumber cn = new ComplexNumber(xs + i, ys + i*gradient);
ret[0].add(cn);
ret[1].add(c);
}
}
return ret;
}
ArrayList[] createFormula(String formula, float xs, float xe, float dx)
{
ArrayList[] ret = new ArrayList[2];
ret[0] = new ArrayList();
ret[1] = new ArrayList();
for(float i = xs; i < xe; i += dx)
{
Color c = new Color(0,100+(int)(i%75),100+(int)(i%63));
ComplexNumber cn = new ComplexNumber(i,evalFormula(formula,i));
ret[0].add(cn);
ret[1].add(c);
}
return ret;
}
float evalFormula(String formula, float x)
{
fParser.addVariable("x",(double)x);
fParser.parseExpression(formula);
return (float)fParser.getValue();
}
void CalculateComplexs()
{
ArrayList stor = (ArrayList)complexs.clone();
complexs.clear();
boolean fail = false;
float step = arr.size()/20;
for(int i = 0; i < arr.size(); i++)
{
if(i % step == 0)
println("Complexs: " + Float.toString(round(100*(float)i/arr.size())) + " %");
ComplexNumber cn = (ComplexNumber)arr.get(i);
ComplexNumber tcn = transform.Invoke(cn);
if((tcn.real == Float.MAX_VALUE) && (tcn.imaginary == Float.MAX_VALUE))
{
fail = true;
complexs = stor;
break;
}
else
{
complexs.add(tcn);
}
}
status("Complexs: 100.0 %");
if(fail == false)
outputError.setValue("Finished Calculation");
}
ComplexNumber evalString(String str, ComplexNumber cn, String var)
{
if(str.trim() != "")
{
parser.addVariable(var, (double)cn.real, (double)cn.imaginary);
parser.parseExpression(str);
Complex c = parser.getComplexValue();
if(c == null)
{
outputError.setValue("Error: incorrect syntax");
return new ComplexNumber(Float.MAX_VALUE, Float.MAX_VALUE);
}
else
return new ComplexNumber((float)c.re(), (float)c.im());
}
else
return cn;
}
boolean ClampChoose(float min, float max, float num)
{
boolean ret = true;
if(num < min) ret = false;
else if(num > max) ret = false;
return ret;
}
GUIController guic;
IFButton outputBtn;
IFTextField outputTrans;
IFLabel[] labelsr = new IFLabel[6];
IFLabel[] labelsl = new IFLabel[6];
IFButton resetBtnr;
IFButton resetBtnl;
IFTextField outputError;
IFButton inputBtn;
IFTextField inputTrans;
IFTextField inputError;
IFButton helpBtn;
IFButton examplesBtn;
GUIController guic_examples[];
IFButton[] examplesBtns;
IFButton functionHelpBtn;
void InitialiseGUI()
{
guic = new GUIController(this);
outputTrans = new IFTextField("output",width/2+15,(int)h+15,270);
outputTrans.setValue("z^2");
outputBtn = new IFButton("Do",outputTrans.getX() + outputTrans.getWidth() + 10,(int)h+15,60,20);
outputBtn.addActionListener(this);
examplesBtn = new IFButton("Examples!",outputBtn.getX() + outputBtn.getWidth() + 10,outputBtn.getY(),80,20);
examplesBtn.addActionListener(this);
labelsr[0] = new IFLabel("Zoom Factor:",outputTrans.getX(), outputTrans.getY() + outputTrans.getHeight() + 15);
labelsr[1] = new IFLabel("1x",outputTrans.getX() + 75, labelsr[0].getY());
labelsr[2] = new IFLabel("Offset X:",labelsr[1].getX() + 100, labelsr[0].getY());
labelsr[3] = new IFLabel("0",labelsr[2].getX() + 55, labelsr[0].getY());
labelsr[4] = new IFLabel("Offset Y:",labelsr[3].getX() + 75, labelsr[0].getY());
labelsr[5] = new IFLabel("0",labelsr[4].getX() + 55, labelsr[0].getY());
resetBtnr = new IFButton("Reset",labelsr[0].getX(),labelsr[0].getY() + 20);
resetBtnr.addActionListener(this);
outputError = new IFTextField("",resetBtnr.getX() + resetBtnr.getWidth() + 45, resetBtnr.getY(),270);
inputTrans = new IFTextField("input",15,(int)h+15,300);
inputTransOrig = "grid(-300, -300, 300, 300, 10, 10)";
inputTrans.setValue(inputTransOrig);
inputBtn = new IFButton("Do",inputTrans.getX() + inputTrans.getWidth() + 5,(int)h+15,60,20);
inputBtn.addActionListener(this);
helpBtn = new IFButton("Help",inputBtn.getX() + inputBtn.getWidth() + 5,inputBtn.getY(),60,20);
helpBtn.addActionListener(this);
labelsl[0] = new IFLabel("Zoom Factor:",15, inputTrans.getY() + inputTrans.getHeight() + 15);
labelsl[1] = new IFLabel("1x",labelsl[0].getX() + 75, labelsl[0].getY());
labelsl[2] = new IFLabel("Offset X:",labelsl[1].getX() + 100, labelsl[0].getY());
labelsl[3] = new IFLabel("0",labelsl[2].getX() + 55, labelsl[0].getY());
labelsl[4] = new IFLabel("Offset Y:",labelsl[3].getX() + 75, labelsl[0].getY());
labelsl[5] = new IFLabel("0",labelsl[4].getX() + 55, labelsl[0].getY());
resetBtnl = new IFButton("Reset",labelsl[0].getX(),labelsl[0].getY() + 20);
resetBtnl.addActionListener(this);
inputError = new IFTextField("",resetBtnl.getX() + resetBtnl.getWidth() + 45, resetBtnl.getY(),270);
functionHelpBtn = new IFButton("Function Help",width/2-105,55,100, 20);
functionHelpBtn.addActionListener(this);
// Evens are el, odds are er!!!!!
examplesBtns = new IFButton[el.length+er.length];
guic_examples = new GUIController[el.length+er.length+1]; // +1 for the "Function Help" button.
for(int i = 0; i < examplesBtns.length; i+=2)
{
examplesBtns[i] = new IFButton("Test", width/2-55, 255+i*10-3, 40, 20);
examplesBtns[i].addActionListener(this);
guic_examples[i] = new GUIController(this);
examplesBtns[i+1] = new IFButton("Test", width-55, 255+i*10-3, 40, 20);
examplesBtns[i+1].addActionListener(this);
guic_examples[i+1] = new GUIController(this);
}
guic_examples[examplesBtns.length-1] = new GUIController(this);
guic.add(outputTrans);
guic.add(outputBtn);
guic.add(examplesBtn);
GUIControllerAddRange(guic,labelsr);
guic.add(resetBtnr);
guic.add(outputError);
guic.add(inputTrans);
guic.add(inputBtn);
GUIControllerAddRange(guic,labelsl);
guic.add(resetBtnl);
guic.add(inputError);
guic.add(helpBtn);
}
void GUIControllerAddRange(GUIController g, IFLabel[] ifs)
{
for(int i = 0; i < ifs.length; i++)
{
g.add(ifs[i]);
}
}
void actionPerformed(GUIEvent e)
{
println("Component: " + e.getSource());
println ("Message: " + e.getMessage());
if(e.getSource() == outputBtn)
{
final String str = outputTrans.getValue();
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return evalString(str,cn,"z");
}
};
rcd();
}
else if(e.getSource() == resetBtnr)
{
zoomr = 1;
offsetrx = 0;
offsetry = 0;
rd();
}
else if(e.getSource() == inputBtn)
{
final String in = inputTrans.getValue().trim().replace(" ","");
if(in.contains("func("))
{
Pattern pattern = Pattern.compile("func\\((.*),(\\-?[0-9\\.]*),(\\-?[0-9\\.]*),(\\-?[0-9\\.]*)\\)");
Matcher m = pattern.matcher(in);
if(m.matches())
{
final String[] s = new String[] {
m.group(1), m.group(2), m.group(3), m.group(4) };
input = new ArrayDelegate() {
ArrayList[] Invoke() {
return createFormula(s[0], Float.valueOf(s[1]).floatValue(), Float.valueOf(s[2]).floatValue(), Float.valueOf(s[3]).floatValue() );
}
};
}
else
{
inputError.setValue("Error: format = func(eqn,num,num,num)");
}
CalculateInitials();
}
else
{
ChangeIntialDelegate(in);
}
rcd();
}
else if(e.getSource() == resetBtnl)
{
zooml = 1;
offsetlx = 0;
offsetly = 0;
rd();
}
else if(e.getSource() == helpBtn)
{
if(display == Display.Normal)
toHelp();
else if(display == Display.Help)
backFromHelp();
}
else if(e.getSource() == examplesBtn)
{
if(display == Display.Normal)
toExamples();
else if(display == Display.Examples)
backFromExamples();
else if(display == Display.FunctionHelp)
{
examplesBtn.setLabel("Examples!");
display = Display.Normal;
rd();
}
}
else if(display == Display.Examples)
{
testExampleButtonActions(e);
}
}
void toHelp()
{
helpBtn.setLabel("Back");
display = Display.Help;
}
void backFromHelp()
{
helpBtn.setLabel("Help");
display = Display.Normal;
rd();
}
void toExamples()
{
examplesBtn.setLabel("Back!");
display = Display.Examples;
addTestExampleButtons();
}
void backFromExamples()
{
examplesBtn.setLabel("Examples!");
display = Display.Normal;
removeTestExampleButtons();
rd();
}
void addTestExampleButtons()
{
for(int i = 0; i < examplesBtns.length; i++)
{
guic_examples[i].add(examplesBtns[i]);
}
guic_examples[examplesBtns.length-1].add(functionHelpBtn);
}
void removeTestExampleButtons()
{
for(int i = 0; i < examplesBtns.length; i++)
{
guic_examples[i].remove(examplesBtns[i]);
}
guic_examples[examplesBtns.length-1].remove(functionHelpBtn);
}
void testExampleButtonActions(GUIEvent guie)
{
if(guie.getSource() == functionHelpBtn)
{
removeTestExampleButtons();
display = Display.FunctionHelp;
}
else
{
for(int i = 0; i < examplesBtns.length; i++)
{
if(guie.getSource() == examplesBtns[i])
{
backFromExamples();
if(i%2 == 0)
{
inputTrans.setValue(el[i/2]);
actionPerformed(new GUIEvent(inputBtn, "Clicked"));
}
else
{
outputTrans.setValue(er[(i-1)/2]);
actionPerformed(new GUIEvent(outputBtn, "Clicked"));
}
}
}
}
}
void mousePressed()
{
if(display == Display.Normal)
{
switch(mouseButton)
{
case LEFT:
if(mouseY < h)
{
if((mouseX < width/2)) zooml *= 2;
else zoomr *= 2;
rd();
}
break;
case RIGHT:
if(mouseY < h)
{
if((mouseX < width/2)) zooml /= 2;
else zoomr /= 2;
rd();
}
break;
}
}
}
void CheckCenterMouse()
{
if(mousePressed && (mouseButton == CENTER))
{
if(mouseY < h)
{
if(mouseX < width/2)
{
boolean nox = false, noy = false;
if(mouseX < width/6)
offsetlx += 50;
else if(mouseX > width*2/6)
offsetlx -= 50;
else
nox = true;
if(mouseY < h/3)
offsetly += 50;
else if(mouseY > h*2/3)
offsetly -= 50;
else
noy = true;
if(nox && noy)
{
if(mouseY < h/2)
zooml *= 2;
else
zooml /= 2;
}
rd();
}
else if(mouseX > width/2)
{
boolean nox = false, noy = false;
if(mouseX < width*4/6)
offsetrx += 50;
else if(mouseX > width*5/6)
offsetrx -= 50;
else
nox = true;
if(mouseY < h/3)
offsetry += 50;
else if(mouseY > h*2/3)
offsetry -= 50;
else
noy = true;
if(nox && noy)
{
if(mouseY < h/2)
zoomr *= 2;
else
zoomr /= 2;
}
rd();
}
}
}
}
void rd()
{
drawNow = true;
}
void rcd()
{
CalculateComplexs();
drawNow = true;
}
void keyPressed()
{
if(!(guic.getFocusStatusForComponent(outputTrans) || guic.getFocusStatusForComponent(inputTrans)) && (display == Display.Normal))
switch(key)
{
case 'n':
numberPoints = !numberPoints;
rcd();
break;
case '1':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return cn.Power(2);
}
};
rcd();
break;
case '2':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return cn.Power(3);
}
};
rcd();
break;
case '3':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return new ComplexNumber(1,0).Divide(cn.Add(1));
}
};
rcd();
break;
case '4':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return new ComplexNumber(1,0).Divide(cn.Power(2));
}
};
rcd();
break;
case '5':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return new ComplexNumber(1,0).Divide(cn.Roots(10)[1].Multiply(cn.Roots(10)[0]).Multiply(cn.Roots(10)[2]));
}
};
rcd();
break;
case '6':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return cn.Divide(cn.getConjugate());
}
};
rcd();
break;
case '7':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return cn.Roots(3)[1].Multiply(cn.Roots(4)[3]);
}
};
rcd();
break;
case '8':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return cn.getConjugate().Add(cn).Divide(cn.Roots(11)[4]);
}
};
rcd();
break;
case '9':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return cn.Roots(5)[2].Add(cn.Roots(2)[1]).Divide(cn.Add(40));
}
};
rcd();
break;
case '0':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return cn.Divide(cn.Roots(4)[3].getConjugate()).Divide(cn.Roots(4)[3]);
}
};
rcd();
break;
case '-':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return cn.Divide(cn.getConjugate().Add(cn.Roots(4)[2].Multiply(cn.Roots(4)[0])));
}
};
rcd();
break;
case '=':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return cn.Power(2.7);
}
};
rcd();
break;
case ']':
transform = new ComplexDelegate() {
ComplexNumber Invoke(ComplexNumber cn) {
return evalString("z^2.6",cn,"z");
}
};
rcd();
break;
case 'a':
offsetlx += 50;
rd();
break;
case 'w':
offsetly += 50;
rd();
break;
case 's':
offsetly -= 50;
rd();
break;
case 'd':
offsetlx -= 50;
rd();
break;
case 'j':
offsetrx += 50;
rd();
break;
case 'i':
offsetry += 50;
rd();
break;
case 'k':
offsetry -= 50;
rd();
break;
case 'l':
offsetrx -= 50;
rd();
break;
case 'z':
zooml *= 2;
rd();
break;
case 'x':
zooml /= 2;
rd();
break;
case 'm':
zoomr *= 2;
rd();
break;
case ',':
zoomr /= 2;
rd();
break;
}
}
String[] el = new String[]
{
"grid(-300, -300, 300, 300, 5, 5)",
"circle(0, 0, 300, pi/64)",
"ellipse(0, 0, 3, 4, 300, pi/70)",
"filledCircle(0, 0, 300, 15, pi/32)",
"filledEllipse(0, 0, 3, 4, 300, 20, pi/100)",
"line(100, -500, 100, 500, 5)",
"func(x^2/100, -500, 500, 2)",
"func(x^3/100, -500, 500, 2)",
"func(300*sin(x/100), -5000, 5000, 2)",
"func(10*(x % 11), -5000, 5000, 2)"
};
String[] er = new String[]
{
"z^2",
"z^3",
"1/z",
"1/z^2",
"root(z,5,1)*root(z,5,2)*root(z,5,3)",
"z/conj(root(z,4,4))/root(z,4,4)",
"z/(conj(z)+root(z,4,3))*root(z,4,1)",
"z^0.4",
"(z+1)^2/(z-1)^2",
"conj(z)/conj(root(-z,7,2))"
};
String[] fe = new String[]
{
"grid(startx, starty, endx, endy, xgap, ygap)",
"circle(centerx, centery, radius, angle_increment (in radians))",
"ellipse(centerx, centery, xmultiply, ymultiply, radius, angle_inc_radians)",
"filledCircle(centerx, centery, radius, gap, angle_inc)",
"filledEllipse(centerx, centery, xmultiply, ymultiply, radius, gap, angle_inc)",
"line(startx, starty, endx, endy, xgap)",
"func(expression_in_x, start_x_value, end_x_value, x_increment)"
};
void drawExamplesGUI()
{
textFont(calibri);
textSize(30);
textAlign(LEFT, TOP);
fill(0);
text("Examples",15,15);
textFont(calibri25);
textSize(25);
text("Input",15,55);
text("Output",width/2 + 15,55);
textFont(calibri14);
textSize(14);
for(int i = 0; i < fe.length; i++)
{
text(fe[i],15,95+i*20);
}
for(int i = 0; i < el.length; i++)
{
text(el[i],15,255+i*20);
}
float w = width/2+15;
text("Trig: sin(x), cos(x), tan(x), cosh(x), sinh(x), tanh(x)",w,95);
text("Trig: asin(x), acos(x), atan(x), acosh(x), asinh(x), atanh(x)",w,115);
text("Logs: log(x), ln(x), exp(x), mod(x,y) = x % y",w,135);
text("Others: abs(x), rand(x), sqrt(x), sum(x,y,z), if(condition,trueval,falseval)",w,155);
text("Complex: re(z), im(z), cmod(z), arg(z), conj(z), complex(x,y), polar(r,theta)",w,175);
text("Complex: root(z,x,y) - returns the yth complex xth root of unity of z",w,195);
text("Constants: e, pi, i",w,215);
for(int i = 0; i < er.length; i++)
{
text(er[i],w,255+i*20);
}
}
void drawHelpGUI()
{
textFont(calibri);
textSize(30);
textAlign(LEFT, TOP);
fill(0);
float w = width/2+15;
float l = width/4+15;
text("Help",15,15);
textFont(calibri25);
textSize(25);
text("Controls",15,55);
text("What are Complex Numbers?",w,55);
text("What is the \"angle increment?\"",w,295);
textFont(calibri14);
textSize(14);
text("W - Move left graph up", 15,95);
text("A - Move left graph left", 15,115);
text("S - Move left graph down", 15,135);
text("D - Move left graph right", 15,155);
text("I - Move right graph up",l,95);
text("J - Move right graph left",l,115);
text("K - Move right graph down",l,135);
text("L - Move right graph right",l,155);
text("N - Display numbers over each point",15,175);
text("Left Click: Zoom in",15,205);
text("Right Click: Zoom out",l,205);
text("Z/X - Zoom in/out for the left graph",15,225);
text("M/, - Zoom in/out for the right graph",l,225);
text("Middle Click: Depends on where you click on the graph:",15,245);
text("Complex Numbers are numbers that consist of a real number and an",w,95);
text("imaginary number. An imaginary number is one that is a multiple of i,",w,115);
text("where i is the square root of -1 (for example 3i or 4i). A real number",w,135);
text("is one that your used to, like 2 or -6 or 5.333452. A complex number",w,155);
text("is these two combined in the form \"a + bi\" (1 + 2i for example).",w,175);
text("This program takes a set of these complex numbers (such as a grid) and then",w,205);
text("applies some transformation to them, such as squaring them, and displays",w,225);
text("the results on the right hand side. It can use functions like conj(z) to",w,245);
text("find Conjugates and root() to find Complex Roots of Unity, as well as others.",w,265);
text("When drawing a circle, this defines is how many points should be used to",w,335);
text("create that circle. Simply use \"2*pi/x\" replacing x with the number of",w,355);
text("points you want to use.",w,375);
drawAngleIncrementExplaination(width*0.75,415,40,PI/8);
drawMiddleClickExplaination(15,260,(h-250)*4/3,h-250);
}
void drawMiddleClickExplaination(float x, float y, float wi, float hi)
{
stroke(0);
line(x,y,x+wi,y);
line(x,y,x,y+hi);
line(x+wi,y,x+wi,y+hi);
line(x,y+hi,x+wi,y+hi);
line(x+wi/2,y,x+wi/2,y+hi);
line(x,y+hi/2,x+wi,y+hi/2);
noStroke();
fill(#F5B800, 200);
rect(x,y,wi/3,hi);
rect(x+wi*2/3,y,wi/3,hi);
rect(x,y,wi,hi/3);
rect(x,y+hi*2/3,wi,hi/3);
fill(#B8F500, 200);
rect(x+wi/3, y+hi/3, wi/3,hi/6);
fill(#00F5B8, 200);
rect(x+wi/3, y+hi/2, wi/3,hi/6);
fill(0);
textFont(calibri14);
textSize(14);
textAlign(CENTER, CENTER);
text("Up and Left",x+wi/6, y+hi/6);
text("Up",x+wi/2, y+hi/6);
text("Up and Right",x+wi*5/6, y+hi/6);
text("Left",x+wi/6, y+hi/2);
text("Right",x+wi*5/6, y+hi/2);
text("Down and Left",x+wi/6, y+hi*5/6);
text("Down",x+wi/2, y+hi*5/6);
text("Down and Right",x+wi*5/6, y+hi*5/6);
text("Zoom In",x+wi/2, y+hi*5/12);
text("Zoom Out",x+wi/2, y+hi*7/12);
}
void drawAngleIncrementExplaination(float x, float y, float radius, float angle)
{
textFont(calibri14);
textSize(14);
textAlign(LEFT, CENTER);
angle -= PI/2;
stroke(0);
noFill();
ellipse(x,y,2*radius,2*radius);
line(x,y-radius,x,y);
line(x,y,x+radius*cos(angle),y+radius*sin(angle));
line(x+3,y-radius*2/3,x+radius+10,y-radius/3);
text("Angle Increment",x+radius+15,y-radius/3);
}
void drawFunctionHelpGUI()
{
textFont(calibri);
textSize(30);
textAlign(LEFT, TOP);
fill(0);
float w = width/2+15;
float q = w+10;
text("Function Help",15,15);
textFont(calibri25);
textSize(25);
text("Grid",15,55);
text("Circle",15,190);
text("Ellipse",15,325);
text("Filled Circle",w,55);
//text("Filled Ellipse",w,175);
text("Line",w,175);
text("Func",w,315);
textFont(calibri14);
textSize(14);
text("Creates a grid of points.",15,85);
text(fe[0],15,105);
text("startx/starty - The (x,y) position of the top left corner of the grid",25,125);
text("endx/endy - The (x,y) position of the bottom right corner of the grid",25,145);
text("gapx/gapy - The gap between each point in the x and y directions",25,165);
text("Creates a circle.",15,220);
text(fe[1],15,240);
text("centerx/centery - The (x,y) position of the center of the circle",25,260);
text("radius - The radius of the circle from the center",25,280);
text("angle increment - See \"Help\" button after going \"Back!\"",25,300);
text("Creates an ellipse.",15,355);
text(fe[2],15,375);
text("center/centery/radius/angle_increment - See \"Circle\"",25,395);
text("xmultiply/ymultiply - The amount the radius is streched by in the x/y direction",25,415);
text("Creates a number of concentric circles.",w,85);
text(fe[3],w,105);
text("center/centery/radius/angle_increment - See \"Circle\"",q,125);
text("gap - The difference in radius between each circle",q,145);
/*text("Creates a number of concentric ellipses.",w,205);
text(fe[4],w,225);
text("center/centery/radius/xmultiply/ymultiply/angle_increment - See \"Ellipse\"",q,245);
text("gap - The difference in unmultipled radius between each ellipse",q,265);*/
text("Creates a straight line between two points.",w,205);
text(fe[5],w,225);
text("startx/starty - The (x,y) position of the start of the line",q,245);
text("endx/endy - The (x,y) position of the end of the line",q,265);
text("xgap - The difference between the x-coords between to consecutive points",q,285);
text("Draws out a mathematical function in the form y = f(x).",w,345);
text(fe[5],w,365);
text("expression_in_x - An expression that uses x as variable",q,385);
text("start/end_x_value - The x value range to apply the expression over",q,405);
text("x_increment - The difference in x between two consecutive points",q,425);
}