• ベストアンサー

ある形式で与えられる空間中の2直線間の距離・中点を求めたいのですが

「空間中の2直線間に、共通垂線を一本引いて、垂線が各直線に対して持つ二つの足の間の距離(---1)と、二つの足の間の中点の位置(---2)」を、求めたいのですが、どのようにするのでしょうか.  直線は、"平面xy座標上の一点aを通り、かつ、方位角bと仰角cとで定まる方向"という形式で与えられるのです. 最終目標としては、空間中にいろいろと与えられる二直線について、冒頭の「」を求めるプログラムを書きたいのです. また、冒頭の「」内のことは、捩れの位置で始めて成立するわけですが、交わるのか捩れの位置なのかを、プログラムでもって、簡単に識別する方法ってあるのでしょうか? このあたりの領域に詳しい方、どうぞ教えてください.

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

  • ベストアンサー
回答No.1

ベクトルを考えると考えやすいです。 まず、2直線をA,Bとし、それぞれの単位方向ベクトルをa^b^します。 (方位角と仰角からすぐにだせます) また、xy座標平面上で、直線Aの交点 Aa から直線Bの交点 Ba に引いたベクトルをc_ 置きます。(ちょっと分かりにくいですが、x^ は単位ベクトル、x_ はベクトルを表すとします) また垂線に平行な単位ベクトルをn^ と置き、2直線の距離(足の間の距離)をd と置きます。 すると  n^⊥x^, n^⊥y^  (1) n^ = x^ × y^ (外積) (2) としよてく、また、α、βを直線A,B上で足の位置を表すパラメータとして α x^ + d n^ = c_ + β y^ (3) が成立します。この式の両辺似たいしてn^ との内積をとり、(1)とn^ の大きさは1であることに注意すると求める距離d は  d = c_・n~  と簡単に求まります。 また、(3)式からx^ と内積をとった式、y^ と内積をとった式、を作るなどしてαを求めます。 直線A のxy平面上の点Aa に引いた位置ベクトルをe_ で表せば、中点の位置は  e_ + α x^ + (d / 2) n^ で表されます。 このやり方で求めたとき、交わるときには  d = 0 を与え、特別にチェックする必要は無いです。 むしろ特別な配慮が必要なのは2直線の平行度で、平行な時には上の量は本当に数学的にも定義できなくなります。 平行に近いとき(厳密に平行でなくても)、プログラム上では非常に誤差が大きくなりますので、適当に誤差を見積もり、評価してやる必要があります。 (x^ と y^ の内積をとって平行度を調べるなどして)

finetoothcomb
質問者

お礼

ありがとうございます.最初はわからなかったのですが、解ったらすごく簡単に書けることに驚きました.以下のように、自分なりに、まとめてみたのですが、あっているでしょうか. ------------------------------------------------------------------------------------- 直線Aとxy平面との交点 a_=(ax, ay, az) 直線Aの方位角 θa 直線Aの仰角 φa 直線Bとxy平面との交点 b_=(bx, by, bz) 直線Bの方位角 θb 直線Bの仰角 φb とすると、上記の値だけを使って、以下の左辺の値は、右辺のように書くことができる. 直線Aの単位ベクトル a^=(cos(θa)cos(φa), sin(θa)cos(φa), sin(φa)) 直線Bの単位ベクトル b^=(cos(θb)cos(φb), sin(θb)cos(φb), sin(φb)) 共通垂線の単位ベクトル n^=a^×b^ 共通垂線の足間距離 d= (b_-a_)・(a^×b^) [=即ち直線間距離]  = (b_-a_)・n^ 共通垂線足間中点位置 m_=a_ + α a^ + (d/2) n^ [即ち直線間中点]    =a_ + α a^ + (1/2){(b_-a_)・(a^xb^)}・(a^×b^) 但し α=[{a^・(b_-a_)}-{b^・(b_-a_)*(a^・b^)}]/{1-(a^・b^)(a^・b^)} (但しa^・b^=1でない時) -------------------------------------------------------------------------------------

その他の回答 (4)

  • ametsuchi
  • ベストアンサー率31% (81/257)
回答No.5

