import javafx.geometry.Point2D;
import javafx.scene.shape.ArcTo;
import java.util.ArrayList;
import java.util.List;
public class ArcToConverter {
public static List<Point2D> convertArcToPoints(double startX, double startY, ArcTo arc, int numSegments) {
List<Point2D> points = new ArrayList<>();
double endX = arc.getX();
double endY = arc.getY();
double rx = Math.abs(arc.getRadiusX());
double ry = Math.abs(arc.getRadiusY());
double xAxisRotation = Math.toRadians(arc.getXAxisRotation());
boolean largeArcFlag = arc.isLargeArcFlag();
boolean sweepFlag = arc.isSweepFlag();
// 处理半径为零的情况
if (rx == 0 || ry == 0) {
points.add(new Point2D(startX, startY));
points.add(new Point2D(endX, endY));
return points;
}
// 将端点转换到旋转后的坐标系
double dx = (startX - endX) / 2.0;
double dy = (startY - endY) / 2.0;
double x1p = Math.cos(xAxisRotation) * dx + Math.sin(xAxisRotation) * dy;
double y1p = -Math.sin(xAxisRotation) * dx + Math.cos(xAxisRotation) * dy;
// 调整半径以防止椭圆过小
double lambda = (x1p * x1p) / (rx * rx) + (y1p * y1p) / (ry * ry);
if (lambda > 1) {
rx *= Math.sqrt(lambda);
ry *= Math.sqrt(lambda);
}
// 计算中心点(cx', cy')
double sign = (largeArcFlag == sweepFlag) ? -1 : 1;
double denominator = (rx * rx * y1p * y1p) + (ry * ry * x1p * x1p);
if (denominator == 0) {
return points; // 避免除以零
}
double sqrtTerm = Math.sqrt(Math.max(0, (rx * rx * ry * ry - rx * rx * y1p * y1p - ry * ry * x1p * x1p) / denominator));
double factor = sign * sqrtTerm;
double cxp = factor * (rx * y1p) / ry;
double cyp = factor * (-ry * x1p) / rx;
// 转换回原始坐标系
double midX = (startX + endX) / 2.0;
double midY = (startY + endY) / 2.0;
double cx = midX + Math.cos(xAxisRotation) * cxp - Math.sin(xAxisRotation) * cyp;
double cy = midY + Math.sin(xAxisRotation) * cxp + Math.cos(xAxisRotation) * cyp;
// 计算起始角度和结束角度
double dxStart = startX - cx;
double dyStart = startY - cy;
double dxStartRot = Math.cos(xAxisRotation) * dxStart + Math.sin(xAxisRotation) * dyStart;
double dyStartRot = -Math.sin(xAxisRotation) * dxStart + Math.cos(xAxisRotation) * dyStart;
double theta1 = Math.atan2(dyStartRot / ry, dxStartRot / rx);
double dxEnd = endX - cx;
double dyEnd = endY - cy;
double dxEndRot = Math.cos(xAxisRotation) * dxEnd + Math.sin(xAxisRotation) * dyEnd;
double dyEndRot = -Math.sin(xAxisRotation) * dxEnd + Math.cos(xAxisRotation) * dyEnd;
double theta2 = Math.atan2(dyEndRot / ry, dxEndRot / rx);
// 计算角度差
double deltaTheta = theta2 - theta1;
if (sweepFlag) {
if (deltaTheta < 0) deltaTheta += 2 * Math.PI;
} else {
if (deltaTheta > 0) deltaTheta -= 2 * Math.PI;
}
// 生成点
for (int i = 0; i <= numSegments; i++) {
double t = (double) i / numSegments;
double theta = theta1 + t * deltaTheta;
double xEllipse = rx * Math.cos(theta);
double yEllipse = ry * Math.sin(theta);
// 旋转并平移回原始坐标系
double x = cx + Math.cos(xAxisRotation) * xEllipse - Math.sin(xAxisRotation) * yEllipse;
double y = cy + Math.sin(xAxisRotation) * xEllipse + Math.cos(xAxisRotation) * yEllipse;
points.add(new Point2D(x, y));
}
return points;
}
public static void main(String[] args) {
// 示例用法
ArcTo arc = new ArcTo();
arc.setRadiusX(50);
arc.setRadiusY(30);
arc.setX(100);
arc.setY(100);
arc.setLargeArcFlag(true);
arc.setSweepFlag(true);
arc.setXAxisRotation(45);
List<Point2D> points = convertArcToPoints(0, 0, arc, 100);
for (Point2D p : points) {
System.out.println(p.getX() + ", " + p.getY());
}
}
}
9085

被折叠的 条评论
为什么被折叠?



