当用户绘制时,我会在每次输入事件触发时捕获其输入的位置,然后在每个点之间绘制直线。
不幸的是,这会产生一种非常锯齿状的外观,并且它会变得更糟,这取决于用户相对于输入事件触发的速度移动输入的速度。
我想要的是一个函数,它接受一个点数组并返回一个已经平滑的点数组,既填充点之间的任何大间隙,又删除锯齿状边缘并用平滑替换它们曲线。
我知道这是一个众所周知的问题,只是没有运气形成搜索查询以找到我正在寻找的东西。
谢谢!
如果函数是用c#编写的,则为奖励积分:)
谢谢!
答案 0 :(得分:9)
public static NoiseReduction(this float[] src, int severity = 1)
{
for (int i = 1; i < src.Length; i++)
{
//---------------------------------------------------------------avg
var start = (i - severity > 0 ? i - severity : 0);
var end = (i + severity < src.Length ? i + severity : src.Length);
float sum = 0;
for (int j = start; j < end; j++)
{
sum += src[j];
}
var avg = sum / (end - start);
//---------------------------------------------------------------
src[i] = avg;
}
}
答案 1 :(得分:6)
我不会得到奖励积分(这是一项家庭作业吗?;),但有一个很容易理解和实施的解决方案。它被称为Catmull-Rom插值。
看看这里
http://en.wikipedia.org/wiki/Catmull-Rom_spline
在这里
http://www.mvps.org/directx/articles/catmull/
(忽略最后一个的DirectX部分)
答案 2 :(得分:3)
谢谢大家!我根据发布的链接编写了以下功能。它可以清理任何间隔太近的点,然后使用Catmull-Rom来平滑点列表。
public static void Smooth(this List<Vector2> pointList)
{
List<Vector2> smoothedPoints = new List<Vector2>();
for (int i = 1; i < pointList.Count; i++)
{
if (Vector2.Distance(pointList[i - 1], pointList[i]) < 30f)
{
pointList.RemoveAt(i);
i--;
}
}
if (pointList.Count < 4) return;
smoothedPoints.Add(pointList[0]);
for (int i = 1; i < pointList.Count - 2; i++)
{
smoothedPoints.Add(pointList[i]);
smoothedPoints.Add(Vector2.CatmullRom(pointList[i - 1], pointList[i], pointList[i + 1], pointList[i + 2], .5f));
//smoothedPoints.Add(Vector2.CatmullRom(pointList[i - 1], pointList[i], pointList[i + 1], pointList[i + 2], .2f));
//smoothedPoints.Add(Vector2.CatmullRom(pointList[i - 1], pointList[i], pointList[i + 1], pointList[i + 2], .3f));
//smoothedPoints.Add(Vector2.CatmullRom(pointList[i - 1], pointList[i], pointList[i + 1], pointList[i + 2], .7f));
//smoothedPoints.Add(Vector2.CatmullRom(pointList[i - 1], pointList[i], pointList[i + 1], pointList[i + 2], .8f));
//smoothedPoints.Add(Vector2.CatmullRom(pointList[i - 1], pointList[i], pointList[i + 1], pointList[i + 2], .9f));
}
smoothedPoints.Add(pointList[pointList.Count - 2]);
smoothedPoints.Add(pointList[pointList.Count - 1]);
pointList.Clear();
pointList.AddRange(smoothedPoints);
}
答案 3 :(得分:1)
你在做什么画画?
如果您正在使用System.Drawing,您是否可以将这些点传递给DrawBeziers,这应该可以为您做好反对别名。