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

com.day.cq.graphics.chart.LineChart Maven / Gradle / Ivy

/*
 * Copyright 1997-2004 Day Management AG
 * Barfuesserplatz 6, 4001 Basel, Switzerland
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * Day Management AG, ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Day.
 */
package com.day.cq.graphics.chart;

import com.day.cq.graphics.Graph;
import com.day.image.Layer;
import com.day.image.LineStyle;

/**
 * @author fmeschbe
 */
public class LineChart extends Chart {

    int style;
    int numlines;
    float linewidth;

    public static String getName() {
        return "line";
    }

    public Layer draw(Graph graph, boolean doDraw) {
        Metrics metrics = graph.getMetrics();
        getLineMetrics(graph, metrics);

        Axis yAxis = graph.getYAxis();
        yAxis.setType(Axis.Y_AXIS);

        yAxis.height = metrics.height + 1;
        yAxis.numticks = metrics.numlines;

        yAxis.setRangemin(metrics.bottomvalue);
        yAxis.setRangemax(metrics.topvalue);
        yAxis.setRangestep(metrics.distance);
        yAxis.setRangescale(metrics.height / (yAxis.getRangemax() - yAxis.getRangemin()));
        yAxis.numticks = (int) ((yAxis.getRangemax() - yAxis.getRangemin()) / yAxis.getRangestep());
        yAxis.setRangeoffset(-yAxis.getRangemin());
        yAxis.setLabelformat("%." + metrics.coma + "f");

        Axis xAxis = graph.getXAxis();
        xAxis.setType(Axis.U_AXIS);

        xAxis.setRangemin(0);
        xAxis.setRangemax(graph.getData().numcols - 1);
        xAxis.setRangestep(1);
        xAxis.setRangeoffset(0);
        xAxis.setLabelformat(
                (xAxis.labeltype == Axis.LABEL_TYPE_NUMBER) ? "%s" : "%Y");

        if ((graph.getFlags() & Graph.FLAGS_FIT) != 0) {
            xAxis.setRangescale((double) (xAxis.width - xAxis.labelwidth) / (double) (graph.getData().numcols - 1));
        } else {
            xAxis.setRangescale((double) (xAxis.width - xAxis.labelwidth) / (double) (graph.getData().numcols));
        }

        Layer[] axisLayers = new Layer[2];
        axisLayers[0] = graph.getYAxis().draw(graph, doDraw);
        axisLayers[1] = graph.getXAxis().draw(graph, doDraw);

        Layer dataLayer = drawLines(graph, doDraw);
        dataLayer.merge(axisLayers);

        return doDraw ? dataLayer : null;
    }

    public void setStyle(int style) {
        if (this.style == 0) this.style = style;
    }

    public void setNumlines(int numlines) {
        if (this.numlines == 0) this.numlines = numlines;
    }

    public void setLinewidth(float linewidth) {
        if (this.linewidth == 0) this.linewidth = linewidth;
    }

    //---------- internal ------------------------------------------------------

    private void getLineMetrics(Graph graph, Metrics mx) {
        Data data = graph.getData();
        double maxValue = -Double.MAX_VALUE;
        double minValue = Double.MAX_VALUE;
        double power = 0;
        double distance = 0;
        double topValue = 0;
        double botValue = 0;
        double delta;
        int numlines = 0;

        // init locals
        int approx = this.numlines;

        // get min, max value
        for (int j = 0; j < data.numcols; j++) {
            for (int i = 0; i < data.numrows; i++) {
                double rest = data.datarows[i].samples[j];
                if (rest > maxValue) maxValue = rest;
                if (rest < minValue) minValue = rest;
            }
        }

        // get next 'nice' number, for the moment, we take a power of 10
        delta = maxValue - minValue;

        // be 0 aware
        if (delta == 0) {

            distance = maxValue;
            topValue = minValue + distance;
            botValue = 0;
            numlines = 3;

        } else {

            power = Math.log(delta) / Math.log(10);
            if (power == Math.floor(power)) power -= 1.0;
            power = Math.floor(power);

            // try to improve resolution
            double[] factors = new double[]{0.1, 0.2, 0.25, 0.3, 0.5, 0.6, 1};
            for (int i = 0; i < factors.length; i++) {

                distance = Math.pow(10, power) * factors[i];

                topValue = Math.ceil(maxValue / distance) * distance;
                if (topValue == maxValue) topValue += distance;
                botValue = Math.floor(minValue / distance) * distance;

                numlines = (int) ((topValue - botValue) / distance);

                if (numlines <= approx) break;
            }
        }

        //re-compute tickdistance depending on new number of lines and graph height
        graph.getYAxis().tickdistance = graph.getExtent().height / numlines;

        int height = graph.getYAxis().tickdistance * numlines;
        int coma = 0;
        double rest = distance - Math.rint(distance);
        while (rest > 0.0 && rest < 1.0 && coma < 4) {
            coma++;
            rest = (rest * 10.0) - Math.rint(rest * 10.0);
        }

        double width = graph.getXAxis().width;

        mx.scalex = width / (double) (data.numcols - 1);
        mx.height = height;
        mx.coma = coma;
        mx.topvalue = topValue;
        mx.bottomvalue = botValue;
        mx.distance = distance;
        mx.scaley = height / (topValue - botValue);
        mx.shifty = -(int) (topValue * mx.scaley);
        mx.numlines = numlines;
        mx.maxvalue = maxValue;
    }

    private Layer drawLines(Graph graph, boolean doDraw) {

        // return if not to draw
        if (!doDraw) return null;

        Axis xAxis = graph.getXAxis();
        Axis yAxis = graph.getYAxis();

        int w = xAxis.width;
        int h = yAxis.height;
        int hx = xAxis.height;

        Layer l = graph.createLayer(true, w, h + hx);

        // draw the grid first
        graph.getGrid().draw(l, doDraw);

        // let's go now
        l.setY(-h);
        l.setX(1);

        // the data
        for (int row = 0; row < graph.getData().numrows; row++) {
            int x2 = (int) ((xAxis.getRangemin() + xAxis.getRangeoffset()) * xAxis.getRangescale());
            int y2 = h - 1 - (int) (yAxis.getRangescale() *
                    (yAxis.getRangeoffset() +
                            graph.getData().datarows[row].samples[0]));
            int col = (int) xAxis.getRangemin();
            graph.getData().xcoords[row][col] = x2;
            graph.getData().ycoords[row][col] = y2;

            l.setLineStyle(new LineStyle(graph.getData().datarows[row].color,
                    -1, -1, linewidth));

            for (col++; col <= xAxis.getRangemax(); col++) {
                int x1 = x2;
                int y1 = y2;

                x2 = (int) ((col + xAxis.getRangeoffset()) * xAxis.getRangescale());
                y2 = h - 1 - (int) (yAxis.getRangescale() *
                        (yAxis.getRangeoffset() +
                                graph.getData().datarows[row].samples[col]));
                graph.getData().xcoords[row][col] = x2;
                graph.getData().ycoords[row][col] = y2;
                l.drawLine(x1, y1, x2, y2);

            }
        }
        return l;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy