• ベストアンサー

3次元座標上の2直線の交点判定について

座標A(x1,y1,z1)から座標B(x2,y2,z2)への線分ABと 座標C(x3,y3,z3)から座標B(x4,y4,z4)への線分CDがあり、 線分ABと線分CDが交点を持つかどうかのプログラムを作りたいです。 C言語かVBかFortranで記述され、DirectXやOpenGLのライブラリを使わない方法の サンプルソースの載っているページを教えていただけませんか? また、ご迷惑でなければソースコードを記述していただけると助かります。

質問者が選んだベストアンサー

  • ベストアンサー
  • nineexit
  • ベストアンサー率100% (8/8)
回答No.4

2線分の最短距離を求めてそれが0になる場合,交わっていると判断するのが良いと思います. piyoは2線分の最短距離を求めるサブルーチンです. 2線分が平行なときは別の処理が必要ですね. subroutine piyo(r1,r2,r3,r4,d) implicit none real(8),intent(in)::r1(3),r2(3),r3(3),r4(3) real(8),intent(out)::d real(8) r12(3),r34(3),b(2),a(2,2),s,t,rr(3),deta r12(:)=r2(:)-r1(:) r34(:)=r4(:)-r3(:) !!! 2つの直線の距離の2乗をdとする !!! d=|((r1+s*r12)-(r3+t*r34))|^2 !!! dの最小値を求める !!! dをsについて偏微分 !!! r12・((r1+s*r12)-(r3+t*r34))=0 !!! dをtについて偏微分 !!! -r34・((r1+s*r12)-(r3+t*r34))=0 !!! sとtについてまとめると !!! r12・r12 s - r12・r34 t = -r12・r1 +r12・r3 !!! -r34・r12 s + r34・r34 t = r34・r1 -r34・r3 a(1,1)=dot_product(r12,r12) a(2,1)=-dot_product(r12,r34) a(1,2)=a(2,1) a(2,2)=dot_product(r34,r34) b(1)=-dot_product(r12,r1)+dot_product(r12,r3) b(2)=dot_product(r34,r1)-dot_product(r34,r3) deta=a(1,1)*a(2,2)-a(1,2)*a(2,1) !!! sとtについて解く if(deta /=0.d0) then s=(a(2,2)*b(1)-a(1,2)*b(2))/deta t=(-a(2,1)*b(1)+a(1,1)*b(2))/deta !!! elseif !!! deta=0の場合は別途処理する必要あり.2つの線分が平行な場合deta=0となる. end if !!! この時点で0<s<1, 0<t<1でなければ,交わっていないことが分かる. !!! if(s<0.d0.or.1.d0<s.or.t<0.d0.or.1.d0<t) then !!! write(*,*) "交わってない" !!! stop if(s<0.d0) then s=0.d0 elseif(1.d0<s)then s=1.d0 end if if(t<0.d0) then t=0.d0 elseif(1.d0<t)then t=1.d0 end if !!! 最短距離の計算 rr(:)=r1(:)+s*r12(:)-(r3(:)+t*r34(:)) d=sqrt(dot_product(rr,rr)) end subroutine piyo program hoge implicit none real(8) r1(3),r2(3),r3(3),r4(3),d r1(:)=(/0.d0,0.d0,0.d0/) r2(:)=(/1.d0,1.d0,1.d0/) r3(:)=(/1.d0,0.d0,0.d0/) r4(:)=(/1.d0,1.d0,0.d0/) call piyo(r1,r2,r3,r4,d) if(d<1.d-15) then write(*,*) "交わる" endif end program

Gyustab
質問者

お礼

わざわざFortranのプログラムを記述いただきありがとうございます。 本日、線分が半径を持つことが判明したため、 線分が衝突しないためには、 線分間で 半径*2 より大きい離隔距離が必要になりました そのため nineexitさんのコードを解析し、理解したく思います。 まず、 !!! 2つの直線の距離の2乗をdとする !!! d=|((r1+s*r12)-(r3+t*r34))|^2 の部分がわからず、なぜこのように定義できるのか現在ネットで調査しています。 dot_product はFortranの関数でベクトル間の内積を求めるということがわかりました、 以下のページを参考にエクセルVBAのコードに落とせるよう調べています。 http://homepage1.nifty.com/gfk/vector-naiseki.htm まだまだ時間がかかりますが少しづつコードを解析していきます。

Gyustab
質問者

補足

質問者のGyustabです。 以下3点質問させてください。 (1)!!! 2つの直線の距離の2乗をdとする  !!! d=|((r1+s*r12)-(r3+t*r34))|^2  !!! dの最小値を求める  の部分について   線分r1r2上の点を(r1+s*r12)  線分r3r4上の点を(r3+t*r34) とすると    2点間の距離は  sqrt( ( (r3+t*r34)-(r1+s*r12) )^2 ) ⇒ (r3+t*r34)-(r1+s*r12) となり  距離の2乗は ((r3+t*r34)-(r1+s*r12))^2 となるという理解で良いでしょうか? (2)距離の2乗をdとしているのは、  s,tについて微分出来る形にするためわざと2乗していると考えれば良いですか? (3) a(1,1)=dot_product(r12,r12)   a(2,1)=-dot_product(r12,r34)   a(1,2)=a(2,1)   a(2,2)=dot_product(r34,r34)   b(1)=-dot_product(r12,r1)+dot_product(r12,r3)   b(2)=dot_product(r34,r1)-dot_product(r34,r3)   deta=a(1,1)*a(2,2)-a(1,2)*a(2,1)      上記数式がわかりません、   一連の流れは内積を使って何を計算しているのでしょうか?

その他の回答 (5)

  • nineexit
  • ベストアンサー率100% (8/8)
回答No.6

> つまり、2直線間の距離の2乗であるdは、 > 2直線間の距離同士の内積と考えるということでしょうか? 2つの直線上にある"2つの点"の距離の自乗がdです. 「2直線間の距離同士の内積」ではありません. 内積は距離同士でとるものではなくベクトル同士でとるものです. 同じベクトル同士の内積を取ると長さの自乗が得られるので,内積を取っています.

Gyustab
質問者

お礼

>2つの直線上にある"2つの点"の距離の自乗がdです. >「2直線間の距離同士の内積」ではありません。 >内積は距離同士でとるものではなくベクトル同士でとるものです。 >同じベクトル同士の内積を取ると長さの自乗が得られるので,内積を取っています. ご指摘ありがとうございます、数学素人の回答ですいません、 ベクトルと距離がごちゃまぜになっていました、 ご指摘いただいた点および今まで教えていただいた点を 含めて一度ソースコードを納得できるところまでコーディングしてみます。

  • nineexit
  • ベストアンサー率100% (8/8)
回答No.5

回答に対する質問への回答です。 (1) r1, r2, r3, r4, r12, r34はベクトルです。 ベクトルa=(a1,a2,a3)の長さの自乗はa同士の内積(a・a)になります。 サブルーチンの終わりに rr(:)=r1(:)+s*r12(:)-(r3(:)+t*r34(:)) d=sqrt(dot_product(rr,rr)) とありますが、これが長さの自乗を計算しているところです。 (2) 微分しやすいように自乗しています。 2直線上の点の距離の最小値を求めるためには、2直線上の点の距離の自乗の最小値を求めればよいので、このようなことをしています。 最後に最短距離を算出するときは、きちんとルートを取っています。 (3) !!! r12・r12 s - r12・r34 t = -r12・r1 +r12・r3 !!! -r34・r12 s + r34・r34 t = r34・r1 -r34・r3 を行列A、ベクトルbを用いて表記しました。 Ax=bの形でxはsとtからなるベクトルです。x=(s,t) detaは行列A行列式です。 ただの連立一次方程式なので、行列やベクトルを持ち出す必要はありません。

Gyustab
質問者

お礼

返答ありがとうございます。 >ベクトルa=(a1,a2,a3)の長さの自乗はa同士の内積(a・a)になります。 つまり、2直線間の距離の2乗であるdは、 2直線間の距離同士の内積と考えるということでしょうか? >d=sqrt(dot_product(rr,rr)) >とありますが、これが長さの自乗を計算しているところです。 ベクトルa=(a1,a2,a3)の長さの自乗はa同士の内積(a・a)ということなので、 dot_product(rr,rr)はベクトルrrの長さの2乗と同じ意味ですね、 ということはベクトルrr同士の内積の平方根を求めるとベクトルrrの長さが出てくるという事ですね >微分しやすいように自乗しています。 >2直線上の点の距離の最小値を求めるためには、 >2直線上の点の距離の自乗の最小値を求めればよいので、このようなことをしています。 >最後に最短距離を算出するときは、きちんとルートを取っています。 とてもわかりやすかったです、 紙上に数式を記述し、展開してs,tに対して微分したところ、 sとtについてまとめた数式まで辿り着けました。

  • nag0720
  • ベストアンサー率58% (1093/1860)
