五点光滑曲线拟合

Point.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 五点法
{
    public class Point
    {
        public Point(string str)
        {
            string[] splitstr=str.Split(',');
            n=splitstr[0];
            x= Convert.ToDouble(splitstr[1]);
            y= Convert.ToDouble(splitstr[2]);
        }
        public Point()
        { }

        public double x;
        public double y;
        public string n="null";
    }
}

主程序

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace 五点法
{
    public partial class MDIParent1 : Form
    {
        private int childFormNumber = 0;

        public MDIParent1()
        {
            InitializeComponent();
        }

        private void ShowNewForm(object sender, EventArgs e)
        {
            Form childForm = new Form();
            childForm.MdiParent = this;
            childForm.Text = "窗口 " + childFormNumber++;
            childForm.Show();
        }
        List<Point> points = new List<Point>();
        private void OpenFile(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "文本文件(*.txt)|*.txt|所有文件(*.*)|*.*";
            if (openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                points.Clear();
                string FileName = openFileDialog.FileName;
                string[] data = File.ReadAllLines(FileName);
                foreach(string line in data)
                {
                    Point point = new Point(line);
                    points.Add(point);
                }
            }
        }

        private void SaveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            saveFileDialog.Filter = "文本文件(*.txt)|*.txt|所有文件(*.*)|*.*";
            if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                string FileName = saveFileDialog.FileName;
            }
        }

        //不封闭,计算补充点
        List<Point> openData;
        public List<Point> length(List<Point> p)
        {
            Point pa = new Point();
            Point pb = new Point();
            pa.x = p[0].x - 3 * p[1].x + 3 * p[2].x;
            pa.y = p[0].y - 3 * p[1].y + 3 * p[2].y;
            p.Add(pa);
            pb.x = p[1].x - 3 * p[2].x + 3 * p[3].x;
            pb.y = p[1].y - 3 * p[2].y + 3 * p[3].y;
            p.Add(pb);
            return p;
        }
        public void computePoint(List<Point> p)
        {
            int num = p.Count;
            List<Point> startfragment = p.Take(3).ToList();
            List<Point> endfragment = p.Skip(num - 3).ToList();
            startfragment.Reverse();
            startfragment = length(startfragment);
            endfragment = length(endfragment);
            openData = new List<Point>(p); 
            openData.Insert(0, startfragment[3]);
            openData.Insert(0, startfragment[4]);
            openData.Add(endfragment[3]);
            openData.Add(endfragment[4]);
        }

        //存储内插点
        List<List<Point>> insertPointdata = new List<List<Point>>();
        //计算cosθ和sinθ,并以元组形式返回
        public (double,double) gradient(List<Point> p)
        {
            double a1 = p[1].x - p[0].x;
            double a2 = p[2].x - p[1].x;
            double a3 = p[3].x - p[2].x;
            double a4 = p[4].x - p[3].x;
            double b1 = p[1].y - p[0].y;
            double b2 = p[2].y - p[1].y;
            double b3 = p[3].y - p[2].y;
            double b4 = p[4].y - p[3].y;
            double w2 = Math.Abs(a3 * b4 - a4 * b3);
            double w3 = Math.Abs(a1 * b2 - a2 * b1);
            double a0 = w2 * a2 + w3 * a3;
            double b0 = w2 * b2 + w3 * b3;
            double cosTheta = a0 / Math.Sqrt(a0 * a0 + b0 * b0);
            double sinTheta = b0 / Math.Sqrt(a0 * a0 + b0 * b0);
            return (cosTheta, sinTheta);
        }
        //计算内插点坐标,存储在insertPointdata中
        public void insertPoint(List<Point> p,int unm)
        {
            for (int i = 0; i < p.Count - 5; i++)
            {
                List<Point> parameterp1 = new List<Point>(p.Skip(i).Take(5).ToList());
                List<Point> parameterp2 = new List<Point>(p.Skip(i + 1).Take(5).ToList());
                var (cosTheta1, sinTheta1) = gradient(parameterp1);
                var (cosTheta2, sinTheta2) = gradient(parameterp2);
                double r = Math.Sqrt((parameterp1[3].x - parameterp1[2].x) * (parameterp1[3].x - parameterp1[2].x) +
                    (parameterp1[3].y - parameterp1[2].y) * (parameterp1[3].y - parameterp1[2].y));
                double E0 = parameterp1[2].x;
                double E1 = r * cosTheta1;
                double E2 = 3 * (parameterp1[3].x - parameterp1[2].x) - r * (cosTheta2 + 2 * cosTheta1);
                double E3 = -2 * (parameterp1[3].x - parameterp1[2].x) + r * (cosTheta2 + cosTheta1);
                double F0 = parameterp1[2].y;
                double F1 = r * sinTheta1;
                double F2 = 3 * (parameterp1[3].y - parameterp1[2].y) - r * (sinTheta2 + 2 * sinTheta1);
                double F3 = -2 * (parameterp1[3].y - parameterp1[2].y) + r * (sinTheta2 + sinTheta1);
                List<Point> LsInsertPoint = new List<Point>();
                for (double m = 1 / (double)unm; m < 1;)
                {
                    Point Lsp = new Point();
                    Lsp.x = E0 + E1 * m + E2 * m * m + E3 * m * m * m;
                    Lsp.y = F0 + F1 * m + F2 * m * m + F3 * m * m * m;
                    LsInsertPoint.Add(Lsp);
                    m += 1 / (double)unm;
                }
                insertPointdata.Add(LsInsertPoint);
            }
        }
        //初始化部分,每次运算都重置chart、dataGridView控件和存储数据的List数组
        public void initialize()
        {
            dataGridView1.Rows.Clear();
            allPoint.Clear();
            chart1.Series[0].Points.Clear();
            insertPointdata = new List<List<Point>>();
        }
        //可视化部分,sign=='o'代表不封闭
        public void visualization(List<Point> p,char sign='o')
        {
            int num = p.Count;
            if (sign == 'o')
                num = num - 1;
            for(int i=0;i<num;i++)
            {
                chart1.Series[0].Points.AddXY(p[i].x, p[i].y);
                allPoint.Add(p[i]);
                List<Point> lp = new List<Point>(insertPointdata[i]);
                for (int j = 0; j < lp.Count; j++)
                {
                    chart1.Series[0].Points.AddXY(lp[j].x, lp[j].y);
                    allPoint.Add(lp[j]);
                }
            }
            if(sign=='o')
            {
                chart1.Series[0].Points.AddXY(p[openData.Count - 1].x, p[openData.Count - 1].y);
                allPoint.Add(p[p.Count - 1]);
            }
            else
            {
                chart1.Series[0].Points.AddXY(p[0].x, p[0].y);
                allPoint.Add(p[0]);
            }
            for (int i = 0; i < allPoint.Count; i++)
            {
                dataGridView1.Rows.Add();
                dataGridView1.Rows[i].Cells[1].Value = allPoint[i].x;
                dataGridView1.Rows[i].Cells[2].Value = allPoint[i].y;
                dataGridView1.Rows[i].Cells[0].Value = allPoint[i].n;
            }
        }
        List<Point> allPoint = new List<Point>();
        private void 不闭合曲线ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            initialize();
            openData = new List<Point>();
            computePoint(points);
            insertPoint(openData,10);
            openData.RemoveAt(0);
            openData.RemoveAt(0);
            openData.RemoveAt(openData.Count - 1);
            openData.RemoveAt(openData.Count - 1);
            visualization(openData);
        }
        private void 闭合曲线ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            initialize();
            List<Point> closeData = new List<Point>(points);
            closeData.Insert(0, points[points.Count - 1]);
            closeData.Insert(0, points[points.Count - 2]);
            closeData.Add(points[0]);
            closeData.Add(points[1]);
            closeData.Add(points[2]);
            insertPoint(closeData, 10);
            closeData.RemoveAt(0);
            closeData.RemoveAt(0);
            closeData.RemoveAt(closeData.Count - 1);
            closeData.RemoveAt(closeData.Count - 1);
            closeData.RemoveAt(closeData.Count - 1);
            visualization(closeData, 'c');
        }
    }
}

运行结果

封闭

4ba556984aeb4a87a5d486e039263ba8.pngdc167c61ee5f422cb44e920d19dbc65e.png不封闭

50aab4dda28b48b3aafa38d7c2e8b94c.pngd599dc48856f4daea09460c66118f81a.png

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值