434 lines
14 KiB
Plaintext
434 lines
14 KiB
Plaintext
|
|
/* =================================================================================
|
|
The Graph class contains functions and variables that have been created to draw
|
|
graphs. Here is a quick list of functions within the graph class:
|
|
|
|
Graph(int x, int y, int w, int h,color k)
|
|
DrawAxis()
|
|
Bar([])
|
|
smoothLine([][])
|
|
DotGraph([][])
|
|
LineGraph([][])
|
|
|
|
=================================================================================*/
|
|
|
|
|
|
class Graph
|
|
{
|
|
float maxY = 0;
|
|
float maxX = 0;
|
|
int maxI = 0;
|
|
boolean Dot=true; // Draw dots at each data point if true
|
|
boolean RightAxis; // Draw the next graph using the right axis if true
|
|
boolean ErrorFlag=false; // If the time array isn't in ascending order, make true
|
|
boolean ShowMouseLines=true; // Draw lines and give values of the mouse position
|
|
|
|
int xDiv=5, yDiv=5; // Number of sub divisions
|
|
int xPos, yPos; // location of the top left corner of the graph
|
|
int Width, Height; // Width and height of the graph
|
|
|
|
|
|
color GraphColor;
|
|
color BackgroundColor=color(255);
|
|
color StrokeColor=color(180);
|
|
|
|
String Title="Title"; // Default titles
|
|
String xLabel="x - Label";
|
|
String yLabel="y - Label";
|
|
|
|
float yMax=1024, yMin=0; // Default axis dimensions
|
|
float xMax=10, xMin=0;
|
|
float yMaxRight=1024, yMinRight=0;
|
|
|
|
// PFont Font; // Selected font used for text
|
|
|
|
// int Peakcounter=0,nPeakcounter=0;
|
|
|
|
Graph(int x, int y, int w, int h, color k) { // The main declaration function
|
|
xPos = x;
|
|
yPos = y;
|
|
Width = w;
|
|
Height = h;
|
|
GraphColor = k;
|
|
}
|
|
|
|
|
|
void DrawAxis() {
|
|
|
|
/* =========================================================================================
|
|
Main axes Lines, Graph Labels, Graph Background
|
|
========================================================================================== */
|
|
|
|
fill(BackgroundColor);
|
|
color(0);
|
|
stroke(StrokeColor);
|
|
strokeWeight(1);
|
|
int t=60;
|
|
|
|
rect(xPos-t*1.6, yPos-t, Width+t*2.5, Height+t*2); // outline
|
|
textAlign(CENTER);
|
|
textSize(18);
|
|
float c=textWidth(Title);
|
|
fill(BackgroundColor);
|
|
color(0);
|
|
stroke(0);
|
|
strokeWeight(1);
|
|
rect(xPos+Width/2-c/2, yPos-35, c, 0); // Heading Rectangle
|
|
|
|
fill(0);
|
|
text(Title, xPos+Width/2, yPos-37); // Heading Title
|
|
textAlign(CENTER);
|
|
textSize(14);
|
|
text(xLabel, xPos+Width/2, yPos+Height+t/1.5); // x-axis Label
|
|
|
|
rotate(-PI/2); // rotate -90 degrees
|
|
text(yLabel, -yPos-Height/2, xPos-t*1.6+20); // y-axis Label
|
|
rotate(PI/2); // rotate back
|
|
|
|
textSize(10);
|
|
noFill();
|
|
stroke(0);
|
|
smooth();
|
|
strokeWeight(1);
|
|
//Edges
|
|
line(xPos-3, yPos+Height, xPos-3, yPos); // y-axis line
|
|
line(xPos-3, yPos+Height, xPos+Width+5, yPos+Height); // x-axis line
|
|
|
|
stroke(200);
|
|
if (yMin<0) {
|
|
line(xPos-7, // zero line
|
|
yPos+Height-(abs(yMin)/(yMax-yMin))*Height, //
|
|
xPos+Width,
|
|
yPos+Height-(abs(yMin)/(yMax-yMin))*Height
|
|
);
|
|
}
|
|
|
|
if (RightAxis) { // Right-axis line
|
|
stroke(0);
|
|
line(xPos+Width+3, yPos+Height, xPos+Width+3, yPos);
|
|
}
|
|
|
|
/* =========================================================================================
|
|
Sub-devisions for both axes, left and right
|
|
========================================================================================== */
|
|
|
|
stroke(0);
|
|
|
|
for (int x=0; x<=xDiv; x++) {
|
|
|
|
/* =========================================================================================
|
|
x-axis
|
|
========================================================================================== */
|
|
|
|
line(float(x)/xDiv*Width+xPos-3, yPos+Height, // x-axis Sub devisions
|
|
float(x)/xDiv*Width+xPos-3, yPos+Height+5);
|
|
|
|
textSize(10); // x-axis Labels
|
|
String xAxis=str(xMin+float(x)/xDiv*(xMax-xMin)); // the only way to get a specific number of decimals
|
|
String[] xAxisMS=split(xAxis, '.'); // is to split the float into strings
|
|
text(xAxisMS[0]+"."+xAxisMS[1].charAt(0), // ...
|
|
float(x)/xDiv*Width+xPos-3, yPos+Height+15); // x-axis Labels
|
|
}
|
|
|
|
|
|
/* =========================================================================================
|
|
left y-axis
|
|
========================================================================================== */
|
|
|
|
for (int y=0; y<=yDiv; y++) {
|
|
line(xPos-3, float(y)/yDiv*Height+yPos, // ...
|
|
xPos-7, float(y)/yDiv*Height+yPos); // y-axis lines
|
|
|
|
textAlign(RIGHT);
|
|
fill(20);
|
|
|
|
String yAxis=str(yMin+float(y)/yDiv*(yMax-yMin)); // Make y Label a string
|
|
String[] yAxisMS=split(yAxis, '.'); // Split string
|
|
|
|
text(yAxisMS[0]+"."+yAxisMS[1].charAt(0), // ...
|
|
xPos-15, float(yDiv-y)/yDiv*Height+yPos+3); // y-axis Labels
|
|
|
|
|
|
/* =========================================================================================
|
|
right y-axis
|
|
========================================================================================== */
|
|
|
|
if (RightAxis) {
|
|
|
|
color(GraphColor);
|
|
stroke(GraphColor);
|
|
fill(20);
|
|
|
|
line(xPos+Width+3, float(y)/yDiv*Height+yPos, // ...
|
|
xPos+Width+7, float(y)/yDiv*Height+yPos); // Right Y axis sub devisions
|
|
|
|
textAlign(LEFT);
|
|
|
|
String yAxisRight=str(yMinRight+float(y)/ // ...
|
|
yDiv*(yMaxRight-yMinRight)); // convert axis values into string
|
|
String[] yAxisRightMS=split(yAxisRight, '.'); //
|
|
|
|
text(yAxisRightMS[0]+"."+yAxisRightMS[1].charAt(0), // Right Y axis text
|
|
xPos+Width+15, float(yDiv-y)/yDiv*Height+yPos+3); // it's x,y location
|
|
|
|
noFill();
|
|
}
|
|
stroke(0);
|
|
}
|
|
}
|
|
|
|
|
|
/* =========================================================================================
|
|
Bar graph
|
|
========================================================================================== */
|
|
|
|
void Bar(float[] a, int from, int to) {
|
|
|
|
|
|
stroke(GraphColor);
|
|
fill(GraphColor);
|
|
|
|
if (from<0) { // If the From or To value is out of bounds
|
|
for (int x=0; x<a.length; x++) { // of the array, adjust them
|
|
rect(int(xPos+x*float(Width)/(a.length)),
|
|
yPos+Height-2,
|
|
Width/a.length-2,
|
|
-a[x]/(yMax-yMin)*Height);
|
|
}
|
|
}
|
|
|
|
else {
|
|
for (int x=from; x<to; x++) {
|
|
|
|
rect(int(xPos+(x-from)*float(Width)/(to-from)),
|
|
yPos+Height-2,
|
|
Width/(to-from)-2,
|
|
-a[x]/(yMax-yMin)*Height);
|
|
}
|
|
}
|
|
}
|
|
void Bar(float[] a ) {
|
|
|
|
stroke(GraphColor);
|
|
fill(GraphColor);
|
|
|
|
for (int x=0; x<a.length; x++) { // of the array, adjust them
|
|
rect(int(xPos+x*float(Width)/(a.length)),
|
|
yPos+Height-2,
|
|
Width/a.length-2,
|
|
-a[x]/(yMax-yMin)*Height);
|
|
}
|
|
}
|
|
|
|
|
|
/* =========================================================================================
|
|
Dot graph
|
|
========================================================================================== */
|
|
|
|
void DotGraph(float[] x, float[] y) {
|
|
|
|
for (int i=0; i<x.length; i++) {
|
|
strokeWeight(2);
|
|
stroke(GraphColor);
|
|
noFill();
|
|
smooth();
|
|
ellipse(
|
|
xPos+(x[i]-x[0])/(x[x.length-1]-x[0])*Width,
|
|
yPos+Height-(y[i]/(yMax-yMin)*Height)+(yMin)/(yMax-yMin)*Height,
|
|
2, 2
|
|
);
|
|
}
|
|
}
|
|
|
|
/* =========================================================================================
|
|
Streight line graph
|
|
========================================================================================== */
|
|
|
|
void LineGraph(float[] x, float[] y) {
|
|
|
|
for (int i=0; i<(x.length-1); i++) {
|
|
strokeWeight(2);
|
|
stroke(GraphColor);
|
|
noFill();
|
|
smooth();
|
|
line(xPos+(x[i]-x[0])/(x[x.length-1]-x[0])*Width,
|
|
yPos+Height-(y[i]/(yMax-yMin)*Height)+(yMin)/(yMax-yMin)*Height,
|
|
xPos+(x[i+1]-x[0])/(x[x.length-1]-x[0])*Width,
|
|
yPos+Height-(y[i+1]/(yMax-yMin)*Height)+(yMin)/(yMax-yMin)*Height);
|
|
}
|
|
}
|
|
|
|
/* =========================================================================================
|
|
smoothLine
|
|
========================================================================================== */
|
|
|
|
void smoothLine(float[] x, float[] y) {
|
|
|
|
float tempyMax=yMax, tempyMin=yMin;
|
|
|
|
if (RightAxis) {
|
|
yMax=yMaxRight;
|
|
yMin=yMinRight;
|
|
}
|
|
|
|
int counter=0;
|
|
int xlocation=0, ylocation=0;
|
|
|
|
// if(!ErrorFlag |true ){ // sort out later!
|
|
|
|
beginShape();
|
|
strokeWeight(6);
|
|
stroke(GraphColor);
|
|
noFill();
|
|
smooth();
|
|
maxY = 0;
|
|
//find max
|
|
for (int i=0; i<x.length; i++) {
|
|
|
|
if (maxY < y[i])
|
|
{
|
|
|
|
maxY =y[i];
|
|
maxI = i;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
for (int i=0; i<x.length; i++) {
|
|
|
|
/* ===========================================================================
|
|
Check for errors-> Make sure time array doesn't decrease (go back in time)
|
|
===========================================================================*/
|
|
if (i<x.length-1) {
|
|
if (x[i]>x[i+1]) {
|
|
|
|
ErrorFlag=true;
|
|
}
|
|
}
|
|
|
|
/* =================================================================================
|
|
First and last bits can't be part of the curve, no points before first bit,
|
|
none after last bit. So a streight line is drawn instead
|
|
================================================================================= */
|
|
|
|
if (i==0 || i==x.length-2)line(xPos+(x[i]-x[0])/(x[x.length-1]-x[0])*Width,
|
|
yPos+Height-(y[i]/(yMax-yMin)*Height)+(yMin)/(yMax-yMin)*Height,
|
|
xPos+(x[i+1]-x[0])/(x[x.length-1]-x[0])*Width,
|
|
yPos+Height-(y[i+1]/(yMax-yMin)*Height)+(yMin)/(yMax-yMin)*Height);
|
|
|
|
/* =================================================================================
|
|
For the rest of the array a curve (spline curve) can be created making the graph
|
|
smooth.
|
|
================================================================================= */
|
|
|
|
curveVertex( xPos+(x[i]-x[0])/(x[x.length-1]-x[0])*Width,
|
|
yPos+Height-(y[i]/(yMax-yMin)*Height)+(yMin)/(yMax-yMin)*Height);
|
|
|
|
/* =================================================================================
|
|
If the Dot option is true, Place a dot at each data point.
|
|
================================================================================= */
|
|
if (i == maxI)
|
|
{
|
|
ellipse(
|
|
xPos+(x[i]-x[0])/(x[x.length-1]-x[0])*Width,
|
|
yPos+Height-(y[i]/(yMax-yMin)*Height)+(yMin)/(yMax-yMin)*Height,
|
|
20, 20
|
|
);
|
|
}
|
|
if (Dot)ellipse(
|
|
xPos+(x[i]-x[0])/(x[x.length-1]-x[0])*Width,
|
|
yPos+Height-(y[i]/(yMax-yMin)*Height)+(yMin)/(yMax-yMin)*Height,
|
|
2, 2
|
|
);
|
|
|
|
/* =================================================================================
|
|
Highlights points closest to Mouse X position
|
|
=================================================================================*/
|
|
|
|
if ( abs(mouseX-(xPos+(x[i]-x[0])/(x[x.length-1]-x[0])*Width))<5 ) {
|
|
|
|
|
|
float yLinePosition = yPos+Height-(y[i]/(yMax-yMin)*Height)+(yMin)/(yMax-yMin)*Height;
|
|
float xLinePosition = xPos+(x[i]-x[0])/(x[x.length-1]-x[0])*Width;
|
|
strokeWeight(1);
|
|
stroke(240);
|
|
// line(xPos,yLinePosition,xPos+Width,yLinePosition);
|
|
strokeWeight(2);
|
|
stroke(GraphColor);
|
|
|
|
ellipse(xLinePosition, yLinePosition, 4, 4);
|
|
}
|
|
}
|
|
|
|
endShape();
|
|
|
|
yMax=tempyMax;
|
|
yMin=tempyMin;
|
|
float xAxisTitleWidth=textWidth(str(map(xlocation, xPos, xPos+Width, x[0], x[x.length-1])));
|
|
|
|
|
|
if ((mouseX>xPos&mouseX<(xPos+Width))&(mouseY>yPos&mouseY<(yPos+Height))) {
|
|
if (ShowMouseLines) {
|
|
// if(mouseX<xPos)xlocation=xPos;
|
|
if (mouseX>xPos+Width)xlocation=xPos+Width;
|
|
else xlocation=mouseX;
|
|
stroke(200);
|
|
strokeWeight(0.5);
|
|
fill(255);
|
|
color(50);
|
|
// Rectangle and x position
|
|
line(xlocation, yPos, xlocation, yPos+Height);
|
|
rect(xlocation-xAxisTitleWidth/2-10, yPos+Height-16, xAxisTitleWidth+20, 12);
|
|
|
|
textAlign(CENTER);
|
|
fill(160);
|
|
text(map(xlocation, xPos, xPos+Width, x[0], x[x.length-1]), xlocation, yPos+Height-6);
|
|
|
|
// if(mouseY<yPos)ylocation=yPos;
|
|
if (mouseY>yPos+Height)ylocation=yPos+Height;
|
|
else ylocation=mouseY;
|
|
|
|
// Rectangle and y position
|
|
stroke(200);
|
|
strokeWeight(0.5);
|
|
fill(255);
|
|
color(50);
|
|
|
|
line(xPos, ylocation, xPos+Width, ylocation);
|
|
int yAxisTitleWidth=int(textWidth(str(map(ylocation, yPos, yPos+Height, y[0], y[y.length-1]))) );
|
|
rect(xPos-15+3, ylocation-6, -60, 12);
|
|
|
|
textAlign(RIGHT);
|
|
fill(GraphColor);//StrokeColor
|
|
// text(map(ylocation,yPos+Height,yPos,yMin,yMax),xPos+Width+3,yPos+Height+4);
|
|
text(map(ylocation, yPos+Height, yPos, yMin, yMax), xPos -15, ylocation+4);
|
|
if (RightAxis) {
|
|
|
|
stroke(200);
|
|
strokeWeight(0.5);
|
|
fill(255);
|
|
color(50);
|
|
|
|
rect(xPos+Width+15-3, ylocation-6, 60, 12);
|
|
textAlign(LEFT);
|
|
fill(160);
|
|
text(map(ylocation, yPos+Height, yPos, yMinRight, yMaxRight), xPos+Width+15, ylocation+4);
|
|
}
|
|
noStroke();
|
|
noFill();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void smoothLine(float[] x, float[] y, float[] z, float[] a ) {
|
|
GraphColor=color(188, 53, 53);
|
|
smoothLine(x, y);
|
|
GraphColor=color(193-100, 216-100, 16);
|
|
smoothLine(z, a);
|
|
}
|
|
}
|
|
|
|
|