我必须用pdfbox绘制一个饼图。
让数据是:
设半径和中心为100像素和(250,400)。
让我们取平行于x轴的初始线
绘制初始行语句将为:
contentStream。抽绳(250400350400);
我坚持:
a)在距离初始线一定程度的圆圈上找到点的x, y坐标,以绘制半径
b)使用贝塞尔曲线在两点之间绘制圆弧。
任何帮助解决问题将不胜感激!
如果您只想使用PDFBox将一些图表绘制成PDF,而不想自己完成所有的数学运算等,那么您可以使用我的PDFBox Graphics2D适配器。这允许您使用任何基于Graphics2D的java库来绘制图表(例如JFreeChart)。它将创建一个XForm,然后您可以在PDF中自由放置它。
如果您真的想自己这样做,您仍然可以使用Java2D API来帮助处理形状。
Arc2D.Float arc = new Arc2D.Float(x,y,w,h,start,extend, Arch2D.OPEN);
AffineTransform tf = new AffineTransform();
// You may need to setup tf to correctly position the drawing.
float[] coords = new float[6];
PathIterator pi = arc.getPathIterator(tf);
while (!pi.isDone()) {
int segment = pi.currentSegment(coords);
switch (segment) {
case PathIterator.SEG_MOVETO:
if (isFinite(coords, 2))
contentStream.moveTo(coords[0], coords[1]);
break;
case PathIterator.SEG_LINETO:
if (isFinite(coords, 2))
contentStream.lineTo(coords[0], coords[1]);
break;
case PathIterator.SEG_QUADTO:
if (isFinite(coords, 4))
contentStream.curveTo1(coords[0], coords[1], coords[2], coors[3]);
break;
case PathIterator.SEG_CUBICTO:
if (isFinite(coords, 6))
contentStream.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
break;
case PathIterator.SEG_CLOSE:
contentStream.closePath();
break;
}
pi.next();
}
contentStream.fill();
另请参见我的图形适配器形状漫游代码。
根据角度在圆上求x,y坐标是学校数学,即sin()和cos(),棘手的部分是用贝齐尔曲线绘制圆弧。
这是一些绘制您要求的饼图的代码。请注意,createSmallArc()
只能处理高达90°的角度。如果您想要更多,您要么必须通过绘制几个弧线来修改代码,直到您返回(0,0),要么只是绘制几个切片。
(createSmallArc()
由Hans Muller提供,许可证:知识共享属性3.0。所做的更改:将原始AS代码实现为java。算法由Aleksas Riš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 < 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绘制一个饼图。 令数据为: 主题分数百分比累计分数 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
我正试图用PDFbox绘制饼图,但各片之间有白线,有人能帮我吗?是否有此选项? 附上我正在使用的绘制圆弧的代码: 结果的附加图像: 谢啦
问题内容: 我想在PDFBox中用透明线绘制线条和多边形。这是一些有关如何绘制蓝线的示例代码,但是我无法弄清楚更改颜色的Alpha值。 问题答案: 您不能使用的alpha值,因为PDFBox仅使用RGB值。根据它的javadoc 只是: 设置描边颜色,指定为RGB。 一种选择是将背景色设置为描边色,以使线条不可见。 注意- 不可见!=透明(因此您不会获得透视效果)
我想用ApachePDFBox在PDF上绘制一个矢量图像。 这是我用来绘制普通图像的代码 如果我使用或图像而不是png,则生成的PDF文档会损坏。 我希望图像是矢量图像的主要原因是,使用PNG或JPG时,图像看起来很糟糕,我认为它会被压缩,所以看起来很糟糕。对于矢量图像,这不应该发生(当我在Inkscape中将svg路径导出为PDF时,它不会发生,矢量路径会被保留)。 有没有办法使用Apache
问题内容: 这是我在stackoverflow.com上遇到的第一个问题,所以请原谅我做错了什么。 我想创建一个基本上像进度条的圆圈。现在,我想通过一些代码设置百分比。 我想要实现的是:https : //raw.github.com/psud/Melde-App/master/res/drawable- hdpi/circlemiddle.png 我的问题: 无法使用两种颜色的圆圈工作(已经在论
我正在尝试使用pdfbox将图像添加到pdf的中心。下面是我的代码,但我无法在pdf中获得图像的正确位置。我在PDFBox中遵循了以下链接,如何更改PDRectangle对象的原点(0,0)?要获得正确的位置,但静止图像偏离中点位置?