R2021aを使用し​て、直線と円弧の交​​点を求める関数はあり​ますか?

R2021aを使用し、直線から円弧の外側のライン上を順に移動する円の交点を求める方法を教えてください。
A点からA’点に円が移動するとき、円の交点BやB’の交点、さらにC点やC’点を求める関数や方法はありますか?

3 Comments

Atsushi Ueno
Atsushi Ueno on 29 Jul 2021
カーリングのような動きを想定しましたが想定合ってますか?(Aと中心とする円が動き、点線の円は動かない。「直線と円弧の交点」ではなく「円と円の交点」になる)
HO
HO on 29 Jul 2021
説明不足で申し訳ございません。
A点を中心とする円は、中心が実線(青)のライン上を右から左側に動くものとイメージください。その動作の各ポイント時に、この円に接するBの位置を求めたいと考えております。よって、構成は3つの種類があります。
1,A点が直線上にある時のカーブ上にあるBの位置
2,A点がカーブ上にある時のカーブ上にあるBの位置
3,A点がカーブ上にある時の直線上にあるB点の位置
この円に交わる交点(B点)の場所を求める方法があればと考えております。
Atsushi Ueno
Atsushi Ueno on 29 Jul 2021

Sign in to comment.

 Accepted Answer

Atsushi Ueno
Atsushi Ueno on 29 Jul 2021
Edited: Atsushi Ueno on 3 Aug 2021

0 votes

を使いました。変数stepの値とpause(0.05)の時間を変更すれば、変化の粗さや表示速度を調整できます。
BとCは同心円なので単に角度から対応する座標を求めました。
step = 5; llen = 20;
xb = 0; yb = 0; rb = 12;
xc = 0; yc = 0; rc = 8;
xa = rb; ya = 0; ra = 15;
figure;
for ya = -llen:step:0 % 直線部
draw_path(xb,yb,rb,xc,yc,rc,llen);
draw_intersec(xa,ya,ra,xb,yb,rb,xc,yc,rc);
end
for th = 0:step/rb:pi % 円弧部
xa = xb + rb * cos(th);
ya = yb + rb * sin(th);
draw_path(xb,yb,rb,xc,yc,rc,llen);
draw_intersec(xa,ya,ra,xb,yb,rb,xc,yc,rc);
end
xa = -rb;
for ya = 0:-step:-5 % 直線部
draw_path(xb,yb,rb,xc,yc,rc,llen);
draw_intersec(xa,ya,ra,xb,yb,rb,xc,yc,rc);
end
%% 以下はサブルーチン化した関数
function draw_path(xb,yb,rb,xc,yc,rc,llen) % 軌跡を描く
arc(xb,yb,rb,1,'--');
xlim([-30 30]); ylim([-35 30]); xlim manual; ylim manual; hold on;
arc(xc,yc,rc,1,'--');
line([xb+rb xb+rb],[yb yb-llen],'LineStyle','--');
line([xb-rb xb-rb],[yb yb-llen],'LineStyle','--');
line([xc+rc xc+rc],[yc yc-llen],'LineStyle','--');
line([xc-rc xc-rc],[yc yc-llen],'LineStyle','--');
end
function draw_intersec(xa,ya,ra,xb,yb,rb,xc,yc,rc) % 円と交点を描く
[crs1x,crs1y] = circcirc(xb,yb,rb,xa,ya,ra); % 外側経路の円弧部(円B)と円Aの交点
[crs2x,crs2y] = linecirc(inf,-rb,xa,ya,ra); % 外側経路の左側直線部と円Aの交点
if (crs1x(1) < 0) && (crs1y(1) > 0)
crs1x(2) = []; crs1y(2) = [];
crs2x(crs2y>0) = []; crs2y(crs2y>0) = []; % 線対円: y座標が負の交点に絞る(NaNは残す)
[crs2y index] = sort(crs2y,'descend');
crs2x = crs2x(index); % 線対円: y座標の降順でソート (NaNは残す)
else
crs1x(crs1y<0) = []; crs1y(crs1y<0) = []; % 円対円: y座標が正の交点に絞る(NaNは残す)
crs2x(crs2y>0) = []; crs2y(crs2y>0) = []; % 線対円: y座標が負の交点に絞る(NaNは残す)
[crs1x index] = sort(crs1x,'ascend');
crs1y = crs1y(index); % 円対円: x座標の昇順でソート (NaNは残す)
[crs2y index] = sort(crs2y,'descend');
crs2x = crs2x(index); % 線対円: y座標の降順でソート (NaNは残す)
end
if isempty(crs2x) || any(isnan(crs2x)) % 線対円がNaN or y<=0の交点が無い
crsxb = crs1x; crsyb = crs1y; % 円対円の交点を採用(NaNでもOK)
else
crsxb = crs2x; crsyb = crs2y; % 線対円の交点を採用(NaNでもOK)
end
theta = atan2(crsyb,crsxb); % 円B上の交点の角度を求める
crsxc = xc + rc * cos(theta); % 円c上の交点を上記角度から求める
crsyc = yc + rc * sin(theta);
arc(xa,ya,ra,2,'-'); % 円Aを描画
plot(crsxb,crsyb,'*'); % 円B上の交点を描画
plot(crsxc,crsyc,'+'); % 円C上の交点を描画
line([xa crsxb],[ya crsyb]); % 円Aの中心と円B上の交点を線で結ぶ
pause(0.05); hold off;
end
function arc(x,y,r,rsw,linestyle) % rsw=1:半円を描く、rsw=2:円を描く
ang=0:0.01:rsw*pi;
xp=r*cos(ang);
yp=r*sin(ang);
plot(x+xp,y+yp,linestyle);
end

