C#路径选点-点沿着路径运动

要想让目标在指定的路径上运行,需要在路径轨迹上选择很多点,再通过插值方法插入数据点,当点足够多的时候,运行起来看着就是连续的运动。起始坐标和终点坐标对应路径总长。所以,直接给定路径值小车即可运行到指定坐标位置。

操作方法:在运行路径上选点,尽量在运行路径上选择足够多的点,然后保存点坐标,通过插值法将这些选择的坐标扩展很多个。设置路径总长,对应起始坐标和终点坐标。则计算出路径上每一个位置对应的坐标。

1、界面效果图

创建一个环形路径轨迹,创建两个小车,设置上客区站台、下客区站台 ,在初始情况下1#小车在上客区站台,2#小车在下客区站台。启动后1#车和2#车分别运行。

 2、路径选点

电机选点按钮,然后在路径上需要的位置按鼠标右键即可选择点,点和点之间会形成红色的连线提示选择的路径。

 选好以后点击保存

 然后重新启动软件,重新启动以后再启动,小车就沿着刚刚选中的路径运行。

3、轨迹地图功能类封装

public class DrawMap
    {
        public List<Point> m_pointList;//声明点集合(屏幕坐标点)
        public List<Point> m_screenPointList;//原来的屏幕坐标点集合

        public List<double> xy_List, length_List, k_List;
        public PictureBoxCar[] m_pictureArray;//声明
        public int pointcount = 0;
        public long RealRail_length = 2000;
        public double lengthflag;//图像轨道长与实际轨道之比
        public Form mapFrom;
        public DrawMap()
        {
            m_pointList = new List<Point>();
            m_screenPointList = new List<Point>();
            xy_List = new List<double>();
            k_List = new List<double>();
            length_List = new List<double>();

            ReadPoint();//读取原来的坐标点
            DealList(pointcount);//建立轨道


        }
        public DrawMap(Form map, long Real_length)
        {
            m_pointList = new List<Point>();
            m_screenPointList = new List<Point>();
            xy_List = new List<double>();
            k_List = new List<double>();
            length_List = new List<double>();
            RealRail_length = Real_length;
            ReadPoint();//读取原来的坐标点
            DealList(pointcount);//建立轨道

            mapFrom = map;
            m_pictureArray = new PictureBoxCar[20];
            for (int i = 0; i < 20; i++)
            {
                m_pictureArray[i] = new PictureBoxCar(i, mapFrom);
            }
        }
        public void DealList(int point_count)
        {
            int x1, x2, y1, y2;
            double raillength = 0;
            double ff = 0;
            for (int i = 0; i < point_count; i++)
            {
                if (i == point_count - 1)
                {
                    x1 = m_screenPointList[i].X;
                    y1 = m_screenPointList[i].Y;
                    x2 = m_screenPointList[0].X;
                    y2 = m_screenPointList[0].Y;
                }
                else
                {
                    x1 = m_screenPointList[i].X;
                    y1 = m_screenPointList[i].Y;
                    x2 = m_screenPointList[i + 1].X;
                    y2 = m_screenPointList[i + 1].Y;
                }
                double xy = Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2));//两点距离
                double o = Math.Atan2((y2 - y1), (x2 - x1));//两点斜率
                raillength = raillength + xy;
                xy_List.Add(xy);
                k_List.Add(o);
            }
            lengthflag = raillength / RealRail_length;//MAP轨道长度与实际轨道长度之比
            for (int i = 0; i < point_count; i++)
            {
                if (i > 0)
                {
                    length_List.Add(ff + (xy_List[i] * RealRail_length / raillength));
                    ff += xy_List[i] * RealRail_length / raillength;
                }
                else
                {
                    length_List.Add(xy_List[i] * RealRail_length / raillength);
                    ff += xy_List[i] * RealRail_length / raillength;
                }
            }
        }
        delegate void DrawCarDelegate1(int carIndex, float location);
        //渲染小车的方法(model 0画上去 1为擦除)
        public void DrawCar1(int carID, float location)
        {
            int flag = 0;
            double ff = 0;
            List<Point> pointList = m_screenPointList;//定义的坐标点
            List<double> k_list1 = k_List;//坐标直线的斜率
            List<double> length_list1 = length_List;//模拟的每条线段的长度

            if (mapFrom.InvokeRequired)
            {
                DrawCarDelegate1 d = new DrawCarDelegate1(DrawCar1);
                mapFrom.Invoke(d, new object[] { carID, location });
            }
            else
            {
                for (int i = 0; i < length_list1.Count; i++)
                {
                    if (location < length_list1[i])
                    {
                        flag = i;
                        break;
                    }
                    ff += length_list1[i];
                }
                if (flag == 0)
                {
                    double x = pointList[flag].X + location * Math.Cos(k_list1[flag]) * lengthflag;
                    double y = pointList[flag].Y + location * Math.Sin(k_list1[flag]) * lengthflag;
                    //    m_pictureArray[carID].Picturebox.Location = new Point((int)Math.Ceiling(x), (int)Math.Ceiling(y));
                    m_pictureArray[carID].Picturebox.Location = new Point((int)Math.Ceiling(x - 10), (int)Math.Ceiling(y - m_pictureArray[carID].Picturebox.Height / 2));
                    m_pictureArray[carID].Picturebox.Visible = true;
                }
                else
                {
                    double x = pointList[flag].X + (location - length_list1[flag - 1]) * Math.Cos(k_list1[flag]) * lengthflag;
                    double y = pointList[flag].Y + (location - length_list1[flag - 1]) * Math.Sin(k_list1[flag]) * lengthflag;
                    m_pictureArray[carID].Picturebox.Location = new Point((int)Math.Ceiling(x - 10), (int)Math.Ceiling(y - m_pictureArray[carID].Picturebox.Height / 2));
                    m_pictureArray[carID].Picturebox.Visible = true;
                }
            }
        }

        public void Hide_Carpicture(int carID)//隐藏掉线车辆
        {
            mapFrom.Invoke(new Action(() => { m_pictureArray[carID].Picturebox.Visible = false; }));
        }
        public void SaveScreenPoint(List<Point> pointList)
        {
            FileStream fs2 = null; //声明文件流的对象
            StreamWriter sw = null;
            string writePath = Application.StartupPath + "\\ScreenPoint\\screenPointList.txt";
            //创建文件流  
            fs2 = new FileStream(writePath,  //文件路径4
                FileMode.Create, //打开文件的方式
                FileAccess.Write, //控制对文件的读写  
                FileShare.None);  //控制其它进程对此文件的访问
            //创建写入器
            sw = new StreamWriter(fs2, Encoding.Default);

            for (int i = 0; i < pointList.Count; i++)
            {
                sw.WriteLine(pointList[i].X.ToString() + "," + pointList[i].Y.ToString());
            }

            sw.Flush();

            if (fs2 != null)
            {
                if (sw != null)
                {
                    sw.Close();
                }

                fs2.Close();
            }
        }
        public void savePoint(bool m_saveBool)
        {
            if (m_saveBool)
            {
                if (m_pointList.Count > 0)
                {
                    MessageBoxButtons messButton = MessageBoxButtons.OKCancel;
                    DialogResult dr = MessageBox.Show("确定保存吗?", "保存提示", messButton);
                    if (dr == DialogResult.OK)
                    {
                        List<Point> screenPointList = m_screenPointList;
                        screenPointList.Clear();//先清除之前的屏幕坐标点集合1915413225
                        //将本地的点集合传递给管理类的屏幕坐标集合
                        for (int i = 0; i < m_pointList.Count; i++)
                        {
                            screenPointList.Add(m_pointList[i]);
                        }
                        SaveScreenPoint(m_pointList);
                    }
                    m_pointList.Clear();//移除list中所有元素
                }
            }
        }
        public void selectPoint(bool m_selectBool, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right && m_selectBool)
            {
                int x = e.Location.X;//获取到的x坐标
                int y = e.Location.Y;//获取到的y坐标
                //  if (m_pointList.Count < 20)//20个点
                // {
                m_pointList.Add(new Point(x, y));
                // }
                var fff = m_pointList.Count;
                if (fff > 1)
                {
                    Graphics g = mapFrom.CreateGraphics();
                    g.DrawLine(new Pen(Color.Red, 3), m_pointList[fff - 1], m_pointList[fff - 2]);
                }
            }
        }
        public void ReadPoint()
        {
            string path = Application.StartupPath + "\\ScreenPoint\\screenPointList.txt";
            FileStream fs1 = null; //声明文件流的对象
            FileStream fs2 = null; //声明文件流的对象
            StreamReader sr = null; //声明读取器的对象
            StreamWriter sw = null;

            try
            {
                //创建文件流  
                fs1 = new FileStream(path,  //文件路径  
                                    FileMode.Open, //打开文件的方式  
                                    FileAccess.ReadWrite, //控制对文件的读写  
                                    FileShare.None);  //控制其它进程对此文件的访问  
                //创建读取器  
                sr = new StreamReader(fs1,  //文件流对象  
                                      Encoding.Default);  //字符编码

                string str;
                while ((str = sr.ReadLine()) != null)
                {
                    string[] ss = str.Split(',');
                    int x = Convert.ToInt32(ss[0]);
                    int y = Convert.ToInt32(ss[1]);
                    m_screenPointList.Add(new Point(x, y));
                    pointcount++;// 6/19加入
                }

            }
            catch (Exception ex)
            {
                if (ex is System.IO.FileNotFoundException)
                {
                    string writePath = Application.StartupPath + "\\ScreenPoint\\screenPointList.txt";
                    //创建文件流  
                    fs2 = new FileStream(writePath,  //文件路径
                        FileMode.Create, //打开文件的方式
                        FileAccess.Write, //控制对文件的读写  
                        FileShare.None);  //控制其它进程对此文件的访问
                    //创建写入器
                    sw = new StreamWriter(fs2, Encoding.Default);

                    sw.WriteLine("100,100");
                    sw.WriteLine("200,100");
                    sw.WriteLine("200,200");
                    sw.WriteLine("100,200");

                    m_screenPointList.Add(new Point(100, 100));
                    m_screenPointList.Add(new Point(200, 100));
                    m_screenPointList.Add(new Point(200, 200));
                    m_screenPointList.Add(new Point(100, 200));
                    sw.Flush();

                }
                else
                {
                    MessageBox.Show("文件操作异常:" + "坐标格式不正确");
                }
            }
            finally
            {
                if (fs1 != null)
                {
                    if (sr != null)
                    {
                        sr.Close(); //关闭读取器
                    }

                    fs1.Close(); //关闭文件流  
                }

                if (fs2 != null)
                {
                    if (sw != null)
                    {
                        sw.Close();
                    }

                    fs2.Close();
                }
            }
        }
}

4、小车绘制图

public PictureBoxCar(int carID, Form handle)
        {
            //carID = carID+1;//1-5id
            m_picturebox = new PictureBox();
            bmp = new Bitmap(65, 20);
            m_g = Graphics.FromImage(bmp);
            m_picturebox.Width = 65;
            m_picturebox.Height = 20;
            m_picturebox.BackColor = Color.Transparent;

            m_g.FillEllipse(new SolidBrush(Color.Blue), new System.Drawing.Rectangle(0, 0, 20, 20));//擦除作用
            m_g.DrawString("车" + carID.ToString(), new Font("宋体", 12), new SolidBrush(Color.Black), new System.Drawing.Rectangle(20, 3, 55, 20));
            m_picturebox.Image = bmp;
            m_picturebox.Parent = handle;
            m_picturebox.Visible = false;
        }

5、运动路径轨迹也可以是旋转的圆形

 6、测试工程下载连接

https://download.csdn.net/download/panjinliang066333/87765399

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Big_潘大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值