导览
源代码和关键功能代码介绍
- 工程源代码下载
- 图像坐标系转换
- UI设计代码
01
工程和源代码下载
https://pan.baidu.com/s/1XaKFZLudnnISui7lV8540A
提取码:5ytm
现已经支持的点格式:.asc/.csv/.xyz
02
图像坐标系转化
窗口的交互设计都是基于C#中的PictureBox的坐标系
图像原点与图像框坐标原点
我们基于鼠标事件得到坐标都是基于图像框坐标系的,我们的点云坐标是与图像坐标对应的,因此需要将图像框的坐标转换到图片的坐标。
一般经过两次变化:平移 缩放
平移
缩放
代码语言:javascript复制 private Point TransImageToPicbox(Point e)
{
try
{
//取得当前图像在图片框中的位置和长宽
rectangle_curr = (Rectangle)pictureBox1.GetType().GetProperty("ImageRectangle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(pictureBox1, null);
int currentWidth = rectangle_curr.Width;
int currentHeight = rectangle_curr.Height;
//计算缩放系数
double rate_h = (double)currentHeight / (double)pictureBox1.Image.Height; double rate_w = (double)currentWidth / (double)pictureBox1.Image.Width;
//计算XY偏移
int black_left_width = (currentWidth == this.pictureBox1.Width) ? 0 : (this.pictureBox1.Width - currentWidth) / 2;
int black_top_height = (currentHeight == this.pictureBox1.Height) ? 0 : (this.pictureBox1.Height - currentHeight) / 2;
int zoom_x = e.X - black_left_width;
int zoom_y = e.Y - black_top_height;
double original_x = (double)zoom_x / rate_w;
double original_y = (double)zoom_y / rate_h;
//如果鼠标落在图片区域外则返回原点坐标
if (e.X < black_left_width || e.X >= currentWidth rectangle_curr.Location.X)
{
return new Point(0, 0);
}
if (e.Y < black_top_height || e.Y >= currentHeight rectangle_curr.Location.Y)
{
return new Point(0, 0);
}
//返回实际图像坐标
return new Point((int)original_x, (int)original_y);
}
catch (Exception)
{
return new Point(0, 0);
}
}
02
交互代码
通过鼠标拉线获取线上所有点云数据
1.设置鼠标事件 2.
代码语言:javascript复制 private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
//鼠标按下时,记录开始点坐标
StrPoint_pic = e.Location;
//转换坐标系到图像
StrPoint = TransImageToPicbox(e.Location);
break;
}
3.
代码语言:javascript复制 private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
//鼠标松开记录结束点坐标
bitmap = (Bitmap)pictureBox1.Image;
Graphics graphics = Graphics.FromImage(this.bitmap);
EndPoint_pic = e.Location;
//转换坐标系到图像
EndPoint = TransImageToPicbox(new Point(EndPoint_pic.X, StrPoint_pic.Y));
double[] data = new double[Get_Point_line(StrPoint, EndPoint).Count]; int count = 0;
foreach (Point3 item in Get_Point_line(StrPoint, EndPoint))
{
data[count] = item.Z; count ;
}
FileOpt.data_buffer = data.ToList();
chart.chart1.ChartAreas[0].AxisY.Maximum = data.Max() 10; chart.chart1.ChartAreas[0].AxisY.Minimum = data.Min() - 10;
chart.chart1.Series[0].IsValueShownAsLabel = false;
chart.chart1.Series[0].Points.DataBindY(data);
//将两点的连线画在图像上
graphics.DrawLine(new Pen(Color.Red, 3), StrPoint, EndPoint);
pictureBox1.Image = bitmap;
break;
}
4.计算线的图像坐标系方程
5.
代码语言:javascript复制 private List<Point3> Get_Point_line(Point str,Point end)
{
//声明直线方程的k和b,声明一个存放线上点云数据的表
float k;float b;List<Point3> point_list1 = new List<Point3>();
try
{
Point3 point3 = new Point3();
k = (float)(end.Y - str.Y) /(float)(end.X - str.X);
b = str.Y - k * (float)str.X;
//k存在,k>1或者0>k>-1
if (k>1||((k<0)&&(k<-1)))
{
for (int i = Math.Min(str.Y, end.Y); i < Math.Max(str.Y, end.Y); i )
{
point3.Y = i; point3.X = (int)((i-b)/k); point3.Z = FileOpt.datamat_buffer[point3.X, point3.Y];
point_list1.Add(point3);
}
point_list = point_list1;
}
//k存在,k<1或者k<-1
else
{
for (int i = Math.Min(str.X, end.X); i < Math.Max(str.X, end.X); i )
{
point3.X = i; point3.Y = (int)(k * (float)i b); point3.Z = FileOpt.datamat_buffer[point3.X, point3.Y];
point_list1.Add(point3);
}
point_list = point_list1;
}
return point_list1;
}
catch (Exception)
{
//k不存在,此时线属于铅垂线
Point3 point3 = new Point3();
for (int i = Math.Min(str.Y, end.Y); i < Math.Max(str.Y, end.Y); i )
{
point3.X = str.X; point3.Y = i; point3.Z = FileOpt.datamat_buffer[point3.X, point3.Y];
point_list1.Add(point3);
}
point_list = point_list1;
return point_list1;
throw;
}
}
小结
1. 坐标系变化
2. 交互设计