Show older comments
複数の円を囲む凸包を求める方法についての質問です。
複数の異なる半径を持つ円があるときに、それを囲む凸包を求めたいです。
半径が同一の円であれば、中心を囲む凸包をconvhullで求めた後に、半径をpolybufferでバッファーとすれば求められましたが、
半径が異なる場合はその方法が使えません。
解決策やアドバイスをお持ちの方がいましたら、ご教授いただきたいです。
よろしくお願いいたします。
6 Comments
YA
on 10 Apr 2023
>凸包の角は円周を使うのではなく直線で角を作るものとします
つまり円の接線で構成され面積最小の多角形を求める事になりますね。難しいですね。
下記は円周を覆う凸包になりました。
x = []; y = []; th = (0:pi/5:2*pi)';
for n = 1:10
r = randi(50,1,1) + 50;
x = [x; r * cos(th) + randi(1000,1,1)];
y = [y; r * sin(th) + randi(1000,1,1)];
end
K = convhull([x y]);
plot(x,y,'*')
hold on
plot(x(K),y(K),'r')
YA
on 11 Apr 2023
>接線を求めて地道に求めていくしかなさそうですね
もう作ってしまったかもしれませんが...
中心を囲む凸包をconvhullで求めた後に、半径分離れた直線(まだ繋がっていない)を引いてみました。あとは直線同士の交点を求めれば良さそうですが、円の中心を囲む凸包に含まれない円の半径が大きいと凸包の外にはみ出してしまうので、もう少し検討すべきかなと思いました。
th = (0:0.2:2*pi)';
r = [randi(800,10,2) + 100, randi(200,10,1)+50]; % x座標、y座標、半径
K = convhull(r(:,1:2)); % (x,y)座標の組から凸包のインデックスを得る
plot(r(K,1),r(K,2),'o-'); hold on % 円の中心を囲む凸包を結ぶ
plot(r(:,1)'+cos(th)*r(:,3)',r(:,2)'+sin(th)*r(:,3)','.'); % 円を点線で描画
for k = [K(1:end-1)'; circshift(K(1:end-1),-1)']
theta = atan2(diff(r(k,2)),diff(r(k,1))); % 凸包の一辺の角度を求める
x = r(k,1) + cos(theta - pi/2)*r(k,3); % 円を囲む凸包の座標
y = r(k,2) + sin(theta - pi/2)*r(k,3); % 円を囲む凸包の座標
plot(x,y,'LineWidth',2); % 円を囲む凸包の描画(まだ角が繋がっていない)
end
Atsushi Ueno
on 13 Apr 2023
Moved: Atsushi Ueno
on 13 Apr 2023
>接線を求めて地道に求めていくしかなさそうですね
- 凸包を求める
- 接線を結ぶ点群に絞る(円周上の点群を削除)
- 接線同士の交点を求め点群に追加・凸包のindexに挿入
th = (0:pi/1000:2*pi)';
x = []; y = [];
for n = 1:20
r = randi(100,1,1) + 50;
x = [x; r * cos(th) + randi(1000,1,1)]; % 複数の円状に並んだ点群
y = [y; r * sin(th) + randi(1000,1,1)];
end
K = convhull(x,y); % 複数の円状に並んだ点群を囲む凸包のindexを求める
dst = hypot(diff(x(K)),diff(y(K))); % 凸包の点間距離を求める
idx = dst > mean(dst); % 円周上の点群距離は平均値で、接線のみ比較的長い
K = K([idx; false] | [false; idx]); % 接線の始点と終点のみ選り分ける
temp = [K circshift(K,-1) circshift(K,-2) circshift(K,-3)]';
K = [reshape(K,2,[]); size(x,1)+1:size(x,1)+size(temp,2)/2];
K = K(:); % 3つおきに交点のindexを挿入
for k = temp(:,1:2:end) % 4点ずつ並べて2つおきに走査する
[x(end+1),y(end+1)] = intersection(x(k),y(k)); % 交点を求める
end
plot(x,y); hold on
plot(x(K),y(K),'o-','lineWidth',2)
function [xi,yi] = intersection(x,y) % 交点を求める
numx = (x(1)*y(2)-y(1)*x(2))*(x(3)-x(4))-(x(1)-x(2))*(x(3)*y(4)-y(3)*x(4));
numy = (x(1)*y(2)-y(1)*x(2))*(y(3)-y(4))-(y(1)-y(2))*(x(3)*y(4)-y(3)*x(4));
den = (x(1)-x(2))*(y(3)-y(4))-(y(1)-y(2))*(x(3)-x(4));
xi = numx / den;
yi = numy / den;
end
Atsushi Ueno
on 14 Apr 2023
上記のプログラムを若干整理して回答にしました。
Accepted Answer
More Answers (0)
Categories
Find more on 境界領域 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!


