• 締切済み

ある点がモデルに内包されるかどうかの判別

プログラミングカテゴリに投稿しようか迷ういましたがこちらに投稿させていただきます。 やりたいのは、3D空間で一つのベクトルによって表現されるある点が、三角形のメッシュの集合としてあらわされるある閉じたモデル(要は一般的な3Dモデルデータのことですが)の内部にあるか外部にあるかを判別するアルゴリズムがしりたいです。 その情報が載っているサイトでもいいです 英語でも構いません 一応ここでいう内部とは各面の法線ベクトルの反対方向に存在する閉じた空間のことです。 -ここから蛇足- Blenderなどの3Dモデリングツールではおなじみのboolean演算ですが、なんとなく一から作ってみようと思っていろいろ調べてみたんですが、三角形メッシュ vs 三角形メッシュ の衝突判定と交線を求めるアルゴリズムは調べてすぐ出てきたんですが、メッシュのモデル内包判定とかVertex のモデル内包判定とか調べても出たなかったので・・・ なのでぶっちゃけbooleanのアルゴリズムについて詳しく書いてあるページがあればそういう情報も大歓迎です

みんなの回答

noname#199771
noname#199771
回答No.4

プログラミングのことは全くわかりませんが、 以下のようにしたらどうでしょう? メッシュが有限個しかなくて全体で向き付け 可能な閉曲面になっていて、内部が空集合で ないとします。 点Oを1つ固定します。 十分大きな正数Rをとって、すべてのメッシュが 中心O半径Rの球Bの内部にすっぽり入るように します。 判定したい点Aを1つ固定します。 A自身がいずれかのメッシュを構成する三角形 に含まれたらそこで判定終了なのでどれにも 含まれないとしてよいです。 単位ベクトルu(uの長さが1)を1つ固定して、 U={A+tu|t≧0}を考えます。 (Aを始点とする半直線) メッシュを構成する三角形のうち、Uと共有点を もつもの全体Xを考えます。 A+tuが共有点を与えるとき、0<t<2Rなるtだけ 考えればよいです。 Xに属する三角形のうち、Uとの共有点がその 三角形の頂点または辺の上にある場合は 「uを少し動かし」て、Xに属する三角形のうち Uとの共有点があるものはすべてその三角形 の内部にもち、頂点や辺では決して共有点を もたないようにしておきます。 このときのXの個数を数えて、偶数ならAは外側、 奇数ならAは内側と判定できます。 なぜそうかというと、Uの上を点が動いていくと して、1つのメッシュを構成する三角形の内部 を突き抜けると、それは外部から内部へ突き 抜けるか内部から外部へ突き抜けるかどちら か一方だからです。球Bの外はもちろん外部 ですがAから出発してUに沿って進み、偶数回 突き抜けて球Bの外部に到達すればAは外部 だったということになりますから。 上述の説明で共有点の有無の判定と「uを少し 動かし」の部分は、テクニックが必要な気がし ます。それと、球より直方体とかのほうが扱い やすいかも。

nasumiso2022
質問者

お礼

回答ありがとうございました! なるほど・・・こんなに単純に実現できるとは思いませんでした・・・ この方法はペイントツールなんかの塗りつぶしなんかにも使われてますねそういえば 盲点でした

回答No.3

<回答No.2 すみません.ちょっと考えればこの方法は元の形が凸の時しかうまくいきませんね.勘違いでした,無視してください. ## 正四面体を考えながら読んでたので,アホな勘違いをしました ^^;

回答No.2

