実行結果の直線を曲線にしたい

sspファイルを用いて行っています 現段階で点を直線で結び「み」と表示されるようになっています。 点を結んだ際の直線を曲線にするにはどうしたらよいでしょうか。
function df_editor
% オブジェクトをマウスで動かすサンプル例
% Figure に各種コールバックを設定
figure('WindowButtonDownFcn',@myBDCallback,'WindowButtonUpFcn',@myBUCallback)
%pos=[50 50; 60 60; 70 70];
%axis([0,100,0,100]); axis square; hold on;
%xlabel('x'), ylabel('y');
%sspファイルの読み込み
po=sspread('mi.ssp');
pos(:,1)=po(:,1);
pos(:,2)=po(:,2);
%-200から200までの座標表示
axis([-200,200,-200,200]); axis square; hold on;
xlabel('x'), ylabel('y');
%img = imread('circle.png'); % 面を表示
for i=1:length(pos)-1
hL(i)=plot(pos(i:i+1,1),pos(i:i+1,2),'k-');
end
for i=1:length(pos)
h(i)=plot(pos(i,1),pos(i,2),'bx');
end
function myBDCallback(src,eventdata)
% WindowButtonDownFcn
% マウスを押したときのコールバック関数
set(src,'WindowButtonMotionFcn',@myBMCallback);
function myBMCallback(src,evnt)
% WindowButtonMotionFcn
% マウスを動かしたときのコールバック関数
Cp = get(gca,'CurrentPoint'); % 座標軸上のマウスの位置を取得
Xf = Cp(1,1); % X 軸上の位置
Yf = Cp(1,2); % Y 軸上の位置
[dp,Ip] = min((pos(:,1)-Xf).^2+(pos(:,2)-Yf).^2) %debug用にコメントアウト
set(h(Ip),'XData',Xf) % ボタンのX軸位置を変更
set(h(Ip),'YData',Yf) % ボタンのY軸位置を変更
if Ip==1
set(hL(Ip),'XData',[Xf,pos(Ip+1,1)]) % ボタンのX軸位置を変更
set(hL(Ip),'YData',[Yf,pos(Ip+1,2)]) % ボタンのY軸位置を変更
pos(Ip,:)=[Xf Yf];
elseif Ip==length(pos)
set(hL(Ip-1),'XData',[pos(Ip-1,1),Xf]) % ボタンのX軸位置を変更
set(hL(Ip-1),'YData',[pos(Ip-1,2),Yf]) % ボタンのY軸位置を変更
pos(Ip,:)=[Xf Yf];
else
set(hL(Ip),'XData',[Xf,pos(Ip+1,1)]) % ボタンのX軸位置を変更
set(hL(Ip),'YData',[Yf,pos(Ip+1,2)]) % ボタンのY軸位置を変更
set(hL(Ip-1),'XData',[pos(Ip-1,1),Xf]) % ボタンのX軸位置を変更
set(hL(Ip-1),'YData',[pos(Ip-1,2),Yf]) % ボタンのY軸位置を変更
pos(Ip,:)=[Xf Yf];
end
drawnow % 強制描画
end
end
function myBUCallback(src,evantdata)
% WindowButtonUpFcn
% マウスを放したときのコールバック関数
set(src,'WindowButtonMotionFcn','');
end
end

 Accepted Answer

Hirokazu Tanaka
Hirokazu Tanaka on 12 Oct 2018
Edited: Hirokazu Tanaka on 12 Oct 2018

1 vote

po=sspread('mi.ssp');
の箇所、sspread 関数は MATLABに入っている関数では無さそうですね? mi.ssp ファイルもないのでサンプルコードを実行できませんが、、要は各点を直線で結ぶのではなく、滑らかに繋いでプロットされたいということですか?
% 元データ x, y 間をスプライン補完し
% 各点を"滑らか"にプロットするサンプルコード
% もともとのデータ5点
x = rand(5,1);
y = rand(5,1);
plot(x,y,'r-o'); % プロット
hold on
% 上の5点のデータを最初の点 (x(1),y(1)) を起点とした
% 距離に対する関数と考えて、距離を細かく区切り補完します。
dx = diff(x);
dy = diff(y);
% 各点の x(1), y(1) からの距離
dist = cumsum(sqrt(dx.^2 + dy.^2));
dist = [0; dist];
% N個均等に区切った距離で内挿します。
N = 100;
newdist = linspace(0,max(dist),N)';
newx = interp1(dist,x,newdist,'spline'); % スプライン補間
newy = interp1(dist,y,newdist,'spline'); % スプライン補間
% プロット
plot(newx,newy,'b-o');
hold off
legend({'元データ','滑らかに繋いだ点'})

13 Comments

