如何使用pdfbox绘制饼图?

我必须使用pdfbox绘制一个饼图。

令数据为:

主题分数百分比累计分数

Sub-1 80 80 80

Sub-2 70 70150

Sub-3 65 65215

Sub-4 90 90305

Sub-5 55 55360

令半径和中心为100像素和(250,400)。

让我们取平行于x轴的初始线。

绘图的初始线条语句将为:

contentStream.drawLine(250,400,350,400);

我坚持:

a)在圆弧上找到与初始线相距一定角度的点的x,y坐标,以绘制半径

b)使用贝塞尔曲线在两点之间绘制圆弧。

解决问题的任何帮助将不胜感激!

回答:

根据角度在圆上找到x,y坐标是学校数学,即sin()和cos(),棘手的部分是绘制带有贝塞尔曲线的圆弧。

这是一些绘制所需饼图的代码。请注意,createSmallArc()只能在最大90°的角度下工作。如果需要更多,则必须通过绘制多个弧线来修改代码,直到返回(0,0),或者仅绘制多个切片。

createSmallArc()由Hans Muller提供,许可证:Creative Commons Attribution

3.0。所做的更改:将原始的AS代码实现为Java。算法由AleksasRiškus提供)

public class PieChart

{

public static void main(String[] args) throws IOException

{

PDDocument doc = new PDDocument();

PDPage page = new PDPage();

doc.addPage(page);

PDPageContentStream cs = new PDPageContentStream(doc, page);

cs.transform(Matrix.getTranslateInstance(250, 400));

cs.setNonStrokingColor(Color.yellow);

drawSlice(cs, 100, 0, 80);

cs.fill();

cs.setNonStrokingColor(Color.red);

drawSlice(cs, 100, 80, 150);

cs.fill();

cs.setNonStrokingColor(Color.green);

drawSlice(cs, 100, 150, 215);

cs.fill();

cs.setNonStrokingColor(Color.blue);

drawSlice(cs, 100, 215, 305);

cs.fill();

cs.setNonStrokingColor(Color.ORANGE);

drawSlice(cs, 100, 305, 360);

cs.fill();

cs.close();

doc.save("piechart.pdf");

doc.close();

}

private static void drawSlice(PDPageContentStream cs, float rad, float startDeg, float endDeg) throws IOException

{

cs.moveTo(0, 0);

List<Float> smallArc = createSmallArc(rad, Math.toRadians(startDeg), Math.toRadians(endDeg));

cs.lineTo(smallArc.get(0), smallArc.get(1));

cs.curveTo(smallArc.get(2), smallArc.get(3), smallArc.get(4), smallArc.get(5), smallArc.get(6), smallArc.get(7));

cs.closePath();

}

/**

* From https://hansmuller-flex.blogspot.com/2011/10/more-about-approximating-circular-arcs.html

*

* Cubic bezier approximation of a circular arc centered at the origin,

* from (radians) a1 to a2, where a2-a1 &lt; pi/2. The arc's radius is r.

*

* Returns a list with 4 points, where x1,y1 and x4,y4 are the arc's end points

* and x2,y2 and x3,y3 are the cubic bezier's control points.

*

* This algorithm is based on the approach described in:

* Aleksas Riškus, "Approximation of a Cubic Bezier Curve by Circular Arcs and Vice Versa,"

* Information Technology and Control, 35(4), 2006 pp. 371-378.

*/

private static List<Float> createSmallArc(double r, double a1, double a2)

{

// Compute all four points for an arc that subtends the same total angle

// but is centered on the X-axis

double a = (a2 - a1) / 2;

double x4 = r * Math.cos(a);

double y4 = r * Math.sin(a);

double x1 = x4;

double y1 = -y4;

double q1 = x1*x1 + y1*y1;

double q2 = q1 + x1*x4 + y1*y4;

double k2 = 4/3d * (Math.sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4);

double x2 = x1 - k2 * y1;

double y2 = y1 + k2 * x1;

double x3 = x2;

double y3 = -y2;

// Find the arc points' actual locations by computing x1,y1 and x4,y4

// and rotating the control points by a + a1

double ar = a + a1;

double cos_ar = Math.cos(ar);

double sin_ar = Math.sin(ar);

List<Float> list = new ArrayList<Float>();

list.add((float) (r * Math.cos(a1)));

list.add((float) (r * Math.sin(a1)));

list.add((float) (x2 * cos_ar - y2 * sin_ar));

list.add((float) (x2 * sin_ar + y2 * cos_ar));

list.add((float) (x3 * cos_ar - y3 * sin_ar));

list.add((float) (x3 * sin_ar + y3 * cos_ar));

list.add((float) (r * Math.cos(a2)));

list.add((float) (r * Math.sin(a2)));

return list;

}

}

以上是 如何使用pdfbox绘制饼图? 的全部内容, 来源链接: utcz.com/qa/400817.html

回到顶部