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

13 ビュー (過去 30 日間)
Norihisa Shimamura
Norihisa Shimamura 2020 年 2 月 5 日
ここでは接触しない一対の歯車を例にとります。
お互いが回転しているときに、その最短距離となる場所が表示されるようにしたいです。
gear2.PNG

採用された回答

michio
michio 2020 年 2 月 5 日
編集済み: michio 2020 年 2 月 5 日
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);

その他の回答 (1 件)

michio
michio 2020 年 2 月 5 日
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 件のコメント
Norihisa Shimamura
Norihisa Shimamura 2020 年 2 月 5 日
ありがとうございます!
とても参考になりました。

サインインしてコメントする。

タグ

製品


リリース

R2019a

Community Treasure Hunt

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

Start Hunting!