くどいですが、もう一つ補足。 2直線の外積を求めるやり方でも、私流のやり方でもコストは変わらんと言いましたが、実際に計算してみると、私流のやり方の方がコストが安いと分かりました。 直線上のパラメータt0,t1、v0,v1:直線の方向(単位ベクトル)、p0,p1:通過点とすると、直線上の点は P0(t)=p0+t0*v0 P1(t)=p1+t1*v1 1) 2直線を通過する2点の差分ベクトル:p01=p0-p1 2) 内積 s01=v0・v1 3) 内積 s0 =v0・p01 4) 内積 s1 =v1・p01 として、 5) det=s01^2 – 1.0 6) t0 = (-s0 + s01*s1) / det 7) t1 = ( s1 - s01*s0) / det 直線上のパラメータt0,t1が求まります。ここまでで、乗除算:11回、加減算:10回。 一方、外積を取るやり方だと、外積計算だけで、乗除算:12回、加減算:3回。その後、正規化するわけですが、掛け算3回、足し算2回、それに、sqrt()という四則演算に比べてズッとコストのかかる計算をしなくてはならないのです。 しかし、球座標で持つようだと、複数回の三角関数の計算に更に時間を要するので結局どちらでも大差なくなってしまいます。

finetoothcomb
質問者

お礼

皆さんありがとうございました.ポイントですが、お二人に同じく20ポイントx10をつけたいぐらいです.特にametsuchiさんの各論の回答はものすごく重要です.今後ともどうぞよろしくお願い致します.

  • ametsuchi
  • ベストアンサー率31% (81/257)
回答No.4

hogehogeninjaさんの訂正もあったのでお任せしとこうと思いましたが、finetoothcombさんから質問が出てきたので再びシャシャリでてきました。 1)「別方法」: 私は「コストのかかる計算」は嫌いで、外積よりも内積計算を好みます。外積を使って計算時間やコーディングステップ数が減る場合に限って外積を使います。 今の問題の場合、hogehogeninjaさんの言われるように、題意を充たす時、  n^⊥x^, n^⊥y^  (1) だから n・x^=0、 n・y^=0 (1’)  です。x^、y^はGiven。「n」は、線上の2パラメータ:α、βに依存しますが、(1’)の条件を課すと、α、βに関する2元一次の連立方程式が得られます。 と言っちゃうと非常にシチメンドクサイことのようですが、紙の上で整理・計算するととても簡単な形になります。 ただ、実質的には、同じ計算量で、外積を使ったからコストがよりかかるという訳ではない(はず)です。ですから、気にしないで下さい。finetoothcombさんにとって分かり易い方を選択してください。 2)「この演算を実行する前段階に、|n_|=0...」 その通りです。2ベクトルの内積による検査を省き、この分母が0に近いかどうかを見ればよいのです。そうすればあとはゼロ割や精度の低下を気にしないでいいです。 ただ、その判定基準、「閾値」だの「トレランス」だのと言いますが、それが実は問題なのです。0割を防ぐだけなら、Cのヘッダファイル("float.h")に入っている「FLT_EPSILON」、または「DBL_EPSILON」でもいいのですが、場合によってはもっと大きい数値になる場合もあります。最下層のライブラリとしては、 a)引数として外に出すこと。(=呼び出し側から値を与える) b)全体として、矛盾を生じないように、「距離」、「角度」など明確な「単位」を持たせることが望ましい。「角度」はコストのかかる計算になりがちなので、正規化したベクトル同士の「内積値」を使う場合がある。 今回の場合、「ベクトル同士の内積値評価は無駄」と言いましたが、それに相当するように、εを手計算で決めておけばいいのです。 上位側、即ちライブラリを使う側を含めてシステム全体で、「ゼロ割りを起こさないよう」気を付けているだけでは、矛盾をきたします。この辺は10分20分で語り尽くせないところなので、省略します。 3)「幾何計算ライブラリ」の目的・利点: 仰せのとおり、「速度向上でなく、再利用性の向上」のためです。処理速度は一般的には遅くなります。 「再利用性の向上」は、広い意味で言われているのだと思いますが、 a)開発工数の減少 b)障害発生頻度の減少 c)メンテナンスのし易さ d)慣れた人がライブラリを開発することにより、品質や、性能(「処理速度」も)が向上 e)後で全く別のシステムに再利用(=狭義の「再利用性」) とメリットは限りなくあります。 4)(開発)環境: Borland C+ 5.5.1 だろうが、VC++だろうが、基本は同じです。AnsiのC++で書けばいいのではないでしょうか? 私は20年以上各種の幾何計算ライブラリの開発に関わってきましたが、基本は、 ■処理系に依存しない ■なるべく保守的に書く ということです。それでも、ここ20年の間になるべく保守的に選んだ言語ですら、 ・Fortran4 ・Fortran77 ・C(K&R) ・AnsiC ・AnsiC++(VC++だが..) と変わりました。しかし、上の思想で作っておくと、DOSだろうと、UNIXだろうと、問題なく動きます。一昨年通信会社向けに作ったライブラリもSGIと、PCで問題なく動いています。 しかし去年別の用途で作ったものは心ならずも、 ・MFC を使っています。これだと、SGIやSunなどのEWSに持って行けないです。初めからターゲットマシンが限定されていましたし...。 5)三角関数利用について: 今の持ち方だと、 ・直線の通る位置は直交座標 ・直線の方向は球座標 という変則的な持ち方ですよね?私の経験では、「球座標」は、 a)地球上での位置(緯度・経度) b)飛行機や自由に3D空間を動くカメラなどの向きを「Euler角」で表現 くらいしか扱ったことがなく、今回の例のように2つの線が「球座標」原点を通る保証がなく一般の捩れの位置にあるというのを大変奇異に感じています。 「球座標」である合理性がなく、基本的に「直交座標」である場合、私の限られた経験では、直線は、 ・直線が通る位置(1点) ・直線の方向(単位ベクトル) で表わすのが普通、というか多かったです。 基本的に「直交座標」でも、カメラ(または「視点」)などを回転させたりするなら、角度や角度を使った三角関数の計算は避けられません。しかし、内部的なデータの持ち方としては、直交座標だけで十分だと私は思います。回転などが加わった場合だけ、座標変換すればいいのです。 三角関数に限定するなら「テーブル云々」は「労多くして益少なし」だと思います。気が付かれているように、角度は任意ですから、補間などしなくてはなりませんから...。

