// Plot2D.java // This file contains the basic classes to draw 2D graphs. import java.awt.*; import java.util.*; public class Plot2D extends Panel { private Font font; private FontMetrics fm; public String x_label,y_label; protected Vector data_sets; private boolean draw_line=false; private double vertical_line; protected int bl_x,bl_y,tr_x,tr_y; private boolean auto_scale=true; protected double x_min=0,x_max=0,y_min=0,y_max=0; protected boolean log_x=false,log_y=false; // This acts like a matrix of doubles. Each row is an array of data. public Plot2D() { font=new Font("serif",Font.PLAIN,10); fm=this.getFontMetrics(font); x_label="X"; y_label="Y"; data_sets=new Vector(3,3); } public void AddDataSet(DataSet2D ds) { data_sets.addElement(ds); } public void RemoveDataSet(int which) { data_sets.removeElementAt(which); } public void RemoveAllData() { data_sets.removeAllElements(); } public void SetIndicatorLine(double x_val) { draw_line=true; vertical_line=x_val; } public void RemoveIndicatorLine() { draw_line=false; } public boolean ToggleAutoScale() { auto_scale=!auto_scale; return(auto_scale); } public void SetRange(double xmin,double ymin,double xmax,double ymax) { auto_scale=false; x_min=xmin; x_max=xmax; y_min=ymin; y_max=ymax; } public boolean ToggleLogX() { log_x=!log_x; return(log_x); } public boolean ToggleLogY() { log_y=!log_y; return(log_y); } // This function draws the graph and returns the Graphics. The // parameter is the row that is to be used for the x values. If // -1 is passed then the x values are the indices of the arrays. public void paint(Graphics g) { int i,j; DataSet2D ds; Point p1,p2; Point2D p2d; double x,y; int label_length; String x_min_label,y_min_label,x_max_label,y_max_label; TwoStrings ts; // Draw the axes and labels g.setColor(Color.black); g.fillRect(0,0,size().width,size().height); g.setColor(Color.white); g.setFont(font); g.drawString(y_label,0,fm.getHeight()); g.drawString(x_label,(size().width-fm.stringWidth(x_label))/2,size().height-2); // Draw legend if more than one data set is in this plot if(data_sets.size()>1) { int y_step; // Write out all strings in the proper colors y_step=fm.getHeight(); for(i=0; ix_max) x_max=x; y=ds.GetElement(j).y; if(yy_max) y_max=y; } } catch(DataSet.DataException de) { return; } } if((x_min==x_max) && (x_min==0.0)) { x_min-=1.0; x_max+=1.0; } x_min-=(x_max+x_min)*1e-2; x_max+=(x_max+x_min)*1e-2; if((y_min==y_max) && (y_min==0.0)) { y_min-=1.0; y_max+=1.0; } y_min-=(y_min+y_min)*1e-2; y_max+=(y_min+y_min)*1e-2; } // Add range labels y_min_label=Double.toString(y_min); y_max_label=Double.toString(y_max); ts=ConcatLabelStrings(y_min_label,y_max_label); y_min_label=ts.s1; y_max_label=ts.s2; x_min_label=Double.toString(x_min); x_max_label=Double.toString(x_max); ts=ConcatLabelStrings(x_min_label,x_max_label); x_min_label=ts.s1; x_max_label=ts.s2; label_length=Math.max(fm.stringWidth(y_min_label),fm.stringWidth(y_max_label)); g.setColor(Color.white); g.drawString(y_max_label,0,fm.getHeight()*2); g.drawString(y_min_label,0,size().height-fm.getHeight()-1); g.drawString(x_max_label,size().width-fm.stringWidth(x_max_label)-3,size().height-1); g.drawString(x_min_label,label_length+2,size().height-1); // Move these in for range text bl_x=label_length;; bl_y=size().height-fm.getHeight()-1; tr_x=size().width; tr_y=fm.getHeight()+1; g.setColor(Color.white); g.drawLine(bl_x,bl_y,bl_x,tr_y); g.drawLine(bl_x,bl_y,tr_x,bl_y); g.drawLine(bl_x,tr_y,bl_x+1,tr_y); g.drawLine(tr_x,bl_y,tr_x,bl_y-1); // Draw the plot p2d=new Point2D(); for(i=0; ix_min) && (vertical_line<=x_max)) { int px; g.setColor(Color.yellow); p2d.x=vertical_line; p2d.y=1; p2=ConvertPoint(p2d); if(p2!=null) g.drawLine(p2.x,bl_y,p2.x,tr_y); } } public void update(Graphics g) { paint(g); } protected Point ConvertPoint(Point2D p2d) { Point ret=new Point(0,0); if(((x_min<=0.0) && (log_x)) || ((y_min<=0.0) && (log_y))) return null; if(log_x) { if(p2d.x<=0.0) return null; ret.x=(int)(bl_x+Math.log(p2d.x/x_min)*(tr_x-bl_x)/Math.log(x_max/x_min)); } else { ret.x=(int)(bl_x+(p2d.x-x_min)*(tr_x-bl_x)/(x_max-x_min)); } if(log_y) { if(p2d.y<=0.0) return null; ret.y=(int)(bl_y+Math.log(p2d.y/y_min)*(tr_y-bl_y)/Math.log(y_max/y_min)); } else { ret.y=(int)(bl_y+(p2d.y-y_min)*(tr_y-bl_y)/(y_max-y_min)); } return(ret); } protected Point2D ConvertPoint(Point p) { Point2D ret=new Point2D(); if(((x_min<=0.0) && (log_x)) || ((y_min<=0.0) && (log_y))) return null; if(log_x) { ret.x=x_min*Math.exp((p.x-bl_x)*Math.log(x_max/x_min)/(tr_x-bl_x)); } else { ret.x=x_min+(p.x-bl_x)*(x_max-x_min)/(tr_x-bl_x); } if(log_y) { ret.y=y_min*Math.exp((p.y-bl_y)*Math.log(y_max/y_min)/(tr_y-bl_y)); } else { ret.y=y_min+(p.y-bl_y)*(y_max-y_min)/(tr_y-bl_y); } return ret; } private TwoStrings ConcatLabelStrings(String n1,String n2) { TwoStrings ret=new TwoStrings(); int pos1,pos2,j; pos1=n1.indexOf('.'); if(pos1<0) pos1=n1.length()-1; pos2=n2.indexOf('.'); if(pos2<0) pos2=n2.length()-1; for(; (pos1=n1.length()) pos1=n1.length()-1; if(pos2>=n2.length()) pos2=n2.length()-1; ret.s1=n1.substring(0,pos1); ret.s2=n2.substring(0,pos2); for(j=pos1+1; (j