PDF 生成中的绘图和圆弧
Draw and Arc in PDF generation
基本上我需要使函数 drawArc 来创建 PDF 文件。
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
我在PDF specification but does not talk about a command to draw an Arc (like in PostScript)中搜索过...所以我想我需要以某种方式用曲线模拟Arc,但它似乎太难了。
任何帮助将不胜感激,谢谢!
编辑。我找到了解决 drawEllipse here 问题的答案,但我需要实现方法 drawArc(而不是 drawEllipse)。
所以,最后我编写了一个分为两个函数的解决方案:
pdfDrawArc
private void pdfDrawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
System.out.println("Arc");
width -= 1;
height -= 1;
int n = (int)(Math.ceil(Math.abs(arcAngle / maxAnglePerCurve())));
int i;
double currentStartAngle = startAngle;
double actualArcAngle = ((double)arcAngle) / n;
for (i = 0; i < n; i++) {
double[] bezier = bezierCurve(this.x + x, this.y + y, width, height, currentStartAngle, actualArcAngle);
if (i == 0)
this.pdfMoveTo(bezier[0], bezier[1]);
this.pdfCurveTo(bezier [2], bezier [3], bezier [4], bezier [5], bezier [6], bezier [7]);
this.pdfStroke();
currentStartAngle += actualArcAngle;
}
}
贝泽曲线
基于 L. Maisonobe solution.
private double[] bezierCurve(double x, double y, double width, double height, double startAngle, double arcAngle) {
double pi = 3.141592;
double a = width / 2;
double b = height / 2;
//center
double cx = x + a;
double cy = y + b;
//calculate trigonometric operations so we don't need to repeat the calculus
double cos1 = Math.cos(startAngle * pi / 180);
double sin1 = Math.sin(startAngle * pi / 180);
double cos2 = Math.cos((startAngle + arcAngle) * pi / 180);
double sin2 = Math.sin((startAngle + arcAngle) * pi / 180);
//point p1. Start point
double p1x = cx + a * cos1;
double p1y = cy - b * sin1;
//point d1. First derivative at start point.
double d1x = -a * sin1;
double d1y = -b * cos1;
//point p2. End point
double p2x = cx + a * cos2;
double p2y = cy - b * sin2;
//point d2. First derivative at end point
double d2x = -a * sin2;
double d2y = -b * cos2;
//alpha constant
double aux = Math.tan((arcAngle / 2) * pi / 180);
double alpha = Math.sin(arcAngle * pi / 180) * (Math.sqrt(4 + 3 * aux * aux) - 1.0) / 3.0;
//point q1. First control point
double q1x = p1x + alpha * d1x;
double q1y = p1y + alpha * d1y;
//point q2. Second control point.
double q2x = p2x - alpha * d2x;
double q2y = p2y - alpha * d2y;
return new double[] { p1x, p1y, q1x, q1y, q2x, q2y, p2x, p2y };
}
基本上我需要使函数 drawArc 来创建 PDF 文件。
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
我在PDF specification but does not talk about a command to draw an Arc (like in PostScript)中搜索过...所以我想我需要以某种方式用曲线模拟Arc,但它似乎太难了。
任何帮助将不胜感激,谢谢!
编辑。我找到了解决 drawEllipse here 问题的答案,但我需要实现方法 drawArc(而不是 drawEllipse)。
所以,最后我编写了一个分为两个函数的解决方案:
pdfDrawArc
private void pdfDrawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
System.out.println("Arc");
width -= 1;
height -= 1;
int n = (int)(Math.ceil(Math.abs(arcAngle / maxAnglePerCurve())));
int i;
double currentStartAngle = startAngle;
double actualArcAngle = ((double)arcAngle) / n;
for (i = 0; i < n; i++) {
double[] bezier = bezierCurve(this.x + x, this.y + y, width, height, currentStartAngle, actualArcAngle);
if (i == 0)
this.pdfMoveTo(bezier[0], bezier[1]);
this.pdfCurveTo(bezier [2], bezier [3], bezier [4], bezier [5], bezier [6], bezier [7]);
this.pdfStroke();
currentStartAngle += actualArcAngle;
}
}
贝泽曲线 基于 L. Maisonobe solution.
private double[] bezierCurve(double x, double y, double width, double height, double startAngle, double arcAngle) {
double pi = 3.141592;
double a = width / 2;
double b = height / 2;
//center
double cx = x + a;
double cy = y + b;
//calculate trigonometric operations so we don't need to repeat the calculus
double cos1 = Math.cos(startAngle * pi / 180);
double sin1 = Math.sin(startAngle * pi / 180);
double cos2 = Math.cos((startAngle + arcAngle) * pi / 180);
double sin2 = Math.sin((startAngle + arcAngle) * pi / 180);
//point p1. Start point
double p1x = cx + a * cos1;
double p1y = cy - b * sin1;
//point d1. First derivative at start point.
double d1x = -a * sin1;
double d1y = -b * cos1;
//point p2. End point
double p2x = cx + a * cos2;
double p2y = cy - b * sin2;
//point d2. First derivative at end point
double d2x = -a * sin2;
double d2y = -b * cos2;
//alpha constant
double aux = Math.tan((arcAngle / 2) * pi / 180);
double alpha = Math.sin(arcAngle * pi / 180) * (Math.sqrt(4 + 3 * aux * aux) - 1.0) / 3.0;
//point q1. First control point
double q1x = p1x + alpha * d1x;
double q1y = p1y + alpha * d1y;
//point q2. Second control point.
double q2x = p2x - alpha * d2x;
double q2y = p2y - alpha * d2y;
return new double[] { p1x, p1y, q1x, q1y, q2x, q2y, p2x, p2y };
}