日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1. 前言

主要記錄一些關于坐標和線段的計算方法。因為經常會碰見,需要在平面上,計算坐標點。

例如兩個坐標點之間的距離,兩個線段是否平行,兩個不相交的線段的交點。

由于程序中的坐標原點,都是左上角開始的。所以很少涉及象限的問題。以下的一些算法,不會強調象限問題。

這里,主要介紹如何使用勾股定理計算坐標距離,斜率計算線段交點等。

2. 根據兩個坐標點,計算距離

平面中,兩點之間,直線最短。而在已知兩個坐標點的x軸和y軸的情況下。我們可以通過勾股定理,來計算兩個坐標點的距離。

因為,兩個坐標點之間x軸的距離和y軸的距離可以看做三角形的兩條直角邊。斜邊就是我們要計算的距離了。

而勾股定理為:a^2^+b^2^=C^2^

讓我們帶入到代碼中來實現:

public double getPointDistance(Point point1, Point point2) {
       int a = point2.y - point1.y;
       int b = point2.x - point1.x;
       return Math.sqrt(a * a + b * b);
}
 

兩個坐標point1,point2 其實順序無所謂。

兩個x軸坐標相減,得到的是在x軸上的距離。這個值可能為正,也可能為負。但無所謂,因為進行平方之后。只會是正數。

同理,Y軸也是一樣的。所以我們計算時不用管哪個坐標點是前還是后。

Math.sqrt()是 JAVA 提供的開平方工具。

我們得到的X軸的距離和Y軸的距離,都是相對于x軸和y軸垂直的。所以這兩個距離組合的就是直角三角形的兩條直角邊。

兩點的距離就是直角三角形的斜邊了。也就是上面公式中的勾股定義直接計算即可。

有些小伙伴可能就會問了,如果這兩個點的Y軸或者X軸的值是相同的。那么還可以這么計算么?

結論當然是可以了。

用上面的代碼舉例子,如果兩個坐標點的Y軸相同。那么它們的距離實際上就是X軸的距離。

int a = point2.y - point1.y; //兩個值相同,那么a的結果就是0
int b = point2.x - point1.x; // 那么距離就是 b的值。
// 帶入進去0的平方也是0.那么就是b的平方進行開方運算。結果也就是b。(來源:zinyan.com)
Math.sqrt(0+b*b);

所以,如果兩個坐標點的Y軸相同,或者X軸相同。那么最后計算的結果仍然是正確的。

但,我們可以添加一個判斷,來減少這種情況下的多余的平方,開方計算。

所以,完整版代碼如下所示:

public double getPointDistance(Point point1, Point point2) {
       int a = point2.y - point1.y;
       int b = point2.x - point1.x;
       if (a == 0)
           return b;
       if (b == 0)
           return a;
       return Math.sqrt(a * a + b * b);
}
 

但是,如果我們的x軸和y軸的坐標值是 double? 或者 float 。就不能這么判斷了。

因為浮點運算,本身就不精確。我們判斷的時候,需要考慮到這個浮動范圍。

我們也可以不用考慮這方面的優化。因為多一個平方開方,也耗費不了多少內存和時間。

3. 計算兩個線段的交點

計算:在平面直角坐標系中點A和點B組成了線段A,點C和點D組成了線段B。如果他們有交點。那么交點坐標是多少。

而在平面直角坐標系中,同一平面內兩條直線只有相交和平行兩種情況。這個定義是一個數學定理。

所以我們計算交點的時候,可以先處理一下兩個線段是否平行的問題。

3.1 判斷線段是否平行

那么,該如何判斷兩個線段是否平行呢?很簡單比較兩個線段的斜率是否相同即可。

斜率,計算的是一條直線相對橫坐標軸的傾斜角度。所以它也叫做角系數。

例如,這兩個線段,都相較于X軸傾斜了30°,那么不就是證明了這兩個線段是平行線了么。

而直線的斜率公式為:k=(y2-y1)/(x2-x1)。其中K值就是斜率結果了。

那么線段是否平行就可以寫為:

public boolean getParallel(Point pointA, Point pointB, Point pointC, Point pointD) {
   int line1K = (pointB.y - pointA.y) / (pointB.x - pointA.x);
   int line2K = (pointD.y - pointC.y) / (pointD.x - pointC.x);
   return  line1K==line2K
}

