質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

MATLAB

MATLABはMathWorksで開発された数値計算や数値の視覚化のための高水準の対話型プログラミング環境です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

5回答

7333閲覧

位置の異なる円を重ならずに描画するコードのアルゴリズム

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

MATLAB

MATLABはMathWorksで開発された数値計算や数値の視覚化のための高水準の対話型プログラミング環境です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/01/03 04:02

編集2018/01/03 05:29

###前提・実現したいこと
Matlabでランダムに円を描画しようとしています。
1200x1200の画面に半径は全て20pxの円を重ならないように描画しようとしています。
現状では、図形が重なってしまい、また円になっていません。
ランダムに複数個(個数と位置がランダム)円を生成する仕様にする際にどのようにアルゴリズムを組めば良いかわからず、困っています。

###発生している問題・エラーメッセージ
実行したコード

Matlab

1% 等間隔ベクトルの作成 2t = linspace(0,2*pi,100); 3 4figure 5cx = 200 + (rand(20, 1) .* 400); cy = 300 + (rand(20, 1) .* 400); % 中心 6r = 0; % 半径 7 8 9for i =0:20 10 fill(r*sin(t)+cx,r*cos(t)+cy, 'k') 11 r = r+1; 12end 13i=i+1; 14 15axis([0,1200,0,1200]) 16axis square

思い通りに動いているコード
20pxの半径の円を1つ画面の中心に描画するコード

Matlab

1% 等間隔ベクトルの作成 2t = linspace(0,2*pi,100); 3 4figure 5cx = 600; cy = 600; % 中心 6r = 0; % 半径 7 8 9for i =0:20 10 fill(r*sin(t)+cx,r*cos(t)+cy, 'k') 11 r = r+1; 12end 13i=i+1; 14 15axis([0,1200,0,1200]) 16axis square

###補足情報(言語/FW/ツール等のバージョンなど)
MatlabR2017b
MacOS high Sierra

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

a_saitoh

2018/01/09 03:31

「現状では、図形が重なってしまい、また円になっていません。」とはどういうことですか?図形が重なるのはわかりますが、「円にならない」わけはないのですが。
a_saitoh

2018/01/09 03:32

今になって気が付きましたが「ランダムに」とは「ランダムな位置に」でしょうか、「(決まった位置に)ランダムな順序に」ですか?
guest

回答5

0

ベストアンサー

(アルゴリズムのタグが付いていたので)考え方だけですが、全て同じ半径ということなので、2つの円の中心間の直線距離が半径×2 以上であれば重なることはありません。(ただし円を描く線は幅0と見做します。ちょうど2倍の場合、描画上線は重なります。それが嫌なら、半径の2倍より大きいという条件にすればOKです)

ランダムに円を描くということなので、中心座標を配列に記憶しておいて、新たな座標で円を描く前に、既に描いていた全ての円の座標と新しい座標との直線距離を求めてそれが半径の2倍以上であれば描くようにし、2倍未満ならその座標は捨てて、次の座標に進めば良いのです。
予め配列のサイズは決めておく必要がありますが、描く平面の大きさが決まれば、その中に一番多く重ならずに円を描くには、隣接する3つの円の中心を結んだ時の図形が正3角形になるように配置した時なので、計算すればサイズは決まるはずです。(まあ、多めに取っておけば大丈夫でしょう)
既にいくつ描いたかは、描く度にカウントすればいいので、そのカウントの分だけ配列をスキャンして判定すればできると思います。

MATLABは殆ど使ったことが無いので、どういうコードになるかはご自身あるいは他の方に聞いてください。

投稿2018/01/05 08:29

PineMatsu

総合スコア3579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

a_saitoh

2018/01/09 03:37

基本、この回答でもうfinal answerだとおもうのですが、なぜかまだ解答募集中ですね。 なお、大雑把にいうと1200×1200÷(π×20×20)*0.906=1038個が円の個数の上界だとおもいます。
PineMatsu

2018/01/09 08:46

そうですね。実際のコードが欲しいのかもしれませんね。 円の一部でも良いとなるともう少し描けるのでは?(たぶんあと50個近く) ただ、ランダムに中心座標を選ぶので、整列する確率はまずゼロなので1000個でも十分かもしれません。
guest

0

終了条件をどう定義するつもりだったのか気になりますが、計算量を減らそうとするならアイディア勝負ですね。

80x80 の正方形をキャンパスに敷き詰め、その正方形内に1つ円を描いてみるとかどうでしょうか?正方形の中でランダムに描画することで、見た目はソコソコ乱雑に並んでいるようにみえると思います。
正方形を直径80の円に変えて敷き詰めれば、より多く並べることが出来ます。

これなら、終了条件も定義が楽だし、描画も重なることがありません。
まぁ、ランダムじゃねぇじゃんって回答ですけどね^^;

投稿2018/01/07 08:28

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

逆の発想で、

  1. 1に初期化した1200x1200の配列Aを最初に用意します。
  2. 配列Aから要素が1である点を1つ取ってきます。
  3. 取ってきた点を、円の中心座標にしてプロットします。
  4. 点から半径40の距離のインデックスに対して配列Aの要素を0にします。

以上2〜4を繰り返す。

無駄な取り出しをしないので、稠密に円を書きたい場合に有利です。

投稿2018/01/07 07:04

編集2018/01/07 08:14
mkgrei

総合スコア8560

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2018/01/07 07:21

重なるかどうかの判定と塗りつぶしが面倒くさいのでは?
Zuishin

2018/01/07 07:28

訂正します。重なり判定は楽ですね。半径を倍にするわけですか。
mkgrei

2018/01/07 08:12

取り出して重なったら破棄するのと、置かれた円の数だけ毎度判定するのが大変かと思いまして。 配列Aの1の部分が重ならずにおける場所になります。
guest

0

描画した円の中心座標を記録しておいて今まで描画した円と次に描画する円の中心座標の距離が 20px 以下であれば座標を計算しなおすといいでしょう。

修正

20px は 40px の間違いです。

投稿2018/01/03 04:11

編集2018/01/03 06:58
Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/01/07 06:41

ご回答いただきましてありがとうございました。
guest

0

どのくらいの大きさの空間に何個の丸を描きたいのかと、どの程度の速度で「ここに新しい丸を描くと既存の丸と重なる」チェックを行わねばならないかの要件がよく分かりません。

効率が重要なら計算機科学の最近傍検索を調べた方が良いですね。

あと、画面(?)の大きさから描ける丸の個数に上限が決まりますが、上限に近い個数の丸を描きたいのなら「乱数で座標を決めて駄目ならもう一度乱数」という方式では不都合になってきますよ。

投稿2018/01/03 05:04

a_saitoh

総合スコア702

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/01/03 05:31

ご回答いただきましてありがとうございます。1200x1200の画面に20pxの半径の円を描きたいです。重なるかどうかの判断は目で見て重なっていないくらいの要件ですが、それを数理モデルで表す方法がわからず、困っている状況です。
a_saitoh

2018/01/04 01:04

だから「最近傍検索」のアルゴリズム(wikipediaに何個か挙げられています)を使えばどうですか?というはなし。重なるかどうかは「新しい円の中心の候補地と最も近い円の中心との距離≦直径」という判断基準でいけるでしょう。
退会済みユーザー

退会済みユーザー

2018/01/07 06:40

追加のご説明をいただきましてありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問