Keiichi Hirayama
Keiichi Hirayama on 12 Oct 2018
ありがとうございます。 一度参考にして試してみます。
Hirokazu Tanaka
Hirokazu Tanaka on 13 Oct 2018
可能でしょう・・としか。上で紹介した方法では各点を滑らか(定義はあいまいですが)に繋いで表示することはできませんでしたか?
データを見るに (x,y,z) の3次元のデータのようですね。。どこまでできていて、どこで困っているのか具体的に教えてください。
Keiichi Hirayama
Keiichi Hirayama on 13 Oct 2018
私が質問に載せているコードを実行し、三次元データのsspファイルを読み込むと、現在はX.Yの二次元が表示され、表示された制御点を動かすことができるところまでできています。 制御点は動かせるのですが他の点と重なった際に点が入れ替わって動くエラーなどがあります。 しかし、その前に私がやりたいことは表示された制御点を結んだ線を曲線にしたいということです。 bスプラインを使うと曲線にできるそうなのですがよくわかっていないので、どんな形でもいいので、まずは直線を曲線にするところからやりたいと思っています。 なので、制御点は動かせなくてもよいので、sspファイルのデータを使って曲線の表示はできますでしょうか。
いただいたサンプルコードは動かすことができました。 しかし、私のコードの方でうまく動かすことができませんでした。
Hirokazu Tanaka
Hirokazu Tanaka on 13 Oct 2018
Edited: Hirokazu Tanaka on 13 Oct 2018
伺いたかったのは、
>> しかし、私のコードの方でうまく動かすことができませんでした。
の点で、何を試されて、何ができなかったか(期待通りの結果になっていない、エラーがでる)という点でした。
私の言葉足らずでサンプルコードの説明が足りなくて何をやっているか分からないのであれば、そこをぜひ指摘してください。ただ「できますか?」「うまくいきません」では、状況もさっぱりわからずお手伝いしたくても何も答えられませんので。。他に見ている方も同じかと思います。ここ(MATLAB Answers)に限らず多くの場合、そういう質問は無視されますよ。
ちなみに、私のサンプルコードは
x = rand(5,1);
y = rand(5,1);
の部分で適当に x座標, y座標の値が入ったベクトルを定義してもらえれば、そのまま使えるかと思います。例えば Keiichi Hirayama さんのコードの
po=sspread('mi.ssp');
pos(:,1)=po(:,1);
pos(:,2)=po(:,2);
でおそらくsspファイルを読み取っているだろうと推測していますが、
po=sspread('mi.ssp');
x = po(:,1);
y = po(:,2);
として、私のコードを後に繋がればなんとなくそれらしい結果になるかなと。試してみてください。調整が必要になりそうなのは、
% N個均等に区切った距離で内挿します。
N = 100;
の 100 という値ですね。
聞き方が悪くて申し訳ありません。
私が試してみたのは、sspファイル読み込みの部分とサンプルコードをつないでみました。
このようにしてみたところ制御点の部分が赤〇つないだ線が赤の直線で表示されました。
エラーとして表示されたのが エラー: griddedInterpolant グリッド ベクトルは一意の点で構成されなければなりません。
エラー: interp1 (line 151) F = griddedInterpolant(X,V,method);
エラー: test (line 19) newx = interp1(dist,x,newdist,'spline'); % スプライン補間 というものでした。
%sspファイルの読み込み
po=sspread('mi.ssp');
x =po(:,1);
y=po(:,2);
plot(x,y,'r-o'); % プロット
hold on
% 上の5点のデータを最初の点 (x(1),y(1)) を起点とした
% 距離に対する関数と考えて、距離を細かく区切り補完します。
dx = diff(x);
dy = diff(y);
% 各点の x(1), y(1) からの距離
dist = cumsum(sqrt(dx.^2 + dy.^2));
dist = [0; dist];
% N個均等に区切った距離で内挿します。
N = 100;
newdist = linspace(0,max(dist),N)';
newx = interp1(dist,x,newdist,'spline'); % スプライン補間
newy = interp1(dist,y,newdist,'spline'); % スプライン補間
% プロット
plot(newx,newy,'b-o');
hold off
legend({'元データ','滑らかに繋いだ点'})
ここの部分は点と点の間の直線をこの場合100個で区切ったということでしょうか。
% N個均等に区切った距離で内挿します。
N = 100;
> ここの部分は点と点の間の直線をこの場合100個で区切ったということでしょうか。
これは、最初の点から最後の点の間を100個で区切ったということです。各点間の直線それぞれ何点で区切られるかはわかりません。
また、エラーメッセージありがとうございます!こちらでも実行してみたいので、
po=sspread('mi.ssp');
save('po.mat','po');
と実行して po.mat ファイルに変数 po の値を保存して、添付して頂けませんか?
Keiichi Hirayama
Keiichi Hirayama on 13 Oct 2018
ありがとうございます。 matファイルに変換できたとおもいます。 これであっていますでしょうか。
ありがとうございます。po に同じ重複する座標点があるのが原因でした。
load po.mat
xy = po(:,1:2);
xyunique = unique(xy,'rows'); % 行同士を比較して重複を除きます
x = xyunique(:,1);
y = xyunique(:,2);
と unique 関数で重複する点を除いてあげると、こんな図になります。unique 関数の使い方はドキュメンテーションページみて確認してみてください。
Keiichi Hirayama
Keiichi Hirayama on 13 Oct 2018
ありがとうございます
3重点や2重点があったからなんですね。
unique関数についてはドキュメンテーションをみてみます。
この実行結果はmi.sspを元に重複点を除いたらこのようになるということでしょうか。
Hirokazu Tanaka
Hirokazu Tanaka on 13 Oct 2018
はい。添付して頂いた mat ファイルに入っている po のデータを使うと、添付画像のような結果になります。
Keiichi Hirayama
Keiichi Hirayama on 13 Oct 2018
わかりました。
本当にありがとうございます。
もしよろしければ この続きでわからないことがあった時はまた質問させてください。
Hirokazu Tanaka
Hirokazu Tanaka on 13 Oct 2018
ぜひぜひ。面白そうなことをされていますね。 新しい質問もお待ちしてますー。

Sign in to comment.

More Answers (0)

Categories

Find more on Language Fundamentals in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!