ベクトルによる平面幾何の計算

 投稿者:山中和義  投稿日:2009年12月24日(木)10時49分37秒
 
!ベクトルによる平面幾何の計算 - 点、直線(線分)

LET cEps=1e-13 !精度

!ベクトル(a1,a2)とベクトル(b1,b2)との演算
DEF fnDot(a1,a2, b1,b2)=a1*b1+a2*b2 !内積
DEF fnCross(a1,a2, b1,b2)=fnDot(-a2,a1,b1,b2) !擬似外積、パープ内積 a1*b2-a2*b1
DEF fnABS(a,b)=SQR(a*a+b*b) !絶対値、大きさ

DIM a(2),b(2),c(2),d(2) !点A、B、C、D

DATA  4, 4 !A
DATA -1, 1 !B
DATA -3, 2 !C
DATA  3,-4 !D

MAT READ A
MAT READ B
MAT READ C
MAT READ D

SET WINDOW -5,5,-5,5 !グラフを描く
DRAW grid
SET TEXT HEIGHT 0.4
PLOT LINES: A(1),A(2); B(1),B(2) !線分AB
PLOT TEXT ,AT A(1),A(2): "A"
PLOT TEXT ,AT B(1),B(2): "B"
PLOT LINES: C(1),C(2); D(1),D(2) !線分CD
PLOT TEXT ,AT C(1),C(2): "C"
PLOT TEXT ,AT D(1),D(2): "D"


DIM s(2),t(2),u(2),v(2) !作業用

!点Aと点Bを通る直線と点Cと点Dを通る直線との直交・平行判定
!内積が0なら、直交。 外積が0なら、平行。

MAT s=b-a
MAT t=d-c
IF fnDot(s(1),s(2),t(1),t(2))=0 THEN PRINT "直交"
IF fnCross(s(1),s(2),t(1),t(2))=0 THEN PRINT "平行"


!点Aと点Bを通る直線と点Cと点Dを通る直線との交点

MAT s=b-a
MAT t=d-c
LET DD=fnCross(t(1),t(2),s(1),s(2))
IF DD<>0 THEN
   MAT u=c-a
   MAT v=( fnCross(t(1),t(2),u(1),u(2))/DD ) * s
   MAT v=a+v
   MAT PRINT v; !交点
ELSE
   PRINT "平行です。"
END IF


!点Aと点Bを結ぶ線分と点Cと点Dを結ぶ線分との交点

MAT s=b-a
MAT t=c-a
LET d1=fnCross(s(1),s(2),t(1),t(2))
!MAT s=b-a
MAT t=d-a
LET d2=fnCross(s(1),s(2),t(1),t(2))
MAT s=d-c
MAT t=a-c
LET d3=fnCross(s(1),s(2),t(1),t(2))
!MAT s=d-c
MAT t=b-c
LET d4=fnCross(s(1),s(2),t(1),t(2))
IF d1*d2<=0 AND d3*d4<=0 THEN
   MAT u=b-a
   MAT u=( ABS(d3)/(ABS(d3)+ABS(d4)) ) * u
   MAT u=a+u
   MAT PRINT u; !交点
ELSE
   PRINT "交差なし"
END IF


!点Cと、点Aと点Bを通る直線との位置関係

MAT s=b-a
MAT t=c-a
LET DD=fnCross(s(1),s(2),t(1),t(2))
IF DD=0 THEN
   PRINT "線上"
ELSEIF DD>0 THEN
   PRINT "左側"
ELSE
   PRINT "右側"
END IF


!点Cが、点Aと点Bを結ぶ線分上にあるかどうかの判定
!三角不等式 |a-b|≦|a-c|+|c-b|

MAT s=a-c
MAT t=c-b
MAT u=a-b
IF fnABS(s(1),s(2))+fnAbs(t(1),t(2))<fnABS(u(1),u(2))+cEps THEN PRINT "線上"


!点Cと、点Aと点Bを通る直線との距離

MAT s=b-a
MAT t=c-a
PRINT ABS(fnCross(s(1),s(2),t(1),t(2))) / fnABS(s(1),s(2))


!点Cと、点Aと点Bを結ぶ線分との距離(最近接点)

MAT s=b-a
MAT t=c-a
MAT u=c-b
IF fnDot(s(1),s(2),t(1),t(2))<cEps THEN !点A外側
   PRINT fnABS(t(1),t(2)) !点Aとの距離
ELSEIF fnDot(-s(1),-s(2),u(1),u(2))<cEps THEN !点B外側
   PRINT fnABS(u(1),u(2)) !点Bとの距離
ELSE !線分AB内
   PRINT ABS(fnCross(s(1),s(2),u(1),u(2))) / fnABS(s(1),s(2)) !垂線
END IF


END

!投稿(記述例)、数学、ベクトルと図形方程式、アルゴリズム、ゲーム、当たり判定
 

戻る