finetoothcomb
質問者

お礼

ありがとうございます.経験のある詳しい人に意見を貰うと、ほんと役立つなぁ、と思いました. >1)「別方法」: 「"内積"のみ使用して攻める方針は、コスト面で事実上の利がある.例外的な高コスト関数(三角関数等)が並存するなら意味がなくなるかもしれぬが(No.4のご説明)」と理解しました.ものすごく役立ちます.ありがとうございました.なにか、思いつかれるヒントがまた発生されましたら、追加補足していただけましたら幸いです. >2)「この演算を実行する前段階に、|n_|=0...」 >その通りです。… "float.h"の、FLT_EPSILON, DBL_EPSILONは初耳でした.あー、すごいなぁ. この***_EPSILONを使わしていただこうと思います.あと(2)の後半のご説明は経験に裏打ちされた深い知識に見えて、簡単には理解しきれなかったのでも少し時間をかけて読もうと思います.コメントありがとうございます. >3)「幾何計算ライブラリ」の目的・利点: >処理速度は一般的には遅くなります。 え、そうだったんですか.知らなかったです.意外でした. > …とメリットは限りなくあります。 こ、これはすごい.なるほど~、かなりメリットですね. >4)(開発)環境: >■処理系に依存しない >■なるべく保守的に書く なるほど.原則このようにする、といろいろ困ったことも起こらず良いいわけですね.あと、MFCだと移植があまりよろしくないという事実は、とても役立ちます.必要に迫られなければ特に使わないようにしようと思いました. >5)三角関数利用について: >…今回の例のように2つの線が「球座標」原点を通る保証がなく一般の捩れの位置にあるというのを大変奇異に感じています。 うーん、これは実に嬉しいご指摘です.なぜなら、「奇異なのか、今私が取り組もうとしている(私が自分に課した)課題は」と解るようになれたからです.現状認識を正しくもてることは、ある意味で、励みになります.特にこのあたりのご指摘はものすごく参考になりました. いろいろありがとうございます.

回答No.3

ametsuchiさんのおっしゃるとおり、  n^ は x^ × y^ ではなくて、外積を正規化したものです。 このままやると正しい答えになりません。 finetoothcombさんもつられてしまって n^=a^×b^ と書いてしまっていますが、  n_=x^×y^  n^=n_/|n_| と訂正させてください。

finetoothcomb
質問者

お礼

ありがとうございます.なにしろ知らないことが多いので、なるほど、忘れることがあるから気をつけるべき事なんですね、と、今後に役に立つようで、ありがたい事と感じます.

  • ametsuchi
  • ベストアンサー率31% (81/257)
回答No.2

hogehogeninjaさんの答えも的確だし、finetoothcombさんもチャンと理解しているようだから、横から口出すのも何ですが...。 1)hogehogeninjaさんの言われる「n^ = x^ × y^ (外積)(2)」の右辺は単位ベクトルとは限らないので、正規化しなくてはなりません。「n^」はそのつもりで書かれたと思うのですが、finetoothcombさん気を付けてください。私は別の方法をよく使いますが、この方法でも計算量は基本的に同じです。 2)hogehogeninjaさんが、「特別な配慮が必要なのは2直線の平行度云々」はとても大事なことです。幾何計算ライブラリやCADシステムを構築する時、一番厄介なのがこの辺です。ただし、「x^ と y^ の内積をとって平行度を調べる」までもなく、(2)で外積計算をして正規化しなくてはならないので、この際自然に検査が必要になります。だから、このやり方なら、「x^ と y^ の内積をとって平行度を調べ」るのは2度手間です。 3)問題自体、「方位角」、「仰角」になっているのでやむをえないのですが、これには三角関数計算が必要です。三角関数はコストの高い計算で、なるべくなら使わない方がよいです。(この場合は仕方ないです!!!)

