MATLAB Answers

2つの回転体(非接触​歯車)の最小位置を表​示させたい。

5 views (last 30 days)
ここでは接触しない一対の歯車を例にとります。
お互いが回転しているときに、その最短距離となる場所が表示されるようにしたいです。
gear2.PNG

  0 Comments

Sign in to comment.

Accepted Answer

michio
michio on 5 Feb 2020
Edited: michio on 5 Feb 2020
dsearchn 関数を使いました。データ点が多くなると処理速度面が心配ですが、数百点程度であれば特に気になりませんでした。データも添付しましたので下記のコードで確認してみてください。
% サンプルデータ(注:手書きの歯車, x,y 座標、32x2)
load Data001.mat
data = [Data001;Data001(1,:)];
% polyshape 作成(少しずらして 2 つ作成)
gear1 = polyshape(data);
gear2 = translate(gear1,0.7,0);
% 回転させるために重心取得
[refx1,refy1] = centroid(gear1);
[refx2,refy2] = centroid(gear2);
% 30度回転(かみ合うように)
gear1 = rotate(gear1,30,[refx1,refy1]);
% プロット
plot([gear1, gear2]);
% 境界(外枠の座標取得)
[x1,y1] = boundary(gear1);
[x2,y2] = boundary(gear2);
% 座標点の内挿
d1 = cumsum([0;sqrt(diff(x1).^2 + diff(y1).^2)]);
d2 = cumsum([0;sqrt(diff(x2).^2 + diff(y2).^2)]);
data1 = interp1(d1,[x1,y1],linspace(0,max(d1),100));
data2 = interp1(d2,[x2,y2],linspace(0,max(d2),100));
% ここまではデータ準備(もともと密なデータがあればここからスタート可)
% data2 (gear2)の全座標点から最も近い data1 (gear1) の座標点を検索
[k,d] = dsearchn(data1,data2);
% k が最も近いデータのインデックス in data1、 d が距離
% 距離が近い順に並べ替え
[~,idx] = sort(d,'ascend');
idx2 = idx(1); % もっとも近いとされた点のインデックス in data2
idx1 = k(idx(1)); % もっとも近いとされた点のインデックス in data1
% もっとも近い点同士を線で結合
point1 = data1(idx1,:);
point2 = data2(idx2,:);
% gear1 上の点
line(point1(1),point1(2),'Marker','o','MarkerFaceColor','b');
% gear2 上の点
line(point2(1),point2(2),'Marker','o','MarkerFaceColor','r');
% 上の 2 つをつなぐ線
line([point1(1),point2(1)],[point1(2),point2(2)],'LineWidth',2);

  0 Comments

Sign in to comment.

More Answers (1)

michio
michio on 5 Feb 2020
GIFを作るコードも付けておきます。水平に回転していないように見えるのが気になりますが・・。
output.gif
% サンプルデータ(注:手書きの歯車, x,y 座標、32x2)
load Data001.mat
data = [Data001;Data001(1,:)];
% polyshape 作成(少しずらして 2 つ作成)
gear1 = polyshape(data);
gear2 = translate(gear1,0.7,0);
% 回転させるために重心取得
[refx1,refy1] = centroid(gear1);
[refx2,refy2] = centroid(gear2);
% 30度回転(かみ合うように)
gear1 = rotate(gear1,30,[refx1,refy1]);
filename = 'output.gif';
for ii=1:50
% ちょっとづつ回転させて動画にします。
gear1 = rotate(gear1,ii/10,[refx1,refy1]);
gear2 = rotate(gear2,-ii/10,[refx2,refy2]);
if ii==1
hpoly = plot([gear1, gear2]);
% 座標軸の設定等
set(gca,'XLim',[0,1.8]);
set(gca,'YLim',[0,1]);
axis equal
set(gca,'XColor','white');
set(gca,'YColor','white');
set(gcf,'Color','white');
else
hpoly(1).Shape = gear1;
hpoly(2).Shape = gear2;
end
% 境界(外枠の座標取得)
[x1,y1] = boundary(gear1);
[x2,y2] = boundary(gear2);
% 座標点の内挿
d1 = cumsum([0;sqrt(diff(x1).^2 + diff(y1).^2)]);
d2 = cumsum([0;sqrt(diff(x2).^2 + diff(y2).^2)]);
data1 = interp1(d1,[x1,y1],linspace(0,max(d1),100));
data2 = interp1(d2,[x2,y2],linspace(0,max(d2),100));
% ここまではデータ準備(もともと密なデータがあればここからスタート可)
% data2 (gear2)の全座標点から最も近い data1 (gear1) の座標点を検索
[k,d] = dsearchn(data1,data2);
% k が最も近いデータのインデックス in data1、 d が距離
% 距離が近い順に並べ替え
[~,idx] = sort(d,'ascend');
idx2 = idx(1); % もっとも近いとされた点のインデックス in data2
idx1 = k(idx(1)); % もっとも近いとされた点のインデックス in data1
% もっとも近い点同士を線で結合
point1 = data1(idx1,:);
point2 = data2(idx2,:);
if ii==1
% gear1 上の点
h_p1 = line(point1(1),point1(2),'Marker','o','MarkerFaceColor','b');
% gear2 上の点
h_p2 = line(point2(1),point2(2),'Marker','o','MarkerFaceColor','r');
% 上の 2 つをつなぐ線
h_line12 = line([point1(1),point2(1)],[point1(2),point2(2)],'LineWidth',2);
else
h_p1.XData = point1(1);
h_p1.YData = point1(2);
h_p2.XData = point2(1);
h_p2.YData = point2(2);
h_line12.XData = [point1(1),point2(1)];
h_line12.YData = [point1(2),point2(2)];
end
frame = getframe(gcf); %#ok<UNRCH> % Figure 画面をムービーフレーム(構造体)としてキャプチャ
tmp = frame2im(frame); % 画像に変更
[A,map] = rgb2ind(tmp,256); % RGB -> インデックス画像に
if ii == 1 % 新規 gif ファイル作成
imwrite(A,map,filename,'gif','LoopCount',Inf,'DelayTime',0.1);
else % 以降、画像をアペンド
imwrite(A,map,filename,'gif','WriteMode','append','DelayTime',0.1);
end
pause(0.2)
end

  1 Comment

Norihisa Shimamura
Norihisa Shimamura on 5 Feb 2020
ありがとうございます!
とても参考になりました。

Sign in to comment.

Tags

Products


Release

R2019a

Community Treasure Hunt

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

Start Hunting!