回答No.3

#1です。 >下記4つの数式の条件を満たすのは4点の座標の値が整数の場合のみでしょうか? >座標の値が単精度浮動小数点や倍精度浮動小数点の場合は有効桁数の範囲内であれば成立しますか? 数学的には、実数の範囲で成立します。 コンピュータで単精度、倍精度で計算する場合は当然有効桁数の問題がでてきます。 特に、減算で有効桁数が桁落ちする可能性がでてくるので、十分考慮する必要があります。 前回の回答で、最初に「コードを書くのは面倒」と書いたのはそういう意味です。悪しからず。

Gyustab
質問者

お礼

ご返答いただきありがとうございます。 >前回の回答で、最初に「コードを書くのは面倒」と書いたのはそういう意味です。 >悪しからず。 いえいえ、疑問に対する答えがわかっただけで助かりました。 明日、会社にて数式の許容誤差や 計算上の有効桁数の桁落ちをどのようにすれば良いかを熟考してみます。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.2

学校の宿題か何かの回答をここに丸投げ質問してないですか。そういうのは先般の大学入試問題にでも批判を浴びたはず。 もしそうなら、授業で先生に教えてもらえるのではないですか。それをここで教えるのは授業妨害とも言える。 Googleででも「空間 2直線 交点座標 」などで照会すれば記事はある。 ベクトルや行列の知識が必要な記事が多いが。そういうのは理解できるのか。 http://www.teu.ac.jp/aqua/GS/text/PDF/3DMath.pdf

Gyustab
質問者

お礼

>学校の宿題か何かの回答をここに丸投げ質問してないですか。そういうのは先般の大学入試問題にでも>批判を浴びたはず。 >もしそうなら、授業で先生に教えてもらえるのではないですか。それをここで教えるのは授業妨害とも>言える。 いいえ違います社会人です、仕事上必要であったため質問しました、 教えてくれる先生などいませんし、授業を妨害している暇はありません。 >Googleででも「空間 2直線 交点座標 」などで照会すれば記事はある。 「線分 交点 3次元」、「直線 衝突判定 3次元」、「直線 交点 サンプルプログラム」等で 検索しましたが、概念はたくさんあっても私の解読できるC言語・VisualBasic・Fortran・javaのソースが発見できなかったためここに質問しました。 客先にはエクセルで提供するのでDirectXやOpenGLのようなライブラリを要するものは使用したくないのです。 >ベクトルや行列の知識が必要な記事が多いが。そういうのは理解できるのか。 数学者でも教師でも数値解析エンジニアでもないのでベクトルや行列について1~100まで 理解する気はありません、客先の仕様を満たすために必要な概念と考え方、 ソースコードへ落とす事が必要なだけです。 以上、なにか返答があればどうぞ

  • nag0720
  • ベストアンサー率58% (1093/1860)
回答No.1

コードを書くのは面倒なので考え方だけ。 x12=x2-x1、y12=y2-y1、z12=z2-z1、 x34=x4-x3、y34=y4-y3、z34=z4-z3とすると、 線分AB上の点は(x1+s*x12, y1+s*y12, z1+s*z12) (0≦s≦1) 線分CD上の点は(x3+t*x34, y3+t*y34, z3+t*z34) (0≦t≦1) と表現できます。 線分ABと線分CDが交点を持つとすると、 (1) x1+s*x12=x3+t*x34 (2) y1+s*y12=y3+t*y34 (3) z1+s*z12=z3+t*z34 が成り立ちます。 (1),(2)式からs,tを求めると、 s=((x3-x1)*y34-x34*(y3-y1))/(x12*y34-x34*y12) t=((x1-x3)*y12-x12*(y1-y3))/(x34*y12-x12*y34) このS,tが0≦s≦1 , 0≦t≦1 の条件を満たし、かつ、 このs,tを(3)式に代入して等号が成立するときに交点を持ちます。 あとは、これをコードにすればいいだけです。 補足 x12*y34=x34*y12 の場合、2直線は、同じか、並行か、ねじれ位置にあるので交差していないことになります。

