All Downloads are FREE. Search and download functionalities are using the official Maven repository.

JSci.awt.Histogram.vm Maven / Gradle / Ivy

package ${package};

import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
#if(!($api == "AWT"))import JSci.awt.*;
#end
import JSci.maths.ExtraMath;

/**
* A histogram ${api} component.
* The y-values are the counts for each bin.
* Each bin is specified by an interval.
* So that y[i] contains the counts for the bin from x[i-1] to x[i].
* The value of y[0] is disregarded.
* @version 1.0
* @author Mark Hale
*/
public class ${className} extends ${extendsClassName} implements GraphDataListener {
        /**
        * Data model.
        */
        protected Graph2DModel model;
        /**
        * Origin.
        */
        protected Point origin = new Point();
        /**
        * Series colors.
        */
        protected Color seriesColor[]={Color.blue,Color.green,Color.red,Color.yellow,Color.cyan,Color.lightGray,Color.magenta,Color.orange,Color.pink};
        /**
        * Axis numbering.
        */
        protected boolean numbering = true;
        protected NumberFormat xNumberFormat = new DecimalFormat("${numberFormat}");
        protected NumberFormat yNumberFormat = new DecimalFormat("${numberFormat}");
        protected boolean gridLines = false;
        private final Color gridLineColor = Color.lightGray;
        /**
        * Axis scaling.
        */
        private float xScale,yScale;
        /**
        * Axis extrema.
        */
        private float minX, minY, maxX, maxY;
        private boolean autoXExtrema=true, autoYExtrema=true;
        private float xGrowth, yGrowth;
        /**
        * Axis numbering increment.
        */
        private final float xIncPixels = 40.0f;
        private final float yIncPixels = 40.0f;
        private float xInc,yInc;
        private boolean autoXInc=true,autoYInc=true;
        /**
        * Padding.
        */
        protected final int scalePad=5;
        protected final int axisPad=25;
        protected int leftAxisPad;
        /**
        * Constructs a histogram.
        */
        public ${className}(Graph2DModel gm) {
                model=gm;
                model.addGraphDataListener(this);
                dataChanged(new GraphDataEvent(model));
        }
        /**
        * Sets the data plotted by this graph to the specified data.
        */
        public final void setModel(Graph2DModel gm) {
                model.removeGraphDataListener(this);
                model=gm;
                model.addGraphDataListener(this);
                dataChanged(new GraphDataEvent(model));
        }
        /**
        * Returns the model used by this graph.
        */
        public final Graph2DModel getModel() {
                return model;
        }
        /**
        * Implementation of GraphDataListener.
        * Application code will not use this method explicitly, it is used internally.
        */
        public void dataChanged(GraphDataEvent e) {
                if(e.isIncremental()) {
                        Graphics g = getOffscreenGraphics();
                        if(g == null)
                                return;
                        final int series = e.getSeries();
                        if(series == GraphDataEvent.ALL_SERIES) {
                                model.firstSeries();
                                int n = 0;
                                do {
                                        final int i = model.seriesLength() - 1;
                                        incrementalRescale(model.getXCoord(i), model.getYCoord(i));
                                        g.setColor(seriesColor[n]);
                                        drawDataPoint(g, i);
                                        n++;
                                } while(model.nextSeries());
                        } else {
                                model.firstSeries();
                                int n=0;
                                for(; nseriesColor.length) {
                                Color tmp[]=seriesColor;
                                seriesColor=new Color[n];
                                System.arraycopy(tmp,0,seriesColor,0,tmp.length);
                                for(int i=tmp.length; i maxX)
                        max = autoXExtrema ? Math.max(x, maxX+xGrowth) : maxX+xGrowth;
                else
                        max = maxX;
                rescaleX(min, max);

                if(y < minY)
                        min = autoYExtrema ? Math.min(y, minY-yGrowth) : minY-yGrowth;
                else
                        min = minY;
                if(y > maxY)
                        max = autoYExtrema ? Math.max(y, maxY+yGrowth) : maxY+yGrowth;
                else
                        max = maxY;
                rescaleY(min, max);
        }
        /**
        * Turns axis numbering on/off.
        * Default is on.
        */
        public final void setNumbering(boolean flag) {
                numbering=flag;
                leftAxisPad=axisPad;
                if(numbering && getFont() != null) {
                        // adjust leftAxisPad to accomodate y-axis numbering
                        final FontMetrics metrics = getFontMetrics(getFont());
                        final int maxYNumLen = metrics.stringWidth(yNumberFormat.format(maxY));
                        final int minYNumLen = metrics.stringWidth(yNumberFormat.format(minY));
                        int yNumPad = Math.max(minYNumLen, maxYNumLen);
                        if(minX<0.0f) {
                                final int negXLen = (int)((Math.max(getSize().width,getMinimumSize().width)-2*(axisPad+scalePad))*minX/(minX-maxX));
                                yNumPad = Math.max(yNumPad-negXLen, 0);
                        }
                        leftAxisPad += yNumPad;
                }
                rescale();
        }
        public void addNotify() {
                super.addNotify();
                // getFont() is now not null
                // recalculate padding
                setNumbering(numbering);
        }
        /**
        * Sets the display format used for axis numbering.
        * Convenience method.
        * @see #setXNumberFormat(NumberFormat)
        * @see #setYNumberFormat(NumberFormat)
        */
        public final void setNumberFormat(NumberFormat format) {
                xNumberFormat = format;
                yNumberFormat = format;
                setNumbering(numbering);
        }
        /**
        * Sets the display format used for x-axis numbering.
        */
        public final void setXNumberFormat(NumberFormat format) {
                xNumberFormat = format;
                setNumbering(numbering);
        }
        /**
        * Sets the display format used for y-axis numbering.
        */
        public final void setYNumberFormat(NumberFormat format) {
                yNumberFormat = format;
                setNumbering(numbering);
        }
        /**
        * Turns grid lines on/off.
        * Default is off.
        */
        public final void setGridLines(boolean flag) {
                gridLines = flag;
                redraw();
        }
        /**
        * Sets the x-axis numbering increment.
        * @param dx use 0.0f for auto-adjusting (default).
        */
        public final void setXIncrement(float dx) {
                if(dx < 0.0f) {
                        throw new IllegalArgumentException("Increment should be positive.");
                } else if(dx == 0.0f) {
                        if(!autoXInc) {
                                autoXInc = true;
                                rescale();
                        }
                } else {
                        autoXInc = false;
                        if(dx != xInc) {
                                xInc = dx;
                                rescale();
                        }
                }
        }
        /**
        * Returns the x-axis numbering increment.
        */
        public final float getXIncrement() {
                return xInc;
        }
        /**
        * Sets the y-axis numbering increment.
        * @param dy use 0.0f for auto-adjusting (default).
        */
        public final void setYIncrement(float dy) {
                if(dy < 0.0f) {
                        throw new IllegalArgumentException("Increment should be positive.");
                } else if(dy == 0.0f) {
                        if(!autoYInc) {
                                autoYInc = true;
                                rescale();
                        }
                } else {
                        autoYInc = false;
                        if(dy != yInc) {
                                yInc = dy;
                                rescale();
                        }
                }
        }
        /**
        * Returns the y-axis numbering increment.
        */
        public final float getYIncrement() {
                return yInc;
        }
        /**
        * Sets the minimum/maximum values on the x-axis.
        * Set both min and max to 0.0f for auto-adjusting (default).
        */
        public final void setXExtrema(float min, float max) {
                if(min==0.0f && max==0.0f) {
                        autoXExtrema=true;
                        // determine min and max from model
                        min=Float.POSITIVE_INFINITY;
                        max=Float.NEGATIVE_INFINITY;
                        float tmp;
                        model.firstSeries();
                        do {
                                for(int i=0;i 0.0f;
                if(autoYInc) {
                        yInc = (float) ExtraMath.round((double)yIncPixels/(double)yScale, 1);
                        if(yInc == 0.0f)
                                yInc = Float.MIN_VALUE;
                }
                //assert yInc > 0.0f;
                origin.x=leftAxisPad-Math.round(minX*xScale);
                origin.y=thisHeight-axisPad+Math.round(minY*yScale);
                redraw();
        }
        /**
        * Converts a data point to screen coordinates.
        */
        protected final Point dataToScreen(float x,float y) {
                return new Point(origin.x+Math.round(xScale*x), origin.y-Math.round(yScale*y));
        }
        /**
        * Converts a screen point to data coordinates.
        */
        protected final Point2D.Float screenToData(Point p) {
                double x = (double)(p.x-origin.x) / (double)xScale;
                double y = (double)(origin.y-p.y) / (double)yScale;
                return new Point2D.Float((float)x, (float)y);
        }
        /**
        * Draws the graph axes.
        */
        protected final void drawAxes(Graphics g) {
#if($api == "Swing")
                // Swing optimised
                final int width = getWidth();
                final int height = getHeight();
#else
                final Dimension size = getSize();
                final int width = size.width;
                final int height = size.height;
#end
                g.setColor(getForeground());
// grid lines and numbering
                if(gridLines || numbering) {
// x-axis numbering and vertical grid lines
                        float xAxisY;
                        if(minY > 0.0f) {
                                xAxisY = minY;
                        } else if(maxY <= 0.0f) {
                                xAxisY = maxY;
                        } else {
                                xAxisY = 0.0f;
			}
                        for(double x=(minX>0.0f)?minX:xInc; x<=maxX; x+=xInc) {
                                Point p=dataToScreen((float)x, xAxisY);
                                if(gridLines) {
                                        g.setColor(gridLineColor);
                                        g.drawLine(p.x, axisPad-scalePad, p.x, height-(axisPad-scalePad));
                                        g.setColor(getForeground());
                                }
                                if(numbering) {
					drawXLabel(g, x, p);
                                }
                        }
                        for(double x=-xInc; x>=minX; x-=xInc) {
                                Point p=dataToScreen((float)x, xAxisY);
                                if(gridLines) {
                                        g.setColor(gridLineColor);
                                        g.drawLine(p.x, axisPad-scalePad, p.x, height-(axisPad-scalePad));
                                        g.setColor(getForeground());
                                }
                                if(numbering) {
					drawXLabel(g, x, p);
                                }
                        }
// y-axis numbering and horizontal grid lines
                        float yAxisX;
                        if(minX > 0.0f)
                                yAxisX = minX;
                        else if(maxX < 0.0f)
                                yAxisX = maxX;
                        else
                                yAxisX = 0.0f;
                        for(double y=(minY>0.0f)?minY:yInc; y<=maxY; y+=yInc) {
                                Point p=dataToScreen(yAxisX, (float)y);
                                if(gridLines) {
                                        g.setColor(gridLineColor);
                                        g.drawLine(leftAxisPad-scalePad, p.y, width-(axisPad-scalePad), p.y);
                                        g.setColor(getForeground());
                                }
                                if(numbering) {
					drawYLabel(g, y, p);
                                }
                        }
                        for(double y=-yInc; y>=minY; y-=yInc) {
                                Point p=dataToScreen(yAxisX, (float)y);
                                if(gridLines) {
                                        g.setColor(gridLineColor);
                                        g.drawLine(leftAxisPad-scalePad, p.y, width-(axisPad-scalePad), p.y);
                                        g.setColor(getForeground());
                                }
                                if(numbering) {
					drawYLabel(g, y, p);
                                }
                        }
                }

// axis lines
                // horizontal axis
                if(minY > 0.0f) {
                        // draw at bottom
                        g.drawLine(leftAxisPad-scalePad, height-axisPad, width-(axisPad-scalePad), height-axisPad);
                } else if(maxY < 0.0f) {
                        // draw at top
                        g.drawLine(leftAxisPad-scalePad, axisPad, width-(axisPad-scalePad), axisPad);
                } else {
                        // draw through y origin
                        g.drawLine(leftAxisPad-scalePad, origin.y, width-(axisPad-scalePad), origin.y);
                }
                // vertical axis
                if(minX > 0.0f) {
                        // draw at left
                        g.drawLine(leftAxisPad, axisPad-scalePad, leftAxisPad, height-(axisPad-scalePad));
                } else if(maxX < 0.0f) {
                        // draw at right
                        g.drawLine(width-axisPad, axisPad-scalePad, width-axisPad, height-(axisPad-scalePad));
                } else {
                        // draw through x origin
                        g.drawLine(origin.x, axisPad-scalePad, origin.x, height-(axisPad-scalePad));
                }
        }
	protected void drawXLabel(Graphics g, double x, Point p) {
		String str = xNumberFormat.format(x);
		FontMetrics metrics=g.getFontMetrics();
		int strWidth=metrics.stringWidth(str);
		int strHeight=metrics.getHeight();
		boolean numberingAbove = (maxY <= 0.0f);
		if(numberingAbove) {
			g.drawLine(p.x,p.y,p.x,p.y-5);
			g.drawString(str,p.x-strWidth/2,p.y-7);
		} else {
			g.drawLine(p.x,p.y,p.x,p.y+5);
			g.drawString(str,p.x-strWidth/2,p.y+5+strHeight);
		}
	}
	protected void drawYLabel(Graphics g, double y, Point p) {
		String str = yNumberFormat.format(y);
		FontMetrics metrics=g.getFontMetrics();
		int strWidth=metrics.stringWidth(str);
		int strHeight=metrics.getHeight();
		g.drawLine(p.x,p.y,p.x-5,p.y);
		g.drawString(str,p.x-8-strWidth,p.y+strHeight/3);
	}
        /**
        * Draws the graph data.
        * Override this method to change how the graph data is plotted.
        */
        protected void drawData(Graphics g) {
// bars
                model.firstSeries();
                for(int i=1; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy