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

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

ただいまの
回答率

90.50%

  • C

    3699questions

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

  • C++

    3457questions

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

  • アルゴリズム

    412questions

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

  • MATLAB

    155questions

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

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

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 784

tenjin

score 214

前提・実現したいこと

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

発生している問題・エラーメッセージ

実行したコード

% 等間隔ベクトルの作成
t = linspace(0,2*pi,100);

figure
cx = 200 + (rand(20, 1) .* 400); cy = 300 + (rand(20, 1) .* 400); % 中心
r = 0; % 半径


for i =0:20 
    fill(r*sin(t)+cx,r*cos(t)+cy, 'k')
    r = r+1;    
end
i=i+1;

axis([0,1200,0,1200])
axis square 

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

% 等間隔ベクトルの作成
t = linspace(0,2*pi,100);

figure
cx = 600; cy = 600; % 中心
r = 0; % 半径


for i =0:20 
    fill(r*sin(t)+cx,r*cos(t)+cy, 'k')
    r = r+1;    
end
i=i+1;

axis([0,1200,0,1200])
axis square 

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

MatlabR2017b
MacOS high Sierra

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • a_saitoh

    2018/01/09 12:31

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

    キャンセル

  • a_saitoh

    2018/01/09 12:32

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

    キャンセル

回答 5

checkベストアンサー

+4

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/09 12:37

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

    キャンセル

  • 2018/01/09 17:46

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

    キャンセル

+2

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

修正

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/03 13:34

    座標の記録は配列にするのがいいと思います。
    配列の使い方は http://www.cc.kyoto-su.ac.jp/~yamada/programming/array.html
    二点間の距離の求め方は http://www.sousakuba.com/Programming/gs_distance_2point.html
    ループの使い方は http://www.orchid.co.jp/computer/cschool/clec12.html

    キャンセル

  • 2018/01/07 15:41

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

    キャンセル

+2

逆の発想で、

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

以上2〜4を繰り返す。

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/07 16:21

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

    キャンセル

  • 2018/01/07 16:28

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

    キャンセル

  • 2018/01/07 17:12

    取り出して重なったら破棄するのと、置かれた円の数だけ毎度判定するのが大変かと思いまして。

    配列Aの1の部分が重ならずにおける場所になります。

    キャンセル

+2

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/03 14:31

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

    キャンセル

  • 2018/01/04 10:04

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

    キャンセル

  • 2018/01/07 15:40

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

    キャンセル

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

  • ただいまの回答率 90.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    matlabでの計算について

    matlabで計算をしたいのですが、使い方がいまいちわかっておりません 計算というのは例えば 13 1 15 7 ≈ 58 576 のように1行614400列の行

  • 解決済

    matlabでの作業効率化2

    5つのデータがあるとして、それぞれ違う名前をつけたい(a b c d eのように)ときにどのような手順を踏めばいいのでしょうか。 for N=1:5%ファイルの数だけ繰り返す

  • 解決済

    matlabでのfor文を使った行列の結合

    題名にもある通りfor文を使って行列の結合をしたいと考えています。 k1=(1,2,3);k2=(4,5,6);k3=(7,8,9);k4=(10,11,12);このようにkが9

  • 解決済

    MATLABで読み込んだwavファイルの一部を切り取り、もう一度wavファイルで書き出す方法

    matlabに複数のwavファイルを読み込み 読み込んだwavファイルの初めの1秒間のみを切り出して 「長さが1秒間のwav」を作成、再度wavファイルの形で書き出すプログラム

  • 解決済

    円上の任意の点での接戦を描画したい

    matlabで描画したいと思っています。 表題の通りで円上に任意の点での接戦を描画しようしています。 単純に円を描画するところまではかけました。 figure cx

  • 解決済

    MATLAB ファイル読み込み

    観測したzipファイルを手で解凍し、MATLABで読み込む方法についてです。 観測で得られたzipファイルを手動で解凍し、開くと ーーーーーーーーーー e16A0319.

  • 解決済

    Matlabでのtxtファイル出力について

    前提・実現したいこと iが1から21までループさせ、その結果を1つのテキストファイル(ファイル.txt)に縦に出力させたいです。 ↓fa↓ SizeX0 = 0; Si

  • 解決済

    Matlabで円を描画する

    前提・実現したいこと Matlabで円を描画しようとしています。 発生している問題・エラーメッセージ 実行したコード % 等間隔ベクトルの作成 % 中心 r = 0; %

同じタグがついた質問を見る

  • C

    3699questions

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

  • C++

    3457questions

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

  • アルゴリズム

    412questions

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

  • MATLAB

    155questions

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