但是如果碰見了線段的x軸是相同的怎么辦?也就是說線段垂直于X軸上。那么上面的方法就有問題了。

因為pointB.x - pointA.x =0了。

所以,我們需要進行變種:

//實際比較模式:
(pointB.y - pointA.y) / (pointB.x - pointA.x)==(pointD.y - pointC.y) / (pointD.x - pointC.x)
   
//改除法為乘法:
(pointB.y - pointA.y) * (pointD.x - pointC.x) == (pointD.y - pointC.y)  * (pointB.x - pointA.x)

這兩個等式是相同的。

這樣我們就可以判斷兩個線條是否平行了。完整代碼如下:

public boolean getParallel(Point pointA, Point pointB, Point pointC, Point pointD) {
   return (pointB.y - pointA.y) * (pointD.x - pointC.x) == (pointD.y - pointC.y)  * (pointB.x - pointA.x)
}

 

那么,方法中的坐標點,有前后要求么?答案是沒有的。只需要知道這個直線上的任意兩點就可以。

點斜式斜率公式:K=(y2-y1)/(x2-x1)?也可以寫為:K=(y1-y2)/(x1-x2) 這兩個公式的結果是等值的。

公式中的K?就是斜率值,而x和y是坐標點X軸和Y軸的值。

將上面的公式進行簡單的變換,我們可以得到:

  • y2=K(x2-x1)+y1
  • x2=(y2-y1)/K+x1  

也就是說,x1,y1 是已知的坐標點。斜率K也知道的情況下。我們如果知道交點的X軸就可以計算出Y軸坐標。反之當我們知道Y軸坐標也可以計算出X軸坐標。

3.2 計算線段交點

在某種情況下,交點坐標的某個值是可以快速確定的。例如其中一條線段垂直X軸。或者平行于X軸。那么它們兩個線段的交點的X軸或者Y軸就是已經明確了。

例如有坐標點:Point pointA?, Point pointB?, Point pointC?, Point pointD。其中 pointA 和 pointB 組合成線段1,pointC 和pointD組合成線段2。

public  Point getCross1(Point pointA, Point pointB, Point pointC, Point pointD) {
  Point point =new Point();
  if (pointA.x - pointB.x == 0) {
       //線段1 兩個坐標的x軸相等 說明是垂直x軸的情況,它們的交點x軸就是pointA的x軸
       point.x= pointA.x ;
       //解釋1:線段1垂直X軸,所以它的斜率值計算是0.無法計算,所以我們使用線段2的坐標計算斜率。
       //解釋2:我在其他方法中判斷過平行線的情況,所以如果線段1垂直,那么線段2肯定不會垂直。
       int k = (pointD.y-pointC.y)/(pointD.x-pointC.x);
        //解釋3:代入公式:y2=K(x2-x1)+y1。在已知x2,x1,y1,K的情況下求y2
        point.y= k*(point.x-pointC.x)+pointC.y;
  }else if (pointC.x - pointD.x == 0) {
     //線段2 垂直X軸的情況。它們的交點X軸就是線段2中的坐標的X軸
       point.x = pointC.x;
        //解釋1:線段2垂直X軸,所以它的斜率值計算是0.無法計算,所以我們使用線段1的坐標計算斜率。
       int k = (pointB.y - pointA.y) / (pointB.x - pointA.x);
       //代入公式進行計算y軸坐標值
       point.y =  k * (point.x - pointA.x) + pointA.y;
  }
   return point;
}

可以得到垂直的,而平行于x軸的情況也可以參照上面的示例進行額外處理:

