如果你有兩個點,(x1,y1)和(x2,y2),它們代表一個矩形的兩個對角,以及另外兩個點(x3,y3)和(x4,y4),它們代表兩個端點如何檢查線段是否與矩形相交?如何檢查線段是否與矩形相交?
(線段只是包含在給定的端點之間的段,它不是由這兩個點定義的無限長度線。)
如果你有兩個點,(x1,y1)和(x2,y2),它們代表一個矩形的兩個對角,以及另外兩個點(x3,y3)和(x4,y4),它們代表兩個端點如何檢查線段是否與矩形相交?如何檢查線段是否與矩形相交?
(線段只是包含在給定的端點之間的段,它不是由這兩個點定義的無限長度線。)
一個非常簡單的選擇將是使用a standard algorithm for checking whether two line segments intersect檢查線路是否線段與構成盒子角落的四條線段中的任何線段相交。檢查兩條線段是否相交在計算上非常有效,所以我期望這可以很快運行。
希望這會有所幫助!
用線段的方向向量獲取所有4個頂點(矩形的角)的點積。如果所有4都具有相同符號的值,則所有頂點位於該線的同一側(不是線段,而是無限線),因此該線不與該矩形相交。這種方法僅適用於2D交叉點檢測。這可以用來快速過濾大部分數據(僅使用乘法和加法)。您必須對線段進行更多檢查,而不是線路。
我一直在想這個...這是不正確的。所有的頂點可以位於線的同一側,但仍產生相反符號的點積。同樣使用方向矢量不考慮線的實際位置。可以選擇兩條平行線:一條與矩形相交,另一條不相交。由於它們的方向相同,所以四個點的產品將產生兩條線的相同值,這明顯與定理矛盾。儘管最初的想法很好,但我必須得到-1。 – 2015-08-31 21:00:15
要了解如何導出測試線段是否與矩形相交的公式,請務必記住vector dot product的屬性。
將線段表示爲單位矢量以及線段起點與原點之間的距離。下面是一些C#代碼來計算從PointF
變量a_ptStart
和a_ptEnd
,使用Vector
:
Vector vecLine = new Vector(a_ptEnd.X - a_ptStart.X, a_ptEnd.Y - a_ptStart.Y);
double dLengthLine = vecLine.Length;
vecLine /= dLengthLine;
double dDistLine = Vector.Multiply(vecLine, new Vector(a_ptStart.X, a_ptStart.Y));
您還需要計算垂直向量,它從原點的距離的線段。將單位矢量旋轉90 °爲easy。
Vector vecPerpLine = new Vector(-vecLine.Y, vecLine.X);
double dDistPerpLine = Vector.Multiply(vecPerpLine, new Vector(a_ptStart.X, a_ptStart.Y));
假設矩形的四個角在Vector
變量稱爲vecRect1
,vecRect2
,vecRect3
,和vecRect4
,計算線段和目標的邊界矩形的所有四個角之間的distance:
double dPerpLineDist1 = Vector.Multiply(vecPerpLine, vecRect1) - dDistPerpLine;
double dPerpLineDist2 = Vector.Multiply(vecPerpLine, vecRect2) - dDistPerpLine;
double dPerpLineDist3 = Vector.Multiply(vecPerpLine, vecRect3) - dDistPerpLine;
double dPerpLineDist4 = Vector.Multiply(vecPerpLine, vecRect4) - dDistPerpLine;
double dMinPerpLineDist = Math.Min(dPerpLineDist1, Math.Min(dPerpLineDist2,
Math.Min(dPerpLineDist3, dPerpLineDist4)));
double dMaxPerpLineDist = Math.Max(dPerpLineDist1, Math.Max(dPerpLineDist2,
Math.Max(dPerpLineDist3, dPerpLineDist4)));
如果所有的距離都是正值,或者所有的距離都是負值,那麼矩形位於線的另一側,所以沒有交點。 (零程度矩形被認爲不與任何線段相交。)
if (dMinPerpLineDist <= 0.0 && dMaxPerpLineDist <= 0.0
|| dMinPerpLineDist >= 0.0 && dMaxPerpLineDist >= 0.0)
/* no intersection */;
接着,項目中的目標的邊界矩形的所有四個角到線段。這給了我們線的原點和該線上的矩形角的投影之間的距離。
double dDistLine1 = Vector.Multiply(vecLine, vecRect1) - dDistLine;
double dDistLine2 = Vector.Multiply(vecLine, vecRect2) - dDistLine;
double dDistLine3 = Vector.Multiply(vecLine, vecRect3) - dDistLine;
double dDistLine4 = Vector.Multiply(vecLine, vecRect4) - dDistLine;
double dMinLineDist = Math.Min(dDistLine1, Math.Min(dDistLine2,
Math.Min(dDistLine3, dDistLine4)));
double dMaxLineDist = Math.Max(dDistLine1, Math.Max(dDistLine2,
Math.Max(dDistLine3, dDistLine4)));
如果矩形的點不在線段的範圍內,那麼就沒有相交。
if (dMaxLineDist <= 0.0 || dMinLineDist >= dLengthLine)
/* no intersection */;
我相信這就夠了。
這種方法對3D進行推廣嗎?假設我們有那個矩形的正常。通過分段方向和法線,我們可以得到與這兩個方向垂直的第三個方向,因此我們可以計算'vecPerpLine'。其餘的是使用點積和距離的減法。這對我來說很有意義。有人可以評論我的想法? – kotu 2017-10-25 08:32:06
[行矩形碰撞檢測]的可能重複(http://stackoverflow.com/questions/2368211/line-rectangle-collision-detection) – templatetypedef 2013-04-24 23:11:37
你的行稱爲段 – kassak 2013-04-25 12:31:15