8 Comments

HO
HO on 30 Jul 2021
Edited: HO on 30 Jul 2021
丁寧にご説明とCodeまで作成して頂き、誠に有難うございます。動かしながら理解を深めて行きたいと思います。
交点にマークを記載して頂いたのですが、図形を確認するとマークが入らないところがあるのですが、順番にマークを書かれていくので何故このような現象が起こりえるのでしょうか?さらに斜めに走るラインが記載されるのは交点を2か所としてみなしているからでしょうか?
算出した座標を配列内に格納したいと思い、下記を追加したのですが上手くいきません。posi_Bを配列にしない場合は格納できるのですが、配列にして順に格納する場合はどのようにすれば行えますでしょうか?
ちなみにhold off on/offを切り替える部分は、forループ後にhold offすればと思い確認しましたが上手くいきません。ご教授頂ければと幸いです。
Atsushi Ueno
Atsushi Ueno on 30 Jul 2021
Edited: Atsushi Ueno on 30 Jul 2021
回答のコードが低品質で申し訳ございません。
  • マークが入らないところは何か私の意図しない動作(バグ)かもしれません。アニメーション表示すれば特定できると思います(私はcirccirc関数が実行出来ない為アニメーション表示を確認してません)
  • 斜めに走るラインは、円同士の交点を選択する方法が単純でY座標が正か否かで判断しているので、1点に絞れない範囲が有り、始点⇒一つ目の交点⇒2つ目の交点を結んでしまっている為です。
  • (この動きがフライス切削のように見えてきたのですが)円同士の交点の内、一度接触した所は以降交点として認識しないような処理が必要そうです。
  • >posi_Bを配列にして順に格納する場合はどのようにすれば行えますでしょうか?⇒これも交点が全て1点に絞れれば配列に格納しても動作しますが、1点に絞れず2点格納しようとした時点でエラーになります。posi_Bをセル配列にすればエラーは回避できるかもしれませんが、やはり円の交点を1点に絞るアルゴリズムを検討した方が良いと思います。
  • あと直線との交点も表示していません。やる気があれば捕捉します
Atsushi Ueno
Atsushi Ueno on 30 Jul 2021
circcirc()の代替方法も見つけないといけないかな...
HO
HO on 2 Aug 2021
Edited: HO on 2 Aug 2021
code更新、誠にありがとうございます。
下記のエラーが出た為、&&部分を&へ変更して試してみました。
Operands to the logical and (&&) and or (||) operators must be convertible to logical scalar values.
Error in Find_Out_Each_Points>draw_intersec (line 35)
if ~isnan(crs2xb) && (crs2yb < 0) % 外側経路の左側直線部と円Aの交点が有る場合
Error in Find_Out_Each_Points (line 8)
draw_intersec(xa,ya,ra,xb,yb,rb,xc,yc,rc);
動かせたのですが、どうも厳選する交点の部分の関係だと思うのですが、下記のようにラインがA-B点間にない場合があります。後半の直線部分では、円につられてA-B間ラインがズレていました。
最初の時点で、交点を示す”*”が円上にあります。
Atsushi Ueno
Atsushi Ueno on 2 Aug 2021
エラーがあって申し訳ありません。MappingToolboxが無くデバッグが上手く出来ないんです。
>&&部分を&へ変更して試してみました⇒&に変更した上any(or判定)を追加する必要があります。
直線と円、円と円の交点は0~2点存在するので、条件の組み合わせが沢山ありますね。
汎用性はありませんが以下の条件を実装し、常に一つの交点が選択されるようにします。
  • (↑優先度高い)
  • 直線と円の交点は y<=0 の交点に絞る
  • 線分と円の交点(y<=0)が存在する場合、円と円の交点は無視する
  • 線分と円の交点が2点存在する場合、y座標の小さい方を選択する
  • 円と円の交点は y>=0 の交点に絞る
  • 半円と円の交点(y>=0)が2点存在する場合、x座標の小さい方を選択する
  • (↓優先度低い)