public  Point getCross1(Point pointA, Point pointB, Point pointC, Point pointD) {
   Point point =new Point();
   if (pointA.x - pointB.x == 0) {
       //線段1 兩個坐標的x軸相等 說明是垂直x軸的情況,它們的交點x軸就是pointA的x軸
       point.x= pointA.x ;
       //解釋1:線段1垂直X軸,所以它的斜率值計算是0.無法計算,所以我們使用線段2的坐標計算斜率。
       //解釋2:我在其他方法中判斷過平行線的情況,所以如果線段1垂直,那么線段2肯定不會垂直。
       //因為是交點,所以交點坐標是滿足線段2的斜率公式的。
       int k = (pointD.y-pointC.y)/(pointD.x-pointC.x);
        //解釋3:代入公式:y2=K(x2-x1)+y1。 在已知x2,x1,y1,K的情況下求y2
        point.y= k*(point.x-pointC.x)+pointC.y;
  }else if (pointC.x - pointD.x == 0) {
     //線段2 垂直X軸的情況。它們的交點X軸就是線段2中的坐標的X軸
       point.x = pointC.x;
        //解釋1:線段2垂直X軸,所以它的斜率值計算是0.無法計算,所以我們使用線段1的坐標計算斜率。
       int k = (pointB.y - pointA.y) / (pointB.x - pointA.x);
       //代入公式 進行計算y軸坐標值
       point.y =  k * (point.x - pointA.x) + pointA.y;
  }else if(pointA.y-pointB.y==0){
       //說明線段1,平行于X軸
        point.y= pointA.y;
       //使用線段2,計算斜率K。因為線段1平行x軸是沒有斜率的
       int k = (pointD.y-pointC.y)/(pointD.x-pointC.x);
       //代入公式: x2=(y2-y1)/K+x1   在已知y2,y1,K,x1的情況下求x2
        point.x = (point.y - line2start.y) / k + line2start.x;
  }else if(pointD.y-pointC.y==0){
       //說明線段2,平行于X軸
       point.y = pointD.y;
       int k = (pointB.y-pointA.y)/(pointB.x-pointA.x);
       //使用線段1,計算斜率K。因為線段2平行x軸是沒有斜率的zinyan.com
       point.x =(point.y - line1start.y) / k + line1start.x;
  }


   return point;
   
}
 

通過上面的方法,應該給大家詳細介紹了。線段平行或者垂直情況下??焖儆嬎憬稽c的運算邏輯。

但是,如果線段并不垂直或者平行于X軸或者Y軸。那么如何計算呢?在實際處理過程中,不垂直才是最多的場景。所以上面的方法還需要進行擴充。

仍然使用:Point pointA?, Point pointB?, Point pointC?, Point pointD  這四個坐標點,計算未知的交點。

假如交點坐標是Point point。我們來一步步推導相關的方程組。

int k1 = (pointB.y - pointA.y) / (pointB.x - pointA.x); //線段1的斜率
int k2=  (pointD.y - pointC.y) / (pointD.x - pointC.x); //線段2的斜率
 

線段1的斜率和線段2的斜率肯定是不一樣的。但是線段公式中斜率是一個常量。也就是說只要是直線上的任意兩點,計算出來的斜率是固定的。我們再根據點斜式公式的變種:y2=K(x2-x1)+y1? 和x2=(y2-y1)/K+x1??梢缘玫揭韵拢?/p>

PS: x1 ,x2,y1,y2 只是表示的變量,不是數值*2哦。別弄混了。

 

int k1 = (pointB.y - pointA.y) / (pointB.x - pointA.x); //線段1的斜率
int k2= (pointD.y - pointC.y) / (pointD.x - pointC.x); //線段2的斜率


point.x =(point.y-pointB.y)/k1+porintB.x; // 根據線段1的點斜式公式可以得到的方程組
point.x =(point.y-pointD.y)/k2+porintD.x; // 根據線段2的點斜式公式可以得到的方程組
point.y = k1(point.x-pointA.x)+pointA.y; 
point.y = k2(point.x-pointC.x)+pointC.y;
 

在上面的計算過程中,x和y的兩種算法得到的結果是相同的。我們先求x軸坐標的話,從y的兩個等式進行計算。得到以下方程組:

k1(point.x-pointA.x)+pointA.y-(k2(point.x-pointC.x)+pointC.y)=0; //第一步
//第一步去除乘法括號
k1*point.x-k1*pointA.x+pointA.y-(k2*point.x-k2*pointC.x+pointC.y)=0;
//去除所有的括號
k1*point.x-k1*pointA.x+pointA.y-k2*point.x+k2*pointC.x-pointC.y=0;
//由于point.x 是未知數,其他的都是已知數。我們將未知數和已知進行等式的移動, 從左邊移動到右邊的時候,正負要互換
k1*point.x-k2*point.x=k1*pointA.x-pointA.y-k2*pointC.x+pointC.y;
//左邊的等式可以繼續簡化
(k1-k2)*point.x = k1*pointA.x-pointA.y-k2*pointC.x+pointC.y;
//確保左邊只有一個point.x 這個未知變量
point.x= (k1*pointA.x-pointA.y-k2*pointC.x+pointC.y)/(k1-k2);

