如何反转使用 C# 中的数组构建的 SVG 曲线?
How do I reverse an SVG curve built using an array in C#?
我是 c#/svg 的新手,正在尝试转换其点存在于数组中的相对 <90 曲线:float arcArray[2,4]
并尝试将所有内容保留在我的 ArcPlot
class using System
并将实际的 svg 函数放在单独的 class.
中
这将在视觉上生成正确的曲线,但我需要它朝相反的方向移动以附加到现有的 svg 字符串:
float [,] arcPoint = ArcPlot.arcPointsArray(StartAngle, SweepAngle, Radius, -RadiusOffset, Clockwise);
svgOut += " m " + arcPoint[0, 0] + " " + arcPoint[1, 0] + " c " + arcPoint[0, 1] + " " + arcPoint[1, 1] + " " + arcPoint[0, 2] + " " + arcPoint[1, 2] + " " + arcPoint[0, 3] + " " + arcPoint[1, 3];
这个:
float [,] arcPoint = ArcPlot.reverseArcArray(ArcPlot.arcPointsArray(StartAngle, SweepAngle, Radius, -RadiusOffset, Clockwise));
svgOut += " m " + arcPoint[0, 0] + " " + arcPoint[1, 0] + " c " + arcPoint[0, 1] + " " + arcPoint[1, 1] + " " + arcPoint[0, 2] + " " + arcPoint[1, 2] + " " + arcPoint[0, 3] + " " + arcPoint[1, 3];
使用这个函数:
public static float[,] reverseArcArray(float[,] ArcArray)
{
float [,] arcArray = ArcArray;
float [,] swapArray = new float [2,4];
swapArray[0, 0] = arcArray[0, 3] - arcArray[0, 3];
swapArray[1, 0] = arcArray[1, 3] - arcArray[1, 3];
swapArray[0, 1] = arcArray[0, 2] - arcArray[0, 3];
swapArray[1, 1] = arcArray[1, 2] - arcArray[1, 3];
swapArray[0, 2] = arcArray[0, 1] - arcArray[0, 3];
swapArray[1, 2] = arcArray[1, 1] - arcArray[1, 3];
swapArray[0, 3] = arcArray[0, 0] - arcArray[0, 3];
swapArray[1, 3] = arcArray[1, 0] - arcArray[1, 3];
return swapArray;
}
在正确的位置开始曲线 (0,0)
,其余三个控制点很接近,但被我忽略的东西抵消了。我假设这是绝对弧和相对弧之间的区别,我遗漏了一些简单的东西,比如对实际曲线坐标的推导。
粗暴 forcing/trial 错误对我不起作用。
我第一次尝试使用 ArcPlot.arcPointsArray(StartAngle + SweepAngle, SweepAngle, Radius, -RadiusOffset, !Clockwise)
时也没有运气,这将是避免完全逆转的首选方法,但是,我再次明显遗漏了一些东西。我仍然想弄清楚反向函数,以更好地理解相对 svg。
如果有帮助,这是我用来创建弧线的实际函数:
public static float[,] arcPointsArray(double StartAngle, double SweepAngle, double Radius, double RadiusOffset = 0d,
bool Clockwise = false, float XCenter = 0f, float YCenter = 0f)
{
double radius = Radius, startAngle = StartAngle, sweepAngle = SweepAngle, radiusOffset = RadiusOffset;
bool arcClockwise = Clockwise;
float xCenter = XCenter, yCenter = YCenter;
double startRadiusAngle = arcClockwise ? startAngle - (pi / 2) : startAngle + (pi / 2);
startRadiusAngle -= Convert.ToInt32(startRadiusAngle / (pi * 2)) * (pi * 2); // mathematical overcircle check
sweepAngle -= Convert.ToInt32(sweepAngle / (pi * 2)) * (pi * 2);
double toCenterAngle = arcClockwise ? startAngle + (pi / 2) : startAngle - (pi / 2);
if (toCenterAngle > (pi * 2)) toCenterAngle -= pi * 2; // functional overcircle check
if (toCenterAngle < 0) toCenterAngle += pi * 2;
if (XCenter == 0f) xCenter = Convert.ToSingle(Math.Cos(toCenterAngle) * radius);
if (YCenter == 0f) yCenter = Convert.ToSingle(Math.Sin(toCenterAngle) * radius);
radius += radiusOffset;
float[,] arcArray = new float[2, 4];
arcArray[0, 0] = Convert.ToSingle(xCenter + (Math.Cos(startRadiusAngle) * radius)); // relocate start point
arcArray[1, 0] = Convert.ToSingle(yCenter + (Math.Sin(startRadiusAngle) * radius));
double circleFraction = pi * 2 / sweepAngle;
double bezierLength = radius * 4 / 3 * Math.Tan(pi / (2 * circleFraction));
arcArray[0, 1] = Convert.ToSingle(arcArray[0, 0] + (Math.Cos(startAngle) * bezierLength)) - arcArray[0, 0];
arcArray[1, 1] = Convert.ToSingle(arcArray[1, 0] + (Math.Sin(startAngle) * bezierLength)) - arcArray[1, 0];
double endRadiusAngle = arcClockwise ? startRadiusAngle + sweepAngle : startRadiusAngle - sweepAngle;
if (endRadiusAngle > (pi * 2)) endRadiusAngle -= pi * 2;
if (endRadiusAngle < 0) endRadiusAngle += pi * 2;
arcArray[0, 3] = Convert.ToSingle(xCenter + (Math.Cos(endRadiusAngle) * radius)) - arcArray[0, 0];
arcArray[1, 3] = Convert.ToSingle(yCenter + (Math.Sin(endRadiusAngle) * radius)) - arcArray[1, 0];
double endAngle = arcClockwise ? endRadiusAngle - (pi / 2) : endRadiusAngle + (pi / 2);
if (endAngle > (pi * 2d)) endAngle -= pi * 2;
if (endAngle < 0d) endAngle += pi * 2;
arcArray[0, 2] = Convert.ToSingle(arcArray[0, 3] + (Math.Cos(endAngle) * bezierLength));
arcArray[1, 2] = Convert.ToSingle(arcArray[1, 3] + (Math.Sin(endAngle) * bezierLength));
return arcArray;
}
我在 python 和 javascript 中看到过类似的问题,但对语法或结构的理解不够,无法翻译。
我假设答案只是换位、不正确的假设或数学错误,但如果不是,伪代码将是首选,这样我可以获得概念而不是 cut/paste 解决方案。
下面的 gif 显示了我遇到的旋转问题,因为内部相对弧没有被正确翻译。我将单独处理这个问题,作为之前的尝试(它不再存在,因为我直到之后才开始使用 git )在渲染具有绝对定位的所有内容时不会出现这个问题。我遇到的实际问题是可以正确渲染内部弧线,但只能在错误的方向上渲染。当使用上面显示的反转方法或使用 arcPointsArray
将其向后绘制时,这些部分需要分别识别和连接,而不是使用循环,因为它们需要稍微不同的方法。想法是最终将绿线以均匀的距离包裹在红线中,而不考虑起始角度、方向和比例。
为什么不直接修改对 arcPointsArray()
的调用?这样的东西有用吗?
float [,] arcPoint = ArcPlot.arcPointsArray(StartAngle + SweepAngle,
-SweepAngle,
Radius,
-RadiusOffset,
!Clockwise);
这是我最终用于反转相对三次 svg 曲线的代码:
public static float[,] reverseArcArray(float[,] ArcArray)
{
float [,] arcArray = ArcArray;
float [,] swapArray = new float [2,4];
swapArray[0, 0] = 0f;
swapArray[1, 0] = 0f;
swapArray[0, 1] = arcArray[0, 2] - arcArray[0, 3];
swapArray[1, 1] = arcArray[1, 2] - arcArray[1, 3];
swapArray[0, 2] = arcArray[0, 1] - arcArray[0, 3];
swapArray[1, 2] = arcArray[1, 1] - arcArray[1, 3];
swapArray[0, 3] = -arcArray[0, 3];
swapArray[1, 3] = -arcArray[1, 3];
return swapArray;
}
我的问题是误解了第一个坐标和最后一个坐标之间的关系。如问题中所述,该功能将正确完成工作。它既会反转相对曲线,又会在反转时将绝对值转换为相对值。
因为我只处理相对曲线,所以我可以丢弃第一个坐标,因为它们始终为 0,0,并且可以根据需要用起始位置覆盖它。
Paul 的回答中得出的解决方案表明这是一个 xy 问题。重新评估我如何使用 arcPointsArray 方法消除了对 reverseArcArray 方法的需要。
我留下这个答案是为了让任何实际搜索 y 问题的人都不会被 x 解决方案所困。
我是 c#/svg 的新手,正在尝试转换其点存在于数组中的相对 <90 曲线:float arcArray[2,4]
并尝试将所有内容保留在我的 ArcPlot
class using System
并将实际的 svg 函数放在单独的 class.
这将在视觉上生成正确的曲线,但我需要它朝相反的方向移动以附加到现有的 svg 字符串:
float [,] arcPoint = ArcPlot.arcPointsArray(StartAngle, SweepAngle, Radius, -RadiusOffset, Clockwise);
svgOut += " m " + arcPoint[0, 0] + " " + arcPoint[1, 0] + " c " + arcPoint[0, 1] + " " + arcPoint[1, 1] + " " + arcPoint[0, 2] + " " + arcPoint[1, 2] + " " + arcPoint[0, 3] + " " + arcPoint[1, 3];
这个:
float [,] arcPoint = ArcPlot.reverseArcArray(ArcPlot.arcPointsArray(StartAngle, SweepAngle, Radius, -RadiusOffset, Clockwise));
svgOut += " m " + arcPoint[0, 0] + " " + arcPoint[1, 0] + " c " + arcPoint[0, 1] + " " + arcPoint[1, 1] + " " + arcPoint[0, 2] + " " + arcPoint[1, 2] + " " + arcPoint[0, 3] + " " + arcPoint[1, 3];
使用这个函数:
public static float[,] reverseArcArray(float[,] ArcArray)
{
float [,] arcArray = ArcArray;
float [,] swapArray = new float [2,4];
swapArray[0, 0] = arcArray[0, 3] - arcArray[0, 3];
swapArray[1, 0] = arcArray[1, 3] - arcArray[1, 3];
swapArray[0, 1] = arcArray[0, 2] - arcArray[0, 3];
swapArray[1, 1] = arcArray[1, 2] - arcArray[1, 3];
swapArray[0, 2] = arcArray[0, 1] - arcArray[0, 3];
swapArray[1, 2] = arcArray[1, 1] - arcArray[1, 3];
swapArray[0, 3] = arcArray[0, 0] - arcArray[0, 3];
swapArray[1, 3] = arcArray[1, 0] - arcArray[1, 3];
return swapArray;
}
在正确的位置开始曲线 (0,0)
,其余三个控制点很接近,但被我忽略的东西抵消了。我假设这是绝对弧和相对弧之间的区别,我遗漏了一些简单的东西,比如对实际曲线坐标的推导。
粗暴 forcing/trial 错误对我不起作用。
我第一次尝试使用 ArcPlot.arcPointsArray(StartAngle + SweepAngle, SweepAngle, Radius, -RadiusOffset, !Clockwise)
时也没有运气,这将是避免完全逆转的首选方法,但是,我再次明显遗漏了一些东西。我仍然想弄清楚反向函数,以更好地理解相对 svg。
如果有帮助,这是我用来创建弧线的实际函数:
public static float[,] arcPointsArray(double StartAngle, double SweepAngle, double Radius, double RadiusOffset = 0d,
bool Clockwise = false, float XCenter = 0f, float YCenter = 0f)
{
double radius = Radius, startAngle = StartAngle, sweepAngle = SweepAngle, radiusOffset = RadiusOffset;
bool arcClockwise = Clockwise;
float xCenter = XCenter, yCenter = YCenter;
double startRadiusAngle = arcClockwise ? startAngle - (pi / 2) : startAngle + (pi / 2);
startRadiusAngle -= Convert.ToInt32(startRadiusAngle / (pi * 2)) * (pi * 2); // mathematical overcircle check
sweepAngle -= Convert.ToInt32(sweepAngle / (pi * 2)) * (pi * 2);
double toCenterAngle = arcClockwise ? startAngle + (pi / 2) : startAngle - (pi / 2);
if (toCenterAngle > (pi * 2)) toCenterAngle -= pi * 2; // functional overcircle check
if (toCenterAngle < 0) toCenterAngle += pi * 2;
if (XCenter == 0f) xCenter = Convert.ToSingle(Math.Cos(toCenterAngle) * radius);
if (YCenter == 0f) yCenter = Convert.ToSingle(Math.Sin(toCenterAngle) * radius);
radius += radiusOffset;
float[,] arcArray = new float[2, 4];
arcArray[0, 0] = Convert.ToSingle(xCenter + (Math.Cos(startRadiusAngle) * radius)); // relocate start point
arcArray[1, 0] = Convert.ToSingle(yCenter + (Math.Sin(startRadiusAngle) * radius));
double circleFraction = pi * 2 / sweepAngle;
double bezierLength = radius * 4 / 3 * Math.Tan(pi / (2 * circleFraction));
arcArray[0, 1] = Convert.ToSingle(arcArray[0, 0] + (Math.Cos(startAngle) * bezierLength)) - arcArray[0, 0];
arcArray[1, 1] = Convert.ToSingle(arcArray[1, 0] + (Math.Sin(startAngle) * bezierLength)) - arcArray[1, 0];
double endRadiusAngle = arcClockwise ? startRadiusAngle + sweepAngle : startRadiusAngle - sweepAngle;
if (endRadiusAngle > (pi * 2)) endRadiusAngle -= pi * 2;
if (endRadiusAngle < 0) endRadiusAngle += pi * 2;
arcArray[0, 3] = Convert.ToSingle(xCenter + (Math.Cos(endRadiusAngle) * radius)) - arcArray[0, 0];
arcArray[1, 3] = Convert.ToSingle(yCenter + (Math.Sin(endRadiusAngle) * radius)) - arcArray[1, 0];
double endAngle = arcClockwise ? endRadiusAngle - (pi / 2) : endRadiusAngle + (pi / 2);
if (endAngle > (pi * 2d)) endAngle -= pi * 2;
if (endAngle < 0d) endAngle += pi * 2;
arcArray[0, 2] = Convert.ToSingle(arcArray[0, 3] + (Math.Cos(endAngle) * bezierLength));
arcArray[1, 2] = Convert.ToSingle(arcArray[1, 3] + (Math.Sin(endAngle) * bezierLength));
return arcArray;
}
我在 python 和 javascript 中看到过类似的问题,但对语法或结构的理解不够,无法翻译。
我假设答案只是换位、不正确的假设或数学错误,但如果不是,伪代码将是首选,这样我可以获得概念而不是 cut/paste 解决方案。
下面的 gif 显示了我遇到的旋转问题,因为内部相对弧没有被正确翻译。我将单独处理这个问题,作为之前的尝试(它不再存在,因为我直到之后才开始使用 git )在渲染具有绝对定位的所有内容时不会出现这个问题。我遇到的实际问题是可以正确渲染内部弧线,但只能在错误的方向上渲染。当使用上面显示的反转方法或使用 arcPointsArray
将其向后绘制时,这些部分需要分别识别和连接,而不是使用循环,因为它们需要稍微不同的方法。想法是最终将绿线以均匀的距离包裹在红线中,而不考虑起始角度、方向和比例。
为什么不直接修改对 arcPointsArray()
的调用?这样的东西有用吗?
float [,] arcPoint = ArcPlot.arcPointsArray(StartAngle + SweepAngle,
-SweepAngle,
Radius,
-RadiusOffset,
!Clockwise);
这是我最终用于反转相对三次 svg 曲线的代码:
public static float[,] reverseArcArray(float[,] ArcArray)
{
float [,] arcArray = ArcArray;
float [,] swapArray = new float [2,4];
swapArray[0, 0] = 0f;
swapArray[1, 0] = 0f;
swapArray[0, 1] = arcArray[0, 2] - arcArray[0, 3];
swapArray[1, 1] = arcArray[1, 2] - arcArray[1, 3];
swapArray[0, 2] = arcArray[0, 1] - arcArray[0, 3];
swapArray[1, 2] = arcArray[1, 1] - arcArray[1, 3];
swapArray[0, 3] = -arcArray[0, 3];
swapArray[1, 3] = -arcArray[1, 3];
return swapArray;
}
我的问题是误解了第一个坐标和最后一个坐标之间的关系。如问题中所述,该功能将正确完成工作。它既会反转相对曲线,又会在反转时将绝对值转换为相对值。
因为我只处理相对曲线,所以我可以丢弃第一个坐标,因为它们始终为 0,0,并且可以根据需要用起始位置覆盖它。
Paul 的回答中得出的解决方案表明这是一个 xy 问题。重新评估我如何使用 arcPointsArray 方法消除了对 reverseArcArray 方法的需要。
我留下这个答案是为了让任何实际搜索 y 问题的人都不会被 x 解决方案所困。