我最近写了一个java program将 SVG 文档转换为HTML / 画布:很容易翻译一个路径,例如
d="M 0 0 L 100 100 z"
类似
GeneralPath L= new GeneralPath();
L.moveTo(0,0);
L.lineTo(100,100);
L.closePath();
但是我不知道如何将 Elliptical Arc 命令转换为Java / GeneralPath。例如,有谁知道我应该如何将以下命令转换为Java / GeneralPath?
d = "M 750 200 a 100 50 135 1 1 250 50"
感谢您的帮助。
答案 0 :(得分:7)
GeneralPath中没有直接命令。我用这个函数,
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);
}