小编最近的更新频率比较慢,是因为最近在准备这个全国大学生测绘学科创新创业智能大赛(测绘程序设计)–专业组的比赛,为了这个比赛,小编高强度的准备了一个月,也是取得了较为喜人的成绩。
如果有准备在2026年参加这个比赛的,可以加入小编和其它大佬所建的群242845175一起来备赛,为2026年的比赛打基础,也可以私信小编,为你答疑解惑
话不多说,接下来是代码与正文
一、读写数据文件
public static List<Point> pts= new List<Point>();
public static List<Point> Readfile(string filename)
{
string str;
StreamReader sr = new StreamReader(filename);
int n = 1;
while(!sr.EndOfStream)
{
str= sr.ReadLine();
string[]Buf=str.Split(new char[]{' ','\t'},StringSplitOptions.RemoveEmptyEntries);
Point pt=new Point(double.Parse(Buf[0]), double.Parse(Buf[1]), double.Parse(Buf[2]),n);
pts.Add(pt);
n++;
}
return pts;
}
public static void Savefile(string report)
{
SaveFileDialog sf= new SaveFileDialog();
sf.Filter = "文本数据|*.txt";
sf.Title = "选择保存路径";
sf.FileName = "result";
if(sf.ShowDialog() == DialogResult.OK)
{
StreamWriter sw= new StreamWriter(sf.FileName);
sw.Write(report);
sw.Flush();
}
}
二、点的相关属性
public class Point
{
public double x;
public double y;
public double z;
public int n;
//格网划分所需参数
public int i;
public int j;
public int k;
//候选点
public List<Point> after=new List<Point>();
//最近邻点
public List<(int, double)> mind =new List<(int, double)>();
//平均距离
public double avd;
public double sigema;
//噪点判定
public int number;
public Point(double x, double y, double z,int n)
{
this.x= x;
this.y= y;
this.z= z;
this.n= n;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(x.ToString()+" "+y.ToString()+" "+z.ToString()+" "+n.ToString());
return sb.ToString();
}
}
}
三、格网划分与点云分配
public static double fai = 3;
public static List<Point> zaopoint = new List<Point>();
//寻找各项极值
public static void Jizhi(out double xmax,out double ymax,out double zmax,out double xmin,out double ymin,out double zmin)
{
xmax = Read.pts.Max(p => p.x);
ymax = Read.pts.Max(p => p.y);
zmax = Read.pts.Max(p => p.z);
xmin = Read.pts.Min(p => p.x);
ymin = Read.pts.Min(p => p.y);
zmin = Read.pts.Min(p => p.z);
}
//计算格网最大值
public static void Gewang(out double xmax1,out double ymax1,out double zmax1)
{
Jizhi(out double xmax, out double ymax, out double zmax, out double xmin, out double ymin, out double zmin);
xmax1 = (int)((xmax - xmin) / fai + 1) * fai + xmin;
ymax1 = (int)((ymax - ymin) / fai + 1) * fai + ymin;
zmax1 = (int)((zmax - zmin) / fai + 1) * fai + zmin;
}
//格网划分
public static void Classify(List<Point> pts,out int sum)
{
Jizhi(out double xmax, out double ymax, out double zmax, out double xmin, out double ymin, out double zmin);
foreach (Point p in pts)
{
p.i = (int)((p.x - xmin) / fai);
p.j = (int)((p.y - ymin) / fai);
p.k = (int)((p.z - zmin) / fai);
}
//统计(0,0,0)的个数
sum = 0;
foreach(Point p in pts)
{
if (p.i == 0 && p.j == 0 && p.k == 0)
{
sum++;
}
}
}
四、k邻近点搜索(k=6)
值得注意的是,有些点的候选点可能不足6个,需要进行特殊处理(不足六个点,则全部选取)
//欧式距离计算
public static double Distance(Point P1,Point P2)
{
double d = (P1.x - P2.x) * (P1.x - P2.x) + (P1.y - P2.y) * (P1.y - P2.y) + (P1.z - P2.z) * (P1.z - P2.z);
return Math.Sqrt(d);
}
//统计点的候选点
//(pt.i-p.i=1||pt.i-p.i=0||pt.i-p.i=-1)&&(pt.j-p.j=1||pt.j-p.j=0||pt.j-p.j=-1)&&(pt.k-p.k=1||pt.k-p.k=0||pt.k-p.k=-1)
//Math.Abs(pt.i-p.i)<=1&& Math.Abs(pt.j - p.j) <= 1 && Math.Abs(pt.k - p.k) <= 1
public static List<Point> Tongji(Point p)
{
List<Point> list = new List<Point>();
foreach(Point pt in Read.pts)
{
if(Math.Abs(pt.i - p.i) <= 1 && Math.Abs(pt.j - p.j) <= 1 && Math.Abs(pt.k - p.k) <= 1)
{
list.Add(pt);//此处并未排除自身点,在后续输出中进行排除
}
}
return list;
}
//计算每个点最近邻点
public static void Mind(List<Point> pts)
{
foreach(Point pt in pts)
{
pt.after = Tongji(pt);
List<(int,double)> list = new List< (int, double) >();
foreach(Point p in pt.after)
{
if (p.n == pt.n)
{
continue;
}
list.Add((p.n, Distance(pt,p)));
}
List<(int, double)> before = new List<(int, double)>();
before = list.OrderBy(p => p.Item2).ToList();
int k = 0;
if (before.Count > 6)
{
k=6;
}
else
{
k=before.Count;
}
for (int i = 0; i < k; i++)
{
pt.mind.Add(before[i]);
}
}
}
五、统计特征计算
//计算每个点的平均距离和标准差
public static void Alhelp(List<Point> pts)
{
foreach(Point pt in pts)
{
pt.avd = pt.mind.Average(p => p.Item2);
double sum = 0;
for(int i=0;i < pt.mind.Count; i++)
{
sum += (pt.mind[i].Item2 - pt.avd) * (pt.mind[i].Item2 - pt.avd);
}
pt.sigema=Math.Sqrt(sum/ pt.mind.Count);
}
}
//计算全局平均距离均值和标准差
public static void Allpoint(out double avds,out double sigemas)
{
avds=Read.pts.Average(p=>p.avd);
sigemas=Read.pts.Average(p=> p.sigema);
}
六、全局噪点判断
//全局判断噪点
public static void Alljudge(List<Point> pts)
{
Allpoint(out double avds, out double sigemas);
foreach (Point pt in pts)
{
if(pt.avd > (avds + 2 * sigemas))
{
pt.number = 1;
}
else
{
zaopoint.Add(pt);
pt.number = 0;
}
}
}
窗体交互
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
openFile.FileOk += openFile_FileOk;
}
public static List<Point> before=new List<Point>();
public string report;
private void toolStripLabel1_Click(object sender, EventArgs e)
{
if (openFile.ShowDialog() == DialogResult.OK)
{
string name=openFile.FileName;
before=Read.Readfile(name);
dataGridView1.RowCount= before.Count;
for(int i = 0; i < before.Count; i++)
{
dataGridView1[0, i].Value = before[i].x;
dataGridView1[1,i].Value = before[i].y;
dataGridView1[2,i].Value = before[i].z;
}
}
}
private void openFile_FileOk(object sender, CancelEventArgs e)
{
}
private void toolStripLabel2_Click(object sender, EventArgs e)
{
report += "1\t点 P1 的 x 坐标 " + Read.pts[0].x.ToString("F3") + "\n";
report += "2\t点 P6 的 y 坐标 " + Read.pts[5].y.ToString("F3") + "\n";
report += "3\t点 P789 的 z 坐标 " + Read.pts[788].z.ToString("F3") + "\n";
report += "4\t原始点云的总点数 " + Read.pts.Count + "\n";
Alpoint.Jizhi(out double xmax,out double ymax,out double zmax,out double xmin,out double ymin,out double zmin);
Alpoint.Gewang(out double xmax1, out double ymax1, out double zmax1);
report += "5\t点云数据x最大值 " + xmax.ToString("F3") + "\n";
report += "6\t点云数据y最大值 " + ymax.ToString("F3") + "\n";
report += "7\t点云数据z最大值" + zmax.ToString("F3") + "\n";
report += "8\t格网 xmin " + xmin.ToString("F3") + "\n";
report += "9\t格网 xmax1 " + xmax1.ToString("F3") + "\n";
report += "10\t格网 ymin " + ymin.ToString("F3") + "\n";
report += "11\t格网 ymax1 " + ymax1.ToString("F3") + "\n";
report += "12\t格网 zmin" + zmin.ToString("F3") + "\n";
report += "13\t格网 zmax1 " + zmax1.ToString("F3") + "\n";
Alpoint.Classify(Read.pts, out int sum);
report += "14\t网格 (0,0,0) 内的点个数 " + sum + "\n";
report += "15\t点 P1 的网格索引(i,j,k)中i分量 " + Read.pts[0].i + "\n";
report += "16\t点 P6 的网格索引(i,j,k)中j分量" + Read.pts[5].j + "\n";
Alpoint.Mind(Read.pts);
report += "17\t点 P1 的候选点总数 " + (Read.pts[0].after.Count-1) + "\n";
report += "18\t点 P6 的候选点总数 " + (Read.pts[5].after.Count-1) + "\n";
int b = Read.pts[5].mind.Max(p => p.Item1);
int a = Read.pts[0].mind.Max(p => p.Item1);
report += "19\t点 P1 的 6 个邻近点序号中最大值" + a + "\n";
report += "20\t点 P6 的 6 个邻近点序号中最大值 " + b+ "\n";
Alpoint.Alhelp(Read.pts);
Alpoint.Allpoint(out double avds, out double sigemas);
Alpoint.Alljudge(Read.pts);
report += "21\t点 P1 的邻域平均距离 u₁ " + Read.pts[0].avd.ToString("F3") + "\n";
report += "22\t点 P1 的邻域距离标准差 σ₁ " + Read.pts[0].sigema.ToString("F3") + "\n";
report += "23\t点 P6 的邻域平均距离 u₆" + Read.pts[5].avd.ToString("F3") + "\n";
report += "24\t点 P6 的邻域距离标准差 σ₆ " + Read.pts[5].sigema.ToString("F3") + "\n";
report += "25\t全局平均距离均值 μ " + avds.ToString("F3") + "\n";
report += "26\t全局距离标准差 σ " + sigemas.ToString("F3") + "\n";
report += "27\t点 P1 是否为噪声点(0、1分别表示否、是) " + Read.pts[0].number + "\n";
report += "28\t点 P6 是否为噪声点(0、1分别表示否、是)" + Read.pts[5].number + "\n";
report += "29\t去噪后保留的点云总数 " + Alpoint.zaopoint.Count + "\n";
richTextBox1.Text = report;
}
private void toolStripLabel3_Click(object sender, EventArgs e)
{
Read.Savefile(report);
}
}
七,运行结果
1 点 P1 的 x 坐标 533599.690
2 点 P6 的 y 坐标 3377146.850
3 点 P789 的 z 坐标 28.890
4 原始点云的总点数 44518
5 点云数据x最大值 533774.000
6 点云数据y最大值 3377195.000
7 点云数据z最大值113.120
8 格网 xmin 533574.000
9 格网 xmax1 533775.000
10 格网 ymin 3377000.000
11 格网 ymax1 3377198.000
12 格网 zmin8.560
13 格网 zmax1 113.560
14 网格 (0,0,0) 内的点个数 0
15 点 P1 的网格索引(i,j,k)中i分量 8
16 点 P6 的网格索引(i,j,k)中j分量48
17 点 P1 的候选点总数 69
18 点 P6 的候选点总数 47
19 点 P1 的 6 个邻近点序号中最大值44391
20 点 P6 的 6 个邻近点序号中最大值 1508
21 点 P1 的邻域平均距离 u₁ 1.981
22 点 P1 的邻域距离标准差 σ₁ 0.329
23 点 P6 的邻域平均距离 u₆1.411
24 点 P6 的邻域距离标准差 σ₆ 0.186
25 全局平均距离均值 μ 1.668
26 全局距离标准差 σ 0.339
27 点 P1 是否为噪声点(0、1分别表示否、是) 0
28 点 P6 是否为噪声点(0、1分别表示否、是)0
29 去噪后保留的点云总数 42555
八、报告文档
第一页为封面
第二页为目录
后面为正常模板
总结
本次的比赛也是收获匪浅,总体来说,还是要多练,今年的题目明显带有一定的挑战性质,需要不断多练,不要抱有侥幸心理,认为考过相似的题,就不会再考了,这几年的竞争压力还是很大的,所以一定要抓住时间,勤奋多练,我和诸多大佬都会在群里为你们答疑解惑的,C#,python,C++都有的,欢迎大家进群讨论242845175