damyarou

python, GMT などのプログラム

matplotlib RC円形圧力トンネルモデル図

記事の最後に行く

はじめに

以下に示す、「設計 RC円形圧力トンネルの配筋設計(1)」で示した図を作成するプログラムである。

f:id:damyarou:20190527132711j:plain

ポイント

ノーテーション用矢印とテキスト描画

  • 説明用のボックス内テキストと矢印を描画する。
  • 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)

ひび割れ描画

コンクリート内のひび割れは、サインカーブで定義。 まず、座標  (r_a, 0)- (r_b, 0) 間でサインカーブを定義し、これを座標変換しながら 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 で、 0 から  2\pi を分割して角度を指定して  (x, y) 座標を求め、これを折れ線で結んでいく。

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()

Thank you.

記事の先頭に行く