点的基本操作

点的基本操作

要求
提供空间点数据文本文件,包含ID、name、X、Y四个字段信息,

1)读取数据,并且在窗口中显示点的具体位置,用实心圆绘制。
2)鼠标任意点击三个点,将点连线,用黑色笔刷绘制线。
3)鼠标点击选中其中一条线,将线颜色变为黄色。
4)移动任意一点,将新的坐标信息修改后保存到文本文件中。

思路:1、定义一个点类,存点;定义一个线类,存线数据

​ 2、定义一个服务类,用于处理先关点操作

​ 3、窗口实现

首先是一个点

public  class Point
    {
        public int ID { get; set; }
        public string Name { get;set; }
        public float X { get; set; }
        public float Y { get; set; }

        public Point(int id, string name, float x, float y)
        {
            ID = id;
            Name = name;
            X = x;
            Y = y;
        }
    }

再是一个线

 public   class Line
    {
       
        public List<Point> Coordinates { get; set; }
        public double k{ get; set; }
        public double b{ get; set; }
        public bool isselect { get; set; }
        public Line(List<Point> coords)
        {
            var pt1 = coords[0];
            var pt2 = coords[1];
            Coordinates = coords;
            this.k = (pt2.Y - pt1.Y) / (pt2.X - pt1.X);
            this.b = pt1.Y - k * pt1.X;
            isselect = false;
        }
    }

再是相关服务类

public class PointService
    {
         //读取数据
        public List<Point> ReadToFile(string filepath)
        {
            List<Point> pts = new List<Point>();
            StreamReader sr = new StreamReader(filepath);
            while (!sr.EndOfStream)
            {
                var str = sr.ReadLine();
                var str1 = str.Split(',');
                pts.Add(new Point(Int32.Parse(str1[0]), str1[1], float.Parse(str1[2]), float.Parse(str1[3])));
            }

            return pts;
        }
			//保存数据
        public void SaveToFile(List<Point> pts, string filepath)
        {
            StreamWriter sw = new StreamWriter(filepath);
            foreach (var pt in pts)
            {
                sw.WriteLine(pt.ID+","+pt.Name+","+pt.X+","+pt.Y);
            }
            sw.Close();
        }
		//获取选择点
        public Point getPoint(List<Point> pts, float x, float y)
        {
            Point nearestPoint = null;
            float minDistance = float.MaxValue;

            foreach (var point in pts)
            {
                //这里用float.parse会报错,该方法将string转化为float,不可以在这里用
                float distance = (float)(Math.Sqrt(Math.Pow(x-point.X,2) + Math.Pow(y - point.Y, 2)));
                if (distance < minDistance)
                {
                    minDistance = distance;
                    nearestPoint = point;
                }
            }

            // 可能需要增加一定的阈值来确认点击有效
            return minDistance <=4.5  ? nearestPoint : null;

          
        }

        // 根据给定点查找最近的线要素
        public Line FindNearestLineFeature(List<Line> lines, Point point)
        {
            Line nearestLine = null;
            double minDistance = float.MaxValue;

            // 遍历所有线要素,计算每条线与指定点的距离
            foreach (var line in lines)
            {
                double distance = CalculateDistance(line, point); // 假设存在一个计算距离的方法

                // 如果当前线距指定点的距离小于已找到的最近距离,则更新结果
                if (distance < minDistance)
                {
                    minDistance = distance;
                    nearestLine = line;
                }
            }

            return nearestLine;
        }
        // 计算线要素与点之间的最小距离(实际项目中需使用GIS相关的空间分析算法)
        private double CalculateDistance(Line line, Point point)
        {
            var pt1 = line.Coordinates[0];
            var pt2 = line.Coordinates[1];
            // 这里仅作占位符,实际应实现点到线段的最短距离算法
            return Math.Abs(line.k * point.X - point.Y + line.b) / Math.Sqrt(line.k * line.k + 1);
        }
        
    }

