com.day.cq.graphics.chart.LineChart Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
The newest version!
/*
* 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;
}
}