Gyustab
質問者

お礼

返信ありがとうございます、以下の部分が大変助かりました。 s=((x3-x1)*y34-x34*(y3-y1))/(x12*y34-x34*y12) t=((x1-x3)*y12-x12*(y1-y3))/(x34*y12-x12*y34) さまざまなホームページで紹介されている概念の通りにやれば紙の上では解けるのですが、 どうやって2線分の交点をソースコードに落とせば良いかで四苦八苦しておりました。 今よりコーディングしてみます。 補足もありがとうございます、この部分も条件に組み込みます。

Gyustab
質問者

補足

質問者のGyustabです。 コーディング中疑問に思ったため再度質問させてください。 下記4つの数式の条件を満たすのは4点の座標の値が整数の場合のみでしょうか? 座標の値が単精度浮動小数点や倍精度浮動小数点の場合は有効桁数の範囲内であれば成立しますか? 成立しないのであれば (x12*y34)/(x34*y12)≒1.00000 のように限りなく1に近づく誤差を 計算したり、s=・・・・やt=・・・の式の乗算・除算の順番を考え有効桁数の 精度を考慮した計算をする必要があるのではないかと思っています。 数式1:s=((x3-x1)*y34-x34*(y3-y1))/(x12*y34-x34*y12) 数式2:t=((x1-x3)*y12-x12*(y1-y3))/(x34*y12-x12*y34) 数式3:z1+s*z12=z3+t*z34 数式4:x12*y34=x34*y12