窗口类

  public partial class Form1 : Form
    {
        public List<Point> pts = new List<Point>();//存所有点
        public PointService P = new PointService();//点相关服务初始化
        public List<Point> selectedPoints = new List<Point>();//存用于连成线的点
        List<Line> lines = new List<Line>(); // 存储线条对应的点集合,这个用法是真牛逼,但感觉没有
        Dictionary<int, bool> highlightedLines = new Dictionary<int, bool>(); // 用于记录被高亮的线条
        Pen blackPen = new Pen(Color.Black);
        Pen yellowPen = new Pen(Color.Yellow);
		//这里三个参数通过按钮控制,来控制picturebox中点击事件触发对象
        public bool isSelectPoint = false;//是否选择点
        public bool isSelectLine = false;//是否选择线
        public bool isMovePoint = false;//是否移动线
          //临时存点
        public Point CPoint=null;//选择的移动点
        public Form1()
        {
            InitializeComponent();
        }

        public void drawpicture()
        {

        }
        private void button1_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                pts = P.ReadToFile(openFileDialog1.FileName);
                foreach (var pt in pts)
                {
                    richTextBox1.Text += pt.ID + "\t" + pt.Name + "\t" + pt.X + "\t" + pt.Y + "\n";
                }
                // 触发PictureBox的重绘
                pictureBox1.Invalidate();

            }
            else
            {
                MessageBox.Show("读取失败");
            }
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
           
        }
        //这个是picture自带的事件,该事件触发需要调用对应函数,否则不会主动刷新
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            foreach (var point in pts)
            {
                e.Graphics.FillEllipse(Brushes.Black, new RectangleF(point.X, point.Y, 5, 5));
            }

            foreach (var line in lines)
            {
                var start = line.Coordinates[0];
                        var end = line.Coordinates[1];
                        DrawLine(e.Graphics, start, end, line.isselect? yellowPen : blackPen);//这个用法可以记录一下
            }
        }
          
        private void DrawLine(Graphics g, Point start, Point end, Pen pen)
        {
            g.DrawLine(pen, new PointF(start.X, start.Y), new PointF(end.X, end.Y));
        }
          
     

        private void button2_Click(object sender, EventArgs e)
        {
            isSelectPoint = true;
            isSelectLine = false;
            isMovePoint = false;
        }

        private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
        {
            try
            {
                //启动找点
                if (isSelectPoint && !isSelectLine)
                {
                    var pt = P.getPoint(pts, e.X, e.Y);
                    if (pt != null)
                    {
                        selectedPoints.Add(pt);
                    }

                    if (selectedPoints.Count == 3)
                    {
                        for (int i = 0; i < selectedPoints.Count; i++)
                        {
                            List<Point> ptsList = new List<Point>();
                            ptsList.Add(selectedPoints[i]);
                            ptsList.Add(selectedPoints[(i + 1) % 3]);
                            Line line = new Line(ptsList);
                            lines.Add(line);
                        }

                    }
                    pictureBox1.Invalidate();
                }
                //找线
                if (!isSelectPoint && isSelectLine)
                {
                   int i= lines.IndexOf(P.FindNearestLineFeature(lines, new Point(0, "t", e.X, e.Y)));
                   lines[i].isselect = true;
                   pictureBox1.Invalidate();
                }

            }
            catch (Exception exception)
            {
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            isSelectPoint = false;
            isSelectLine = true;
            isMovePoint = false;
        }

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (isMovePoint)
            {
                CPoint = P.getPoint(pts, e.X, e.Y);
            }
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (isMovePoint)
            {
                if (CPoint != null)
                {
                    CPoint.Y = e.Y;
                    CPoint.X = e.X;
                    pts[pts.IndexOf(CPoint)] = CPoint;
                    pictureBox1.Invalidate();
                }
            }
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (isMovePoint)
            {
                CPoint = null;
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            isSelectPoint = false;
            isSelectLine = false;
            isMovePoint = true;
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog()==DialogResult.OK)
            {
                P.SaveToFile(pts,saveFileDialog1.FileName);
                MessageBox.Show("保存成功!!!");
            }
        }
    }