finetoothcomb
質問者

お礼

ありがとうございます. 有益なコメントに感謝感激です. いろいろな方に方向性の正しさを追認してもらえる、ということにもなり、このジャンルに疎い私としては、ありがたいです. 1-1)外積は正規化が必要なのですね. 気をつけます. 1-2)「別の方法を良く使います(計算量は基本的に同じ)」というのを、お教えいただけたら、とてもありがたいのですが.(どうしても知りたいという訳ではなく、できれば知っておきたいというぐらいなので、もしお時間がありましたらという感じですが.) 2-1)No.3で hogehogeninjaさんが訂正として書いてくださった、n^=n_/|n_|の分母部分ですね.この演算を実行する前段階に、|n_|=0(あるいは、ある小さい値εとして |n_|<ε)かどうかを検査し、もし、それがTRUEなら、平行と見て、処理は中断(というか例外処理)する…という理解をしたのですが、もし間違っていましたら教えてください. 2-2)「幾何計算ライブラリ(やCADシステム)を構築」した経験・知識がなく(やり方が解らない)、Cでべたべたっとプログラムを組むつもりです. 「幾何計算ライブラリ」というのを構築する利点は、速度向上でなく、再利用性の向上というイメージ的理解なのですが、もし間違っていたら教えてくださると幸いです. 使うCの処理系は、DOS上で動くフリーソフトであるところの、Borland C+ 5.5.1 (bcc32.exe)というものを使っているので、それを使う予定です. これで(仮に余裕があれば経験を積むために)幾何計算ライブラリを構築することはできるのかな.普通どのようにするのでしょうか. 3)そうでした.重要なことを忘れていました.ありがとうございます.コストが高い=計算が遅い、ってことですよね. プログラムを作った後で、結構大量の計算をする予定です.高速化のためのなんか良い作戦がないでしょうか. 値は0≦θ<2π, 0<φ<π/2をとり得るのですが. 一般論としては、高頻度の値については結果の表(テーブル)を用意する作戦がある、と聞いたことがあります.しかし、あらゆる値をとりうる場合には、あまり効果がなさそうです.普通に三角関数入りのプログラムを組むしか仕方ないとは思っています.なにかワザが有りましたら教えていただけましたら幸いです.

