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

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

ただいまの
回答率

87.58%

円の軌跡を点を用いて描画する

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 5,746

score 8

前提・実現したいこと

円の軌跡をplt.fill()を用いて描画したいです.そのために円の軌跡の点を求める必要があるのですがどのように求めたら良いでしょうか?

該当のソースコード

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import random

fig = plt.figure()
ax = plt.axes()

# ここで与える点と円の半径rからplt.fill(x, y)におけるxとyを求めたいです.
x = [random.random()+i for i in range(100)]
y = [random.random()+i for i in range(100)]
r = 5

for i in range(len(x)):
    c = patches.Circle(xy=(x[i], y[i]), radius=r, fc='b')
    ax.add_patch(c)

plt.axis('scaled')
ax.set_aspect('equal')

追記

円の数を増やせば

fig = plt.figure()
ax = plt.axes()

x = [i/10 for i in range(100)]
y = [0 for i in range(100)]

# fc = face color, ec = edge color
for i in range(len(x)):
    c = patches.Circle(xy=(x[i], y[i]), radius=1, fc='b')
    ax.add_patch(c)

plt.axis('scaled')
ax.set_aspect('equal')


イメージ説明
このように描画できますが,円の数が少ないと
イメージ説明
このように円間に隙間が生じてしまうので,これをなくすためにplt.fillを用いたいと考えております.

また,円の大きさを変えたりしたいので,円が動く軌跡の周囲の点を得たいです.

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

半径 r の円周上の点は極座標

x = r * sin(t)
y = r * cos(t)

で生成すればよいと思います。

import matplotlib.pyplot as plt
import numpy as np

n_points = 100  # 点の数
theta = np.linspace(0, 2 * np.pi, n_points)
radius = 5  # 半径

x = radius * np.sin(theta)
y = radius * np.cos(theta)

fig, ax = plt.subplots()
ax.set_aspect("equal")
ax.plot(x, y, ".")

イメージ説明

追記

plot() で linewidth を太めに設定して、線を引けばいいのではないでしょうか。

import matplotlib.pyplot as plt
import random

fig, ax = plt.subplots()
ax.set_aspect("equal")

# ここで与える点と円の半径rからplt.fill(x, y)におけるxとyを求めたいです.
xs = [random.random() + i for i in range(10)]
ys = [random.random() + i for i in range(10)]
r = 0.5

for p in zip(xs, ys):
    ax.add_patch(plt.Circle(xy=p, radius=r, fc="none", ec="k", lw=1))
ax.plot(xs, ys, lw=r * 50, alpha=0.3)

ax.autoscale()

イメージ説明

追記

ベクトル (x, y) に直行するベクトルは (y, -x), (y, x) になります。
これをノルムで割り、単位ベクトルにして、半径をかけると、円周上の点になります。

直角なベクトルを作り出す – TauStation

あまりスマートに書けなかったですが、コードにすると以下のようになります。

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()
ax.set_aspect("equal")

points = np.array([(random.random() + i, random.random() + i) for i in range(10)])
r = 0.5


def get_points(points):
    sides1, sides2 = [], []  # 両側の点を格納する配列

    for i in range(len(points) - 1):
        p1, p2 = points[i], points[i + 1]
        v = p2 - p1  # p1 -> p2 のベクトル

        # v に直交する単位ベクトル
        n = np.array([v[1], -v[0]])
        n /= np.linalg.norm(n)

        # 直交する単位ベクトル * 半径が円周の点
        if i == 0:
            sides1.append(p1 + n * r)
            sides2.append(p1 - n * r)
        sides1.append(p2 + n * r)
        sides2.append(p2 - n * r)

    return np.array(sides1 + sides2[::-1])


sides = get_points(points)
print(sides)

ax.fill(sides[:, 0], sides[:, 1], alpha=0.5, ec="k")
for p in points:
    ax.add_patch(plt.Circle(xy=p, radius=r, fc="none", ec="k", lw=1))
ax.autoscale()

イメージ説明

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/12/10 17:01

    意図とあっているかどうかわからないですが、円の直径の同じぐらいの太さの線で軌跡を描画したいということでしょうか。

    キャンセル

  • 2019/12/10 18:14

    @stdioさん
    追記いたしました."ムラ"というのは表現がよくありませんでした."間隔"のほうが正しいです.混乱させてしまいすみません.
    描画ソフトで円をドラッグして軌跡を書くようなことですので,円を点間で平行移動をさせたいということと等しいです.(その移動させる間の円の軌跡の周りの点を得たいです)

    キャンセル

  • 2019/12/10 18:17

    @tiitoiさん
    追記いただきありがとうございます.私の質問も追記いたしました.

    やりたいこととしてはそのプログラムで合っているのですが,今後軌跡の点を用いたり,円の大きさを変えたりしたいと思っておりますので,軌跡の点を用いて描画を行いたいと考えております.

    キャンセル

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

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

関連した質問

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