基于Matplotlib绘制带周期性边界条件的晶格圆形问题
周期性边界条件下的晶格圆形绘制实现
问题背景
项目需求:
- 随机生成晶格内的圆心
(x0, y0) - 将半径
R范围内的晶格点染为蓝色,其余为红色 - 满足周期性边界条件:圆超出晶格边界时,在对侧边界补全圆的缺失部分
已完成晶格点着色(距离计算适配周期性边界),但未实现符合周期性的圆形绘制,现有代码如下:
from matplotlib import pyplot as plt import numpy as np class lattice: def __init__(self, L): self.L = L self.positions = np.array([[[i, j] for i in range(L)] for j in range(L)]) def draw_lattice(self, filename): X = self.positions[:, :, 0].flatten() Y = self.positions[:, :, 1].flatten() plt.scatter(X, Y, s=10) plt.xticks([]) plt.yticks([]) plt.title("Lattice") plt.savefig(filename) def dist_centre(self): x0, y0 = np.random.randint(0, self.L), np.random.randint(0, self.L) self.c0 = (x0, y0) self.distance = np.zeros((self.L, self.L)) for i in range(self.L): for j in range(self.L): x = self.positions[i, j, 0] y = self.positions[i, j, 1] # 周期性边界条件下的距离计算 Dx = -self.L/2 + ((x0-x)+self.L/2)%self.L Dy = -self.L/2 + ((y0-y)+self.L/2)%self.L dist = np.sqrt(Dx**2 + Dy**2) self.distance[i, j] = dist def draw_zone(self, filename, R): colormap = np.where(self.distance <= R, "blue", "red").flatten() X = self.positions[:, :, 0].flatten() Y = self.positions[:, :, 1].flatten() plt.clf() plt.scatter(X, Y, s=10, color=colormap) plt.xticks([]) plt.yticks([]) plt.title("Lattice") plt.savefig(filename) if __name__ == "__main__": L = 10 R = 3 filename = "test.pdf" latt = lattice(L) latt.draw_lattice(filename) latt.dist_centre() latt.draw_zone(filename, R)
解决方案:绘制周期性边界的圆
核心思路:利用周期性边界的镜像特性,绘制原圆及其在晶格四个方向(上下左右、角落)的镜像圆,Matplotlib会自动裁剪出落在原晶格范围内的部分。
修改draw_zone方法,添加周期性圆的绘制逻辑:
def draw_zone(self, filename, R): colormap = np.where(self.distance <= R, "blue", "red").flatten() X = self.positions[:, :, 0].flatten() Y = self.positions[:, :, 1].flatten() plt.clf() plt.scatter(X, Y, s=10, color=colormap) # 绘制周期性边界的圆:原圆+所有可能的镜像圆 x0, y0 = self.c0 L = self.L # 定义所有可能的偏移量(覆盖周期性镜像场景) offsets = [(0, 0), (L, 0), (-L, 0), (0, L), (0, -L), (L, L), (L, -L), (-L, L), (-L, -L)] for dx, dy in offsets: # 创建圆对象,透明填充只显示边框 circle = plt.Circle((x0 + dx, y0 + dy), R, color='black', fill=False, linewidth=1.5) plt.gca().add_patch(circle) # 固定坐标轴范围,确保只显示原晶格区域 plt.xlim(-0.5, L - 0.5) plt.ylim(-0.5, L - 0.5) plt.xticks([]) plt.yticks([]) plt.title("Lattice with Periodic Circle") plt.savefig(filename, bbox_inches='tight')
关键说明
- 镜像圆偏移量:遍历9种偏移组合,覆盖圆超出单边界、双边界的所有补全场景
- 圆样式设置:
fill=False避免遮挡晶格点,linewidth调整边框粗细增强可读性 - 坐标轴范围:设置为
(-0.5, L-0.5)让晶格点居中显示,确保镜像圆的可见部分正确匹配周期性边界
完整修改后代码
from matplotlib import pyplot as plt import numpy as np class lattice: def __init__(self, L): self.L = L self.positions = np.array([[[i, j] for i in range(L)] for j in range(L)]) def draw_lattice(self, filename): X = self.positions[:, :, 0].flatten() Y = self.positions[:, :, 1].flatten() plt.scatter(X, Y, s=10) plt.xticks([]) plt.yticks([]) plt.title("Lattice") plt.savefig(filename) def dist_centre(self): x0, y0 = np.random.randint(0, self.L), np.random.randint(0, self.L) self.c0 = (x0, y0) self.distance = np.zeros((self.L, self.L)) for i in range(self.L): for j in range(self.L): x = self.positions[i, j, 0] y = self.positions[i, j, 1] # 周期性边界条件下的距离计算 Dx = -self.L/2 + ((x0-x)+self.L/2)%self.L Dy = -self.L/2 + ((y0-y)+self.L/2)%self.L dist = np.sqrt(Dx**2 + Dy**2) self.distance[i, j] = dist def draw_zone(self, filename, R): colormap = np.where(self.distance <= R, "blue", "red").flatten() X = self.positions[:, :, 0].flatten() Y = self.positions[:, :, 1].flatten() plt.clf() plt.scatter(X, Y, s=10, color=colormap) # 绘制周期性边界的圆 x0, y0 = self.c0 L = self.L offsets = [(0, 0), (L, 0), (-L, 0), (0, L), (0, -L), (L, L), (L, -L), (-L, L), (-L, -L)] for dx, dy in offsets: circle = plt.Circle((x0 + dx, y0 + dy), R, color='black', fill=False, linewidth=1.5) plt.gca().add_patch(circle) plt.xlim(-0.5, L - 0.5) plt.ylim(-0.5, L - 0.5) plt.xticks([]) plt.yticks([]) plt.title("Lattice with Periodic Circle") plt.savefig(filename, bbox_inches='tight') if __name__ == "__main__": L = 10 R = 3 filename = "test.pdf" latt = lattice(L) latt.draw_lattice(filename) latt.dist_centre() latt.draw_zone(filename, R)
内容的提问来源于stack exchange,提问作者Tirterra
相关产品推荐
相关产品推荐

