圆圈之间的圆弧

时间:2017-02-10 15:16:48

标签: python matplotlib geometry plotly

我正在尝试使用Matplotlib绘制Chord图。我知道已经存在的库,比如Plotly给我的功能,但我真的很想在matplotlib中做。

到目前为止我的代码看起来像这样:

import itertools
import matplotlib.patches as patches
import matplotlib.pyplot as plt
import numpy as np

%matplotlib inline

fig, ax = plt.subplots()

ax.axhline(0, color='black', linestyle='--')
ax.axvline(0, color='black', linestyle='--')

npoints = 3

# Calculate the xy coords for each point on the circle
s = 2 * np.pi / npoints
verts = np.zeros((npoints, 2))
for i in np.arange(npoints):
    angle = s * i
    x = npoints * np.cos(angle)
    y = npoints * np.sin(angle)
    verts[i] = [x, y]


# Plot the arcs
numbers = [i for i in xrange(npoints)]
for i, j in itertools.product(numbers, repeat=2):

    if i == j:
        continue

    x1y1 = x1, y1 = verts[i]
    x2y2 = x2, y2 = verts[j]

    # Calculate the centre of the Arc
    mxmy = mx, my = [(x1 + x2) / 2, (y1 + y2) / 2]

    r = np.sqrt((x1 - mx)**2 + (y1 - my)**2)
    xy = [mx - r, my - r]
    width = 2 * r
    height = 2 * r
    start_angle = np.arctan2(y1 - my, x1 - mx) * 180 / np.pi
    end_angle = np.arctan2(y2 - my, x2 - mx) * 180 / np.pi

    arc = patches.Arc(mxmy, width, height, start_angle, end_angle)
    ax.add_patch(arc)

# Plot the points
x, y = verts.T
ax.scatter(x, y, marker='o', s=50, c='r')
ax.annotate("1", (x[0], y[0]), xytext=(x[0] + .5, y[0] + .5))
ax.annotate("2", (x[1], y[1]), xytext=(x[1] - 1, y[1] + .5))
ax.annotate("3", (x[2], y[2]), xytext=(x[2] - 1, y[2] - 1))

ax.set_xlim(-npoints - 5, npoints + 6)
ax.set_ylim(-npoints - 5, npoints + 6)
ax.set(aspect=1)

有人能告诉我为什么我的情节会是这样吗? my plot

我期待更多类似于以下的内容(图片取自Plotly

chard plotly

编辑1

我想在以下几点之间绘制弧线:

  • 1和2
  • 1和3
  • 2和3

理想情况下,这些弧应位于内部。

编辑2

经过进一步调查后,我发现end_angle似乎是问题的根源。

2 个答案:

答案 0 :(得分:0)

在@ f5r5e5d指出情节中使用的Bézier curve之后,我决定给这个人一个机会。看起来这也是我的理由。

import itertools
import matplotlib.patches as patches
import matplotlib.pyplot as plt
import numpy as np
import sys

%matplotlib inline

fig, ax = plt.subplots()

npoints = 5

# Calculate the xy coords for each point on the circle
s = 2 * np.pi / npoints
verts = np.zeros((npoints, 2))
for i in np.arange(npoints):
    angle = s * i
    x = npoints * np.cos(angle)
    y = npoints * np.sin(angle)
    verts[i] = [x, y]

# Plot the Bezier curves
numbers = [i for i in xrange(npoints)]
bezier_path = np.arange(0, 1.01, 0.01)
for a, b in itertools.product(numbers, repeat=2):
    if a == b:
        continue

    x1y1 = x1, y1 = verts[a]
    x2y2 = x2, y2 = verts[b]

    xbyb = xb, yb = [0, 0]

    # Compute and store the Bezier curve points
    x = (1 - bezier_path)** 2 * x1 + 2 * (1 - bezier_path) * bezier_path * xb + bezier_path** 2 * x2
    y = (1 - bezier_path)** 2 * y1 + 2 * (1 - bezier_path) * bezier_path * yb + bezier_path** 2 * y2

    ax.plot(x, y, 'k-')

x, y = verts.T
ax.scatter(x, y, marker='o', s=50, c='r')

ax.set_xlim(-npoints - 5, npoints + 6)
ax.set_ylim(-npoints - 5, npoints + 6)
ax.set(aspect=1)

上面的代码描绘了我想要做的事情。对风格进行一些修改,应该很好。

enter image description here

答案 1 :(得分:0)

由于潜在的问题是“如何在matplotlib中绘制和弦图”,我只想让您知道现在有一个python库可以做到这一点:mpl-chord-diagram

您可以只做pip install mpl-chord-diagram

[免责声明]我是当前维护者[/免责声明]