HO
HO on 2 Aug 2021
Edited: HO on 3 Aug 2021
無理言って申し訳ございません。まだ私ではこのcodeを組めないので、見させて頂きながら勉強させてもらっています。
すでにCodeに条件を追加済みであることを気が付かなかったです。済みません。
動作確認させて頂き、ほぼ思うような動きが行われています。しかし、一部の円弧の最終段階で交点が絞れていないようです。
この条件下のみ交点を2つ認識しています。
追記、円対円の際にx座標が正&負でy座標が正の場合があるようです。
HO
HO on 3 Aug 2021
円対円の交点を1つに絞ることが何とか出来ました。洗練されてなくお恥ずかしいですが、if (crs1x(1) < 0) && (crs1y(1) > 0)でx座標が負でy座標が正の条件を追加しました。現象を確認で来るところまで準備をして頂いたおかげです。誠にありがとうございます。残りは最後の直線部分で交点を2つ見つけてしまうところがあるので、こちらも条件を付けて絞りたいと思います。
HO
HO on 3 Aug 2021
Edited: HO on 3 Aug 2021
最後の直線部分で交点を2つになる件に関して、AB間以上の長さは必要ないというか、AB間以上は全て直線上なので、ここはstepのendを-5にすることにしました。
for ya = 0:-step:-20 %  ーー> for ya = 0:-step:-5 % 直線部

Sign in to comment.

More Answers (1)

HO
HO on 30 Jul 2021
Edited: HO on 30 Jul 2021

0 votes

アニメーションが確認出来ました。ありがとうございます。こちらを動作させますと動作する円が円弧上で2点の交点を持った際に先行を走るB点と円の中心のA点のラインが、2点の交点に切り替わることが確認できました。また、すでにお気付きの後半部分で円の中心A点から円の接する直線上のB点が上手く表現できてないことも確認ができました。この図形の縦横のスケールが動作しないようにしたいのですが可能でしょうか?

4 Comments

Atsushi Ueno
Atsushi Ueno on 30 Jul 2021
回答に追記しておきました。xlimとylimを用いて表示範囲や範囲モードを設定します。
HO
HO on 1 Aug 2021
誠にありがとうございます。表示範囲が固定され、アニメーションを確認する際にはより分かりやすくなりました。
・[crsxb,crsyb,crsxc,crsyc]の引数を格納しておきたいのですが、配列数が1x1や1x2などと変化する場合にはどのような配列やどんな処理で行えますか?
[crsxb,crsyb,crsxc,crsyc,theta] = draw_intersec(xa,ya,ra,xb,yb,rb,xc,yc,rc);
if isempty(crsxb)==1
else
posi_B(1,m) = crsxb(crsyb >= 0);
posi_B(2,m) = crsyb(crsyb >= 0);
posi_C(1,m) = crsxc;
posi_C(2,m) = crsyc;
・これら[crsxb,crsyb,crsxc,crsyc]の引数を確認し、円同士の交点の条件を作れればと考えています。
・確かにフライス切削のような動きです。実施なものは異なるのですが内側の直線から円の動きを再現させたいと考えています。
・「あと直線との交点も表示していません。やる気があれば捕捉します」ー>はい、あります。お願い致します。
・functionを実行し、一回目に帰ってくる引数が”[]”のようなカッコ(空)でした。どうしてfunctionを実行し、一回目はのそのような引数になるのでしょうか?今は”isempty(crsxb)”で空かを確認して格納タイミングを取っています。
ほんと、初心者で申し訳ないのですがご教授頂きたいです。
HO
HO on 2 Aug 2021
>functionを実行し、一回目に帰ってくる引数が”[]”のようなカッコ(空)でした。どうしてfunctionを実行し、一回目はのそのような引数になるのでしょうか?今は”isempty(crsxb)”で空かを確認して格納タイミングを取っています。
こちらですが、最初はA点もB点も直線上にいるため値が引数がないと言う理解で合っているでしょうか?
Atsushi Ueno
Atsushi Ueno on 2 Aug 2021
>最初はA点もB点も直線上にいるため値が引数がないと言う理解で合っているでしょうか?
多分あってます。交点が無ければlinecircやcirccirc関数はNaNを返すので値が空になります

Sign in to comment.

Categories

Products

Release

R2021a

Asked:

HO
on 29 Jul 2021

Edited:

on 3 Aug 2021

Community Treasure Hunt

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

Start Hunting!