日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【数学计算】判断两条线段是否相交+计算两条线段的交点和夹角

發布時間:2024/3/13 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【数学计算】判断两条线段是否相交+计算两条线段的交点和夹角 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

序言

  • 還是那句話,學習是為了應用。書到用時方恨"用得少"

1. 計算兩條直線的交點

  • 直線一般式方程

A x + B y + C = 0 Ax+By+C = 0 Ax+By+C=0

  • 設線段p1-p2對應的直線方程:a1 * x + b1 * y + c1 = 0
  • 設線段p3-p4對應的直線方程:a2 * x + b2 * y + c2 = 0
  • 求解方程系數:

    A = y2 - y1 = p2.y() - p1.y() B = x1 - x2 = p1.x() - p2.x() C = x2 * y1 - x1 * y2 = p2.x() * p1.y() - p1.x() * p2.y()
  • 聯立方程式求交點坐標

    a1 * x + b1 * y + c1 = 0 -- (1) a2 * x + b2 * y + c2 = 0 -- (2)(1) * b2 - (2) * b1得到: a1 * b2 * x + b1 * b2 * y + c1 * b2 = 0 a2 * b1 * x + b1 * b2 * y + c2 * b1 = 0兩式相減: x = (c2 * b1 - c1 * b2) / denominator(1) * a2 - (2) * a1得到: a1 * a2 * x + b1 * a2 * y + c1 * a2 = 0 a1 * a2 * x + b2 * a1 * y + c2 * a1 = 0兩式相減: y = (c1 * a2 - c2 * a1) / denominator(注:denominator = a1 * b2 - a2 * b1)
  • 交點坐標

