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