天天看點

c# ienumerable 指派_c#通過代碼學數學,求兩條直線的交點,說明過程. - 驚驚

本篇代碼參考:

完整的代碼: 

publicstaticdouble[] GetIntersectionPoint(
            double x1, double y1,
            double x2, double y2,
            double x3, double y3,
            double x4, double y4)
        {
            //double計算容差double rong = 1e-8;

            //因為求斜率需要用除法,分母可能為0,是以求斜率之前,
            //需要兩條線是否x軸平行或者y軸平行if (((x2 - x1) < rong) && ((x4 - x3) < rong))
            {
                thrownew Exception("與y軸平行,兩直線垂直,斜率不存在,無交點");
            }
            if (((y2 - y1) < rong) && ((y4 - y3) < rong))
            {
                thrownew Exception("與x軸平行,兩直線水準,斜率為零,無交點");
            }

            //求斜率,分母為0并不報錯,而是指派成 Infinitydouble a = (y2 - y1) / (x2 - x1); //需考慮分母不能為0 即x2=x1 l1垂直于x軸double b = (y4 - y3) / (x4 - x3); //需考慮分母不能為0 即x4=x3 l2垂直于x軸double _x, _y = 0;

            //L1或L2兩直線可能其中一個有Y軸平行(垂直X軸)的if ((x2 - x1) < rong) //L1垂直于x軸  則x=x1=x2,(x2 - x1)是0==a分母,a=Infinity正無窮            {
                _x = x1;
                _y = b * x1 - b * x3 + y3;//公式變換第一種returnnewdouble[] { _x, _y };
            }
            elseif ((x4 - x3) < rong) //L2垂直于x軸 則x=x3=x4,(x4 - x3)是0==b分母,b=Infinity正無窮            {
                _x = x3;
                _y = a * _x - a * x1 + y1;//公式變換第一種returnnewdouble[] { _x, _y };
            }

            //兩條直線都是非垂直狀态/* 知道了點和斜率,那麼兩條點斜式方程聯立.
               因為直線方程是一條參照線,兩端無限延長,除非平行,否則必有交點.
               又因為交點是兩條線的共同解,是以點斜式:line1和line2的y相減是0,y=k(_x-x1)+y1
               是以未知數y就相減去掉,剩下x,來求y. 
               反之,也可以相減去掉x,來求y.
               [y=a(_x-x1)+y1] - [y=b(_x-x3)+y3] =0; 
               [a*(_x-x1)+y1] - [b*(_x-x3)+y3] =0;
               [a*_x-a*x1+y1] - [b*_x-b*x3+y3] =0;
               a*_x-a*x1+y1 - b*_x+b*x3-y3 =0; 去括号,+-互變 
               (a - b)* _x = 0 + a*x1 - y1 - b*x3 + y3; //移項,+-互變              
               _x = (a * x1 - y1 - b * x3 + y3) / (a - b);
            */
            _x = (a * x1 - y1 - b * x3 + y3) / (a - b);

            //但是上面程式代碼已經算了_x了,直接套入點斜式方程,偷懶...也可以通過公式計算 /* y-y1=k*x-k*x1
               y-y1+k*x1=k*x
               (y-y1+k*x1)/k=x 
               [(y-y1-a*x1)/a] - [(y-y3-b*x3)/b] =0; //這是按照公式的方法
            */

            _y = a * _x - a * x1 + y1;  // 點斜式方程 y-y1=k(x-x1)returnnewdouble[] { _x, _y };
        }
           

View Code

驗證的代碼:

staticvoid Main(string[] args)
        {
            double[] pt;
            //水準平衡
             pt = 求交點.GetIntersectionPoint(0, 0, 10, 0, 0, 5, 10, 5);
             (pt[0].ToString() + "," + pt[1].ToString());

            //垂直平衡
            //pt = 求交點.GetIntersectionPoint(0, 0, 0, 10, 5, 0, 5, 10);
            //(pt[0].ToString() + "," + pt[1].ToString());

            //一斜一水準
            //pt = 求交點.GetIntersectionPoint(0, 0, 10, 10, 0, 5, 10, 5);
            //(pt[0].ToString() + "," + pt[1].ToString());

            //一斜一垂直
            //pt = 求交點.GetIntersectionPoint(0, 0, 10, 10, 5, 0, 5, 10);
            //(pt[0].ToString() + "," + pt[1].ToString());

            //L1線垂直
            //pt = 求交點.GetIntersectionPoint(5, 0, 5, 10, 0, 0, 10, 10);
            //(pt[0].ToString() + "," + pt[1].ToString());

            //L2線垂直
            //pt = 求交點.GetIntersectionPoint(0, 0, 10, 10, 5, 0, 5, 10);
            //(pt[0].ToString() + "," + pt[1].ToString());

            //兩條都是斜的
            //pt = 求交點.GetIntersectionPoint(0, 0, 10, 10, 10, 0, 0, 10);
            //(pt[0].ToString() + "," + pt[1].ToString()); 
        }
           

View Code

首先要說明,看懂本篇您并不需要高中文化水準.....

為了求兩條線的交點,首先要知道什麼能求,而目前來說,我隻知道高中數學的直線方程,

那麼我就要引入直線方程的概念....

然後為什麼直線方程能求交點呢?因為同時滿足兩條聯立的直線方程,它的共同解也就隻能是交點...(這裡沒看懂沒關系,跟着代碼走的時候你就知道了.)

而直線方程實際上是描述一條兩端無限延長的線,cad術語就是參照線,構成的兩點隻是過兩點,而不是端點.