通過上面的推導,當我們知道線段1的斜率,線段2的斜率。以及線段1的某個坐標點坐標。線段2的某個坐標點坐標。

我們就可以直接通過公式:(k1*pointA.x-pointA.y-k2*pointC.x+pointC.y)/(k1-k2)計算出交點的x軸坐標。

當我們知道x軸坐標。之后通過y2=K(x2-x1)+y1點斜式方程的變種。直接計算y軸的坐標:

point.x = (k1*pointA.x-pointA.y-k2*pointC.x+pointC.y)/(k1-k2);
point.y = k1(point.x-pointA.x)+pointA.y; //直接得到Y值的坐標
 

上面計算y軸坐標是使用的線段1的斜率進行計算的。所以x1和y1的值需要時線段1上的坐標點。

我們也可以使用線段2進行計算得到y軸值:

 

point.y = k2(point.x-pointC.x)+pointC.y; //直接得到Y值的坐標

 

到這里,我們就可以得到斜線的交點了。我們總結一下方法:

public  Point getCross1(Point pointA, Point pointB, Point pointC, Point pointD) {
    Point point =new Point();
    if (pointA.x - pointB.x == 0) {
        //線段1 兩個坐標的x軸相等 說明是垂直x軸的情況,它們的交點x軸就是pointA的x軸
        point.x= pointA.x ; 
        //解釋1:線段1垂直X軸,所以它的斜率值計算是0.無法計算,所以我們使用線段2的坐標計算斜率。
        //解釋2:我在其他方法中判斷過平行線的情況,所以如果線段1垂直,那么線段2肯定不會垂直。
        //因為是交點,所以交點坐標是滿足線段2的斜率公式的。
        int k = (pointD.y-pointC.y)/(pointD.x-pointC.x);
         //解釋3:代入公式:y2=K(x2-x1)+y1。 在已知x2,x1,y1,K的情況下求y2
         point.y= k*(point.x-pointC.x)+pointC.y;
    }else if (pointC.x - pointD.x == 0) {
      //線段2 垂直X軸的情況。它們的交點X軸就是線段2中的坐標的X軸
        point.x = pointC.x;
         //解釋1:線段2垂直X軸,所以它的斜率值計算是0.無法計算,所以我們使用線段1的坐標計算斜率。
        int k = (pointB.y - pointA.y) / (pointB.x - pointA.x);
        //代入公式 進行計算y軸坐標值(zinyan.com)
        point.y =  k * (point.x - pointA.x) + pointA.y;
    }else if(pointA.y-pointB.y==0){
        //說明線段1,平行于X軸
         point.y= pointA.y; 
        //使用線段2,計算斜率K。因為線段1平行x軸是沒有斜率的
        int k = (pointD.y-pointC.y)/(pointD.x-pointC.x);
        //代入公式: x2=(y2-y1)/K+x1   在已知y2,y1,K,x1的情況下求x2
         point.x = (point.y - line2start.y) / k + line2start.x;
    }else if(pointD.y-pointC.y==0){
        //說明線段2,平行于X軸
        point.y = pointD.y;
        int k = (pointB.y-pointA.y)/(pointB.x-pointA.x);
        //使用線段1,計算斜率K。因為線段2平行x軸是沒有斜率的
        point.x =(point.y - line1start.y) / k + line1start.x;
    }else{
        int k1 = (pointB.y - pointA.y) / (pointB.x - pointA.x); //線段1的斜率
        int k2= (pointD.y - pointC.y) / (pointD.x - pointC.x); //線段2的斜率
        point.x = (k1*pointA.x-pointA.y-k2*pointC.x+pointC.y)/(k1-k2);
        point.y = k1(point.x-pointA.x)+pointA.y; //直接得到Y值的坐標
    }


    return point;
}

到這里,我們其實就可以獲取交點了。而除此以外,我們還可以通過斜截式公式,來計算交點

3.3 斜截式計算交點

我們上面的推導過程使用的都是點斜式的公式進行的。其實我們還可以通過直線的斜截式方程:y=kx+b來進行推導直線的交點。相較于點斜式,個人認為斜截式可能會更容易理解吧。

在公式中,K表達的是斜率。斜率計算公式在上面有介紹。就不重復了

而y和x就是我們的坐標點的Y軸值和X軸值。b就是Y軸截距。

