首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Matplotlib (圆形包装)中制作不重叠的气泡图

在Matplotlib (圆形包装)中制作不重叠的气泡图
EN

Stack Overflow用户
提问于 2017-09-09 14:12:17
回答 2查看 6.3K关注 0票数 9

目前,我正试图在Matplotlib中制作一个气泡图,其中气泡不重叠,所以在图表中填充圆圈/气泡,类似于

我认为可能有用的东西:

  • 使用x= 1,y=1绘制第一个数据点
  • 通过计算气泡半径随机绘制其他数据点,给出标量值,以避免重叠。

但我一直未能真正落实,亦找不到任何资料。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-09 18:12:24

以下是一种蛮力的方法。

您可以首先将所有的圆圈放置在一个网格上,网格间距的大小是任何圆的最大半径的两倍。

然后,让圆圈进行随机游走,并检查每一步,如果这些圆柱体的“势能”变小,并且所得到的位置是有效的(即没有重叠)。

代码语言:javascript
运行
复制
if (e < self.E and self.isvalid(i)):

作为一个“势”,我们可以简单地使用一个平方径向函数。

代码语言:javascript
运行
复制
self.p = lambda x,y: np.sum((x**2+y**2)**2)

守则:

代码语言:javascript
运行
复制
import numpy as np
import matplotlib.pyplot as plt

# create 10 circles with different radii
r = np.random.randint(5,15, size=10)

class C():
    def __init__(self,r):
        self.N = len(r)
        self.x = np.ones((self.N,3))
        self.x[:,2] = r
        maxstep = 2*self.x[:,2].max()
        length = np.ceil(np.sqrt(self.N))
        grid = np.arange(0,length*maxstep,maxstep)
        gx,gy = np.meshgrid(grid,grid)
        self.x[:,0] = gx.flatten()[:self.N]
        self.x[:,1] = gy.flatten()[:self.N]
        self.x[:,:2] = self.x[:,:2] - np.mean(self.x[:,:2], axis=0)

        self.step = self.x[:,2].min()
        self.p = lambda x,y: np.sum((x**2+y**2)**2)
        self.E = self.energy()
        self.iter = 1.

    def minimize(self):
        while self.iter < 1000*self.N:
            for i in range(self.N):
                rand = np.random.randn(2)*self.step/self.iter
                self.x[i,:2] += rand
                e = self.energy()
                if (e < self.E and self.isvalid(i)):
                    self.E = e
                    self.iter = 1.
                else:
                    self.x[i,:2] -= rand
                    self.iter += 1.

    def energy(self):
        return self.p(self.x[:,0], self.x[:,1])

    def distance(self,x1,x2):
        return np.sqrt((x1[0]-x2[0])**2+(x1[1]-x2[1])**2)-x1[2]-x2[2]

    def isvalid(self, i):
        for j in range(self.N):
            if i!=j: 
                if self.distance(self.x[i,:], self.x[j,:]) < 0:
                    return False
        return True

    def plot(self, ax):
        for i in range(self.N):
            circ = plt.Circle(self.x[i,:2],self.x[i,2] )
            ax.add_patch(circ)

c = C(r)

fig, ax = plt.subplots(subplot_kw=dict(aspect="equal"))
ax.axis("off")

c.minimize()

c.plot(ax)
ax.relim()
ax.autoscale_view()
plt.show()

由于这种方法的随机游走特性,找到解决方案需要一些时间(在本例中为10秒);当然,您可以使用参数(主要是步骤1000*self.N的数目,直到解决方案固定为止),看看什么适合您的需要。

票数 11
EN

Stack Overflow用户

发布于 2020-04-02 11:12:36

您可以尝试circlify包:https://pypi.org/project/circlify/

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46131572

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档