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

基于Matplotlib用图形填充函数区域:空隙问题求助

解决Matplotlib函数曲线下方图案填充空隙问题

核心问题分析

你当前的填充方案存在大量空隙,核心原因是网格排列方式错误和图形尺寸/位置计算偏差:

  • 六边形、三角形这类图形需要蜂窝状交错排列,而你用了矩形网格(x/y均按固定步长平铺),必然留下空隙;
  • 图形的位置、半径计算不准确,导致相邻图形无法接触顶点/边;
  • 关于numVertices参数:它就是RegularPolygon的第一个参数(比如三角形传3、六边形传6),你代码里已经在正确使用,只是可能没对应上参数名而已。

优化方案

  1. 蜂窝状排列适配:对六边形、三角形,奇数行x坐标偏移base_size/2,y方向步长调整为适合图形紧密排列的尺寸;
  2. 精准顶点判断:通过检查图形所有顶点是否在曲线下方,替代原有的单点判断,避免误判;
  3. 修正图形参数:调整正多边形的中心坐标、半径,确保相邻图形刚好接触顶点。

修改后的代码

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Rectangle, RegularPolygon
from scipy.integrate import quad

def plot_function_with_pattern(func, x_range, y_range, base_size, shape="rectangle", include_touching=True, start_x=None, start_y=None):
    fig, ax = plt.subplots()
    x = np.linspace(x_range[0], x_range[1], 1000)
    y = func(x)
    ax.plot(x, y)

    num_figures = 0
    start_x = start_x if start_x is not None else x_range[0]
    start_y = start_y if start_y is not None else y_range[0]

    # 根据图形类型设置排列参数
    if shape in ["hexagon", "triangle"]:
        # 蜂窝排列的y步长:正六边形高为 base_size * √3/2
        y_step = base_size * np.sqrt(3) / 2
        x_offset = base_size / 2
    else:
        y_step = base_size
        x_offset = 0

    row_idx = 0
    for y_i in np.arange(start_y, y_range[1], y_step):
        # 奇数行x轴偏移,实现蜂窝排列
        current_x_start = start_x + (x_offset if row_idx % 2 == 1 else 0)
        for x_i in np.arange(current_x_start, x_range[1], base_size):
            # 计算图形顶点,用于判断是否在曲线范围内
            if shape == "rectangle":
                center = (x_i + base_size/2, y_i + base_size/2)
                vertices = [(x_i, y_i), (x_i+base_size, y_i), (x_i+base_size, y_i+base_size), (x_i, y_i+base_size)]
            elif shape == "triangle":
                center = (x_i + base_size/2, y_i + y_step/2)
                vertices = [(x_i, y_i), (x_i+base_size, y_i), (x_i+base_size/2, y_i + y_step)]
            elif shape == "square":
                center = (x_i + base_size/2, y_i + base_size/2)
                vertices = [(x_i, y_i), (x_i+base_size, y_i), (x_i+base_size, y_i+base_size), (x_i, y_i+base_size)]
            elif shape == "hexagon":
                center = (x_i, y_i + y_step/2)
                angles = np.linspace(0, 2*np.pi, 7)[:-1] + np.pi/2
                vertices = [(center[0] + base_size/2 * np.cos(a), center[1] + y_step * np.sin(a)) for a in angles]

            # 判断图形是否完全在曲线下方
            all_inside = all(func(vx) >= vy for vx, vy in vertices)
            # 判断是否接触曲线(兼容浮点误差)
            touching = any(abs(func(vx) - vy) < 1e-6 or func(vx) >= vy for vx, vy in vertices)

            if (include_touching and (all_inside or touching)) or (not include_touching and all_inside):
                facecolor = 'green' if include_touching else 'red'
                if shape == "rectangle":
                    patch = Rectangle((x_i, y_i), base_size, base_size, facecolor=facecolor)
                elif shape == "triangle":
                    patch = RegularPolygon(center, 3, radius=base_size/np.sqrt(3), orientation=0, facecolor=facecolor)
                elif shape == "square":
                    patch = RegularPolygon(center, 4, radius=base_size/np.sqrt(2), orientation=np.pi/4, facecolor=facecolor)
                elif shape == "hexagon":
                    patch = RegularPolygon(center, 6, radius=base_size/np.sqrt(3), orientation=np.pi/2, facecolor=facecolor)
                ax.add_patch(patch)
                num_figures += 1
        row_idx += 1

    # 固定坐标轴比例,避免图形变形
    ax.set_aspect('equal')
    plt.show()

    integral, _ = quad(func, x_range[0], x_range[1])
    if not include_touching:
        print(f"{num_figures} {shape}(s)完全在函数内部且不接触曲线。基础尺寸{base_size}单位,x范围{x_range},y范围{y_range},函数面积{integral:.4f}。")
    else:
        print(f"{num_figures} {shape}(s)在函数内部(包含接触曲线的)。基础尺寸{base_size}单位,x范围{x_range},y范围{y_range},函数面积{integral:.4f}。")

# 示例函数
def func(x):
    return -0.00002*x**6 + 0.0011*x**5 -0.024 *x**4 + 0.24*x**3 -0.8*x**2 -x + 10

# 调用示例:六边形填充
plot_function_with_pattern(func, x_range=(0, 19.308), y_range=(0, 17.55), base_size=1, shape="hexagon", include_touching=True)

效果说明

修改后,六边形会以蜂窝状紧密排列,消除原有空隙;同时通过顶点判断,确保图形准确贴合曲线范围。

内容的提问来源于stack exchange,提问作者NooberPlays

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 01:15:08