Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw and Arc in PDF generation

Basically I need to make the function drawArc to create a PDF file.

drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)

I searched in PDF specification but does not talk about a command to draw an Arc (like in PostScript)... So I suppose I need to somehow simulate the Arc with curves, but it seems too dificult.

Any help will be appreciate, thanks!

EDIT. I found an answer that resolves the problem for drawEllipse here, but I need to implement the method drawArc (instead of drawEllipse).

like image 764
Enrique Muñoz López Avatar asked Dec 28 '25 19:12

Enrique Muñoz López


1 Answers

So, finally I code a solution divided in two functions:

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;
    }
}

BeizerCurve Based on 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 };
}
like image 103
Enrique Muñoz López Avatar answered Dec 30 '25 22:12

Enrique Muñoz López



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!