matplotlib RC円形圧力トンネルモデル図
はじめに
以下に示す、「設計 RC円形圧力トンネルの配筋設計(1)」で示した図を作成するプログラムである。
ポイント
アノーテーション用矢印とテキスト描画
- 説明用のボックス内テキストと矢印を描画する。
- matplotlib では、annotate により、矢印とテキストを同時に描画できるが、矢印とテキストの関係が思うようにいかないため、ここでは、矢印とボックス内テキストを別々に描画し、連結させている。
- 矢印の色は濃い灰色とし、線の太さは細目に設定。
- bbox_props を定義し、plt.text の中で bbox=bbox_props とすることにより定義したボックス内に文字を描画する。
- この事例では、描画する文字列が2行にわたっているが、行間を詰めるため、plt.text の中で linespacing=1 を指定している。
- 引数の説明は以下の通り。
x1, y1 | 矢印先端座標 |
x2, y2 | 矢印線始点座標(文字列ボックスとの接点座標) |
ss | 描画文字列 |
lstr | ボックスから出る矢印の位置(文字列 l, t, r, b, n のいずれかで指定) |
fszz | 描画文字列のフォントサイズ |
- lstr は、1文字で指定し、その意味は以下の通り。
'l' | 矢印線はボックスの左からスタート |
't' | 矢印線はボックスの上からスタート |
'r' | 矢印線はボックスの右からスタート |
'b' | 矢印線はボックスの下からスタート |
'n' | 矢印は描かず、(x1, y1)、(x2, y2)で指定した2点の中央にボックス入り文字列を描画 |
def sarrow_a(x1,y1,x2,y2,ss,lstr,fszz): # arrow for annotation if lstr=='n': x2=0.5*(x1+x2) y2=0.5*(y1+y2) else: col='#777777' sv=0 aprop=dict(shrink=sv,width=0.3,headwidth=4,headlength=8, connectionstyle='arc3',facecolor=col,edgecolor=col) plt.annotate('', xy=(x1,y1), xycoords='data', xytext=(x2,y2), textcoords='data', fontsize=0, arrowprops=aprop) # text drawing bbox_props = dict(boxstyle='square,pad=0.1', fc='#ffffff', ec='#777777', lw=1) if lstr=='l': hstr='right'; vstr='center' if lstr=='t': hstr='center'; vstr='top' if lstr=='r': hstr='left'; vstr='center' if lstr=='b': hstr='center'; vstr='bottom' if lstr=='n': hstr='center'; vstr='center' plt.text(x2,y2,ss,ha=hstr,va=vstr,fontsize=fszz,bbox=bbox_props,linespacing=1)
荷重用矢印
矢印の色は黒とし、線は太めに設定。
def sarrow_p(x1,y1,x2,y2): # arrow for load col='#000000' sv=0 aprop=dict(shrink=sv,width=1,headwidth=5,headlength=8, connectionstyle='arc3',facecolor=col,edgecolor=col) plt.annotate('', xy=(x1,y1), xycoords='data', xytext=(x2,y2), textcoords='data', fontsize=0, arrowprops=aprop)
ひび割れ描画
コンクリート内のひび割れは、サインカーブで定義。
まず、座標 - 間でサインカーブを定義し、これを座標変換しながら anga
で定めた角度に描画していく。
def crack(ra,rb): ds=0.2 m=4 ell=(rb-ra)/m x0=np.linspace(ra,rb,101) y0=ds*np.sin(2*np.pi/ell*x0) anga=np.linspace(0,2*np.pi,13) for ang in anga: x=x0*np.cos(ang)-y0*np.sin(ang) y=x0*np.sin(ang)+y0*np.cos(ang) plt.plot(x,y,'-',color='#999999')
塗りつぶし
ハッチングの場合
color
でハッチングの色を指定できる。ここでは濃い灰色を指定。ハッチングはクロス線で行う。
plt.fill(xr,yr,fill=False, color='#999999',hatch='xx',lw=0)
単色で塗りつぶす場合
facecolor
で塗りつぶす領域の色を、edgecolor
で境界の色を指定する。
plt.fill(xb,yb,facecolor='#eeeeee',edgecolor='#000000',lw=1)
円を描く
np.linspace
で、 から を分割して角度を指定して 座標を求め、これを折れ線で結んでいく。
angc=np.linspace(0,2*np.pi,181) # for concrete outline xfa=rfa*np.cos(angc) yfa=rfa*np.sin(angc) plt.plot(xfa,yfa,color='#000000',lw=3)
太字の描画
この場合はタイトル描画のために使っているが、fontweight='bold'
で太字を描画できる。
plt.title(tstr,loc='center',fontsize=fsz,fontweight='bold')
プログラム全文
import numpy as np import matplotlib.pyplot as plt # Global variables fsz=12 xmin=-10 ; xmax=10; dx=5 ymin=-10; ymax=10; dy=5 def sarrow_a(x1,y1,x2,y2,ss,lstr,fszz): # arrow for annotation if lstr=='n': x2=0.5*(x1+x2) y2=0.5*(y1+y2) else: col='#777777' sv=0 aprop=dict(shrink=sv,width=0.3,headwidth=4,headlength=8, connectionstyle='arc3',facecolor=col,edgecolor=col) plt.annotate('', xy=(x1,y1), xycoords='data', xytext=(x2,y2), textcoords='data', fontsize=0, arrowprops=aprop) # text drawing bbox_props = dict(boxstyle='square,pad=0.1', fc='#ffffff', ec='#777777', lw=1) if lstr=='l': hstr='right'; vstr='center' if lstr=='t': hstr='center'; vstr='top' if lstr=='r': hstr='left'; vstr='center' if lstr=='b': hstr='center'; vstr='bottom' if lstr=='n': hstr='center'; vstr='center' plt.text(x2,y2,ss,ha=hstr,va=vstr,fontsize=fszz,bbox=bbox_props,linespacing=1) def sarrow_p(x1,y1,x2,y2): # arrow for load col='#000000' sv=0 aprop=dict(shrink=sv,width=1,headwidth=5,headlength=8, connectionstyle='arc3',facecolor=col,edgecolor=col) plt.annotate('', xy=(x1,y1), xycoords='data', xytext=(x2,y2), textcoords='data', fontsize=0, arrowprops=aprop) def crack(ra,rb): ds=0.2 m=4 ell=(rb-ra)/m x0=np.linspace(ra,rb,101) y0=ds*np.sin(2*np.pi/ell*x0) anga=np.linspace(0,2*np.pi,13) for ang in anga: x=x0*np.cos(ang)-y0*np.sin(ang) y=x0*np.sin(ang)+y0*np.cos(ang) plt.plot(x,y,'-',color='#999999') def drawfig(nnn): ra=4 # inner surface rb=7 # outer surface pl=1 # length of load arrow br=rb+1.5 # bedrock area rfa=ra+0.6 # inner reinforcement rfb=rb-0.6 # outer reinforcement angc=np.linspace(0,2*np.pi,181) # for concrete outline angp=np.linspace(0,2*np.pi,19) # for load arrow if nnn==121: tstr='RC Pressure Tunnel under Internal Pressure\n(Double reinforcement model)' if nnn==122: tstr='RC Pressure Tunnel under External Pressure\n(Double reinforcement model)' plt.subplot(nnn) plt.xlim([xmin,xmax]) plt.ylim([ymin,ymax]) plt.axis('off') plt.gca().set_aspect('equal',adjustable='box') plt.title(tstr,loc='center',fontsize=fsz,fontweight='bold') if nnn==121: # hatching of bedrock area xr=br*np.cos(angc) yr=br*np.sin(angc) plt.fill(xr,yr,fill=False, color='#999999',hatch='xx',lw=0) # outer surface line of concrete xb=rb*np.cos(angc) yb=rb*np.sin(angc) plt.fill(xb,yb,facecolor='#eeeeee',edgecolor='#000000',lw=1) # inner surface line of concrete xa=ra*np.cos(angc) ya=ra*np.sin(angc) plt.fill(xa,ya,facecolor='#ffffff',edgecolor='#000000',lw=1) # drawing cracks if nnn==121: crack(ra,rb) # inner reinforcement xfa=rfa*np.cos(angc) yfa=rfa*np.sin(angc) plt.plot(xfa,yfa,color='#000000',lw=3) # outer reinforcement xfb=rfb*np.cos(angc) yfb=rfb*np.sin(angc) plt.plot(xfb,yfb,color='#000000',lw=3) # pressure load drawing if nnn==121: r1=ra; r2=ra-pl if nnn==122: r1=rb; r2=rb+pl xp1=r1*np.cos(angp) # x-coordinate of end of arrow line yp1=r1*np.sin(angp) # y-coordinate of end of arrow line xp2=r2*np.cos(angp) # x-coordinate of start of arrow line yp2=r2*np.sin(angp) # y-coordinate of start of arrow line for x1,y1,x2,y2 in zip(xp1,yp1,xp2,yp2): sarrow_p(x1,y1,x2,y2) if nnn==121: plt.text(ra-pl-0.2,0,'$P_a$',va='center',ha='right',fontsize=fsz+4) if nnn==122: plt.text(rb+pl+0.2,0,'$P_b$',va='center',ha='left',fontsize=fsz+4) # explanation if nnn==121: ss='Concrete\nwith crack' if nnn==122: ss='Concrete\nwithout crack' x1=0.5*(ra+rb)*np.cos(np.radians(135)); x2=x1-3.5 y1=0.5*(ra+rb)*np.sin(np.radians(135)); y2=y1+3.5 sarrow_a(x1,y1,x2,y2,ss,'b',fsz) ss='Outer\nReinforcement' x1=rfb*np.cos(np.radians(225)); x2=x1-3 y1=rfb*np.sin(np.radians(225)); y2=y1-3 sarrow_a(x1,y1,x2,y2,ss,'t',fsz) ss='Inner\nReinforcement' x1=rfa*np.cos(np.radians(315)); x2=x1+4 y1=rfa*np.sin(np.radians(315)); y2=y1-4 sarrow_a(x1,y1,x2,y2,ss,'t',fsz) if nnn==121: ss='Bedrock' x1=0 ; x2=x1 y1=br; y2=y1 sarrow_a(x1,y1,x2,y2,ss,'n',fsz) def main(): plt.figure(figsize=(10,5),facecolor='w') plt.rcParams['font.size']=fsz plt.rcParams['font.family']='sans-serif' nnn=121; drawfig(nnn) nnn=122; drawfig(nnn) plt.tight_layout() fnameF='fig_model.jpg' plt.savefig(fnameF, dpi=100, bbox_inches="tight", pad_inches=0.1) plt.show() #--------------- # Execute #--------------- if __name__ == '__main__': main()