Pregunta

Recientemente escribí un java programa transformar un documento SVG a HTML / Lienzo : fue fácil traducir una ruta como

d="M 0 0 L 100 100 z"

a algo como

GeneralPath L= new GeneralPath();
L.moveTo(0,0);
L.lineTo(100,100);
L.closePath();

Sin embargo, no sé cómo traducir el comando Arco elíptico a Java / GeneralPath. Por ejemplo, ¿alguien sabe cómo debo traducir el siguiente comando a Java / GeneralPath?

d = "M 750 200 a 100 50 135 1 1 250 50"

Gracias por tu ayuda.

¿Fue útil?

Solución

No hay comando directo en GeneralPath. Yo uso esta función,

    public static final void arcTo(GeneralPath path, float rx, float ry, float theta, boolean largeArcFlag, boolean sweepFlag, float x, float y) {
            // Ensure radii are valid
            if (rx == 0 || ry == 0) {
                    path.lineTo(x, y);
                    return;
            }
            // Get the current (x, y) coordinates of the path
            Point2D p2d = path.getCurrentPoint();
            float x0 = (float) p2d.getX();
            float y0 = (float) p2d.getY();
            // Compute the half distance between the current and the final point
            float dx2 = (x0 - x) / 2.0f;
            float dy2 = (y0 - y) / 2.0f;
            // Convert theta from degrees to radians
            theta = (float) Math.toRadians(theta % 360f);

            //
            // Step 1 : Compute (x1, y1)
            //
            float x1 = (float) (Math.cos(theta) * (double) dx2 + Math.sin(theta)
                            * (double) dy2);
            float y1 = (float) (-Math.sin(theta) * (double) dx2 + Math.cos(theta)
                            * (double) dy2);
            // Ensure radii are large enough
            rx = Math.abs(rx);
            ry = Math.abs(ry);
            float Prx = rx * rx;
            float Pry = ry * ry;
            float Px1 = x1 * x1;
            float Py1 = y1 * y1;
            double d = Px1 / Prx + Py1 / Pry;
            if (d > 1) {
                    rx = Math.abs((float) (Math.sqrt(d) * (double) rx));
                    ry = Math.abs((float) (Math.sqrt(d) * (double) ry));
                    Prx = rx * rx;
                    Pry = ry * ry;
            }

            //
            // Step 2 : Compute (cx1, cy1)
            //
            double sign = (largeArcFlag == sweepFlag) ? -1d : 1d;
            float coef = (float) (sign * Math
                            .sqrt(((Prx * Pry) - (Prx * Py1) - (Pry * Px1))
                                            / ((Prx * Py1) + (Pry * Px1))));
            float cx1 = coef * ((rx * y1) / ry);
            float cy1 = coef * -((ry * x1) / rx);

            //
            // Step 3 : Compute (cx, cy) from (cx1, cy1)
            //
            float sx2 = (x0 + x) / 2.0f;
            float sy2 = (y0 + y) / 2.0f;
            float cx = sx2
                            + (float) (Math.cos(theta) * (double) cx1 - Math.sin(theta)
                                            * (double) cy1);
            float cy = sy2
                            + (float) (Math.sin(theta) * (double) cx1 + Math.cos(theta)
                                            * (double) cy1);

            //
            // Step 4 : Compute the angleStart (theta1) and the angleExtent (dtheta)
            //
            float ux = (x1 - cx1) / rx;
            float uy = (y1 - cy1) / ry;
            float vx = (-x1 - cx1) / rx;
            float vy = (-y1 - cy1) / ry;
            float p, n;
            // Compute the angle start
            n = (float) Math.sqrt((ux * ux) + (uy * uy));
            p = ux; // (1 * ux) + (0 * uy)
            sign = (uy < 0) ? -1d : 1d;
            float angleStart = (float) Math.toDegrees(sign * Math.acos(p / n));
            // Compute the angle extent
            n = (float) Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy));
            p = ux * vx + uy * vy;
            sign = (ux * vy - uy * vx < 0) ? -1d : 1d;
            float angleExtent = (float) Math.toDegrees(sign * Math.acos(p / n));
            if (!sweepFlag && angleExtent > 0) {
                    angleExtent -= 360f;
            } else if (sweepFlag && angleExtent < 0) {
                    angleExtent += 360f;
            }
            angleExtent %= 360f;
            angleStart %= 360f;

            Arc2D.Float arc = new Arc2D.Float();
            arc.x = cx - rx;
            arc.y = cy - ry;
            arc.width = rx * 2.0f;
            arc.height = ry * 2.0f;
            arc.start = -angleStart;
            arc.extent = -angleExtent;
            path.append(arc, true);
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top