自定义统计图实现3D饼图

1. 问题概述
润乾报表本身提供了丰富的统计图,但有时候也难以满足有些客户心里想的那种效果,
如下是通过润乾三维饼图实现效果:

客户觉得有些地方不太完美:
1.各个省份的数据能否都分扇显示和带上当前省份?
2.占比比较小的情况下,能否区分开省份,不要那么挤?
3.能否整体布局调整?
因此需要自定义统计图的方式实现,见实例演示


2. 实例演示
根据WORD2007里统计图配色实现润乾取色
配色方案1:

配色方案2:

配色方案3:

3. 案例
通联支付


4. 解决思路
1. 继承润乾报表提供的com.runqian.report4.model.expression.graph.DrawBase类,重载它的public void draw(StringBuffer htmlLink) 方法
DrawBase类里有一些重要的方法和变量可能被用到,这里介绍一下:
protected Graphics2D g; //画布,在其上直接画统计图即可
protected GraphParam gp; //存放统计图的大部分参数
protected ExtGraphProperty egp; //存放统计图的数据以及用户自定义参数(3.4.5.2介绍)
protected Color getColor(int index)//获取配色方案里的第几个颜色值
2. 根据WORD2007里统计图配色实现润乾取色统计图的配色方案,柱图,饼图,折线图.见附件

5. 程序说明
1. Draw3Dpie代码:

package java3d;

import java.awt.BasicStroke;

import java.awt.Color;

import java.awt.Font;

import java.awt.Polygon;

import java.awt.Rectangle;

import java.awt.RenderingHints;

import java.awt.geom.Arc2D;

import java.awt.geom.Area;

import java.awt.geom.Point2D;

import java.util.ArrayList;

import com.runqian.report4.model.expression.graph.DrawBase;

import com.runqian.report4.model.expression.graph.ExtGraphCategory;

import com.runqian.report4.model.expression.graph.ExtGraphSery;

public class Draw3DPie extends DrawBase