関連するQ&A

  • 直線の交点の座標です

    よろしくお願いします。 問題 2直線y=x-2、y=-2x+7の交点の座標を求めなさい。

  • 点と直線

    xy平面上に3点A(-5、-1)、B(2,13)、C(6,1)がある。 (1)∠ABCの大きさを求めよ。 (2)∠BACの二等分線と線分BCとの交点Dの座標を求めよ。 私が求めた所AB=7√5、BC=4√10、CA=5√5になったのですが、三平方の定理を使ってみるときれいな直角三角形にならないですよね? (2)はまず、線分ABとACの方程式を求めました。そして∠BAC上にある点を(X、Y)とおいて、(X、Y)と2直線の距離が等しいという事を使って解いていきました。が、途中で混乱してしまいました。 もっと簡単な解き方があれば教えて下さい。

  • 2直線の交点

    まず、 交わる2直線 a1x+b1y+c1=0-(1) a2x+b2y+c2=0-(2) について、a1x+b1y+c1+k(a2x+b2y+c2)=0-(3) は(1)と(2)の交点を通る直線を表す。 これは、どうやって証明するのでしょうか? また、式自体、よく意味がわかりません、どういうことなのでしょうか?

  • 2直線の交点 

    2直線X+2y-3=0、2X-3y+8=0の交点と点(1、-1)を通る直線の方程式を求めよ。 私の考え方  まず連立方程式で2つの式を解いて二直線の交点の座標は(-1、2)であって(1、-1)をとおるから  y+1= -2分の3(x+1)であってる?でこのあとの回答が導き出せません。このあとどんな計算をすればよいのですか?     

  • 3次元での回転による座標変換

    3次元での回転による座標変換に関して質問があります. X軸,Y軸,Z軸の直交座標系があるとします. この座標系において,ある位置ベクトル(a1,b1,c1)がX軸,Y軸,Z軸と成す角度は,θx,θy,θzは,ベクトルの内積から算出可能だと思います. θx=a1/sqrt(a1^2+b1^2+c1^2) θy=b1/sqrt(a1^2+b1^2+c1^2) θz=c1/sqrt(a1^2+b1^2+c1^2) X,Y,Zの直交座標系を回転させて,この位置ベクトルの向きを基準としたX'軸,Y'軸,Z'軸による新しい直交座標系を設定するには,どのようにすればよいでしょうか? θx,θy,θzと各軸での回転角度は違うものという認識でいいのでしょうか? 元の座標系において,各軸回りに順番に回転させればいいかと思うのですが,どうもイメージがつかみきれません. よろしくお願い致します.

  • 3次元空間中の2つの円の交点の求め方

    3次元空間において、2つの円の各中心座標(x,y,z)、各法線ベクトルおよび各半径が分かっているときに、これらの円が作る交点(x,y,z)を求める方法を教えてください。できれば、交点がいくつ存在するかを示す判別式もお願いします。

  • 3次元空間での2直線の交点の求め方

    悩んでおります.御力添えを願います. 以下の条件下にて,2つの直線式を求め,その交点を求めようとしております. 1.点p(a0,b0,c0)と点q(a1,b1,c1)の座標は既知. 2.点s(d,e,f)は,座標は未知であるが,点p,点qへ向けて2つの直線を延ばしており,それぞれの直線の傾きが既知. 以上の条件をもとに,点s(d,e,f)の座標を求めようとしています. 私の考えた手法は,以下の物ですが上手くいきません. 1.点sから伸びる2つの直線の方向余弦を求める. 例)vx = r * cosα,vy = r * cosβ, vz = r * cosγ (上記の様に2点へと伸びる直線の方向余弦をそれぞれ求める) 2.求めた方向余弦と,点p,点qを用いて2つの直線式を表す. 例)x = a0 + vx0 * t, y = b0 + vy0 * t, z = c0 + vz0 * t x = a1 + vx1 * s, y = b1 + vy1 * s, z = c1 + vz1 * s    3.誤差を考慮し,2直線間の距離が1番小さくなる2点を求める. 例)(距離)^2 = {a0 + vx0 * t - a1 - vx1 * s}^2 = {b0 + vy0 * t - b1 - vy1 * s}^2 = {c0 + vz0 * t - c1 - vz1 * s}^2     上記の式をs,tに関して偏微分してやり,それぞれを0として連立 方程式を解き,s,tを求める.   求めたs,tを各直線式に代入してやり,2直線間の距離が最も短く なる2点を求める. 4.その2点の線分上の中点を求め,点s(d,e,f)とする. 上記手法で求めようとしましたが,どうも点sの座標が求まりません. 点sで方向余弦を求めるのが駄目なのでしょうか? 2直線間の距離が最も短くなる2点の求め方が駄目なのでしょうか? 幾何学初心者なため,混乱しております. 宜しくお願いいたします.

  • 三次元直線が交点を持たない条件

    x1,y1,z1を通るベクトル(a1,b1,c1)を持つ直線と x2,y2,z2を通るベクトル(a2,b2,c2)を持つ直線が 交わらない条件を教えてください

  • 3次元座標の求め方

    3次元座標の求め方 原点 0,0,0 を中心にした球体面上の正面から見た頂点座標で、 回転による移動後の座標の求め方を知りたいです。 例えば、球面の半径が 100 で、頂点の座標 x1, y1, z1 が 100, 0, 0 にある場合、 Y軸に対してπ/2 rad (90度)回転した座標 x2, y2, z2 は 0, 0, -100 になると思うのですが、 この新たな3つの座標 x2, y2, z2 を導くにはどのように計算しているのでしょうか。 平面上の円運動のように cos sin の組み合わせ等で導き出せるのでしょうか。 x1, y1, z1 から、 Y軸に対してr回転 した場合の各 x2, y2, z3 の出し方 X軸に対してθ回転 した場合の各 x3, y3, z3の出し方 Z軸に対してΘ回転 した場合の各 x4, y4, z4 の出し方 のような形で、導くための計算を順にお教えいただけると嬉しいです。 最終的には、元座標 x, y, z をY軸にr、更にそこからX軸にθ、更にそこからZ軸にΘで X, Y, Z になる、といった形で求められるようになりたいと思っています。 座標は原点 0, 0, 0を中心に 上に行くほどYが「減少」 右に行くほどXが「増加」 奥に行くほどZが「増加」 Y減少 ↑ _ Z増加 │/` ├─→ X増加 という形になっています 自分のわかる限りで質問内容を細かく記述したつもりですが、 数学の知識に乏しいので、記号などの使い方や説明の不備があるかもしれません。 何か不足があった場合には補足させて頂きます。 以上宜しくお願い致します。

  • 各座標軸との交点についての質問

    座標の問題についての質問 平面x+4y+8z=6について (1)各座標軸との交点の座標を求めよ 解答(6,0,0)(0,3/2,0),(0,0,3/4) (2)原点から平面上の点までの距離の最小値を求めよ 解答2/3 (3)この平面のx≧0、y≧0、z≧0である部分の面積を求めよ 解答81/16 という問題が答えは分かるのですがいまいち解き方など分からないところがあります どなたかお教えくださるとありがたいです

専門家に質問してみよう