在平面直角坐標系中,直線的Y軸截距是相等的。也就是說不管是在直線的哪個點,代入到上面的公式中來得到的b值都是固定的。

public  Point getCross1(Point pointA, Point pointB, Point pointC, Point pointD) {
    Point point =new Point();
  /**  前面直角的方法省略了 主要是判斷斜線的交點*/
    int k1 = (pointB.y - pointA.y) / (pointB.x - pointA.x); //得到線段1的 斜率K的值
    int b1 = pointA.y - pointA.x * k1; //得到線段1的 Y截距 b的值
    
    int k2 = (pointD.y - pointC.y) / (pointD.x - pointC.x); // 得到線段2的斜率K的值
    //斜截式公式:y=kx+b ,進行簡單轉換一下就是:b= y-kx
    int b2 = pointC.y - pointC.x * k2; //得到線段2的 Y截距b的值。在這里我們可以使用pointC的值,也可以使用pointD的值
}
 

然后,由于交點需要滿足線段1的斜截式,也需要滿足線段2的斜截式公式,所以我們可以得到:

point.y = k1 * point.x + b1; // y=kx+b
point.y = k2 * point.x + b2; // y=kx+b
//根據上面的公式轉換。
k1 * point.x + b1 = k2 * point.x + b2;  //這樣整個表達式中就只有point.x 這一個變量了。
//根據數學表達式的規則,移動等號兩邊的數據。將未知數移動到左邊
k1 * point.x - k2 * point.x = b2 - b1;// 移動過程中要注意加減法
//然后再提取乘法
(k1 - k2) * point.x = b2 - b1;//再進行表達式變換
point.x = (b2 - b1)/(k1 - k2); //也就是最終的結果值了
 

當我們知道x值之后。代入斜截式中可以快速得到y值:

point.y = k1 * point.x + b1;

 

完整版本效果就是:

public  Point getCross1(Point pointA, Point pointB, Point pointC, Point pointD) {
    Point point =new Point();
  /**  前面直角的方法省略了 主要是判斷斜線的交點*/
    int k1 = (pointB.y - pointA.y) / (pointB.x - pointA.x); //得到線段1的 斜率K的值
    int b1 = pointA.y - pointA.x * k1; //得到線段1的 Y截距 b的值
    
    int k2 = (pointD.y - pointC.y) / (pointD.x - pointC.x); // 得到線段2的斜率K的值
    //斜截式公式:y=kx+b ,進行簡單轉換一下就是:b= y-kx
    int b2 = pointC.y - pointC.x * k2; //得到線段2的 Y截距b的值。在這里我們可以使用pointC的值,也可以使用pointD的值


  point.x = (b2 - b1)/(k1 - k2); 
    point.y = k1 * point.x + b1; 
}
 

有些公式可能寫的結果是這樣的:

//情況1
point.x = (b2 - b1)/(k1 - k2); 


//情況2
point.x = (b1 - b2)/(k2 - k1);

 

這兩個情況下,是等效的。在上面介紹了情況1的表達式是如何推導的。現在介紹一下如何推導出情況2:

point.y = k1 * point.x + b1; // y=kx+b
point.y = k2 * point.x + b2; // y=kx+b
//根據上面的公式轉換。
k1 * point.x + b1 = k2 * point.x + b2;  //這樣整個表達式中就只有point.x 這一個變量了。
//將未知數移動到右側
b1-b2 = k2*point.x-k1*point.x;// 移動過程中要注意加減法


//然后再提取乘法
b1-b2 = (k2-k1)*point.x;//再進行表達式變換
point.x = (b1 - b2)/(k2 - k1); //也就是最終的結果值了

 

所以,這種表達式結果是一致的。

PS:在上面的代碼中,我的變量是int型的。那是因為我自定義的類型參數。你如果是double也是沒有關系的。單位格式不影響計算邏輯。只是最終結果值的精度有差異而已。

3. 小結

到這里,詳細介紹了平面坐標系下的距離判斷。線段平行和線段交點的計算。關于斜率的計算,稍微涉及了高中的知識。但是整體的計算過程也就初中水平了。

只是由于很長時間沒有接觸了。一些概念和公式都忘記完了。

所以,才會按照完全不懂的情況下。充分介紹一下這中間的運算過程。

后面可能會更新,如何計算角度。根據坐標點,計算運動方向等等吧。

分享到:
標簽:Java
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定