任意断面の二次モーメントを求めたくなることがある
CADや外部ツールを使わずにサクッとやりたいので、画像から求めてみた
使用ツール
- Python 3.12.4 (Pillow, NumPy)
- 任意のお絵描きツール
お絵描き
計算する断面の画像をつくる
今回はGoogleスライドで H-100×100×6×8(r=8)の断面を描いた
jpgでダウンロードしておく
画像の読み込み
グレースケール画像をnumpy配列で読み込み、適当なしきい値でブール配列にする
moment.py
from PIL import Image
import numpy as np
image = Image.open("H-100x100x6x8.jpg").convert('L')
image_array = np.array(image)
image_bool = image_array < 128
準備
- 図心軸
簡単のために画像の中心とする
moment.py
axis = image_array.shape[0] / 2
- 1ピクセル当たりの長さ
1ピクセルが何ミリになるのかをセット
今回は標準的な 1px=0.26458mm
ピクセル当たりの面積も出しておく
moment.py
millimeter_per_pixel = 0.26458
area_of_pixel = millimeter_per_pixel**2
- 断面二次モーメント
英語で断面二次モーメントは moment of inertia of area というらしい
初期値0をセット
moment.py
moment_inertia_area = 0
ループで計算
ピクセルごとに断面が存在(True)すれば図心軸からの距離を求め、面積と掛けて moment_inertia_area に足していく
moment.py
for y in range(len(image_bool)):
for x in range(len(image_bool[y])):
if image_bool[y][x]:
dist_y = abs(axis - y) * millimeter_per_pixel
moment_inertia_area += dist_y**2 * area_of_pixel
結果
>python moment.py
3712979.0451532584
解析値は 3780000mm4 程度になるので、2%弱の誤差がある
他の断面でも解析値より 1~2%小さくなった
とりあえずざっくりは使えるが、どこかで誤差が出ているのか気になる
numpyっぽい書き方にもしたいが分からず
スクリプト全体
from PIL import Image
import numpy as np
image = Image.open("H-100x100x6x8.jpg").convert('L')
image_array = np.array(image)
image_bool = image_array < 128
axis = image_array.shape[0] / 2
millimeter_per_pixel = 0.26458
area_of_pixel = millimeter_per_pixel**2
moment_inertia_area = 0
for y in range(len(image_bool)):
for x in range(len(image_bool[y])):
if image_bool[y][x]:
dist_y = abs(axis - y) * millimeter_per_pixel
moment_inertia_area += dist_y**2 * area_of_pixel
print(moment_inertia_area)