python作业2:蒙特卡罗方法手搓图形

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# 设置中文显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题

class MonteCarloArtist:
    def __init__(self, width=800, height=600, dpi=100):
        """初始化蒙特卡罗绘图器"""
        self.width = width
        self.height = height
        self.dpi = dpi
        self.points = {'in': [], 'out': []}
        
        # 创建图形和坐标轴
        self.fig, self.ax = plt.subplots(figsize=(width/dpi, height/dpi), dpi=dpi)
        self.ax.set_xlim(0, 1)
        self.ax.set_ylim(0, 1)
        self.ax.set_aspect('equal')
        self.ax.set_title("蒙特卡罗方法绘制图形")
        
        # 初始化散点图
        self.scatter_in = self.ax.scatter([], [], c='blue', s=2, alpha=0.8)
        self.scatter_out = self.ax.scatter([], [], c='red', s=2, alpha=0.8)
        
        # 初始化文本信息
        self.info_text = self.ax.text(0.02, 0.95, '', transform=self.ax.transAxes)
        
        # 图形函数(默认为圆形)
        self.shape_function = self._circle_function
        
    def _circle_function(self, x, y):
        """圆形判定函数:(x-0.5)² + (y-0.5)² <= 0.25"""
        return (x - 0.5)**2 + (y - 0.5)**2 <= 0.25
    
    def _square_function(self, x, y):
        """正方形判定函数:0.25 <= x <= 0.75 且 0.25 <= y <= 0.75"""
        return (0.25 <= x <= 0.75) and (0.25 <= y <= 0.75)
    
    def _triangle_function(self, x, y):
        """三角形判定函数:y <= 2x 且 y <= -2x + 2"""
        return y <= 2*x and y <= -2*x + 2
    
    def set_shape(self, shape_name):
        """设置要绘制的图形"""
        shapes = {
            'circle': self._circle_function,
            'square': self._square_function,
            'triangle': self._triangle_function
        }
        if shape_name in shapes:
            self.shape_function = shapes[shape_name]
            self.ax.set_title(f"蒙特卡罗方法绘制:{shape_name}")
        else:
            print(f"不支持的图形:{shape_name},将使用默认圆形")
    
    def generate_points(self, num_points=100):
        """生成随机点并分类"""
        x = np.random.rand(num_points)
        y = np.random.rand(num_points)
        
        for xi, yi in zip(x, y):
            if self.shape_function(xi, yi):
                self.points['in'].append((xi, yi))
            else:
                self.points['out'].append((xi, yi))
    
    def update(self, frame):
        """动画更新函数"""
        self.generate_points(100)
        
        # 更新散点数据
        in_points = np.array(self.points['in'])
        out_points = np.array(self.points['out'])
        
        if len(in_points) > 0:
            self.scatter_in.set_offsets(in_points)
        if len(out_points) > 0:
            self.scatter_out.set_offsets(out_points)
        
        # 更新统计信息
        total = len(in_points) + len(out_points)
        inside = len(in_points)
        ratio = inside / total if total > 0 else 0
        self.info_text.set_text(f"总点数: {total}\n内部点数: {inside}\n比例: {ratio:.4f}")
        
        return self.scatter_in, self.scatter_out, self.info_text
    
    def animate(self, frames=100, interval=100):
        """创建动画"""
        self.animation = FuncAnimation(
            self.fig, self.update, frames=frames, interval=interval, blit=True
        )
        plt.tight_layout()
        plt.show()
    
    def static_plot(self, num_points=10000):
        """静态绘图"""
        self.generate_points(num_points)
        
        in_points = np.array(self.points['in'])
        out_points = np.array(self.points['out'])
        
        if len(in_points) > 0:
            self.ax.scatter(in_points[:, 0], in_points[:, 1], c='blue', s=2, alpha=0.8)
        if len(out_points) > 0:
            self.ax.scatter(out_points[:, 0], out_points[:, 1], c='red', s=2, alpha=0.8)
        
        total = len(in_points) + len(out_points)
        inside = len(in_points)
        ratio = inside / total if total > 0 else 0
        self.info_text.set_text(f"总点数: {total}\n内部点数: {inside}\n比例: {ratio:.4f}")
        
        plt.tight_layout()
        plt.show()

if __name__ == "__main__":
    # 创建绘图器实例
    artist = MonteCarloArtist()
    
    # 设置要绘制的图形(可选:circle, square, triangle)
    artist.set_shape('circle')
    
    # 方式1:使用动画展示过程
    artist.animate(frames=100, interval=100)
    
    # 方式2:直接生成静态图(取消下面一行的注释)
    # artist.static_plot(num_points=50000)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值