用向量變換的方法求兩條直線的交點

2021-04-16 19:40:04 字數 4062 閱讀 9780

求兩條直線的交點,最常見的寫法是列出兩條直線的方程,聯立求解。

但這種辦法的弊端很大:

1 )演算法是座標系相關的,要考慮直線是水平還是垂直,寫出很多判斷條件,增加了程式的不穩定性

2)即使兩直線都是斜的,只要接近水平或者垂直,也會帶來過大的誤差,導致計算失敗

出現這種問題的核心是聯立方程無法做到座標系無關,總要把求交點的幾何問題繫結到座標系。

從本質上講,兩條直線的交點是幾何圖形的內在性質,不依賴於座標系。用向量變換的方式來求交點,可以避免求解直線方程,也不用判斷直線是否水平垂直,能真正做到座標系無關。類似的演算法還可以推廣到求直線和圓的交點、圓和圓的交點、直線和橢圓的交點等等。

以下是用delphi編寫的用向量變換的方法求兩條直線交點的程式。

該程式不僅能求出交點座標,還能判斷直線是否通過交點,因為有時候交點在延長線上。

unit unit1;

inte***ce

uses

windows, messages, sysutils, variants, classes, graphics, controls, forms,

dialogs, stdctrls, buttons;

type

tform1 = class(tform)

bitbtn1: tbitbtn;

procedure bitbtn1click(sender: tobject);

private

public

calinterpoint(x1, y1, x2, y2, x3, y3, x4, y4: double;

var xj, yj: double): integer;

calpro(vx1, vy1, vx2, vy2: double): double;

end;

varform1: tform1;

implementation

tform1.calinterpoint(x1, y1, x2, y2, x3, y3, x4, y4: double;

var xj, yj: double): integer;

var

px12, py12, //直線12的方向向量

px34, py34, //直線34的方向向量

t12, t34, //12 和34的長度

nx12, ny12, //直線12的單位矢

nx34, ny34, //直線34的單位矢

px13, py13, //13連線向量

ty, //13連線向量在直線12上的投影

tysx, tysy, //13連線向量在直線12上的投影向量

czsx, czsy, //3到12的垂線向量

cossit, //垂線矢跟直線34方向矢的夾角余弦

sux, suy, //3到交點的連線向量

czl, //垂線長度

gene: //變換因子

double;

begin

px12 := x2 - x1; //12連線向量

py12 := y2 - y1;

px34 := x4 - x3; //34連線向量

py34 := y4 - y3;

//如果矢積為0,則說明平行,置平行標誌,返回

if px12 * py34 - px34 * py12 = 0 then

begin

result := -1;

exit;

end;

if (x3 - x1) * (y3 - y2) + (x3 - x2) * (y3 - y1) = 0 then

begin //如果3正好落在直線12上,交點為 (x3,x4)

xj := x3;

yj := y3;

endelse

begin

t12 := sqrt(px12 * px12 + py12 * py12); //12長度

t34 := sqrt(px34 * px34 + py34 * py34); //34長度

nx12 := px12 / t12; //12單位矢

ny12 := py12 / t12;

nx34 := px34 / t34; //34單位矢

ny34 := py34 / t34;

px13 := x3 - x1; //13連線矢

py13 := y3 - y1;

ty := px13 * nx12 + py13 * ny12; //投影

tysx := ty * nx12; //投影向量

tysy := ty * ny12;

czsx := tysx - px13; //垂線矢

czsy := tysy - py13;

czl := sqrt(czsx * czsx + czsy * czsy); //垂線長度

gene := czl / calpro(x4 - x3, y4 - y3, czsx, czsy); //變換因子

xj := x3 + px34 * gene;

yj := y3 + py34 * gene;

end;

result := 0;

if (x1 - xj) * (x2 - xj) + (y1 - yj) * (y2 - yj) < 0 then

result := result + 1; //判斷是否在直線12上

if (x3 - xj) * (x4 - xj) + (y3 - yj) * (y4 - yj) < 0 then

result := result + 2; //判斷是否在直線34上

end;

procedure tform1.bitbtn1click(sender: tobject);

varx1, y1, x2, y2, x3, y3, x4, y4: double;

xo, yo: double;

ret: integer;

info: string;

begin

x1 := 150;

y1 := 150;

x2 := 200;

y2 := 200;

x3 := 200;

y3 := 100;

x4 := 0;

y4 := 150;

form1.canvas.moveto(round(x1), round(y1));

form1.canvas.lineto(round(x2), round(y2));

form1.canvas.moveto(round(x3), round(y3));

form1.canvas.lineto(round(x4), round(y4));

ret := calinterpoint(x1, y1, x2, y2, x3, y3, x4, y4, xo, yo);

form1.canvas.ellipse(round(xo - 10), round(yo - 10), round(xo + 10), round(yo + 10));

info := '';

if (ret and 1) > 0 then

begin

info := info + '交點在直線12上 ';

endelse

begin

info := info + '交點不在直線12上 ';

end;

if (ret and 2) > 0 then

begin

info := info + '交點在直線34上 ';

endelse

begin

info := info + '交點不在直線34上 ';

end;

showmessage(info);

end;

tform1.calpro(vx1, vy1, vx2, vy2: double): double;

// 求向量的投影 向量v1在v2上的投影 (vx1, vy1)是向量v1 (vx2, vy2)是向量v2

begin

result := (vx1 * vx2 + vy1 * vy2) / sqrt(vx2 * vx2 + vy2 * vy2);

end;

end.

求兩條直線(線段)的交點

如圖,如何求得直線 ab 與直線 cd的交點p?以上內容摘自 演算法藝術與資訊學競賽 思路就是利用叉積求得點p分線段dc的比,然後利用高中學習的定比分點座標公式求得分點p的座標。看不懂的可以去複習下 定比分點 的知識。include include include include using nam...

求兩條直線的關係及交點

給你兩條直線,判斷這兩條直線是否共線,相交,不相交 即平行 相交的話輸出交點。判斷平行,然後通過叉積判斷是否共線。平行判斷可以判斷兩條直線的斜率是否相等。交點的話,相當於聯立方程組求解了。這些方程看模板理解的,剛才搜了下,有人講得比較清楚,借鑑下 如何判斷是否同線?由叉積的原理知道如果p1,p2,p...

求空間兩條直線之間的距離

1.前言 最近老闆讓寫一段空間點匹配的 其中涉及到求空間兩直線之間的距離,寫起來滿費勁的,這裡做乙個記錄。2.處理思路 空間兩直線之間的位置關係主要可以分為 重合,平行,相交,異面。2.1 異面情形 含相交 已知空間中兩線段,如果它們無限變粗,判斷是否相交。主要討論不在同一平面的情況 線段ab 線段...