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

Python螺旋孔图案生成中的孔间距控制技术问题

螺旋孔图案生成:恒定间距控制解决方案

问题描述

生成螺旋孔图案时,需要精准控制孔之间的恒定间距。当前调整theta_step会破坏螺旋形状,调整r的系数只能拉大螺线间距,无法同时满足螺旋形状和恒定孔间距的要求,希望生成保持螺旋形态且孔间距恒定的图案。

原实现代码

import numpy as np
import matplotlib.pyplot as plt
from skimage import transform
import random
import time
import os
from skimage.transform import rescale, resize
from InputOutput.pagailleIO import saveEdf
import numba as nb

@nb.jit(nopython=True)
def create_holes(radius, height):
    patch_size = int(2 * radius + 1)
    x = np.arange(patch_size) - radius
    y = x[:, np.newaxis]
    dist = x**2 + y**2
    hole = np.where(dist < radius**2, 0, height)

    return hole

@nb.jit(nopython=True)
def generate_membranes(Nx, Ny, radius, height, output_path):
    hole = create_holes(radius, height)
    patch_size = hole.shape[0]

    image = np.full((Nx + 2 * patch_size, Ny + 2 * patch_size), height)

    theta_step = 0.0001  # Angular spacing between each hole

    theta = np.arange(0, max([Nx,Ny]) * np.pi, theta_step)
    r = radius * theta / np.pi * 1.414  
    x = np.floor(Nx // 2. + r * np.cos(theta))
    y = np.floor(Ny // 2. + r * np.sin(theta))

    x = np.clip(x, patch_size, Nx + patch_size - 1).astype(np.int32)
    y = np.clip(y, patch_size, Ny + patch_size - 1).astype(np.int32)

    for i in range(len(x)):
        if patch_size < x[i] < Nx + patch_size and patch_size < y[i] < Ny + patch_size:
            patchImage = image[x[i] - radius: x[i] + radius + 1, y[i] - radius: y[i] + radius + 1]
            if np.sum(patchImage) == height * patchImage.size:
                image[x[i] - radius: x[i] + radius + 1, y[i] - radius: y[i] + radius + 1] = hole

    return image

if __name__ == "__main__":    
    Nx = 1030  # Size in pixels in x
    Ny = 3000  # Total size
    radius = 2  # Radius in pixels
    hauteur = 0.00008  # Height in m
    Nx = Nx * 2
    h = hauteur * 1e6

    strPath = '/home/Bureau'
    
    image = generate_membranes(Nx, Ny, radius, h, strPath)

问题根源分析

原代码采用固定角度步长生成螺旋点,螺旋线上相邻点的弧长会随半径r增大而变大(弧长=θ_step*r),导致孔间距随半径增加而逐渐变大,无法保持恒定。仅调整r的缩放系数只能改变螺线整体疏密,无法解决沿螺旋线的间距不均问题。

解决方案:基于弧长步长生成等间距螺旋点

要实现恒定间距,需基于弧长步长生成螺旋点,确保相邻孔沿螺旋线的距离始终一致。采用阿基米德螺旋(r = a*θ),通过反向计算弧长对应的角度增量,生成等间距点。

修改后的代码

import numpy as np
import matplotlib.pyplot as plt
from skimage import transform
import random
import time
import os
from skimage.transform import rescale, resize
from InputOutput.pagailleIO import saveEdf
import numba as nb

@nb.jit(nopython=True)
def create_holes(radius, height):
    patch_size = int(2 * radius + 1)
    x = np.arange(patch_size) - radius
    y = x[:, np.newaxis]
    dist = x**2 + y**2
    hole = np.where(dist < radius**2, 0, height)
    return hole

@nb.jit(nopython=True)
def spiral_arc_length(theta, a):
    # 计算阿基米德螺旋从0到theta的弧长
    sqrt_term = np.sqrt(1 + theta**2)
    return (a / 2) * (theta * sqrt_term + np.log(theta + sqrt_term))

@nb.jit(nopython=True)
def generate_equal_spacing_spiral(Nx, Ny, radius, height, arc_step, a):
    hole = create_holes(radius, height)
    patch_size = hole.shape[0]
    image = np.full((Nx + 2 * patch_size, Ny + 2 * patch_size), height)
    
    center_x = Nx // 2.0
    center_y = Ny // 2.0
    
    # 初始化参数
    theta = 0.0
    current_s = 0.0
    points = []
    
    max_r = max(Nx, Ny) / 2.0 - patch_size  # 避免超出图像边界的最大半径
    while True:
        r = a * theta
        if r > max_r:
            break
        # 计算当前点坐标(偏移patch_size避免边界问题)
        x = np.floor(center_x + r * np.cos(theta)) + patch_size
        y = np.floor(center_y + r * np.sin(theta)) + patch_size
        points.append((int(x), int(y)))
        
        # 用二分法求解下一个theta,确保弧长增加arc_step
        target_s = current_s + arc_step
        theta_low = theta
        theta_high = theta + 1.0
        s_high = spiral_arc_length(theta_high, a)
        
        # 快速扩大上界直到满足弧长要求
        while s_high < target_s:
            theta_high += 1.0
            s_high = spiral_arc_length(theta_high, a)
        
        # 二分迭代精确求解
        for _ in range(20):
            theta_mid = (theta_low + theta_high) / 2
            s_mid = spiral_arc_length(theta_mid, a)
            if s_mid < target_s:
                theta_low = theta_mid
            else:
                theta_high = theta_mid
        
        theta = theta_high
        current_s = target_s
    
    # 绘制孔(跳过已被覆盖的位置)
    for (x, y) in points:
        if patch_size <= x < Nx + patch_size and patch_size <= y < Ny + patch_size:
            patch = image[x - radius:x + radius + 1, y - radius:y + radius + 1]
            if np.sum(patch) == height * patch.size:
                image[x - radius:x + radius + 1, y - radius:y + radius + 1] = hole
    return image

if __name__ == "__main__":    
    Nx = 1030 * 2  # X方向像素尺寸
    Ny = 3000       # Y方向像素尺寸
    radius = 2      # 孔半径(像素)
    hauteur = 0.00008  # 高度(米)
    h = hauteur * 1e6

    strPath = '/home/Bureau'
    
    # 关键可调参数
    arc_step = 10.0  # 孔之间的恒定弧长间距(像素,数值越大间距越大)
    a = 5.0          # 阿基米德螺旋系数,控制螺距(a越大,圈与圈间距越大)
    
    image = generate_equal_spacing_spiral(Nx, Ny, radius, h, arc_step, a)
    # 可选:保存或预览图像
    # saveEdf(image, os.path.join(strPath, "spiral_membrane.edf"))
    # plt.imshow(image, cmap='gray')
    # plt.show()

参数说明

  • arc_step:沿螺旋线的孔间距(单位:像素),直接控制孔之间的恒定距离,数值越大间距越大。
  • a:阿基米德螺旋系数,控制螺线的圈间距(螺距=2π*a),数值越大,相邻螺旋圈之间的距离越宽。

方案优势

  • 严格保证沿螺旋线的孔间距恒定,不会随半径增大而变化。
  • 螺旋形状稳定,通过arc_step和a可分别独立控制孔间距和螺线疏密。
  • 保留numba加速,生成效率与原代码持平。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 11:42:04