曲面拟合(C#)

计算一般方程:

求解a、b、c、d、e、f六个未知数

转化为求如下方程组(矩阵、向量元素是均值):

曲面拟合(C#)_第1张图片

程序中需要算线性方程组,所以得导入Math.Net数值计算包,导入过程如下:

--打开 Tools -> Nuget Package Manager -> Package Manager Console;

--在 Package Manager Console 中输入:Install-Package MathNet.Numerics。

完事后,添加划红线的引用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Numerics;
using System.IO;
using MathNet.Numerics.LinearAlgebra.Double;     //C#数值计算包,需要手动导入math.net;

struct Point
    {
        public double x, y, z;
        public Point(double x, double y, double z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
    }
    class Getdata
    {
        public static List GetL(StreamReader srr)
        {
            List strlist = new List();
            List pointlist = new List();
            string strline;
            while (true)
            {
                strline = srr.ReadLine();
                if (strline != null)
                {
                    strlist.Add(strline);
                }
                else { break; }
            }
            for (int i = 0; i < strlist.Count; i++)
            {
                string[] strp = strlist[i].Split(' ');
                Point pt = new Point(double.Parse(strp[0]), double.Parse(strp[1]), double.Parse(strp[2]));
                pointlist.Add(pt);
            }
            return pointlist;
        }

        public static double[] GetC(List ptlt)
        {
            double x1 = 0, y1 = 0, z1 = 0;
            double x2 = 0, x1y1 = 0, y2 = 0, x1z1 = 0, y1z1 = 0, z2 = 0;
            double x3 = 0, x2y1 = 0, x1y2 = 0, y3 = 0, x2z1 = 0, y2z1 = 0, z3 = 0,
                x1z2 = 0, y1z2 = 0;
            double z4 = 0, y4 = 0, x2y2 = 0, x2z2 = 0, y2z2 = 0;
            double n = ptlt.Count;
            double[] outarray = new double[6];
            for (int i = 0; i < n; i++)
            {
                x1 += ptlt[i].x;
                y1 += ptlt[i].y;
                z1 += ptlt[i].z;
                x2 += ptlt[i].x * ptlt[i].x;
                x1y1 += ptlt[i].x * ptlt[i].y;
                y2 += ptlt[i].y * ptlt[i].y;
                x1z1 += ptlt[i].x * ptlt[i].z;
                y1z1 += ptlt[i].y * ptlt[i].z;
                z2 += ptlt[i].z * ptlt[i].z;
                x3 += ptlt[i].x * ptlt[i].x * ptlt[i].x;
                x2y1 += ptlt[i].x * ptlt[i].x * ptlt[i].y;
                x1y2 += ptlt[i].x * ptlt[i].y * ptlt[i].y;
                y3 += ptlt[i].y * ptlt[i].y * ptlt[i].y;
                x2z1 += ptlt[i].x * ptlt[i].x * ptlt[i].z;
                y2z1 += ptlt[i].y * ptlt[i].y * ptlt[i].z;
                z3 += ptlt[i].z * ptlt[i].z * ptlt[i].z;
                y4 += ptlt[i].y * ptlt[i].y * ptlt[i].y * ptlt[i].y;
                z4 += ptlt[i].z * ptlt[i].z * ptlt[i].z * ptlt[i].z;
                x2y2 += ptlt[i].x * ptlt[i].x * ptlt[i].y * ptlt[i].y;
                x2z2 += ptlt[i].x * ptlt[i].x * ptlt[i].z * ptlt[i].z;
                y2z2 += ptlt[i].y * ptlt[i].y * ptlt[i].z * ptlt[i].z;
            }
            var matrixA = DenseMatrix.OfArray(new[,] {{y4/n,y2z2/n,x1y2/n,y3/n,y2z1/n,y2/n},{y2z2/n,z4/n,x1z2/n,y1z2/n,z3/n,z2/n}
                ,{x1y2/n,x1z2/n,x2/n,x1y1/n,x1z1/n,x1/n},{y3/n,y1z2/n,x1y1/n,y2/n,y1z1/n,y1/n},{y2z1/n,z3/n,x1z1/n,y1z1/n,z2/n,z1/n}
                ,{y2/n,z2/n,x1/n,y1/n,z1/n,1}});
            var vectorB = new DenseVector(new[] { -x2y2/n, -x2z2/n, -x3/n, -x2y1/n, -x2z1/n, -x2/n });
            var resultX = matrixA.LU().Solve(vectorB);
            for (int i = 0; i < 6; i++)
            {
                outarray[i] = resultX[i]; 
            }
            return outarray;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            StreamReader sr = new StreamReader("柱体1.txt", Encoding.Default);
            List pointlist = new List();
            double[] pointC = new double[6];
            pointlist = Getdata.GetL(sr);
            sr.Close();
            pointC = Getdata.GetC(pointlist);
            for (int i = 0; i < pointC.GetLength(0); i++)
            {
                Console.WriteLine(pointC[i]); 
            }
                Console.WriteLine("拟合曲面方程一般形式:");
            Console.WriteLine("x*x+({0:f3}*y*y)+({1:f3}*z*z)+({2:f3}*x)+({3:f3}*y)+({4:f3}*z)+({5:f3})=0",
                pointC[0],pointC[1],pointC[2],pointC[3],pointC[4],pointC[5]);
            double oures = 0;
            oures = pointlist[0].x * pointlist[0].x + pointC[0] * pointlist[0].y * pointlist[0].y +
                pointC[1] * pointlist[0].z * pointlist[0].z + pointC[2] * pointlist[0].x + pointC[3] * pointlist[0].y +
                pointC[4] * pointlist[0].z + pointC[5];
            Console.WriteLine(oures);    //代入第一个点,查看误差大小;
            Console.ReadLine();
        }
    }
}

曲面拟合(C#)_第2张图片

你可能感兴趣的:(C#)