平面(ax+by+c​z+d=0)への近似​part2

2 views (last 30 days)
Ichiro Suzuki
Ichiro Suzuki on 18 Dec 2016
Commented: Ichiro Suzuki on 20 Dec 2016
前回は回答者様のおかげで解決することができました。ありがとうございます。
続きですが、質問させていただきます。
ランダムな点(約1000点)から平面(ax+by+cz+d=0)への近似を行うことができました。 しかし、この方法により算出した方程式は図の青緑の面の形とは違うものになってしまいました。
図にあるような面を5000個の点で作成したいのですが、どのようなコードになりますか。 範囲は図のようなx、y、zの範囲でお願いします。
係数の使い方(p00やp10など)を理解できていないのかもしれません。 初心者ですがどなたかアドバイスをよろしくお願い致します。
以下、近似と面作成のコードです
--
%CREATEFIT(PLANE01_X,PLANE01_Y,PLANE01_Z)
% 近似を作成します。
%
% '新規近似 1' に対するデータを近似:
% X 入力: plane01_x
% Y 入力: plane01_y
% Z 出力: plane01_z
% 出力:
% fitresult: 近似を表す fit オブジェクト。
% gof: 適合性情報をもつ構造体。
%
% 参考 FIT, CFIT, SFIT.
% MATLAB からの自動生成日: 16-Dec-2016 15:35:47
%%近似: '新規近似 1'。
[xData, yData, zData] = prepareSurfaceData( plane01_x, plane01_y, plane01_z );
% 近似タイプとオプションを設定します。
ft = fittype( 'poly11' );
% モデルをデータに近似します。
[fitresult, gof] = fit( [xData, yData], zData, ft, 'Normalize', 'on' );
% データの近似をプロットします。
figure( 'Name', '新規近似 1' );
h = plot( fitresult, [xData, yData], zData );
legend( h, '新規近似 1', 'plane01_z vs. plane01_x, plane01_y', 'Location', 'NorthEast' );
% ラベル Axes
xlabel plane01_x
ylabel plane01_y
zlabel plane01_z
grid on
view( 32.1, 12.4 );
%係数の抽出
Coe1_d = fitresult.p00;
Coe1_a = fitresult.p10;
Coe1_b = fitresult.p01;
plane01_x = plane0000001(:,1);
plane01_y = plane0000001(:,2);
plane01_z = plane0000001(:,3);
%推定面の作成
maxX = max(plane0000001(:,1));
maxY = max(plane0000001(:,2));
maxZ = max(plane0000001(:,3));
minX = min(plane0000001(:,1));
minY = min(plane0000001(:,2));
minZ = min(plane0000001(:,3));
a_plane = zeros(5000,3);
for k = 1:5000
randpointX = minX + (maxX - minX)*rand(1,1);
randpointY = minY + (maxY - minY)*rand(1,1);
randpointZ = Coe1_d + Coe1_a*randpointX + Coe1_b*randpointY;
a_plane(k,1) = randpointX;
a_plane(k,2) = randpointY;
a_plane(k,3) = randpointZ;
end

Accepted Answer

michio
michio on 18 Dec 2016
Edited: michio on 18 Dec 2016
しかし、この方法により算出した方程式は図の青緑の面の形とは違うものになってしまいました。
とのことですが、係数は正しく使われていそうに見受けられます。どのような違いとなりましたか? 面の形自体が異なるのかそれとも表示上の(表示範囲)などが異なる結果となりましたでしょうか? もしその異なる表示が再現確認できるプログラムがあれば助かります。
また、5000点のランダムな x,y から z を計算し a_plane を埋める処理は、 fitresult オブジェクトを使用して、また for ループを使用せずに下記でも可能ですので、もし参考になりましたら。
randpointX = minX + (maxX - minX)*rand(5000,1);
randpointY = minY + (maxY - minY)*rand(5000,1);
randpointZ = fitresult(randpointX, randpointY);
a_plane = [randpointX, randpointY, randpointZ];
下記ページが参考になるかもしれませんので紹介しますが、分かりにくい点があれば是非コメントください。
  1 Comment
Ichiro Suzuki
Ichiro Suzuki on 18 Dec 2016
ご回答誠にありがとうございます。再度お世話になります。
上のコードを実行したのが下図(薄くてすみません)です。 z軸の数値があまりにも上図と差がありました。手計算をしても下図の結果になってしまったので係数やその他理解ができていないものだと思っていました。
しかし、Michio様に提案していただいたコードでは欲しいデータを手に入れることができました。重ねてありがとうございます。
問題はクリアしましたが、なぜz軸の結果が変わったしまうのか少しもやもやしますね。

Sign in to comment.

More Answers (1)

michio
michio on 18 Dec 2016
実行結果と fitresult を直接使った場合についての情報、ありがとうございます。
改めてコードを見たところ、近似の際にデータ(x,y) の正規化を行っていることに気が付きました。GUI上ですと「データのセンタリングとスケーリング」チェック、コードですと
% モデルをデータに近似します。
[fitresult, gof] = fit( [xData, yData], zData, ft, 'Normalize', 'on' );
の 'Normalize' = 'on' の部分が該当します。
fitresult
と実行すると(*数値は適当な値です)
ここで、x は平均 0.5236 と標準偏差 0.2943 で正規化されます
ここで、y は平均 0.5232 と標準偏差 0.2881 で正規化されます
などと出力されると思います。
5000点のランダムな x,y から z を計算する際に
randpointZ = fitresult(randpointX, randpointY);
と fitresult を使用する場合は、新しいデータに対しても正規化を実施しますが、係数をそのまま使用して計算する場合(提示頂いたコードで)は別途近似モデルを作成したときと同じ正規化を実施する必要があります。
  1 Comment
Ichiro Suzuki
Ichiro Suzuki on 20 Dec 2016
正規化を行っていたとは、考えていませんでした。 正規化できたんですね。
ありがとうございました。大変お世話になりました。

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!