客户需求情况:要求支持曲线图,并且业务数据中不存在负值,要求曲线中也不存在负值。
目前报表工具所提供的统计图:时间趋势图和折线图,在数据点连续且很密集的情况下,计算出来图形,近似可看作曲线图。但如果客户数据库中只有少量关键点数据,且数据离散,采用以上两种统计图,画出来的图形就不是平滑曲线,而是折线。
这次实现的曲线图,就是在少量且离散的数据状态下,采用拉格朗日插值算法,图形通过各离散点,绘制平滑曲线。
要绘制平滑曲线,各个离散点之间的连接曲线,可以看做是若干点的集合,这些点是通过拉格朗日插值算法插入的虚拟数据点。
提供算法如下:
/**
* 拉格朗日插值算法
* @param points ArrayList,所有点
* @param deltaX int, 插值的X
* @return int,插值朗日后的Y
*/
private double Lagrange(ArrayList points, double deltaX, int BottomY) {
double sum = 0;
double L;
for (int i = 0; i < points.size(); i++) {
L = 1;
Point pi = (Point) points.get(i);
for (int j = 0; j < points.size(); j++) {
Point pj = (Point) points.get(j);
if (j != i) {
L = L * (deltaX – pj.x) / (pi.x – pj.x);
sum = sum + L * pi.y;
//曲线的x轴以下部分纵坐标y赋值为0,即不小于纵标轴最小值,即统计图属性中的”统计图起始值”,这里”统计图起始值”未设置,默认为0。
if(sum>BottomY) return BottomY;
return sum;
}
并通过以下方法来调用:
……
//拉格朗日计算1
Point p1 = (Point) serPoints.get(0);
Point p2 = (Point) serPoints.get(serPoints.size() – 1);
g.setColor(getColor(j));
int x1, y1;
x1 = p1.x;
y1 = p1.y;
for (int x2 = p1.x + 1; x2 <= p2.x; x2 += 1) {
int y2 = (int) Lagrange(serPoints, x2, gp.valueBaseLine);// top,
g.drawLine(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
……
本方案采用自定义统计图实现,代码请参考附件。
配置步骤:1.把解压后的example文件夹拷贝到应用和设计器的WEB-INF\classes文件夹。
2.重启设计器,在”选项”-”自定义”中增加画图类名为:example.CustomCurveGraph ,描述为:自定义统计图(例子中这样写的,要浏览例子不要修改它)
3.打开例子报表,浏览此统计图,完成!