はじめに
MatplotlibとShapelyを使用したテキストのポリゴン化と、gdstk を用いたGDSIIファイル形式への書き出しについて紹介します。
に実行結果は載せています。
以下にその方法を説明します。
必要なライブラリのインポート
まず、必要なライブラリをインポートします。
from matplotlib.textpath import TextPath
from shapely.geometry import Polygon
from matplotlib import font_manager as fm
import matplotlib.pyplot as plt
-
TextPath
はMatplotlib
でテキストからパスを生成するために使用します。 -
font_manager
はフォントのプロパティを管理します。 -
Polygon
はShapely
でポリゴンを扱うためのクラスです。
フォントプロパティの設定
テキストをポリゴン化するためには、フォントの設定が必要です。ここでは、日本語フォントのパスを指定します。
fp = fm.FontProperties(fname='./NotoSerifJP-Regular.otf')
日本語のフォントは、
から好きなフォントのファイルを取得してます。
FontProperties
にはフォントファイルへのパスを指定します。例では、Noto Serif JP
フォントを使用しています。
google colab の方では、
import gdown # https://github.com/wkentaro/gdown
# download data
fileURL="https://drive.google.com/file/d/1ZSovgMRADTRnLAk3K5YlnjcJx1HVeTtF/view?usp=sharing" # download NotoSerifJP-Regular.otf from my drive
localfile="NotoSerifJP-Regular.otf"
gdown.download(fileURL, localfile, quiet=False, fuzzy=True)
のように、私のgoogle drive から、gdown で取得して使うような設定にしてます。
テキストからポリゴンを生成する関数
テキストを受け取り、それをポリゴンに変換する関数を定義します。
def text_to_polygons(text, fontsize, fontprop):
# テキストからTextPathを生成
tp = TextPath((0, 0), text, size=fontsize, prop=fontprop)
# TextPathからポリゴンを生成
polygons = []
for path in tp.to_polygons(closed_only=False):
if len(path) == 0:
continue
exterior = path
polygon = Polygon(exterior)
polygons.append(polygon)
return polygons
この関数は、テキストから TextPath を生成し、そのパスを Polygon オブジェクトに変換します。
コード全文
ジオメトリの生成と確認
from matplotlib.textpath import TextPath
from shapely.geometry import Polygon
from matplotlib import font_manager as fm
import matplotlib.pyplot as plt
# フォントプロパティの設定
fp = fm.FontProperties(fname='./NotoSerifJP-Regular.otf') # 日本語フォントへのパスを指定
def text_to_polygons(text, fontsize, fontprop):
"""
テキストから外周と内部の穴を持つポリゴンを生成する。
Parameters:
text (str): テキスト。
fontsize (int): フォントサイズ。
fontprop (FontProperties): フォントプロパティ。
Returns:
list: Polygonオブジェクトのリスト。
"""
tp = TextPath((0, 0), text, size=fontsize, prop=fontprop)
polygons = []
for path in tp.to_polygons(closed_only=False):
if len(path) == 0:
continue
exterior = path # 外周
polygon = Polygon(exterior) # 内部の穴はないと仮定
polygons.append(polygon)
return polygons
# 使用例
text_polygons = text_to_polygons("2023年12月18日 製作", 100, fp)
# プロット
fig, ax = plt.subplots()
for polygon in text_polygons:
x, y = polygon.exterior.xy
ax.plot(x, y, color="black")
for interior in polygon.interiors:
x, y = interior.xy
ax.plot(x, y, color="red")
ax.set_aspect('equal', adjustable='box')
plt.show()
実行結果
GDSIIファイルへの書き出し
# LSI回路のジオメトリを作成
lib = gdstk.Library()
cell = lib.new_cell("IMAGER_ARRAY")
tag = {
"pixel": {"layer": 1, "datatype": 1},
"int": {"layer": 5, "datatype": 5},
"ext": {"layer": 10, "datatype": 10},
}
# Convert shapely geometries to gdstk polygons
for polygon in text_polygons:
coords = polygon.exterior.coords
cell.add(gdstk.Polygon(coords, **tag["ext"]))
for interior in polygon.interiors:
print ("interior")
coords = interior.coords
cell.add(gdstk.Polygon(coords, **tag["int"]))
# Save the GDS file
outgdsfile="japanese.gds"
lib.write_gds(outgdsfile)
# GDSファイルに保存
lib.write_gds(outgdsfile)
plot_gds_onlypoly(outgdsfile, debug=False)