You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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')

关键说明

  1. 镜像圆偏移量:遍历9种偏移组合,覆盖圆超出单边界、双边界的所有补全场景
  2. 圆样式设置:fill=False避免遮挡晶格点,linewidth调整边框粗细增强可读性
  3. 坐标轴范围:设置为(-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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 09:49:52