实现效果如下

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/460114.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微服务技术栈SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式(五):分布式搜索 ES-中

文章目录 一、DSL查询文档1.1 简单查询1.2 复合查询 二、搜索结果处理三、RestClient演示 查询与结果分析四、案例4.1 问题解析4.2 代码4.2.1 实体bean4.2.2 控制层4.2.3 业务service4.2.4 启动类 一、DSL查询文档 1.1 简单查询 # 1. DSL查询 # 1.1 查询所有GET /hotel/_searc…

Github和TeamCity的持续集成构建

一、简介 TeamCity是JetBrains旗下的一款持续集成[Continuous Integration&#xff0c;简称CI]工具&#xff0c;开箱即用。TeamCity提供一系列特性可以让团队快速实现持续集成&#xff1a;IDE工具集成、各种消息通知、各种报表、项目的管理、分布式的编译等等。 二、安装使用(…

【Maven学习笔记】Maven入门教程(适合新手反复观看学习)

Maven学习笔记 Maven的简要介绍Maven的安装和配置Maven的安装Maven安装的常用配置 Maven的使用入门编写pom编写主代码编写测试代码打包和运行使用Archetype生成项目骨架 Maven核心概念的阐述坐标案例分析依赖依赖的范围传递性依赖依赖范围依赖调节可选依赖Maven依赖常用的技巧 …

关于python中数据分析的一些函数

首先先下载numpy函数库 如果使用的pycharm软件&#xff0c;可在设置中下载&#xff0c;在Python interpreter设置里&#xff0c;点击号&#xff0c;搜索numpy点击下载即可 第一部分 1.array()函数 这是一个将类似数组的数据转为数组的函数&#xff0c;我们还可以控制其数组的…

KMP 算法介绍

1. KMP 算法介绍 KMP 算法&#xff1a;全称叫做 「Knuth Morris Pratt 算法」&#xff0c;是由它的三位发明者 Donald Knuth、James H. Morris、 Vaughan Pratt 的名字来命名的。KMP 算法是他们三人在 1977 年联合发表的。 KMP 算法思想&#xff1a;对于给定文本串 T 与模式串 …

Adobe PDF背景设置护眼模式,缓解眼部疲劳

一、背景 在用Adobe PDF看论文时&#xff0c;默认的白色背景看久了&#xff0c;眼睛会特别疲劳&#xff0c;下面介绍如何设置背景为护眼模式。 二、设置PDF为护眼模式 使用Adobe Acrobat Pro DC打开任意PDF文件&#xff0c;在上方工具栏选择“编辑”&#xff0c;在下拉菜单栏…

SpringMVC重点记录

目录 1.学习重点2.回顾MVC3.回顾servlet4.初始SpringMVC4.1.为什么要学SpringMVC?4.2.SpringMVC的中重点DispatcherServlet4.3.SpringMVC项目的搭建4.4.MVC框架要做哪些事情?4.5.可能会遇到的问题 5.SpringMVC的执行原理6.使用注解开发SpringMVC7.Controller控制总结8.RestF…

excel导入功能(适用于vue和react都可)

如图所示&#xff08;需求&#xff09;&#xff1a;点击导入excel后&#xff0c;数据自动新增到列表数据内 这里以vue3 andt 为例 template 标签内代码 &#xff1a; <a-uploadname"file":multiple"true":show-upload-list"false":customR…

分布式CAP理论

CAP理论&#xff1a;一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;和分区容错性&#xff08;Partition tolerance&#xff09;。是Eric Brewer在2000年提出的&#xff0c;用于描述分布式系统基本性质的定理。这三个性质在分布式系统…

软件杯 深度学习 opencv python 实现中国交通标志识别_1

文章目录 0 前言1 yolov5实现中国交通标志检测2.算法原理2.1 算法简介2.2网络架构2.3 关键代码 3 数据集处理3.1 VOC格式介绍3.2 将中国交通标志检测数据集CCTSDB数据转换成VOC数据格式3.3 手动标注数据集 4 模型训练5 实现效果5.1 视频效果 6 最后 0 前言 &#x1f525; 优质…

微信小程序将高德地图转为腾讯地图的自行车路线规划

微信小程序后台首页开发设置 相关文档 腾讯后台 微信小程序接入JDK JDK腾讯地图文档 腾讯路线规划文档 核心代码 <map id"myMap" ref"myMap" style"width: 100%; height: calc(100vh - 80px)":latitude"latitude" :scale&qu…

springboot274基于web的电影院购票系统

电影院购票系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装电影院购票系统软件来发挥其高效…

CGAN——生成0-9数字图像(Tensorflow+mnist)

1、简介 传统的GAN或者其他的GAN都是通过一堆的训练数据&#xff0c;最后训练出了生成网络&#xff0c;随机输入噪声最后产生的数据是这些训练数据类别中之一&#xff0c;无法提前预测生成的是哪个类别。如果需要定向指定生成某些数据&#xff0c;比如想生成飞机&#xff0c;数…

云计算 3月14号 (TCP三次握手和四次挥手)

1.TCP三次握手和四次挥手 1.TCP的传输过程&#xff1a; Seq 序列号 保障传输过程可靠。 ACK &#xff08;确认消息&#xff09; SYN &#xff08;在建立TCP连接的时候使用&#xff09; FIN &#xff08;在关闭TCP连接的时候使用&#xff09; 3.TCP建立连接的过程&…

ES解析word内容为空的问题和直接使用Tika解析文档的方案

导言 在上一篇文章最后&#xff0c;我们虽然跑通了ES文件搜索的全部流程&#xff0c;但是仍然出现了1个大的问题&#xff1a;ES7.3实测无法索引docx和doc文档&#xff0c;content有值但是无法解析到附件成为可读的可搜索的内容&#xff0c;附件内容为空&#xff08;附件中根本…

Microsoft Remote Desktop Mac

Microsoft Remote Desktop是一款功能强大的远程连接工具&#xff0c;允许用户从远程位置连接到另一台计算机&#xff0c;实现跨设备的无缝协作。无论是在不同的设备之间共享文件、应用程序和其他资源&#xff0c;还是远程访问工作站和服务器&#xff0c;Microsoft Remote Deskt…

Unity开发一个FPS游戏之二

在之前的文章中,我介绍了如何开发一个FPS游戏,添加一个第一人称的主角,并设置武器。现在我将继续完善这个游戏,打算添加敌人,实现其智能寻找玩家并进行对抗。完成的效果如下: fps_enemy_demo 下载资源 首先是设计敌人,我们可以在网上找到一些好的免费素材,例如在Unity…

人机交互三原则,网络7层和对应的设备、公钥私钥

人机交互三原则 heo Mandel提出了人机交互的三个黄金原则&#xff0c;它们强调了相似的设计目标&#xff0c;分别是&#xff1a; 简单总结为&#xff1a;控负持面–>空腹吃面 1&#xff0c;用户控制 2&#xff0c;减轻负担 3&#xff0c;保持界面一致 置用户于控制之下&a…

DHCP在企业网的部署及安全防范

学习目标&#xff1a; 1. DHCP能够解决什么问题&#xff1f; 2. DHCP服务器如何部署&#xff1f; 3. 私接设备会带来什么问题以及如何防范&#xff1f; 给DHCP服务器配置地址&#xff1a; 地址池&#xff1a; DHCP有2种分配模式&#xff1a;全局分配和接口分配 DHCP enable

Upload-labs靶场

文件漏洞上传进行复现 环境搭建--->搭建好环境如下&#xff1a; 打开第一关&#xff0c;尝试文件上传漏洞 根据界面提示&#xff0c;选择一个文件&#xff08;.php文件&#xff09;进行上传&#xff0c;发现无法上传 根据提示是指使用js对不合法文件进行了检查&#xff0c;…
最新文章