1

超シンプルなベン図を描くPythonプログラム

115
0
$$$$

はじめに

PythonとSVGの勉強のためにベン図を描いてみよう。
ということで作成してみました。
モノクロで表示するために、任意の領域をパターンで塗れたら良いな。
と思いましたが、たぶん無理。
inkscapeなどで、パスを分割→各領域を独立させるのが現実的っぽいです。
動作確認は Jupyter Notebook で行いました。

Code

      import math

#ベン図を出力する
n=3                 #集合の個数
r=150               #円(集合)の半径
marginLeft=150       #左余白
marginTop=30        #上余白
marginRight=150      #右余白
marginBottom=30     #下余白

#全体集合の枠線
#rectStrokeWidth=0
#rectStroke='stroke="none"'
rectStrokeWidth=2
rectStroke=f'stroke="black" stroke-width="{rectStrokeWidth}"'       #全体集合の枠線


fillRect='white'    #全体集合の塗りつぶし
fillA='white'       #集合Aの塗りつぶし
fillB='white'       #集合Bの塗りつぶし
fillC='white'       #集合Cの塗りつぶし
op=' fill-opacity="0.5"'  #集合の塗りつぶし
stroke='black'


def createVenn(n,r,marginLeft,marginTop,marginRight,marginBottom,rectStroke,fillRect,fillA,fillB,fillC,op,stroke):
#ベン図を描くsvg文字列を出力する。
    if n==1:  #集合が1個
        cxA=marginLeft+r
        cyA=marginTop+r
        
        cxA=round(cxA,2)
        cxA=round(cxA,2)
        
        width=marginLeft+2*r+marginRight-rectStrokeWidth
        height=marginTop+2*r+marginBottom-rectStrokeWidth
        width=math.ceil(width)
        height=math.ceil(height)
    elif n==2:  #集合が2個
        cxA=marginLeft+r
        cyA=marginTop+r
        cxB=cxA+r
        cyB=cyA
        
        cxA=round(cxA,2)
        cxA=round(cxA,2)
        cxB=round(cxB,2)
        cyB=round(cyB,2)
        
        width=marginLeft+3*r+marginRight-rectStrokeWidth
        height=marginTop+2*r+marginBottom-rectStrokeWidth
        width=math.ceil(width)
        height=math.ceil(height)
    else:  #集合が3個
        cxA=marginLeft+r
        cxB=cxA+r
        cxC=(cxA+cxB)/2
        cyC=marginTop+r
        cyA=cyC+math.sqrt(3)*(cxB-cxA)/2
        cyB=cyA
        
        cxA=round(cxA,2)
        cxB=round(cxB,2)
        cxC=round(cxC,2)
        cyC=round(cyC,2)
        cyA=round(cyA,2)
        cyB=round(cyB,2)
        
        width=marginLeft+3*r+marginRight-rectStrokeWidth
        height=marginTop+2*r+(cyA-cyC)+marginBottom-rectStrokeWidth
        width=math.ceil(width)
        height=math.ceil(height)
    
    
    svgStr=''
    svgStr=svgStr+f'<!-- 画像サイズ:{width} × {height} -->\n'
    svgStr=svgStr+f'<svg viewBox="0 0 {width} {height}" width="{width}px" height="{height}px">\n'
    svgStr=svgStr+f'<rect width="{width}" height="{height}" fill="{fillRect}" {rectStroke}/>\n'   #全体集合
    
    if n==1:    #集合が1つのとき
        svgStr=svgStr+f'<circle id="setA" cx="{cxA}" cy="{cyA}" r="{r}" fill="{fillA}"{op} stroke="{stroke}" stroke-width="2" />\n'
    elif n==2:  #集合が2つのとき
        svgStr=svgStr+f'<circle id="setA2" cx="{cxA}" cy="{cyA}" r="{r}" fill="{fillA}"{op} stroke="{stroke}" stroke-width="2" />\n'
        
        
        svgStr=svgStr+f'<circle id="setB2" cx="{cxB}" cy="{cyB}" r="{r}" fill="{fillB}"{op} stroke="{stroke}" stroke-width="2" />\n'
        svgStr=svgStr+f'<circle id="setA2" cx="{cxA}" cy="{cyA}" r="{r}" fill="{fillA}"{op} stroke="{stroke}" stroke-width="2" />\n'
        
        
    else:       #集合が3つのとき
        svgStr=svgStr+f'<circle id="setA" cx="{cxA}" cy="{cyA}" r="{r}" fill="{fillA}"{op} stroke="{stroke}" stroke-width="2" />\n'
        svgStr=svgStr+f'<circle id="setB" cx="{cxB}" cy="{cyB}" r="{r}" fill="{fillB}"{op} stroke="{stroke}" stroke-width="2" />\n'
        svgStr=svgStr+f'<circle id="setC" cx="{cxC}" cy="{cyC}" r="{r}" fill="{fillC}"{op} stroke="{stroke}" stroke-width="2" />\n'
    svgStr=svgStr+'</svg>'
    print(svgStr)
    
#ベン図のSVGを出力
createVenn(n,r,marginLeft,marginTop,marginRight,marginBottom,rectStroke,fillRect,fillA,fillB,fillC,op,stroke)




    
投稿日:20231022

この記事を高評価した人

高評価したユーザはいません

この記事に送られたバッジ

バッジはありません。

投稿者

tanu
24
11097

コメント

他の人のコメント

コメントはありません。
読み込み中...
読み込み中