基于给定的阈值(角度、距离)对折线进行压缩(平滑)。
使用VS2019,C#,建立窗体应用程序,PictureBox用于线段的自定义生成。
0.准备工作:
button1:用于画线
button2:用于基于距离的压缩
button3:用于基于角度的压缩
(button4:清空画板)
picturebox:画线并存储
numericUpDown1:设置角度阈值(默认为90)
numericUpDown2:设置距离阈值(默认为100)
count:用于计算压缩的点数
代码准备:
List<Point> linePoints = null; linePoints用于存储折断的信息
bool isOpenLine = false; isOpenLine用于判断是否开始画线
设置两个点:开始点,追踪点(Point)
注意:双击停止画线,同时要将linePoints的最后一个点移除。
一、思路
对于压缩,计算各个线段的角度/长度,如果在阈值要求范围内,计算下一个;在阈值范围之外则去除该线段。
对于弯曲度的计算,专指分布走向沿Y轴方向的线段。取线段上各个点的Y值取平均,X取最大和最小值,以这条直线作为衡量折线弯曲度的标准。
采用面向对象的思想,将计算的方法封装成函数,下面将介绍所写的函数。
二、基于距离压缩
public void CondenseCal(List<Point> p)
{
Graphics g = pictureBox1.CreateGraphics();
Pen pen = new Pen(System.Drawing.Color.Red);
double disfree = Convert.ToDouble(numericUpDown2.Text);
for (int i = 0; i < p.Count; i++)
{
if (i + 1 < p.Count)
{
double dis = DisTwoPoint(p[i], p[i + 1]);
if (dis < disfree)
{
p.RemoveAt(i + 1);
count--;
}
}
}
for (int j = 0; j < p.Count; j++)
{
if (j + 1 < p.Count)
{
g.DrawLine(pen, p[j], p[j + 1]);
}
}
g.DrawLine(pen, p[p.Count - 1], p[p.Count - 2]);
}
三、基于角度压缩
计算思路与距离压缩相同,但注意角度的计算需要*180/Mat.PI
(Math.Atan2((p[i + 1].Y - p[i].Y), (p[i + 1].X - p[i].X))) * 180 / Math.PI
四、曲线弯曲度的计算
double minx = 99999;
double maxx = 0;
double ymean = 0;
double sumy = 0;
for (int i = 0; i < linePoints.Count; i++)
{
if (linePoints[i].X < minx)
{
minx = linePoints[i].X;
}
if (linePoints[i].X > maxx)
{
maxx = linePoints[i].X;
}
sumy += linePoints[i].Y;
}
ymean = sumy / linePoints.Count;
Pen p = new Pen(System.Drawing.Color.BlueViolet, 4);
g.DrawLine(p, (float)minx, (float)ymean, (float)maxx, (float)ymean);
五、结果
原创作品,禁止抄袭
需要完整代码,欢迎留言