我是 c#/svg 的新手,正在尝试转换其点存在于数组中的相对 float arcArray[2,4] 并尝试将所有内容保留在我的 ArcPlot
类 {{1}仅将实际的 svg 函数放在一个单独的类中。
这将在视觉上产生正确的曲线,但我需要它朝相反的方向移动以附加到现有的 svg 字符串:
using System
这个:
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,Clockwise));
svgOut += " m " + arcPoint[0,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,1] = arcArray[1,2] - arcArray[1,2] = arcArray[0,1] - arcArray[0,2] = arcArray[1,1] - arcArray[1,3] = arcArray[0,0] - arcArray[0,3] = arcArray[1,0] - arcArray[1,3];
return swapArray;
}
开始曲线,其余三个控制点很接近,但被我俯瞰的东西抵消了。我假设这是绝对弧和相对弧之间的区别,我缺少一些简单的东西,比如对实际曲线坐标的推导。
蛮力/反复试验对我不起作用。
我第一次尝试使用 (0,0)
也没有运气,这将是避免完全逆转的首选方法,但同样,我显然错过了一些东西。我还想弄清楚反向函数,以便更好地理解相对 svg。
如果有帮助,这是我用来创建弧的实际函数:
ArcPlot.arcPointsArray(StartAngle + SweepAngle,!Clockwise)
我在 python 和 javascript 中看到过类似的问题,但对语法或结构的理解不够,无法翻译。
我假设答案只是换位、不正确的假设或数学错误,但如果不是,则首选伪代码,这样我就可以获得概念而不是剪切/粘贴解决方案。
以下 gif 显示了我遇到的旋转问题,因为内部相对弧没有被正确转换。我将在之前的尝试中单独处理这个问题(因为我直到之后才开始使用 git,所以它不再存在)以绝对定位呈现所有内容不会出现这个问题。我遇到的实际问题是可以正确渲染内弧,但只能在错误的方向上渲染。当使用上面显示的反转方法反转它或使用 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,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;
}
向后绘制时,需要单独识别和连接这些部分,而不是使用循环,因为它们需要稍微不同的方法。这个想法是最终将绿线以均匀的距离包裹在红线中,而不管起始角度、方向和比例如何。