関連するQ&A

  • 平面決定とねじれの定義について

      今空間図形をやっていますが、平面決定とねじれの位置について疑問が生じました。   平面の決定条件の一つに、「ねじれの位置でない2直線が与えられたとき」がありますが、一方ねじれの位置にある2直線の定義は、「同一平面上にない2直線」になっています。これでは循環証明になっているのではないかと思います。   数学に詳しい方、難しい数学を使ってもいいので、教えてください。

  • 数学の質問! 直線と中点

    〔問題〕 xyz空間においてP(1,0,3)、Q(3,2,1)がある。 この時、直線PQを軸にして、X(4,0,5)を180度回転したとき、移動後の点の座標を求めよ。 2直線の中点が一致すればいいのですが、どうも合いません。 どこがおかしいんでしょうか? >>P(1,0,3),Q(3,2,1),X(4,0,5) 求める点の座標をY(a,b,c) (1+3)/2=(4+a)/2 (0+2)/2=(0+b)/2 (3+1)/2=(5+c)/2 よって、 a=0 b=2 c=-1 Y(0,2,-1) で→PQ・→XY=0 となるはずなんですが、ならないんです。。。 教えてください!!

  • 空間座標 球面上の点と空間にある点の距離について

    空間座標において 「『球面上の点と空間にある点P』との(最短)距離」は球面中心と点Pを結んだ距離と球面の半径と差で求めると思うのですが、感覚的にはわかる気がしますし、平面座標だと分かりますが、空間座標になると本当にそうなのかと思ってしまいます。式で証明することができるのでしょうか。 また、「『球面上の点と直線の点』との距離」や「『球面上の点と平面の点』との距離」も同じように球面の半径から直線の点もしくは平面の点に垂線を下ろして考えるのでしょうか。

  • 原点で交わる2直線A、Bがあり、直線AはXZ平面上にあってX軸と15度

    原点で交わる2直線A、Bがあり、直線AはXZ平面上にあってX軸と15度をなしており、直線BはXZ平面をZ軸を軸に(反時計方向に)60度回転させた平面上にあってXY平面と20度をなしているとき、2直線によって定義される平面に、Z軸上の任意の点から引かれた垂線とZ軸のなす角度を求めたいのですが・・・。なお。実際には文章中の15度と20度の2つの数値は無理数に置き換えるので、d1、d2という2つの変数を用いた式の形になっていれば充分です。なにやら法線ベクトルという考え方をするらしいのですが、垂線がXY平面に投影された角度については必要ありません。Z軸と垂線とによって定義される平面におけるZ軸と垂線のなす角度がわからないのですが・・・。

  • 空間図形のもんだいです。

    座標空間内に4点P(3,1,4,),A(1,2,3),B(1,1,2),C(2,1,1)がある。直線PAとxy平面の交点をA‘、直線PBとxy平面の交点をB‘、直線とxy平面の交点をC‘とする。 (1)三角形ABCの面積を求めよ。 (2)三角形A‘B‘C‘の面積を求めよ。  この問題をといてくれませんか、よろしくお願いします。

  • 空間内で平面がただ1つに決定されるもの?:中学1年

    以下、よろしくお願いします。 <問題> 次の中から、空間内で平面がただ1つに決定されるものを全て選び、記号で答えなさい。 <選択肢> ア:1つの直線を含む平面。 イ:平行な2直線を含む平面。 ウ:平行な3直線を含む平面。 エ:交わる2直線と他の1直線を含む平面。 オ:1直線上にない3点を含む平面。 カ:交わる2直線を含む平面。 キ:ねじれの位置にある2直線を含む平面。 ク:1直線上にない4点を含む平面。 ケ:1つの直線と、その直線状にない1点を含む平面。 <解答> イ、オ、カ、ケ <疑問点> 解答は概ね理解できますが、なぜ、「ウ、エ、ク」は駄目なのでしょうか?

  • 直線

    xy平面上の4点O(0,0)、A(2,0)、B(-1,0)、P(x,y)(y>0)に対して∠OBP=45゜かつPで直線BPに立てた垂線は∠OPAを二等分するという条件が成り立っているときxとyを求めよ 直線BPがy=x+1ということ以外わかりません 解き方を教えてください

  • 空間(長いです)

    「空間において、定点O,Aがあり、 FはOAの中点を中心とする半径1の球面である。 2点X1,X2をF上に取る時、4点O,A,X1,X2を頂点とする四面体の 体積の最大値を求めよ」 という問題で、(全部書くと長くなるので質問したい所だけ書くと) 『直径OAをx軸上に置き、△OX1Aをxy平面上に取る。 原点をO'として、O(1,0,0),A(-1,0,0)とする。 点X2からxy平面に降ろした垂線の足をHとし、O'Hとx軸の正方向とのなす角をβ、O'X2とz軸の正方向とのなす角をθとすると X2(sinθcosβ,sinθsinβ,cosθ)となる』 とあるのですが、 どうしてX2座標のx座標とy座標はsinθが掛かってるんですか? また、Hの座標は(cosβ,sinβ,0)でOKですか? 回答よろしくお願いします。

  • 空間ベクトルに関する質問

    平面ですと、平行でない2つのベクトルがあったとき、そのベクトル同士のなす角が一意に決まりますが、空間ですと、 (同じく平行でないとき)でもベクトル同士が交わる場合もあれば、ねじれの位置になる場合もあるので、そのなす角とは、どう考えたらよいのでしょう? ベクトルの定義のところで、ベクトルは平行移動してもよいとなっています。 空間ベクトルでも、ねじれの位置にある2つのベクトルを、平行移動して始点を原点に移動して、そのなす角を考えても良いのでしょうか? よろしくお願いします。

  • 高校数学Aのねじれの位置に関する証明について

    「空間内に4点A,B,C,Dがあって、2直線AB,CDがねじれの位置にあれば、2直線AD,BCもねじれの位置にあることを証明せよ」と言う問題で、 模範解答では、「2直線AB,CDがねじれの位置にあるとき、2直線AD,BCもねじれの位置にないと仮定すると・・・」と、 背理法の流れで証明します。 しかしこれを、背理法を使わずに 「2直線AB,CDがねじれの位置にあれば、4点A,B,C,Dが同一平面上にない。とういうことは2直線AD,BCもねじれの位置にあると言える」 という証明法は 何か問題があるから模範解答は背理法を使ってるんだと思うんですが、 その「問題」がなんなのか分からないので教えてください。