{

Point2D.Double cps;

int w = 0;

int h = 0;

int hight = 40;

double pr = 0.0D;

double r1 = 0.0D;

double r2 = 0.0D;

int linel = 0;

static final BasicStroke wideStroke = new BasicStroke(1.2F);

static final double arcPi = 0.0174532925199433D;

private void initProperty(StringBuffer htmlLink)

{

this.gp.coorWidth = 0;

initGraphInset();

createCoorValue();

drawLegend(htmlLink);

drawTitle();

drawLabel();

keepGraphSpace();

adjustCoorInset();

this.gp.graphRect =

new Rectangle(0, 0, this.gp.graphWidth,

this.gp.graphHeight);

if ((this.gp.graphRect.width < 10) || (this.gp.graphRect.height < 10)) {

System.out.println(“The area is too small to draw a picture!”);

return;

}

}

private void initGeometry()

{

this.gp.graphRect =

new Rectangle(0, 0, this.gp.graphWidth,

this.gp.graphHeight);

this.w = (this.gp.graphRect.width - this.gp.leftInset - this.gp.rightInset - this.gp.leftMargin);

this.h =

(this.gp.graphRect.height - this.gp.topMargin - this.gp.topInset -

this.gp.bottomInset);

this.h = Math.min(this.w, this.h);

double s = this.h / 135;

this.pr = (20.0D * s);

this.r1 = (80.0D * s);

this.r2 = (90.0D * s);

this.linel = (int)(135.0D * s);

double x = 145.0D * s + this.gp.leftInset + this.gp.leftMargin;

double y = 55.0D * s + this.gp.topInset + this.gp.topMargin;

this.cps = new Point2D.Double(x, y);

}

public void draw(StringBuffer htmlLink) {

double val;

java.lang.Double d;

double py;

double party;

double prx;

double pry;

Point2D.Double curcps;

java.lang.Double dR1;

double x1;

double y1;

java.lang.Double dX1;

java.lang.Double dY1;

java.lang.Double dR2;

double x2;

double y2;

java.lang.Double dX2;

java.lang.Double dY2;

Color currColor;

initProperty(htmlLink);

initGeometry();

this.g.setBackground(this.g.getBackground());

RenderingHints qualityHints = new RenderingHints(

RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

qualityHints.put(RenderingHints.KEY_RENDERING,

RenderingHints.VALUE_RENDER_QUALITY);

this.g.setRenderingHints(qualityHints);

ArrayList cats = this.egp.categories;

double dSum = 0.0D;

String[][] catvals = new String[this.gp.catNum][2];

for (int i = 0; i < this.gp.catNum; ++i) {

ExtGraphCategory egc = (ExtGraphCategory)cats.get(i);

catvals[i][0] = egc.getNameString();

for (int j = 0; j < this.gp.serNum; ++j) {

ExtGraphSery egs = egc.getExtGraphSery(this.gp.serNames.get(j));

if (egs.isNull()) {

catvals[i][1] = “0″;

}

else {

val = egs.getValue();

dSum += val;

catvals[i][1] = java.lang.Double.toString(val);

}

}

}

String[] temp = new String[2];

for (int i = 0; i < catvals.length / 2 + 1; ++i)

{

int j = 0; for (int k = catvals.length - 1; j < catvals.length - 1; )

{

if (java.lang.Double.parseDouble(catvals[j][1]) >

java.lang.Double.parseDouble(catvals[(j + 1)][1]))

{

temp[0] = catvals[j][0];

temp[1] = catvals[j][1];

catvals[j][0] = catvals[(j + 1)][0];

catvals[j][1] = catvals[(j + 1)][1];

catvals[(j + 1)][0] = temp[0];

catvals[(j + 1)][1] = temp[1];

}

if (java.lang.Double.parseDouble(catvals[k][1]) <

java.lang.Double.parseDouble(catvals[(k - 1)][1]))

{

temp[0] = catvals[k][0];

temp[1] = catvals[k][1];

catvals[k][0] = catvals[(k - 1)][0];

catvals[k][1] = catvals[(k - 1)][1];

catvals[(k - 1)][0] = temp[0];

catvals[(k - 1)][1] = temp[1];

}

++j; –k;

}

}

if (dSum == 0.0D) {

System.out.println(“sum is 0 exit!”);

return;

}

int startAngle = 90;

int arcAngle = 0;

int perPart = 1;

int i = 0; for (int j = 0; i < catvals.length; ++i) {

val = java.lang.Double.parseDouble(catvals[i][1]);

d = new java.lang.Double(360.0D * val / dSum);

if (d != null) {

arcAngle = d.intValue();

party = startAngle + arcAngle / 2;

if (party > 180)

{

perPart = 180 / (i – j);

}

startAngle = startAngle +

arcAngle;

}

}

startAngle = 90;

i = 0; for (int j = 0; i < catvals.length; ++i) {

val = java.lang.Double.parseDouble(catvals[i][1]);

d = new java.lang.Double(360.0D * val / dSum);

if (d != null) {

arcAngle = d.intValue();

py = (startAngle + arcAngle) * 0.0174532925199433D;

party = (startAngle + arcAngle / 2) * 0.0174532925199433D;

prx = (int)this.pr * Math.cos(party) * 12.0D / 17.0D;

pry = (int)this.pr * Math.sin(party) * 5.0D / 17.0D;

curcps = new Point2D.Double(this.cps.x + prx, this.cps.y -

pry);

dR1 = new java.lang.Double(this.r1);

x1 = curcps.x - (dR1.intValue() * 12 / 17) – ((int)this.pr * 12 /

17);

y1 = curcps.y - (dR1.intValue() * 5 / 17) – ((int)this.pr * 5 /

17);

dR2 = new java.lang.Double(this.r2);

x2 = curcps.x - (dR2.intValue() * 12 / 17);

y2 = curcps.y - (dR2.intValue() * 5 / 17);

int[] xx1 = new int[4];

int[] yy1 = new int[4];

xx1[0] =

((int)curcps.x +

(int)(dR2.intValue() * 12 / 17 *

Math.cos(startAngle *

0.0174532925199433D)));

yy1[0] =

((int)curcps.y -

(int)(dR2.intValue() * 5 / 17 *

Math.sin(startAngle *

0.0174532925199433D)) +

this.hight);

xx1[1] = xx1[0];

yy1[1] = (yy1[0] - this.hight);

xx1[2] = (int)curcps.x;

yy1[2] = (int)curcps.y;

xx1[3] = (int)curcps.x;

yy1[3] = ((int)curcps.y + this.hight);

int[] xx2 = new int[4];

int[] yy2 = new int[4];

xx2[0] =

((int)curcps.x +

(int)(dR2.intValue() * 12 / 17 * Math.cos(py)));

yy2[0] =

((int)curcps.y -

(int)(dR2.intValue() * 5 / 17 * Math.sin(py)) +

this.hight);

xx2[1] = xx2[0];

yy2[1] = (yy2[0] - this.hight);

xx2[2] = (int)curcps.x;

yy2[2] = (int)curcps.y;

xx2[3] = (int)curcps.x;

yy2[3] = ((int)curcps.y + this.hight);

this.g.setPaint(Color.BLACK);

this.g.fillPolygon(xx1, yy1, 4);

this.g.fillPolygon(xx2, yy2, 4);

String percent = getFormattedValue(val / dSum);

int[] linex = new int[3];

int[] liney = new int[3];

linex[0] =

((int)curcps.x +

(int)(dR2.intValue() * 12 / 17 * Math.cos(party)));

liney[0] =

((int)curcps.y -

(int)(dR2.intValue() * 5 / 17 * Math.sin(party)) +

(((party > 3.141592653589793D) && (party < 6.283185307179586D)) ? this.hight :

0));

if (party < 3.141592653589793D)

party = (60 + perPart * (i – j)) * 0.0174532925199433D;

linex[1] =

((int)curcps.x +

(int)(this.linel * 12 / 17 * Math.cos(party)));

liney[1] =

((int)curcps.y -

(int)(this.linel * 5 / 17 * Math.sin(party)) +

(((party > 3.141592653589793D) && (party < 6.283185307179586D)) ? this.hight :

0));

linex[2] =

(linex[1] +

(((party > 1.570796326794897D) && (party < 4.71238898038469D)) ? 5 :

-5));

if ((Math.abs(party / 0.0174532925199433D – 90.0D) < 6.0D) ||

(Math.abs(party / 0.0174532925199433D – 270.0D) < 6.0D))

linex[2] = linex[1];

liney[2] = liney[1];

this.g.setColor(Color.BLACK);

this.g.setStroke(wideStroke);

this.g.drawLine(linex[0], liney[0], linex[2], liney[2]);

this.g.drawLine(linex[1], liney[1], linex[2], liney[2]);

this.g.setFont(new Font(宋体, 1, 10));

this.g

.drawString(

catvals[i][0],

linex[1] -

(((party > 1.570796326794897D) && (party < 4.71238898038469D)) ?

catvals[i][0].length() * 10 :

0),

liney[1] -

(((party > 3.141592653589793D) && (party < 6.283185307179586D)) ? -10 :

10));

this.g

.drawString(

percent,

linex[1] -

(((party > 1.570796326794897D) && (party < 4.71238898038469D)) ?

(percent

.length() + 1) *

5 :

0),

liney[1] +

(((party > 3.141592653589793D) && (party < 6.283185307179586D)) ? 20 :

0));

startAngle += arcAngle;

}

}

startAngle = 90;

for (i = 0; i < catvals.length; ++i) {

val = java.lang.Double.parseDouble(catvals[i][1]);

d = new java.lang.Double(360.0D * val / dSum);

if (d != null) {

arcAngle = d.intValue();

if (startAngle + arcAngle < 180) {

startAngle += arcAngle;

}

else

{

py = (startAngle + arcAngle) * 0.0174532925199433D;

party = (startAngle + arcAngle / 2) * 0.0174532925199433D;

prx = (int)this.pr * Math.cos(party) * 12.0D / 17.0D;

pry = (int)this.pr * Math.sin(party) * 5.0D / 17.0D;

curcps = new Point2D.Double(this.cps.x + prx,

(int)this.cps.y - pry);

dR1 = new java.lang.Double(this.r1);

x1 = curcps.x - (dR1.intValue() * 12 / 17) – ((int)this.pr * 12 /

17);

y1 = curcps.y - (dR1.intValue() * 5 / 17) – ((int)this.pr * 5 /

17);

dX1 = new java.lang.Double(x1);

dY1 = new java.lang.Double(y1);

dR2 = new java.lang.Double(this.r2);

x2 = (int)curcps.x - (dR2.intValue() * 12 / 17);

y2 = (int)curcps.y - (dR2.intValue() * 5 / 17);

dX2 = new java.lang.Double(x2);

dY2 = new java.lang.Double(y2);

currColor = getColor(i);

int[] xx = new int[4];

int[] yy = new int[4];

xx[0] =

((int)curcps.x +

(int)(dR2.intValue() * 12 / 17 *

Math.cos(startAngle *

0.0174532925199433D)));

yy[0] =

((int)curcps.y -

(int)(dR2.intValue() * 5 / 17 *

Math.sin(startAngle *

0.0174532925199433D)));

if ((startAngle < 180) && (startAngle + arcAngle > 180)) {

xx[0] = ((int)curcps.x - (dR2.intValue() * 12 / 17));

yy[0] = (int)curcps.y;

}

xx[1] =

((int)curcps.x +

(int)(dR2.intValue() * 12 / 17 * Math.cos(py)));

yy[1] =

((int)curcps.y -

(int)(dR2.intValue() * 5 / 17 * Math.sin(py)));

if (startAngle + arcAngle > 360) {

xx[1] = ((int)curcps.x + dR2.intValue() * 12 / 17);

yy[1] = (int)curcps.y;

}

xx[2] = xx[1];

yy[2] = (yy[1] + this.hight);

xx[3] = xx[0];

yy[3] = (yy[0] + this.hight);

int[] xx3 = new int[3];

int[] yy3 = new int[3];

xx3[0] =

((int)curcps.x +

(int)(dR2.intValue() * 12 / 17 *

Math.cos(startAngle *

0.0174532925199433D)));

yy3[0] =

((int)curcps.y -

(int)(dR2.intValue() * 5 / 17 *

Math.sin(startAngle *

0.0174532925199433D)) +

this.hight);

xx3[1] =

((int)curcps.x +

(int)(dR2.intValue() * 12 / 17 * Math.cos(py)));

yy3[1] =

((int)curcps.y -

(int)(dR2.intValue() * 5 / 17 * Math.sin(py)) +

this.hight);

xx3[2] =

((int)curcps.x -

(int)(5 * dR2.intValue() * 12 / 17 * Math.cos(party)));

yy3[2] =

((int)curcps.y +

(int)(5 * dR2.intValue() * 5 / 17 * Math.sin(party)) +

this.hight);

int[] xx4 = new int[3];

int[] yy4 = new int[3];

xx4[0] =

((int)curcps.x +

(int)(dR2.intValue() * 12 / 17 *

Math.cos((startAngle – 2) * 0.0174532925199433D)));

yy4[0] =

((int)curcps.y -

(int)(dR2.intValue() * 5 / 17 *

Math.sin((startAngle – 2) * 0.0174532925199433D)) +

this.hight);

if ((startAngle < 180) && (startAngle + arcAngle > 180)) {

xx4[0] = ((int)curcps.x - (dR2.intValue() * 12 / 17));

yy4[0] = (int)curcps.y;

}

xx4[1] =

((int)curcps.x +

(int)(dR2.intValue() * 12 / 17 * Math.cos(py + 0.03490658503988659D)));

yy4[1] =

((int)curcps.y -

(int)(dR2.intValue() * 5 / 17 * Math.sin(py + 0.03490658503988659D)) +

this.hight);

if ((startAngle < 360) && (startAngle + arcAngle > 360)) {

xx4[1] = ((int)curcps.x + dR2.intValue() * 12 / 17);

yy4[1] = (int)curcps.y;

}

xx4[2] = (int)curcps.x;

yy4[2] =

((int)curcps.y +

this.hight);

this.g.setPaint(currColor.darker());

Area area1 = new Area(

new Arc2D.Double(dX2.intValue(),

dY2.intValue() +

this.hight, 2 * dR2.intValue() * 12 / 17, 2 *

dR2.intValue() * 5 /

17, startAngle, arcAngle,

1));

System.out.println(area1.toString());

Area areapie = new Area(

new Arc2D.Double(dX2.intValue(),

dY2.intValue() +

this.hight, 2 * dR2.intValue() * 12 / 17, 2 *

dR2.intValue() * 5 /

17, startAngle, arcAngle, 2));

if ((startAngle < 180) && (startAngle + arcAngle > 180) &&

(startAngle + arcAngle < 360))

areapie = new Area(

new Arc2D.Double(dX2.intValue(),

dY2.intValue() +

this.hight, 2 * dR2.intValue() * 12 / 17, 2 *

dR2.intValue() * 5 /

17, 180.0D, startAngle + arcAngle -

180, 2));

else if ((startAngle < 180) && (startAngle + arcAngle > 360))

areapie = new Area(

new Arc2D.Double(dX2.intValue(),

dY2.intValue() +

this.hight, 2 * dR2.intValue() * 12 / 17, 2 *

dR2.intValue() * 5 /

17, 180.0D, 180.0D, 2));

else if ((startAngle > 180) && (startAngle + arcAngle > 360))

areapie = new Area(

new Arc2D.Double(dX2.intValue(),

dY2.intValue() +

this.hight, 2 * dR2.intValue() * 12 / 17, 2 *

dR2.intValue() * 5 /

17, startAngle,

360 – startAngle, 2));

Area trianglarea = new Area(new Polygon(xx3, yy3, 3));

System.out.println(trianglarea.toString());

Area trianglarea2 = new Area(new Polygon(xx4, yy4, 3));

Area pillararea = new Area(new Polygon(xx, yy, 4));

areapie.subtract(trianglarea2);

areapie.add(pillararea);

if (startAngle + arcAngle > 180)

this.g.fill(areapie);

startAngle += arcAngle;

}

}

}

startAngle = 90;

for (i = 0; i < catvals.length; ++i) {

val = java.lang.Double.parseDouble(catvals[i][1]);

d = new java.lang.Double(360.0D * val / dSum);

if (d != null) {

arcAngle = d.intValue();

py = (startAngle + arcAngle) * 0.0174532925199433D;

party = (startAngle + arcAngle / 2) * 0.0174532925199433D;

prx = (int)this.pr * Math.cos(party) * 12.0D / 17.0D;

pry = (int)this.pr * Math.sin(party) * 5.0D / 17.0D;

curcps = new Point2D.Double(this.cps.x + prx, this.cps.y -

pry);

dR1 = new java.lang.Double(this.r1);

x1 = curcps.x - (dR1.intValue() * 12 / 17);

y1 = curcps.y - (dR1.intValue() * 5 / 17);

dX1 = new java.lang.Double(x1);

dY1 = new java.lang.Double(y1);

dR2 = new java.lang.Double(this.r2);

x2 = (int)curcps.x - (dR2.intValue() * 12 / 17);

y2 = (int)curcps.y - (dR2.intValue() * 5 / 17);

dX2 = new java.lang.Double(x2);

dY2 = new java.lang.Double(y2);

currColor = getColor(i);

this.g.setPaint(currColor);

Area careapie = new Area(

new Arc2D.Double(dX2.intValue(),

dY2.intValue(), 2 * dR2.intValue() * 12 / 17,

2 * dR2.intValue() * 5 / 17, startAngle,

arcAngle, 2));

this.g.fill(careapie);

this.g.setStroke(new BasicStroke(1.0F));

this.g.draw(careapie);

Color arcColor = currColor;

int curstartAngle = startAngle;

int curarcAngle = arcAngle;

if ((startAngle + arcAngle < 180) || (startAngle > 360)) {

startAngle += arcAngle;

} else {

if ((startAngle < 180) && (startAngle + arcAngle < 360)) {

curstartAngle = 180;

curarcAngle = startAngle + arcAngle – 180;

} else if ((startAngle < 180) && (startAngle + arcAngle > 360)) {

curstartAngle = 180;

curarcAngle = 180;

} else if (startAngle + arcAngle > 360) {

curarcAngle = 360 – startAngle;

}

for (int j = 0; j < 10; ++j)

{

arcColor = currColor.brighter();

this.g.setPaint(arcColor);

this.g

.drawArc(

dX2.intValue() + j / 2,

dY2.intValue() + j / 2 + 2,

2 * dR2.intValue() * 12 / 17 – j,

2 * dR2.intValue() * 5 / 17 – j,

curstartAngle, curarcAngle);

}

startAngle += arcAngle;

}

}

}

}

}

热门文章