ここは数学カテゴリですし,実際のモデリングツールがどのようにデータを扱うのかわからないので,できるだけ抽象的に問題とその解答を書きます.加えて計算量がどれくらいになるのかもよくわからないので無視します. [概略] 3次元実ベクトル空間V上の3点 a, b, c ∈ V が―つまり三角形の頂点たちが―与えられたとき,それを含む最小の(アフィン)平面 π = π(a, b, c) が決まる.さらに各(アフィン)平面 π に対して半空間ーつまり内側― H(π) が決まる.そして点 x がモデルに内包されるとは三角形から決まる半空間たち{ H_i(π_i) ; 1 ≦ i ≦ r }の共通部分に含まれることである. [三角形の与える(アフィン)平面] ここから実際に定式化していきます.アフィン幾何学のコトバを使うのが自然だと思うので,それらを説明しながら定式化します.(といっても別に難しいことをするわけではありません.今はベクトルと違って始点と終点をもつ有向線分を扱わなければならないだけで,それを可能にするのがアフィン幾何学です.) 3点 a, b, c ∈ Vが与えられたとき,それらを含む最小の(アフィン)平面 π は平面上の点 p ∈ A と n ∈ V を用いいて次のように書けます.ただし B( ・, ・)はVの標準内積. π = π(p, n) = { p + v ∈ A ; v ∈ V, B(n, v) = 0 } ## 実装するときに,もし頂点 a, b, c が与えられているのなら p = a, n = (b - a)×(c - a) とすればよいでしょう. [三角形の内側] (アフィン)平面 π = π(p, n) が与えられたとき,その内側―つまり半空間―は次のように書けます. H = H(π) = { p + v ∈ A ; v ∈ V, B(n, v) < 0 } [モデルの内側] 以上の準備のもとに本題に取り組みます.モデルを構成する各三角形に対して半空間 H_i ( 1 ≦ i ≦ r ) が定まります.点 x ∈ A がモデルの内側にいるとは x ∈ ∩H_i が成り立つことです. アルゴリズムというには計算工夫のまったくない方法ですが,これで一応,計算機で実装することはできるのではないでしょうか.

nasumiso2022
質問者

お礼

回答ありがとうございました! ちょっと難しくて分りませんでしたが…

noname#221368
noname#221368
回答No.1

 3D領域の表面が、三角形メッシュのSurfaceで構成されるという事でいいですか?。  あなたの応用に役立つかどうかわかりませんが、また面倒臭いので自分ではコーディングした事はないですが、立体角を使用する方法はどうですか?。参考URLを揚げます。   http://hooktail.sub.jp/vectoranalysis/GaussSolidAngle/  三角形Surfaceの頂点座標を完全に把握できる場合には、上記方法はプログラミングと非常に相性が良いはずです。まぁ~難しそうな事は書いてますが、2Dで言えば次のような事です。  (1)2D領域内部の点から領域境界を全て見渡そうとし、境界上のある点から出発して同じ点に戻ったら、360°首を回す破目になった(← 死んじゃいそう(^^))。  (2)2D領域外部の点から領域境界を全て見渡そうとし、境界上のある点から出発して同じ点に戻ったら、首は同じ位置だった(← 右見て、左見て、正面向いたら回転角0°(^^))。

nasumiso2022
質問者

お礼

回答ありがとうございました! なるほど・・・内部にある場合と外部にある場合で首を回転させる角度が違うわけですね・・・ 参考になりました 試してみます!