( x , y ) = ( c 2 ? b 1 ? c 1 ? b 2 a 1 ? b 2 ? a 2 ? b 1 , c 1 ? a 2 ? c 2 ? a 1 a 1 ? b 2 ? a 2 ? b 1 ) (x, y) = (\frac{c2 * b1 - c1 * b2}{a1 * b2 - a2 * b1} , \frac{c1 * a2 - c2 * a1}{a1 * b2 - a2 * b1} ) (x,y)=(a1?b2?a2?b1c2?b1?c1?b2?,a1?b2?a2?b1c1?a2?c2?a1?)

  • 兩條直線的夾角(兩條直線所形成的不大于90°的角):

    double denominator = a1 * a2 + b1 * b2; double numerator = a1 * b2 - a2 * b1; if (fabs(denominator) < 0.0000001) {return PI / 2.0; // 兩直線垂直 } return fabs(std::atan(numerator / denominator)); // 返回的是弧度值

2. 判斷兩條線段是否相交:方法1

  • 直線一般式常規方法求解。

  • 證明兩條線段相交:

    • (1) 證明denominator != 0,denominator == 0表示兩條直線平行
    • (1) 根據1中公式求解交點坐標
    • (2) 證明交點既在線段p1-p2上,也在線段p3-p4上。即如下關系成立
    r_x0 = (p.x() - p1.x()) / (p2.x() - p1.x()); r_y0 = (p.y() - p1.y()) / (p2.y() - p1.y()); r_x1 = (p.x() - p3.x()) / (p4.x() - p3.x()); r_y1 = (p.y() - p3.y()) / (p4.y() - p3.y()); bool condition_1 = (r_x0 >= 0.0 && r_x0 <= 1.0) || (r_y0 >= 0.0 && r_y0 <= 1); bool condition_2 = (r_x1 >= 0.0 && r_x1 <= 1.0) || (r_y1 >= 0.0 && r_y1 <= 1.0); if (condition_1 && condition_2) {return true; }
  • 線段比例計算:

r a t i o x 0 = p . x ? p 1 . x p 2 . x ? p 1 . x r a t i o y 0 = p . y ? p 1 . y p 2 . y ? p 1 . y r a t i o x 1 = p . x ? p 3 . x p 4 . x ? p 3 . x r a t i o y 1 = p . y ? p 3 . y p 4 . y ? p 3 . y \begin{aligned} ratio_{x0} &= \frac{p.x - p_1.x}{p_2.x - p_1.x} \\ ratio_{y0} &= \frac{p.y - p_1.y}{p_2.y - p_1.y} \\ ratio_{x1} &= \frac{p.x - p_3.x}{p_4.x - p_3.x} \\ ratio_{y1} &= \frac{p.y - p_3.y}{p_4.y - p_3.y} \\ \end{aligned} ratiox0?ratioy0?ratiox1?ratioy1??=p2?.x?p1?.xp.x?p1?.x?=p2?.y?p1?.yp.y?p1?.y?=p4?.x?p3?.xp.x?p3?.x?=p4?.y?p3?.yp.y?p3?.y??

3. 判斷兩條線段是否相交:方法2

  • 快速排斥實驗和跨立實驗計算。

  • 證明兩條線段相交:

    • (1) 通過快速排斥實驗
    • (2) 且通過跨立實驗
    /* 1. 快速排斥實驗 */ bool cond_1 = max(p1.x, p2.x) < min(p3.x, p4.x); bool cond_2 = max(p1.y, p2.y) < min(p3.y, p4.y); bool cond_3 = max(p3.x, p4.x) < min(p1.x, p2.x); bool cond_4 = max(p3.y, p4.y) < min(p2.y, p2.y); if (cond_1 || cond_1 || cond_1 || cond_1) {return false; // 有一個條件為真,表示兩線段必不相交 } /* 2. 跨立實驗 */ if(cross(p3 - p1,p2 - p1) * cross(p4 - p1, p2 - p1) > 0|| cross(p2 - p3, p4 - p3) * cross(p1 - p3, p4 - p3) > 0) {return false; // 叉積 == 0可能共線,但已通過快速排斥實驗過濾 } return true;
  • 快速排斥實驗:即驗證線段的橫坐標或縱坐標是否總小于或大于另一線段的橫坐標或縱坐標

  • 跨立實驗:通過叉積證明點p1和p2在p3-p4的兩側,以及p3和p4在p1-p2的兩側

    • 兩向量叉積表示向量所在平面的法向量

    • 叉積有一個非常重要的性質,可通過叉積的符號來判斷兩向量的順逆時針關系:

      P x Q > 0, 則向量P在向量Q的順時針方向; P x Q < 0, 則向量P在向量Q的逆時針方向; P x Q = 0,表示P與Q共線,可能同向也可能反向
    • 若向量P = (x1, y1), Q = (x2, y2),則向量叉積P x Q = x1 * y2 - x2 * y1

    • 如果兩線段相交,則線段端點相互跨立,即p1, p2分別在p3-p4兩側,p3, p4分別在p1-p2兩側

    • 判斷p3、p4分別在p1-p2的兩側 ( p 1 p 3 × p 1 p 2 ) ? ( p 1 p 4 × p 1 p 2 ) ≤ 0 (p_1p_3\times p_1p_2) * (p_1p_4\times p_1p_2)\le 0 (p1?p3?×p1?p2?)?(p1?p4?×p1?p2?)0

    • 判斷p1、p4分別在p3-p4的兩側 ( p 3 p 2 × p 3 p 4 ) ? ( p 3 p 1 × p 3 p 4 ) ≤ 0 (p_3p_2\times p_3p_4) * (p_3p_1\times p_3p_4)\le 0 (p3?p2?×p3?p4?)?(p3?p1?×p3?p4?)0

4. 總結

  • 方法2比較直觀,方法1判斷兩條線段是否相交比方法2實現上復雜一點;
  • 方法1能直接計算線段夾角;
  • 方法2叉積可調用Eigen庫函數實現(待補充)

《參考文章》
快速排斥實驗和跨立實驗-1
快速排斥實驗和跨立實驗-2
直線一般式判斷線段相交-1
直線一般式判斷線段相交-2
直線一般式計算兩直線夾角-1
直線一般式計算兩直線夾角-2

created by shuaixio, 2022.10.7

總結

以上是生活随笔為你收集整理的【数学计算】判断两条线段是否相交+计算两条线段的交点和夹角的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。