commit 4c99999b02e2b1aca531fecde726a7ef54b3d3d1 Author: Fisch Date: Sun Jun 9 16:43:53 2019 +0200 initial commit diff --git a/Visualization.pde b/Visualization.pde new file mode 100644 index 0000000..471c95b --- /dev/null +++ b/Visualization.pde @@ -0,0 +1,297 @@ + +abstract class Visualization +{ + float value=0; + float value2=1; + + PVector posOrigin = new PVector(100,100); + float valueMin=0; + float valueMax=100; + float value2Min=0; //value 2 for twodimensional visualization + float value2Max=1; + + float valueMinRecord = Float.NaN; //nan means no value here + float valueMaxRecord = Float.NaN; + float value2MinRecord = Float.NaN; //nan means no value here + float value2MaxRecord = Float.NaN; + boolean showMinMax=false; + + //default colors (not all used by every implementation) + color cmain = color(0,0,0); + color cscale = color(100,100,100); + color cborder = color(204,104,0); + color cmin = color(0,150,0); + color cmax = color(150,0,0); + color ctext = color(0,0,0); + + int textsize=12; + float textWidthScale=1.0/2*this.textsize/2; //*text.length()* + int showdecimals=2; + + String title=""; + + + public abstract void drawVis(); + public void setValue(float pv){ + this.value=constrain(pv,valueMin,valueMax); + if (this.showMinMax){ + if (Float.isNaN(this.valueMinRecord) || this.valuethis.valueMaxRecord){ + this.valueMaxRecord=this.value; + } + } + } + + public void setValue2(float pv){ + this.value2=constrain(pv,valueMin,valueMax); + if (this.showMinMax){ + if (Float.isNaN(this.value2MinRecord) || this.value2this.value2MaxRecord){ + this.value2MaxRecord=this.value2; + } + } + } + + public float getValueNormalized() { + return (this.value-this.valueMin)/(this.valueMax-this.valueMin); + } + public float getValueMinNormalized() { + return (this.valueMinRecord-this.valueMin)/(this.valueMax-this.valueMin); + } + public float getValueMaxNormalized() { + return (this.valueMaxRecord-this.valueMin)/(this.valueMax-this.valueMin); + } + + public float getValue2Normalized() { + return (this.value2-this.value2Min)/(this.value2Max-this.value2Min); + } + public float getValue2MinNormalized() { + return (this.value2MinRecord-this.value2Min)/(this.value2Max-this.value2Min); + } + public float getValue2MaxNormalized() { + return (this.value2MaxRecord-this.value2Min)/(this.value2Max-this.value2Min); + } + + public void setShowMinMax(boolean pshowMinMax){ + this.showMinMax = pshowMinMax; + } + + public void setcmain(color pc){ + this.cmain=pc; + } + public void setcscale(color pc){ + this.cscale=pc; + } + public void setcborder(color pc){ + this.cborder=pc; + } + public void setcmin(color pc){ + this.cmin=pc; + } + public void setcmax(color pc){ + this.cmax=pc; + } + public void setctext(color pc){ + this.ctext=pc; + } + + public void setTitle(String pt) { + this.title=pt; + } + + public void setshowdecimals(int pd) { + this.showdecimals=pd; + } + + public String getFormattedValue(double pv){ + if( ( (int)(pv*100)/100.0 )%1==0){ + return ""+(int)pv; + }else{ //has decimals + return String.format("%."+this.showdecimals+"f", pv); //limit decimal places + } + } + +} + +public class BarV extends Visualization { + PVector size = new PVector(10,100); + + public BarV(int px, int py, int pw, int ph, float pvmin, float pvmax) { + super.valueMin=pvmin; + super.valueMax=pvmax; + super.posOrigin= new PVector(px,py); //lower left corner + this.size = new PVector(pw,ph); //to the right and up + } + + public void drawVis() { + rectMode(CORNERS); + textSize(super.textsize); + + fill(super.cmain); noStroke(); + rect(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+this.size.x,super.posOrigin.y-( this.size.y*super.getValueNormalized()) ); + + + if (!Float.isNaN(super.valueMinRecord)){ + stroke(super.cmin); + line(super.posOrigin.x,super.posOrigin.y-( this.size.y*super.getValueMinNormalized()) ,super.posOrigin.x+this.size.x,super.posOrigin.y-( this.size.y*super.getValueMinNormalized()) ); + } + if (!Float.isNaN(super.valueMaxRecord)){ + stroke(super.cmax); + line(super.posOrigin.x, super.posOrigin.y-( this.size.y*super.getValueMaxNormalized()), super.posOrigin.x+this.size.x,super.posOrigin.y-( this.size.y*super.getValueMaxNormalized()) ); + } + + noFill(); stroke(this.cborder); + rect(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+this.size.x,super.posOrigin.y- this.size.y ); + + //text + fill(super.ctext); + text(super.getFormattedValue(super.valueMin),super.posOrigin.x+this.size.x+1,super.posOrigin.y+super.textsize/2); + text(super.getFormattedValue(super.valueMax),super.posOrigin.x+this.size.x+1,super.posOrigin.y-this.size.y+super.textsize/2); + text(super.getFormattedValue(super.value),super.posOrigin.x+this.size.x+1,super.posOrigin.y-this.size.y/2+super.textsize/2); + + //Title + text(super.title, super.posOrigin.x-super.title.length()*super.textWidthScale, super.posOrigin.y+super.textsize*1.5); + + } +} + +public class BarH extends Visualization { + PVector size = new PVector(10,100); + + public BarH(int px, int py, int pw, int ph,float pvmin, float pvmax) { + super.valueMin=pvmin; + super.valueMax=pvmax; + super.posOrigin= new PVector(px,py); //lower left corner + this.size = new PVector(pw,ph); //to the right and up + } + + public void drawVis() { + rectMode(CORNERS); + textSize(super.textsize); + + fill(super.cmain); noStroke(); + rect(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+( this.size.x*super.getValueNormalized()),super.posOrigin.y- this.size.y ); + + if (!Float.isNaN(super.valueMinRecord)){ + stroke(super.cmin); + line(super.posOrigin.x+( this.size.x*super.getValueMinNormalized()),super.posOrigin.y,super.posOrigin.x+( this.size.x*super.getValueMinNormalized()),super.posOrigin.y- this.size.y ); + } + if (!Float.isNaN(super.valueMaxRecord)){ + stroke(super.cmax); + line(super.posOrigin.x+( this.size.x*super.getValueMaxNormalized()),super.posOrigin.y,super.posOrigin.x+( this.size.x*super.getValueMaxNormalized()),super.posOrigin.y- this.size.y ); + } + + noFill(); stroke(super.cborder); + rect(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+this.size.x,super.posOrigin.y- this.size.y ); + + //text + fill(super.ctext); + text(super.getFormattedValue(super.valueMin),super.posOrigin.x-super.getFormattedValue(super.valueMin).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1); + text(super.getFormattedValue(super.valueMax),super.posOrigin.x+this.size.x-super.getFormattedValue(super.valueMax).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1); + text(super.getFormattedValue(super.value),super.posOrigin.x+this.size.x/2-super.getFormattedValue(super.value).length()*super.textWidthScale,super.posOrigin.y-this.size.y-1); + + + //Title + text(super.title, super.posOrigin.x+this.size.x/2-super.title.length()*super.textWidthScale,super.posOrigin.y+this.size.y+1); + + } +} + +public class Tacho extends Visualization { + int size; + + + public Tacho(int px, int py, int psize, float pvmin, float pvmax) { + super.valueMin=pvmin; + super.valueMax=pvmax; + super.posOrigin= new PVector(px,py); //circle center + this.size = psize; //radius from the center + } + + public void drawVis() { + rectMode(CORNERS); + textSize(super.textsize); + + stroke(super.cmain); + float angle=PI-super.getValueNormalized()*PI; //0=right, positive=CCW + line(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+cos(angle)*this.size*0.8 ,super.posOrigin.y-sin(angle)*this.size*0.8); //draw tacho needle + + if (!Float.isNaN(super.valueMinRecord)){ + stroke(this.cmin); + float angleMin=PI-super.getValueMinNormalized()*PI; //0=right, positive=CCW + line(super.posOrigin.x+cos(angleMin)*this.size*0.65 ,super.posOrigin.y-sin(angleMin)*this.size*0.65,super.posOrigin.x+cos(angleMin)*this.size*0.75 ,super.posOrigin.y-sin(angleMin)*this.size*0.75); //draw tacho needle min + } + if (!Float.isNaN(super.valueMaxRecord)){ + stroke(this.cmax); + float angleMax=PI-super.getValueMaxNormalized()*PI; //0=right, positive=CCW + line(super.posOrigin.x+cos(angleMax)*this.size*0.65 ,super.posOrigin.y-sin(angleMax)*this.size*0.65,super.posOrigin.x+cos(angleMax)*this.size*0.75 ,super.posOrigin.y-sin(angleMax)*this.size*0.75); //draw tacho needle max + } + + stroke(this.cscale); + fill(super.ctext); + float _steps=0.1; + for (float i=0;i<=1+_steps; i+=_steps){ + float a=PI-PI*i; + line(super.posOrigin.x+cos(a)*this.size*0.85 ,super.posOrigin.y-sin(a)*this.size*0.85 ,super.posOrigin.x+cos(a)*this.size ,super.posOrigin.y-sin(a)*this.size); + String _text=super.getFormattedValue(super.valueMin+(super.valueMax-super.valueMin)*i); + text(_text,super.posOrigin.x+cos(a)*this.size*1.1-_text.length()*super.textWidthScale-1 ,super.posOrigin.y-sin(a)*this.size*1.1+super.textsize/2-1); + } + + //text + text(super.getFormattedValue(super.value),super.posOrigin.x-super.getFormattedValue(super.value).length()*super.textWidthScale,super.posOrigin.y+super.textsize/2-this.size*0.3); + + //Title + text(super.title, super.posOrigin.x-super.title.length()*super.textWidthScale, super.posOrigin.y+super.textsize*1.5); + + } +} + + +public class Direction extends Visualization { + int size; + + + public Direction(int px, int py, int psize,float pvmin, float pvmax, float pvlmin, float pvlmax) { + super.valueMin=pvmin; + super.valueMax=pvmax; + super.posOrigin= new PVector(px,py); //center + this.size = psize; //radius from the center + + super.value2Min=pvlmin; + super.value2Max=pvlmax; + } + + + + public void drawVis() { + rectMode(CORNERS); + textSize(super.textsize); + + stroke(super.cborder); noFill(); + ellipseMode(RADIUS); //centerx, centery, width,height for ellipse + ellipse(super.posOrigin.x, super.posOrigin.y, this.size,this.size); + + stroke(super.cmain); + float angle=map(super.value,super.valueMin,super.valueMax,0,2*PI); + float _vecsize=this.size*( (super.value2-super.value2Min)/(super.value2Max-super.value2Min)); + line(super.posOrigin.x,super.posOrigin.y,super.posOrigin.x+cos(angle)*_vecsize,super.posOrigin.y-sin(angle)*_vecsize); + + line(super.posOrigin.x+cos(angle-0.1)*_vecsize*0.9,super.posOrigin.y-sin(angle-0.1)*_vecsize*0.9,super.posOrigin.x+cos(angle)*_vecsize,super.posOrigin.y-sin(angle)*_vecsize); //arrow + line(super.posOrigin.x+cos(angle+0.1)*_vecsize*0.9,super.posOrigin.y-sin(angle+0.1)*_vecsize*0.9,super.posOrigin.x+cos(angle)*_vecsize,super.posOrigin.y-sin(angle)*_vecsize); + + //text + fill(super.ctext); + text("d="+super.getFormattedValue(super.value),super.posOrigin.x-super.getFormattedValue(super.value).length()*super.textWidthScale,super.posOrigin.y+super.textsize/2-this.size*0.3); + if (super.value2