gdstk布尔运算速度远慢于Klayout,求高效实现方案
在gdstk中高效实现矩形批量裁剪孔洞
问题根源
- 循环裁剪的低效性:你之前逐个对每个椭圆执行布尔运算,每次调用
gdstk.boolean都会产生初始化和运算开销,当图形数量较多时,累积的开销会导致速度急剧下降。 - 批量运算返回空的原因:你在
clipcell中同时添加了裁剪后的孔洞和原始大矩形box,导致clipFlat.polygons包含了box本身。执行gdstk.boolean(box,pols, "not")相当于用box减去box加上所有孔洞,结果自然为空。
优化方案
关键修改思路
- 批量布尔运算:将所有椭圆合并为一个集合,一次性与mask执行
not运算,替代循环逐个处理,大幅减少运算次数。 - 清理运算集合:确保用于减法的图形集合只包含需要裁剪的孔洞,不混入原始矩形。
优化后的代码
import gdstk # 参数定义 dc =5.8 eps = 1/20 cW=2000 d = 70 cL = 10000 g = dc/(1.4*(eps)**0.48) # 创建GDS库和单元 lib = gdstk.Library() pD = lib.new_cell("post") pRow = lib.new_cell("pArray") pRef = lib.new_cell("pRef") inv = lib.new_cell("invDld") # 构建基础图形 pD.add(gdstk.ellipse((0,0), d/2, tolerance=0.01)) # 阵列单元 box = gdstk.rectangle((-cL/2,-cW/2),(cL/2,cW/2)) # 原始矩形 ny = int(cL / (g + d)) + 1 # 列数 nx = int(cW / (g + d)) + 1 # 行数 spc = d + g # 阵列间距 extras = int(ny*eps) + 1 # 创建椭圆阵列 for i in range(ny): arr = gdstk.Reference(pD, origin = (i*spc,i*eps*spc - extras*spc), columns = 1, rows= nx + extras, spacing = (0,spc)) pRow.add(arr) rowRef = gdstk.Reference(pRow, origin = (-cL/2,-cW/2), columns = 1, rows= 1, spacing = (0,0)) pRef.add(rowRef) # 创建边缘裁剪mask mask = gdstk.boolean(gdstk.offset(box, (extras+2)*spc)[0], box, 'not')[0] # 批量裁剪椭圆:一次性处理所有椭圆与mask的布尔运算 all_pols = pRef.flatten().polygons # 用mask裁剪所有椭圆,保留在box内的部分 clipped_pols = gdstk.boolean(all_pols, mask, "not") # 过滤掉面积过小的碎片 valid_pols = [pol for pol in clipped_pols if pol.area() > 25] # 执行最终的减法运算:从box中减去所有有效孔洞 result = gdstk.boolean(box, valid_pols, "not")[0] inv.add(result) # 清理临时单元并导出GDS lib.remove(pRef, pRow, pD) lib.write_gds("optimizedExample.gds")
优化点说明
- 批量裁剪:
gdstk.boolean(all_pols, mask, "not")一次性对所有椭圆执行裁剪,避免了循环的重复开销,速度与Klayout的批量操作接近。 - 结果修正:只将有效孔洞传入最终的减法运算,确保
box减去的是纯粹的孔洞集合,得到正确的带孔矩形。 - 代码简化:移除了不必要的
clip中间单元,减少了图形扁平化的次数,进一步提升效率。
内容的提问来源于stack exchange,提问作者Shrinivas Ganti
相关产品推荐
相关产品推荐

