1つの平面で2つに分​けられた3次元空間で​各点が2つの空間のど​ちらに属しているかを​知りたい。

6 vues (au cours des 30 derniers jours)
Yusaku Ohta
Yusaku Ohta le 30 Août 2023
Commenté : Yusaku Ohta le 31 Août 2023
3次元空間上に複数の点があるとします。
1つの平面によって3次元空間を2つに分けた場合、
各点が2つの空間のどちらに属しているかを知りたいです。
平面をa(x-p)+b(y-q)+c(z-r)=0とします。
この場合、平面上の点はP(x,y,z)です。
インデックスで0か1で分かればいいです。
どのように求めればよいのでしょうか教えてください。
分かりづらいところは質問してください。
お答えします。
宜しくお願いします。

Réponse acceptée

Atsushi Ueno
Atsushi Ueno le 30 Août 2023
平面の式を実際に計算した結果を sign 関数に通せば期待する結果が得られると思います。
  • 零:平面上の点 ⇒ 0
  • 正:2つの空間のどちらか ⇒ +1
  • 負:2つの空間のどちらか ⇒ -1
function result = judgement(x,y,z)
p = 1; q = 2; r = 3;
a = 5; b = 5; c = 5;
result = sign(a*(x-p)+b*(y-q)+c*(z-r));
end
注意点:浮動小数点数を入力した場合、結果が0(ちょうど平面上)になる事は滅多にありません。代数的に0になるはずでも演算誤差によって正負どちらかに外れる事が起こり得ます。かといって「絶対に0にならない」とも言い切れないので厄介です。代数的に厳密な結果を方法としては symbolic math toolboxを使用する方法があります。
  1 commentaire
Yusaku Ohta
Yusaku Ohta le 31 Août 2023
シンプルかつ必要十分なご回答ありがとうございました。
私のやりたかったことにドンピシャでした。
大変助かりました。

Connectez-vous pour commenter.

Plus de réponses (1)

交感神経優位なあかべぇ
Modifié(e) : 交感神経優位なあかべぇ le 30 Août 2023
平面を境に空間の点を2分割するコードを書きました。
体力があるときにもうちょっと詳細を解説するかも……
point_cloud = (rand(100,3) - 0.5) .* 100;% 3次元空間上の複数の点 (:,1), (:,2), (:,3)はそれぞれX,Y,Zの値
plane = (rand(2,3) - 0.5) .* 50; % 平面の式 (配列の各要素は[a,b,c;p,q,r]を示す)
is_normal_side = divice_by_plane(point_cloud,plane); % 空間上の各点を平面を境とした分割を判定する。
% 以下データの可視化
conner = get_plane_conner(plane, 75);% 平面の式から、plane_sizeで示す大きさの四角形の4つの頂点座標を取得する。
cData = repmat([0,1,0],size(point_cloud,1),1);
cData(is_normal_side,:) = repmat([1,0,0],nnz(is_normal_side),1);
scatter3(point_cloud(:,1),point_cloud(:,2),point_cloud(:,3),'Marker','.','CData',cData);
hold on;
patch(conner(:,1),conner(:,2),conner(:,3),[0,0,0.3],'FaceAlpha',0.4);
% 空間上の各点を平面を境とした分割を判定する。
function is_normal_side = divice_by_plane(point_cloud,plane)
arguments(Input)
point_cloud(:,3)% 3次元空間上の複数の点 (:,1), (:,2), (:,3)はそれぞれX,Y,Zの値
plane(2,3) % [a,b,c; p,q,r]の配列
end
arguments(Output)
is_normal_side(:,1) logical % 平面を境にした各点の分割判定(1は面の法線方向側)
end
% 体力があるときに以下解説するかも...
point_cloud = point_cloud + plane(2,:);
zRad = atan2(plane(1,2),plane(1,1));
yRad = atan2(-plane(1,3),hypot(plane(1,2),plane(1,1)));
cosZ = cos(-zRad);
sinZ = sin(-zRad);
zmatrix = eye(3,'like',plane);
zmatrix([1,2], [1,2]) = [cosZ,-sinZ;sinZ,cosZ];
cosY = cos(-yRad);
sinY = sin(-yRad);
ymatrix = eye(3,'like',plane);
ymatrix([1,3],[1,3]) = [cosY,sinY;-sinY,cosY];
point_cloud = (ymatrix * zmatrix * (point_cloud)')';
is_normal_side = point_cloud(:,1) > 0;
end
% 平面の式から、plane_sizeで示す大きさの四角形の4つの頂点座標を取得する。
function conner = get_plane_conner(plane, plane_size)
arguments(Input)
plane(2,3) % [a,b,c; p,q,r]の配列
plane_size(1,1) % 平面の大きさ
end
arguments(Output)
conner(4,3) % 四角形の4つの頂点座標
end
zRad = atan2(plane(1,2),plane(1,1));
yRad = atan2(-plane(1,3),hypot(plane(1,2),plane(1,1)));
cosZ = cos(zRad);
sinZ = sin(zRad);
zmatrix = eye(3,'like',plane);
zmatrix([1,2], [1,2]) = [cosZ,-sinZ;sinZ,cosZ];
cosY = cos(yRad);
sinY = sin(yRad);
ymatrix = eye(3,'like',plane);
ymatrix([1,3],[1,3]) = [cosY,sinY;-sinY,cosY];
x = [0,0,0,0];
y = [plane_size,plane_size,-plane_size,-plane_size];
z = [plane_size,-plane_size,-plane_size,plane_size];
conner = (zmatrix * ymatrix * [x;y;z])';
conner = conner - plane(2,:);
end
  1 commentaire
Yusaku Ohta
Yusaku Ohta le 31 Août 2023
詳細な情報ありがとうございます。
私の数学力不足でis_normal_sideの一部が理解不明でしたが、
その他部分は大変参考になりました。
どちらの回答を採用するか大変迷ったのですが、今回はシンプルな回答を採用させていただきます。
申し訳ありません。
とても有益な情報を本当にありがとうございました。

Connectez-vous pour commenter.

Catégories

En savoir plus sur Import Data dans Help Center et File Exchange

Produits


Version

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!