やること
断面二次モーメントを求める
断面二次モーメントを計算する方法は二つある。
断面形状の…
- 長さ寸法と理論式を使って計算する方法
- 座標値を使って、数値計算的に計算する方法。
がある。ここでは2をやる。
1と2の違いは、
積分を形状別に解いて消してから、計算する場合
と、
積分を、狽ナ模擬してそのまま計算する場合
の違い。
ここでは、後者をやる。
任意形状の断面二次モーメントを求める
このページでは、閉じた線で描かれた任意形状の、x、y座標を使って、(面積や)断面二次モーメントを求める手順を考えてみた。
- 断面形状の縁を、閉じた線で描く様な、x,y座標を得る。
- 1を使って面積を求める。
- zに関する、もしくはyに関する断面一次モーメントを求める。
- 図心を求める。
図心(y,z)=(z軸に関する断面一次モーメント, y軸に関する断面一次モーメント)/面積 - 1の座標から4の図心を引いた値を作り、その図形の断面二次モーメントを計算する。
普通は、断面二次モーメントの計算には理論式を使う。
断面二次モーメントは、普通、
- 長さ寸法と理論式を使って計算する。
これを実行するには…- 式を知っている必要がある。
(→式が書いてある本等が要る)
(下記amazon参照) - 断面形状によって式が違う。
- 任意形状では式がない。
- 式を知っている必要がある。
- 理論式がない形状の場合、(solidworksなどの)有名なソフトの断面性能表示機能を使う。
- 有償ソフトが使用できない場合、エクセルなどで自作する。(このページではexcelでやらない。pythonでやる。excelだって有料。)
のどれかで計算すると思う。
2つめ、3つめは、コンピュータで計算するので、理論値からの誤差がある。
←電子化(pdf(メニュー検索機能付き))全部入りDVD←
→1冊/全29冊 紙媒体 目的の式がある。→
↑断面二次モーメントの式が入っている。
長さ寸法を使うなら上の本などを使って計算されたし。
前述したが、閉じた線で描かれた任意形状の、x、y座標を使って、(面積や)断面二次モーメントを求める
1~5をやってみる
1. 文字データのx,y座標の取得
使用する座標値一覧は下の表。閉じた線を表す座標で、図形を表現している。これらの図形は、図心を中心にして作っていない。
図形 | 座標値 | |
---|---|---|
四角 | x | [0,1,2,3,4,5,6,7,8,9,10,10,10,10,10,10,10,10,10,10,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0] |
y | [10,10,10,10,10,10,10,10,10,10,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10] | |
せん断変換した四角 | x | [41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0, 51.0, 49.0, 47.0, 45.0, 43.0, 41.0, 39.0, 37.0, 35.0, 33.0, 31.0, 30.0, 29.0, 28.0, 27.0, 26.0, 25.0, 24.0, 23.0, 22.0, 21.0, 23.0, 25.0, 27.0, 29.0, 31.0, 33.0, 35.0, 37.0, 39.0, 41.0] |
y | [17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0, 9.0, 8.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0] | |
45度回転した四角 | x | [16.97056274847714, 17.67766952966369, 18.384776310850235, 19.09188309203678, 19.798989873223327, 20.506096654409877, 21.213203435596427, 21.920310216782973, 22.62741699796952, 23.334523779156065, 24.041630560342615, 23.334523779156065, 22.62741699796952, 21.920310216782973, 21.213203435596427, 20.506096654409877, 19.798989873223327, 19.09188309203678, 18.384776310850235, 17.67766952966369, 16.97056274847714, 16.26345596729059, 15.556349186104043, 14.849242404917495, 14.14213562373095, 13.435028842544401, 12.727922061357853, 12.020815280171306, 11.31370849898476, 10.606601717798211, 9.899494936611664, 10.606601717798211, 11.31370849898476, 12.020815280171306, 12.727922061357853, 13.435028842544401, 14.14213562373095, 14.849242404917495, 15.556349186104043, 16.26345596729059, 16.97056274847714] |
y | [7.0710678118654755, 6.363961030678928, 5.65685424949238, 4.949747468305833, 4.242640687119286, 3.5355339059327378, 2.82842712474619, 2.1213203435596437, 1.4142135623730958, 0.7071067811865479, 0.0, -0.7071067811865479, -1.4142135623730958, -2.1213203435596437, -2.82842712474619, -3.5355339059327378, -4.242640687119286, -4.949747468305833, -5.65685424949238, -6.363961030678928, -7.0710678118654755, -6.363961030678928, -5.65685424949238, -4.949747468305832, -4.242640687119286, -3.5355339059327378, -2.82842712474619, -2.121320343559643, -1.4142135623730958, -0.7071067811865479, 0.0, 0.7071067811865479, 1.4142135623730958, 2.121320343559643, 2.82842712474619, 3.5355339059327378, 4.242640687119286, 4.949747468305832, 5.65685424949238, 6.363961030678928, 7.0710678118654755] | |
丸 | x | [1.0, 0.94581724, 0.78914051, 0.54694816, 0.24548549, -0.08257935, -0.40169542, -0.67728157, -0.87947375, -0.9863613, -0.9863613, -0.87947375, -0.67728157, -0.40169542, -0.08257935, 0.24548549, 0.54694816, 0.78914051, 0.94581724, 1.0] |
y | [0.0, 3.24699469e-01, 6.14212713e-01, 8.37166478e-01, 9.69400266e-01, 9.96584493e-01, 9.15773327e-01, 7.35723911e-01, 4.75947393e-01, 1.64594590e-01, -1.64594590e-01, -4.75947393e-01, -7.35723911e-01, -9.15773327e-01, -9.96584493e-01, -9.69400266e-01, -8.37166478e-01, -6.14212713e-01, -3.24699469e-01, 0.0] | |
穴あき四角 | x | [[0,1,2,3,4,5,6,7,8,9,10,10,10,10,10,10,10,10,10,10,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0],[1,1,1,1,1,1,1,1,1,2,3,4,5,6,7,8,9,9,9,9,9,9,9,9,9,8,7,6,5,4,3,2,1]] |
y | [[10,10,10,10,10,10,10,10,10,10,10,9,8,7,6,5,4,3,2,1,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10],[9,8,7,6,5,4,3,2,1,1,1,1,1,1,1,1,1,2,3,4,5,6,7,8,9,9,9,9,9,9,9,9,9]] | |
ひらがなの「あ」 | x | [[1190, 1121.0, 1153, 1319.0, 1581.0, 1825.0, 1567.0, 1061.0, 1045, 1692.0, 1547.0, 1323.0, 1180.0, 910.0, 920.0, 930.0, 942.0, 899.0, 860.0, 797.0, 410.0, 244.0, 510.0, 797.0, 806.0, 811.0, 815, 717.0, 404.0, 443, 672.0, 824.0, 828, 830, 838.0, 738.0, 766, 981.0, 961.0, 930.0, 1182.0, 1186.0, 1243.0, 1321.0, 1405.0, 1434.0, 1393.0, 916.0, 893.0, 1190.0], [1194, 889.0, 887.0, 895.0, 1137.0, 1194.0], [793, 789.0, 790.0, 793.0, 621.0, 371.0, 459.0, 793.0]] |
y | [[1008, 1094.0, 1130, 1006.0, 926.0, 541.0, 86.0, -74.0, -27, 541.0, 846.0, 938.0, 639.0, 332.0, 286.0, 250.0, 174.0, 57.0, 35.0, 240.0, 63.0, 268.0, 749.0, 913.0, 1054.0, 1124.0, 1176, 1171.0, 1333.0, 1366, 1251.0, 1262.0, 1307, 1343, 1462.0, 1618.0, 1661, 1522.0, 1421.0, 1280.0, 1356.0, 1358.0, 1393.0, 1419.0, 1399.0, 1366.0, 1321.0, 1186.0, 948.0, 1008.0], [942, 874.0, 680.0, 432.0, 786.0, 942.0], [334, 561.0, 663.0, 831.0, 719.0, 272.0, 163.0, 334.0]] | |
数字の「8」 | x | [[908, 613.0, 740.0, 1043.0, 1322.0, 1459.0, 1143.0, 1528.0, 1401.0, 1028.0, 695.0, 535.0, 908.0], [1065, 1082.0, 1088, 1330.0, 1266.0, 1043.0, 877.0, 752.0, 850.0, 977.0, 1065.0], [977, 957.0, 668.0, 768.0, 1026.0, 1260.0, 1366.0, 1255.0, 1088.0, 977.0]] |
y | [[856, 1225.0, 1477.0, 1573.0, 1495.0, 1231.0, 893.0, 457.0, 187.0, 74.0, 162.0, 453.0, 856.0], [924, 930.0, 934, 1231.0, 1413.0, 1507.0, 1460.0, 1229.0, 1043.0, 963.0, 924.0], [824, 814.0, 455.0, 234.0, 140.0, 222.0, 449.0, 664.0, 777.0, 824.0]] |
上の表の座標値の作り方に関しては3種類あり…
- 四角は、試行錯誤しながら手打ち。穴あきも苦労したが手打ち。四角だったから何とか打てた。蕎麦みたいな書きっぷり。
- せん断、45度回転は、アフィン変換して作った。
- 丸は、x座標はcosθ、y座標はsinθ (0<=θ<=2πを20分割(N=20))で作った。cosとかsinは、pythonのmathモジュールを使った。
ひらがなの「あ」、数字の「8」は、先月のページのやり方で作った。
このページ下部に、フォントの文字データのx,y座標が取得のためのコードを載せました。
(先月のと同じ内容です。IPAフォントのインストールを忘れずに。)フォントファイルのグリフのベクターを座標データに変換しています。
#!/usr/bin/env python
# -*- coding: cp932 -*-
x=ここに上表の右列のxを入力
y=ここに上表の右列のyを入力
こんな感じで変数x,yに入れておき、後のコードで使う。
変数x、yは、曲線のx座標y座標が入った配列です。
また、変数x2、y2の中には、一文字を表すために必要なパーツの分だけ、配列が入っています。
つまり、漢数字の「一」は一筆書できるので1つしか配列が入っていませんが、
同じ漢数字の「二」には配列が二つ(長さ2の配列)入っています。
上の座標を示して描ける線の特徴として、
- 閉じた線
- 外側が時計回り、内側が反時計回り
などがあります。
閉じた線
線を指定する座標は、最初の一点目の座標と同じ座標で終わるように作りました。線の途中で交差したりしていません。線の途中で交差すると、面積の計算に不都合があります。
時計回り、反時計回り。
閉じた線のx、y座標をあらわす配列が、時計回りに動いているか、それとも反時計回りに動いているかは、少なくとも下の二つの用途で重要です。
- 文字の描画
「の」や「○(まる)」などの穴開き文字(正式名称はあるのかすら知らない)に関しては、穴が開いている部分を表す配列が反時計回りになっている。下の図でいう緑の線。
- 面積の計算
∫ydxすると、xが+に動くときdxが+に、xが-に動くときdxが-になる。これがうまい具合に効いて、閉じた曲線の面積が求まる。
また、時計回り、反時計回りが切り替わると、負の面積が出ることがある。負の面積によって、文字の穴空き部分の面積が引き算される仕組みになっている。
閉じた線の中で、交差があるとコレがうまくいかない。
断面形状の縁x、y座標をプロットする
2画以上の文字や、穴空き文字を表現するため、変数x,yは長さが1の配列ではない場合があります。
だから、matplotlib.pyplot.plotでそのまま使えません。matplotlib.pyplot.plotは、x,yの引数は、N*1のリストとかだからです。(Excelで折れ線グラフ一本書くときは、x,yそれぞれ一列ずつ選ぶのと一緒)
一つの変数の中に、たくさん作図すべき閉じた線が含まれる事があるので、
繰り返し構文+indexingで、plotしました。
上の表の座標を
x=
y=
とか書いた後に、下記コードの実行でx、yをプロットできます。
- 必要なモジュール
- matplotlib
- datetime
- time
#!/usr/bin/env python
# -*- coding: cp932 -*-
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'IPAGothic'
import time
from datetime import datetime as dt
f,(ax1) = plt.subplots(1,1)
if len(np.shape(y))==1:
ax1.plot(x,y)
ax1.scatter(x,y,facecolor=[0,0,0,0.3],edgecolor=[0,0,0])
else:
for i in range(len(x)):
ax1.plot(x[i],y[i])
ax1.scatter(x[i],y[i],facecolor=[0,0,0,0.3],edgecolor=[0,0,0])
ax1.set_aspect("equal")
#plt.show()
tdatetime = dt.now()
timtext = tdatetime.strftime('%Y%m%d'+ time.ctime()[11:13] + time.ctime()[14:16] + time.ctime()[17:19])
fname = "%s.png"%(timtext)
plt.savefig(fname)
plt.close()
2.1を使って面積を求める。
x、yでプロットされた図形の面積は台形則で求める。
面積を計算するだけなので、関数とか要らないけど、
これを、台形則で模擬します。
#!/usr/bin/env python
# -*- coding: cp932 -*-
import numpy as np
A=0if type(x[0])!=list:
dx = [x[i+1]-x[i] for i in range(len(x)-1)]
trapzy = [(y[i]+y[i+1])/2.0 for i in range(len(y)-1)]
A = sum([trapzy[i]*dx[i] for i in range(len(y)-1)])
else:
for j in range(len(x)):#1文字に、複数の閉じた線が存在する場合対策
dx = [x[j][i+1]-x[j][i] for i in range(len(x[j])-1)]
trapzy = [(y[j][i]+y[j][i+1])/2.0 for i in range(len(y[j])-1)]
A1 = sum([trapzy[i]*dx[i] for i in range(len(y[j])-1)])
A = A+A1
print A
曲線とは一致しないとは思いますが、曲線を間引いたデータとしては、正しい値が出てくると思います。もちろん細かく座標点をとればとるほど、正確な値に近づきます。
PCで扱うデータは、しょせん間が抜けた折れ線データに過ぎないので、面積に関しては 台形則で表してもいいと思います。
ついでに せん断変形で、面積が変わっていない事を確認
せん断写像のwikipediaにそう書いてあったきがする ので、せん断前後で面積に変化がない事を確認する。
せん断変換前後の図形のx,y座標をせん断変換(アフィン変換)で用意したので、
座標から面積を計算した結果を比較すると、せん断変形しようが、面積は変わらないことが確認できました。
もう理論値からズレてる。
曲線をPCで表現するとき、当然細かい折れ線で描く事になります。
間引いた折れ線データを取得した時点で、データに誤差が生じています。
だから、この後の操作がどんなに正しくとも、座標点として記録した時点で理論値からのズレはあります。
「それでもやるとしたら、どうすべきなの?」という観点で見て下さい。
半径1の円で、線の間引き方によって、値がずれていることが確認できるので載せました。
3. zに関する、もしくはyに関する断面一次モーメントを求める。
y軸に関する断面一次モーメント $$\int y\ dA$$
x軸に関する断面一次モーメント$$\int x\ dA$$
断面一次モーメントは、図形がどの位置に描いてあるかによって、値が変わります。
原点から離れるほど大きくなります。
断面二次モーメントを計算する時も、図形が原点から離れるほど大きくなります。断面二次モーメントは、図心を原点と一致させてから求めることになります。次の手順4で、図形の重心(図心)を求めます。
断面一次モーメントは、その図心を求めるために計算します。
断面一次モーメントを求めるコードは下のように書いてみました。
#!/usr/bin/env python
# -*- coding: cp932 -*-
import numpy as np
C1=0
if type(x[0])!=list:
dx = [x[i+1]-x[i] for i in range(len(x)-1)]
trapzy = [((y[i]+y[i+1])/2.0)*((x[i]+x[i+1])/2.0) for i in range(len(y)-1)]
C = sum([trapzy[i]*dx[i] for i in range(len(y)-1)])
C1 = C1+C
else:
for j in range(len(x)):#1文字に、複数のベクトルが存在する場合対策
dx = [x[j][i+1]-x[j][i] for i in range(len(x[j])-1)]
trapzy = [((y[j][i]+y[j][i+1])/2.0)*((x[j][i]+x[j][i+1])/2.0) for i in range(len(y[j])-1)]
C2 = sum([trapzy[i]*dx[i] for i in range(len(y[j])-1)])
C1 = C1+C2
print("X:%s"%(C1))
C3=0
if type(x[0])!=list:
dy = [y[i+1]-y[i] for i in range(len(x)-1)]
trapzx = [((y[i]+y[i+1])/2.0)*((x[i]+x[i+1])/2.0) for i in range(len(y)-1)]
C4 = sum([trapzx[i]*dy[i] for i in range(len(y)-1)])*-1
C3 = C3+C4
else:
for j in range(len(x)):#1文字に、複数のベクトルが存在する場合対策
dy = [y[j][i+1]-y[j][i] for i in range(len(x[j])-1)]
trapzx = [((y[j][i]+y[j][i+1])/2.0)*((x[j][i]+x[j][i+1])/2.0) for i in range(len(y[j])-1)]
C4 = sum([trapzx[i]*dy[i] for i in range(len(y[j])-1)])*-1
C3 = C3+C4
print("Y:%s"%(C3))
4. 図心を求める。
図心(x,y)=(y軸に関する断面一次モーメント, x軸に関する断面一次モーメント)/面積
あえて書く必要はない気がするけど、
先ず、面積を計算する。
断面一次モーメントを計算する
断面一次/面積
してるのが下記。
#!/usr/bin/env python
# -*- coding: cp932 -*-
import numpy as np
A=0
if type(x[0])!=list:
dx = [x[i+1]-x[i] for i in range(len(x)-1)]
trapzy = [(y[i]+y[i+1])/2.0 for i in range(len(y)-1)]
A = sum([trapzy[i]*dx[i] for i in range(len(y)-1)])
else:
for j in range(len(x)):#1文字に、複数の閉じた線が存在する場合対策
dx = [x[j][i+1]-x[j][i] for i in range(len(x[j])-1)]
trapzy = [(y[j][i]+y[j][i+1])/2.0 for i in range(len(y[j])-1)]
A1 = sum([trapzy[i]*dx[i] for i in range(len(y[j])-1)])
A = A+A1
print A
C1=0
if type(x[0])!=list:
dx = [x[i+1]-x[i] for i in range(len(x)-1)]
trapzy = [((y[i]+y[i+1])/2.0)*((x[i]+x[i+1])/2.0) for i in range(len(y)-1)]
C = sum([trapzy[i]*dx[i] for i in range(len(y)-1)])
C1 = C1+C
else:
for j in range(len(x)):#1文字に、複数のベクトルが存在する場合対策
dx = [x[j][i+1]-x[j][i] for i in range(len(x[j])-1)]
trapzy = [((y[j][i]+y[j][i+1])/2.0)*((x[j][i]+x[j][i+ 1])/2.0) for i in range(len(y[j])-1)]
C2 = sum([trapzy[i]*dx[i] for i in range(len(y[j])-1)])
C1 = C1+C2
print("X:%s"%(C1))
C3=0
if type(x[0])!=list:
dy = [y[i+1]-y[i] for i in range(len(x)-1)]
trapzx = [((y[i]+y[i+1])/2.0)*((x[i]+x[i+1])/2.0) for i in range(len(y)-1)]
C4 = sum([trapzx[i]*dy[i] for i in range(len(y)-1)])*-1
C3 = C3+C4
else:
for j in range(len(x)):#1文字に、複数のベクトルが存在する場合対策
dy = [y[j][i+1]-y[j][i] for i in range(len(x[j])-1)]
trapzx = [((y[j][i]+y[j][i+1])/2.0)*((x[j][i]+x[j][i+1])/2.0) for i in range(len(y[j])-1)]
C4 = sum([trapzx[i]*dy[i] for i in range(len(y[j])-1)])*-1
C3 = C3+C4
print("Y:%s"%(C3))
print "First x moment of area%s"%(C1/A)
print "First y moment of area%s"%(C3/A)
5. 1の座標から4の図心を引いた値を作り、その図形の断面二次モーメントを計算する。
材料力学の教科書とか、ネット検索とから、
$$\int y^2\ dA$$
途中で $$\frac{1}{3} y^3$$ と、1/3が出てきたり、y3とか3乗になったりする点も気を付けたい。
これをx,y座標から数値積分で求めたい。
先ず台形則で、積分を模擬してみた。(本当は二次の積分を台形則で模擬してはいけない気がしている。)
これまで、コードを載せてきたが、この断面二次モーメントの算出の仕方は、間違っているため、まだ載せない。
理論値からずれているのだ。
(ずれていると判定するのに使った理論値は来月載せます。)
理論値からのずれ(誤差)は、なぜ起こるのか。積分を模擬する手法が台形則だからだと思う。
誤差がないものは、何でないのか?
水平、垂直に線が伸びている形状に関しては誤差がない。
斜めに線が伸びている形状は、誤差が大きい。
ここで、キレイなグラフを用意して説明しようとしたのだが、時間と通信残量制限との兼ね合いで、中途半端なままアップロードする。
これに関して改善するには、台形則(一次)で表現している部分をシンプソン則(二次)で表現する必要がありそうですが、来月に続きます。
今月使用した、断面二次モーメントの算出時の積分方法(台形則)と、
シンプソン則を比較したいと思います。多分、違ってくるはず、だと思いたい。不安になってきた。
今月は**「断面二次モーメントを、座標点の配列から計算する(1)計算手順編」**だったのに対し、
来月は**「断面二次モーメントを、座標点の配列から計算する(1)積分模擬変」**にしたいと思う。変って気づいたけど直さない。
8月中に間に合わんかったし、まだとちゅうだが、これは14000文字超えの超大作なので、まあゆるせ。というか間に合ってはいた。auの通信則で制限のせいだから。おらは悪くねぇだ。長続きしていると思う。
続きを読む