是參照線的話,這就有一個非常好的條件: 除非平行,否則必然有交點

那麼在程式設計上,我拿到的資料一般是兩個點..(x1,y1)(x2,y2)

通過這一條線坐标計算出斜率,這個斜率實際上就是直角三角形(高/底)

c# ienumerable 指派_c#通過代碼學數學,求兩條直線的交點,說明過程. - 驚驚
//斜率=高/底           var a = (y2 - y1) / (x2 - x1); //需考慮分母不能為0           var b = (y4 - y3) / (x4 - x3); //需考慮分母不能為0
           

 這樣就有個問題了,會存在分母可能為0的情況,需要先判斷一下:

//因為求斜率需要用除法,分母可能為0,是以求斜率之前,
            //需要判斷兩條線是否x軸平行或者y軸平行if (((x2 - x1) < rong) && ((x4 - x3) < rong))
            {
                thrownew Exception("與y軸平行,兩直線垂直,斜率不存在,無交點");
            }
            if (((y2 - y1) < rong) && ((y4 - y3) < rong))
            {
                thrownew Exception("與x軸平行,兩直線水準,斜率為零,無交點");
            }

            //求斜率,分母為0并不報錯,而是指派成 Infinitydouble a = (y2 - y1) / (x2 - x1); //需考慮分母不能為0 即x2=x1 l1垂直于x軸double b = (y4 - y3) / (x4 - x3); //需考慮分母不能為0 即x4=x3 l2垂直于x軸
           

有了斜率和有兩個點,就可以求直線方程,可以利用"點斜式"來求.

如果你想知道其他的方式,可以看直線方程的五種形式可看樂樂課堂的 

用我的話來說,其他形式最後都會成為點斜式,因為它足夠簡單.

點斜式的公式是:

y-y1=k(x-x1)

這裡k是斜率(我的斜率是a和b),可以了解公式的x=x2,y=y2,為了使得x2,y2是個可變的點,是以用x,y代替(我的是_x,_y),成為未知數....這裡x1,y1就是套入的點.

變換成:第一種 y=k(x-x1)+y1         這種比較重要!

變換成:第二種 x=(y-y1-k*x1)/k

c# ienumerable 指派_c#通過代碼學數學,求兩條直線的交點,說明過程. - 驚驚

然後由于未知數有兩個還沒法求,但是現在知道了一個條件: {知道x就可以推出y,知道y就可以推出x}

通過垂線得到_x,求出_y

我之前的代碼否決了兩條線都平行或者都垂直

還有一種情況未否決,這就是其中一條是垂直,它導緻了一條線的分母是0,在c#中使用了分母為0的并不報錯,而是double的值成為一個Infinity(正無窮)

如果使用了這個斜率就會報錯,是以我需要避免使用這個它..

又由于這個斜率為0肯定是一條垂線,它的x1==x2是确定的,代表了兩條直線的交點的_x肯定是這個x1.

通過條件{知道x就可以推出y,知道y就可以推出x}套入公式即可求_y

double _x, _y = 0;//未知數初始化

            //L1或L2兩直線可能其中一個有Y軸平行(垂直X軸)的if ((x2 - x1) < rong) //L1垂直于x軸  則x=x1=x2,(x2 - x1)是0==斜率a的分母,a=Infinity正無窮            {
                _x = x1;
                _y = b * x1 - b * x3 + y3;//公式變換第一種
                returnnewdouble[] { _x, _y };
            }
            elseif ((x4 - x3) < rong) //L2垂直于x軸 則x=x3=x4,(x4 - x3)是0==斜率b的分母,b=Infinity正無窮            {
                _x = x3;
                _y = a * _x - a * x1 + y1;//公式變換第一種
                returnnewdouble[] { _x, _y };
            }
           

聯立方程.

現在剩下一種情況,就是兩條都是斜的.這個時候需要聯立方程.

再重複提及一下,因為直線方程描述是一條參照線,兩端無限延長,除非平行,否則必有交點.

又因為交點是兩條線的共同解,是以點斜式:line1和line2的y相減必然是0.

{第一條線的直線方程} - {第二條線的直線方程} = 0

這樣做的目的,就是算式剩下未知數是_x.

套到公式就是這樣:

[y=a(_x-x1)+y1] - [y=b(_x-x3)+y3] =0;

[a*(_x-x1)+y1] - [b*(_x-x3)+y3] =0;

[a*_x-a*x1+y1] - [b*_x-b*x3+y3] =0;

a*_x-a*x1+y1 - b*_x+b*x3-y3 =0;             去括号,括号前是-号,故此+-互變

a*_x-b*_x-a*x1+y1+b*x3-y3=0;                未知數的放一塊

(a - b)* _x = 0 + a*x1 - y1 - b*x3 + y3;      移項,+-互變

_x = (a * x1 - y1 - b * x3 + y3) / (a - b);

//上面程式代碼已經算了_x了,直接套入點斜式方程,通過條件{知道x就可以推出y,知道y就可以推出x}

_y = a * _x - a * x1 + y1;

就這樣,大功告成....

當然了.如果你把這個報錯代碼去掉,會出現有意思的東西..

if (((x2 - x1) < rong) && ((x4 - x3) < rong))
            {
                thrownew Exception("與y軸平行,兩直線垂直,斜率不存在,無交點");
            }
            if (((y2 - y1) < rong) && ((y4 - y3) < rong))
            {
                thrownew Exception("與x軸平行,兩直線水準,斜率為零,無交點");
            }
           
c# ienumerable 指派_c#通過代碼學數學,求兩條直線的交點,說明過程. - 驚驚