関連するQ&A

  • 3DCGの自由落下の結果がおかしい

    Blenderを使っております。 既存のモデル(宝箱、フェンス)と立方体の自由落下のシミュレーションをしたところ、立方体は衝突の影響で転がったりと物理的に正しい動きをしたのに対し、宝箱、フェンスのモデルは落とす前の角度を保ちながらそのまま転がったりすることなく斜めに着地してしまいました。 衝突の判定はメッシュにしてあるの間違いないと思うのですが この原因は何かご教示いただけますでしょうか? 特殊な設定はしておらず 地面を作り、最初からある立方体と読み込んだばかりのモデルを上方に配置し落としたのみです。

  • N面体の各面のなす角を算出したい。

    三次元の空間に、N面体があります。 各面のなす角は0~360度で、星型のように、180度以上となる角もあります そのN面体において、隣り合う各面で成される角を算出したいのですが。。。 角度はN面体を外側から見た場合の角度と定義します。 隣り合う平面の方程式を (1) Ax+By+Cz=D (2) ax+by+cz=d と定義した場合に、 成される角は各面の法線ベクトルを用いて、 θ=arccos{(A*a+B*b+C*c)/√((A^2+B^2+C^2)*(a^2+b^2+c^2))} で算出できることが分かりました。 ただ、この式ですと結果が±θと±(180-θ)のうちどれとなるのか分かりません。 成す角が上記の4つのうち、どれなのか知る手立てはありませんか。

  • 4次元空間の4つのベクトルが張る空間が1次元、2次元、3次元、4次元である条件

    4次元空間にゼロベクトルでない4つのベクトルを考えます。 a↑=(a[1],a[2],a[3],a[4]) b↑=(b[1],b[2],b[3],b[4]) c↑=(c[1],c[2],c[3],c[4]) d↑=(d[1],d[2],d[3],d[4]) とします。 これらのベクトルで張られる空間が1次元、2次元、3次元、4次元である条件を求めたいのです。 各ベクトルを並べて行列(a↑ b↑ c↑ d↑)を作り、基本変形で階数を計算するというアルゴリズムではなく、各成分の代数的な関係を求めたいのです。 4つのベクトルで張られる空間が4次元のとき、超体積が0ではないので、行列式 |a↑ b↑ c↑ d↑|≠0 4つのベクトルで張られる空間が1次元のとき、すべて平行なので、 a↑∥b↑∥c↑∥d↑ a[1]:a[2]:a[3]:a[4]=b[1]:b[2]:b[3]:b[4]=c[1]:c[2]:c[3]:c[4]=d[1]:d[2]:d[3]:d[4] (a[1]/a[4],a[2]/a[4],a[3]/a[4])=(b[1]/b[4],b[2]/b[4],b[3]/b[4]) =(c[1]/c[4],c[2]/c[4],c[3]/c[4])=(d[1]/d[4],d[2]/d[4],d[3]/d[4]) このあと、一つの式にする、つまり、イコールを一つだけにしてきたいのですが、複雑そうです。行列式またはシグマ記号を使って、表記できないでしょうか? 4つのベクトルで張られる空間が2次元、3次元のとき、それぞれの各成分にはどういった関係式があるのでしょうか?

  • 制御 状態空間モデルについて

    現在、制御について勉強しています。 可観測標準形と可到達標準形というものが出てきました。 どちらも  x(t+1)=Ax(t)+Bu(t) y(t)=Cx(t)+Du(t) という形で表すことができるようです。 (x:状態変数 y:出力ベクトル u:入力ベクトル) ここで、可観測標準形の状態空間モデルをA,B,C,D 可到達標準形の状態空間モデルをA',B',C',D' と表すと  A'=A^T B'=C^T C'=B^T D'=D ・・・(1) という関係が成り立っていることがわかりました。 (A^T は Aの転置という意味です) そして、このような関係を持つ2つのシステムは 互いに「双対」と呼ぶと書いてありました。 ここで疑問に思ったのが、可観測標準形と可到達標準形は (1)のような性質を持っており伝達関数行列が等しくなりますが、 (1)が成り立つ2つのシステムというのは、 すべて伝達関数行列が等しくなるのでしょうか? 伝達関数行列を求める式 H(z)=C(zI-A)^(-1)B+D にA',B',C',D'を代入して上記のH(z)と同じ式を導こうと思ったんですが どうやったらいいのかよくわからなくなりました。 やり方がわかる方がいたら、どなたか教えてください。 また、他の方法で証明できるのであれば、教えてください。

  • 衝突判定プログラムの作成方法について

    環境 VisualC++ 3D空間上に点1(x1,y1,z1)と点2(x2,y2,z2)の二点があるとします。 その二点を結ぶ直線間に、オブジェクトが存在するか否か判定したいです。 どのようなアルゴリズムにすれば良いでしょうか? わかる方いらっしゃいましたら、是非アドバイスのほうよろしくお願い致します。

  • Javaで3D迷路を作ります。

    Javaで3D迷路を作りたいです。 ポインタを操作し、3D迷路を 進んでいくゲームを作ります。 3D迷路の形は、立方体の中に 迷路があるようなイメージを 考えています。 モデルの作成は「ブレンダー 」というアプリを使います。3 Dのモデルをデータで出力する ようです。 問題は、この3D迷路につける 「当たり判定」がとても難しい らしいということです。ポイ ンタをボールとし、壁と接触し た際に跳ね返るなどの動作を 行いたいです。最悪、壁に触れ たらゲームオーバーというだけ の処理でも構いません。「壁に ふれる」という判定のやり方 を教えてください。 何か、参考になる本、サイトな どはありますでしょうか?また 、Javaプログラミングに詳しい 方がいらっしゃいましたらアド バイスなど頂けますと幸いで す。 ちなみに、Javaの基礎を学んだ 学生数人が開発します。 以上です。よろしくお願いい たします。

  • Vector worksにはAuto-CADのビューポートみたいな機能がありますか?

    ベクター12を使用中です。 ベクターにはオートみたいにビューポートの設定が出来るのか聞きたくて投稿しました。 Auto-CADではビューポートを設定できるので、図面の変更があった時など、モデル空間の一箇所を直せば済むのですが、ベクターだと一つ一つの図面がリンクしていないので、一箇所の変更が出た場合、関連性のある箇所を一つ一つ直さなくてはいけません(私の操作方法です)。 もしベクターにビューポート或いはそれに似た機能があれば、教えていただきたいです。 宜しくお願い致します。

  • 3DCGで使う拡張子PLYファイルの文法

    3D-CGで使用される拡張子PLYのファイルの内部構造(文法)について質問します。 頂点法線の意味、効果、使用法及び計算方法が分かりません。 また、flagsキーワードの使用法についても併せて質問します。 質問の経緯 練習でフリーソフトMeshLabを使った実験をしてみました。 MeshLabに表裏がある正方形の表示させる実験 実験1 STL形式でImportして正方形を表示させるには、 下記のように記述する必要がありました。 [STL形式の中身] solid seihoukei facet normal 0.0e+0 0.0e+0 -1.0e+0 outer loop vertex 0.0e+0 0.0e+0 0.0e+0 vertex 1.0e+0 0.0e+0 0.0e+0 vertex 0.0e+0 1.0e+0 0.0e+0 endloop endfacet facet normal 0.0e+0 0.0e+0 -1.0e+0 outer loop vertex 1.0e+0 1.0e+0 0.0e+0 vertex 0.0e+0 1.0e+0 0.0e+0 vertex 1.0e+0 0.0e+0 0.0e+0 endloop endfacet endsolid seihoukei 疑問点1 三角メッシュを構成する頂点の座標と右ねじの法則で面の形状と表裏の向きが幾何学的に確定する。形状について不明瞭な点は一切無いはずなのに2辺の外積を計算して法線を指定しなければならないのはなぜ? 実際、法線の指定を省略するとMeshLabは何も表示してくれない。この法線は何のために使われているのか? 実験2 実験1で読み込んだファイルをPLY形式でExportする。 [PLY形式の中身] ply format ascii 1.0 comment VCGLIB generated element vertex 6 property float x property float y property float z property float nx property float ny property float nz property int flags element face 2 property list uchar int vertex_indices property int flags end_header 0 0 0 0 0 1.5708 0 1 0 0 0 0 0.785398 0 0 1 0 0 0 0.785398 0 1 1 0 0 0 1.5708 0 0 1 0 0 0 0.785398 0 1 0 0 0 0 0.785398 0 3 0 1 2 0 3 3 4 5 0 疑問点2-1 法線は、幾何的に直線か平面に対してしか意味をなさないと思うが、頂点とペアになっているのは何を意味しているのか?この法線ベクトルは形状について表裏の向き以外のなにか重要な情報を含んでいるのか?どうやって計算したのか? 疑問点2-2 flagsキーワードは、何を意味するのか? ---------- 前回「3DCGのPLY形式で立方体を記述したい」というタイトルで質問しましたが、 より具体的な内容のほうが回答を得やすいと考え本質問を掲示しました。 前回の質問に補足質問を追加しようとしましたが、補足質問の入力ボタンを表示されないため新しく質問し直しました。

  • C言語 格子点が多角形の中にあるかどうか?

    こんにちは. 私はプログラミングを勉強しはじめて3ヵ月くらいです. 今、与えられた多角形(例えば、(0,0),(3,7),(5,7),(8,3),(4,1),(1,0)の五点からなる多角形)の内部に格子点が存在するかどうかをチェックする(存在すれば1を返す等)ということをプログラミングを利用して,解決したいと思っています.最終的にはそれを利用して与えられた多角形をビットマップ表示にすることが目的です. 現在ある一つの自分の決めた点に関しては与えられた多角形を打ち込むことによって中か外かを判定する関数はできているのですが、100×100個の計10000個分の格子点に関してすべて中にあるか外にあるかを判定したいのですが、なかなか上手くいきません. 分かる方いらっしゃいましたら、アドバイスやプログラムの方よろしくお願いします. 今できているプログラムをのせておきます. #include <stdio.h> #include <stdlib.h> /* #define JUST_ON 2 */ #define JUST_ON 1 int insidePolygon(int x, int y, int pn, int *px, int *py); int insidePolygon(int x, int y, int pn, int *px, int *py) /* x and y are the vertex I want to know in polygon. pn is the number of vertex of polygon *px and *py are the vertex of polygon */ { int i, j; int inside; double yy; if (pn < 1) return 0; if (pn == 1) return x==px[0] && y==py[0]; /* Point (x,y) just lies on the edge or vertex of polygon */ for (i = 0, j = pn-1; i < pn; j = i++) { if (py[i] == py[j] && y == py[i] && ((px[i]<=x && x<=px[j]) || (px[j]<=x && x<=px[i]))) return JUST_ON; else if (py[i] != py[j] && ((py[i]<=y && y<=py[j]) || (py[j]<=y && y<=py[i])) && x == (double)(px[j]-px[i])*(y-py[i])/(py[j]-py[i])+px[i]) return JUST_ON; } /* Point (x,y) is inside/outside polygon */ inside = 0; yy = y + 0.5; /* shift y to avoid acrossing the poly's edges or vertices */ for (i = 0, j = pn-1; i < pn; j = i++) { if (((py[i]<=y && y<py[j]) || (py[j]<=y && y<py[i])) && x < (double)(px[j]-px[i])*(yy-py[i])/(py[j]-py[i])+px[i]) inside = !inside; } return inside; } int main() { int ii; int xx, yy; int pnpn; int pxpx[100], pypy[100]; int ret; printf("Enter (x,y) of a point -> "); scanf("%d %d", &xx, &yy); printf("Enter the number of vertics of the polygons -> "); scanf("%d", &pnpn); for (ii= 0; ii < pnpn; ii++) { printf("Enter %d-th vertics's (x, y) -> ", ii+1); scanf("%d %d", &pxpx[ii], &pypy[ii]); } ret = insidePolygon(xx, yy, pnpn, pxpx, pypy); if (ret == 0) printf("The point is outside the polygon.\n"); else printf("The point is inside the polygon\n"); }

  • 3DCGモデリングがなかなかうまくならない

    回答がなかったので、カテゴリーを変更したうえで、再度このカテゴリーにて投稿させていただきました。 予めご了承ください。 3Dモデリングの仕事に従事されている方にお聞きしますが、3DCGモデリングを始めて、まだ日が浅い初心者のものなんですが、Blenderにて3Dモデリングしようとすると、以下の問題が起きてしまい困っております。 (1)モデリングしたものをUV展開すると、ポリゴンが重なったり、ポリゴンがねじれた状態になったりして、綺麗に展開されない。 (2)ポリゴンが多角形になりがち (3)モデリングしていると、面(ポリゴン)同士が重なってしまい、ブーリアンしてもうまくいかなかったりする。 さらにモデリング(造形)しようとしても・・・・ (1)画像からモデリングしようとしても、うまく形にならない (2)図面があっても、複雑すぎて、どうモデリング(造形)すれば良いのかわからない (3)モデリングしてると細かいところまで気がいってしまう。 (4)簡単なものをモデリング(造形)しようとしても、作業が異常に遅い (5)うまく形にならない部分はちまちまと、「頂点を追加」→「辺を作成」「面を張る」といったちまちました事を良くやる ↑これらのことが要因で「綺麗に」「早く」モデリング(造形)することができません。 プロみたいに「早く」「綺麗に」モデリングするにはどうすれば良いのでしょうか? 良い練習方法とかはありませんか? モデリングする際のコツなどを教えて頂けば幸いです。 よろしくお願いします。