ARC在SVG中是顺时针还是逆时针?
Is ARC clockwise or counterclockwise In SVG?
我必须在圆的边缘的两点之间画一条弧。假设弧线总是以尽可能短的距离绘制(edit2:扫描标志设置为 0),我需要知道弧线是顺时针还是逆时针绘制的。
我得到以下输入:
- 起点(point1)
- 终点(point2)
- 中心点
- 半径
Edit1:这个问题与 svg 中的弧线有关。因此它属于编程。
答案是SVG支持顺时针和逆时针弧。您可以通过更改弧 (A) 命令中的“扫描”标志在它们之间切换。
如果您想了解 SVG 弧的工作原理,可以查看 Paths arcs section of the SVG specification。
根据描述的数据,您可以找到更小的圆弧 - CCW 或 CW。
只需检查向量 point1-center
和 point2-center
的叉积符号即可揭示最短弧方向:
cp = (p1.x-c.x)*(p2.y-c.y)-(p1.y-c.y)*(p2.x-c.x)
对于 cp>0
你必须将 sweep
参数设置为 0,否则设置为 1 (反之亦然),而 large-arc-flag
应该总是 0.
在与数学家讨论后,我找到了答案,并在此基础上编写了以下代码:
public static bool IsClockWise(Point point1, Point point2, Circle circle)
{
var dxPoint1 = point1.X - circle.CenterX;
var dyPoint1 = point1.Y - circle.CenterY;
var dxPoint2 = point2.X - circle.CenterX;
var dyPoint2 = point2.Y - circle.CenterY;
double thetaPoint1 = 0, thetaPoint2 = 0;
if (dxPoint1 > 0 && dyPoint1 >= 0)
thetaPoint1 = Math.Asin(dyPoint1 / circle.Radius);
else if (dxPoint1 <= 0 && dyPoint1 > 0)
thetaPoint1 = Math.PI - Math.Asin(dyPoint1 / circle.Radius);
else if (dxPoint1 < 0 && dyPoint1 <= 0)
thetaPoint1 = Math.Abs(Math.Asin(dyPoint1 / circle.Radius)) + Math.PI;
else if (dxPoint1 >= 0 && dyPoint1 < 0)
thetaPoint1 = 2 * Math.PI - Math.Abs(Math.Asin(dyPoint1 / circle.Radius));
if (dxPoint2 > 0 && dyPoint2 >= 0)
thetaPoint2 = Math.Asin(dyPoint2 / circle.Radius);
else if (dxPoint2 <= 0 && dyPoint2 > 0)
thetaPoint2 = Math.PI - Math.Asin(dyPoint2 / circle.Radius);
else if (dxPoint2 < 0 && dyPoint2 <= 0)
thetaPoint2 = Math.Abs(Math.Asin(dyPoint2 / circle.Radius)) + Math.PI;
else if (dxPoint2 >= 0 && dyPoint2 < 0)
thetaPoint2 = 2 * Math.PI - Math.Abs(Math.Asin(dyPoint2 / circle.Radius));
if (thetaPoint1 > thetaPoint2)
{
return !(thetaPoint1 - thetaPoint2 <= Math.PI);
}
return thetaPoint2 - thetaPoint1 <= Math.PI;
}
我必须在圆的边缘的两点之间画一条弧。假设弧线总是以尽可能短的距离绘制(edit2:扫描标志设置为 0),我需要知道弧线是顺时针还是逆时针绘制的。
我得到以下输入:
- 起点(point1)
- 终点(point2)
- 中心点
- 半径
Edit1:这个问题与 svg 中的弧线有关。因此它属于编程。
答案是SVG支持顺时针和逆时针弧。您可以通过更改弧 (A) 命令中的“扫描”标志在它们之间切换。
如果您想了解 SVG 弧的工作原理,可以查看 Paths arcs section of the SVG specification。
根据描述的数据,您可以找到更小的圆弧 - CCW 或 CW。
只需检查向量 point1-center
和 point2-center
的叉积符号即可揭示最短弧方向:
cp = (p1.x-c.x)*(p2.y-c.y)-(p1.y-c.y)*(p2.x-c.x)
对于 cp>0
你必须将 sweep
参数设置为 0,否则设置为 1 (反之亦然),而 large-arc-flag
应该总是 0.
在与数学家讨论后,我找到了答案,并在此基础上编写了以下代码:
public static bool IsClockWise(Point point1, Point point2, Circle circle)
{
var dxPoint1 = point1.X - circle.CenterX;
var dyPoint1 = point1.Y - circle.CenterY;
var dxPoint2 = point2.X - circle.CenterX;
var dyPoint2 = point2.Y - circle.CenterY;
double thetaPoint1 = 0, thetaPoint2 = 0;
if (dxPoint1 > 0 && dyPoint1 >= 0)
thetaPoint1 = Math.Asin(dyPoint1 / circle.Radius);
else if (dxPoint1 <= 0 && dyPoint1 > 0)
thetaPoint1 = Math.PI - Math.Asin(dyPoint1 / circle.Radius);
else if (dxPoint1 < 0 && dyPoint1 <= 0)
thetaPoint1 = Math.Abs(Math.Asin(dyPoint1 / circle.Radius)) + Math.PI;
else if (dxPoint1 >= 0 && dyPoint1 < 0)
thetaPoint1 = 2 * Math.PI - Math.Abs(Math.Asin(dyPoint1 / circle.Radius));
if (dxPoint2 > 0 && dyPoint2 >= 0)
thetaPoint2 = Math.Asin(dyPoint2 / circle.Radius);
else if (dxPoint2 <= 0 && dyPoint2 > 0)
thetaPoint2 = Math.PI - Math.Asin(dyPoint2 / circle.Radius);
else if (dxPoint2 < 0 && dyPoint2 <= 0)
thetaPoint2 = Math.Abs(Math.Asin(dyPoint2 / circle.Radius)) + Math.PI;
else if (dxPoint2 >= 0 && dyPoint2 < 0)
thetaPoint2 = 2 * Math.PI - Math.Abs(Math.Asin(dyPoint2 / circle.Radius));
if (thetaPoint1 > thetaPoint2)
{
return !(thetaPoint1 - thetaPoint2 <= Math.PI);
}
return thetaPoint2 - thetaPoint1 <= Math.PI;
}