日々適当

hibitekitou

SVGファイルを作成するPythonスクリプト

cg |2016-02-14

ダウンロードした線情報が書かれたファイル(テキストファイル)をもとに、Illustratorで線を引こうと思ったのですけど、Illustratorが処理を完了してくれないのですね。何が問題なのかちょっとわからないのですけど、それじゃ、Illustratorで読み込めるパスデータにしてやればいいんじゃないか、例えばSVGなんかどうだろうと考えるのは自然なことだと思います。
余談ながら、Illustratorで直線を引くときはJavascriptでsetEntirePathってコマンドを使うようです。

で、PythonでSVGファイルを取り扱うモジュールはいろいろあるようですが、svgwriteってのが良さげでした。インストールもtar.gzファイルをダウンロードしてきて伸張し sudo python setup.py install を実行するだけです(pipが入っている環境だったらもっと簡単ですか?)

今回やりたいことは、ある領域が記されたテキストファイルから図形をおこすことです。テキストファイルの中身はx,y座標がいっぱい記されていて、それを繋げるとある形状になるってものですね。x,y座標のそれぞれをコントロールポイントと呼ぶとするなら、コントロールポイントの集合は配列で記述します。

例えば、円を描く以下のようなスクリプト。

import math
import svgwrite

points = []

for i in range( 720 ):
	x = 10.0 * math.cos( math.radians( 360.0/720 * i ) )
	y = 10.0 * math.sin( math.radians( 360.0/720 * i ) )
	points.append( [x,y] )

dwg = svgwrite.Drawing( "Circle.svg" )
dwg.add( dwg.polygon( points=points ) )
dwg.save()

これにより、半径が10の円が描かれたファイル Circle.svg が出来上がります。



なを実際には単に円を描くならCircleって関数がsvgwriteにあるから、それ使えばいいです。

svgwrite.Drawing( filename , profile='tiny' ) でSVGファイルを作成しています。ファイル名以外にサイズを指定したり、SVGに規定された値を指定することができるようですが、とりあえずはファイル名の指定だけは必須のようです(当たり前の話ではありますね。どこにファイルを保存するだってことですから)。

で、Drawing.add( element )でファイルに内包する要素(サブエレメント)を追加していきます。
この要素は PathやらLineやらRectやらCircleやらいろいろありますが、今回の用途で楽そうなのはDrawing.polygon( points=[points list] )です。コントロールポイントの配列とSVGのオプションを指定してやれば良いようです。もし閉じた形じゃなかったら、Polylineを使うと良いようですね。
最後にDrawing.save()でファイルを保存します。

Drawing.polygon( points=[points list] ) にSVGのオプションを指定してやることで、見た目の調整を行えます。例えば

dwg.add( dwg.polygon( points=points , stroke='red', fill='none') )

とすることで、ストロークを赤色に、塗りつぶしをしないように出来ます。



stroke_widthで線の太さを指定可能ですね。いろいろとオプションがあるようですが、この辺はSVGの規格に準じるようです。

それでは円を二つ書いてみます。dwg.add()とdwg.save()の間に単純に円をもう一個記すものを追記します。

points = []
for i in range( 720 ):
	x = 20.0 * math.cos( math.radians( 360.0/720 * i ) )
	y = 20.0 * math.sin( math.radians( 360.0/720 * i ) )
	points.append( [x,y] )
dwg.add( dwg.polygon( points=points , stroke='blue', stroke_width=3.0, fill='none') )

この結果、一つ目よりもちょっと大きいサイズの円が描かれるわけですが、下図のようにそれぞれ別のレイヤーに分かれます。



これで問題のないケースもありましょうし、一つのレイヤーになってほしいケースもありましょう。ちなみに、idってオプションを指定すると、それがレイヤー名として認識されるようです。
一つのレイヤーにまとめたい時にどう記すか、ですね。Illustratorでいうところの複合パスを作る方法ですけど、これが実はよくわかっておりません(^^;
次善の策として、グループにまとめるって考え方がありますかね。Illustratorで開くとレイヤーにまとめられるって形で表示されてきます。

import math
import svgwrite

points = []

for i in range( 720 ):
	x = 10.0 * math.cos( math.radians( 360.0/720 * i ) )
	y = 10.0 * math.sin( math.radians( 360.0/720 * i ) )
	points.append( [x,y] )

dwg = svgwrite.Drawing( "Circle.svg" )
grp = dwg.add( dwg.g( id='Group') )
grp.add( dwg.polygon( points=points , stroke='red', stroke_width=2.0, fill='none', id='A') )

points = []
for i in range( 720 ):
	x = 20.0 * math.cos( math.radians( 360.0/720 * i ) )
	y = 20.0 * math.sin( math.radians( 360.0/720 * i ) )
	points.append( [x,y] )
grp.add( dwg.polygon( points=points , stroke='blue', stroke_width=3.0, fill='none', id='B') )

dwg.save()

しかし、どーしたもんかなぁ。
要素の数を減らしたいのだけど、これだと本末転倒のような気がするなぁ。

SVG自体はテキストファイルなので、テキスト処理をしてやって解消はできるのだろうけど、大変そうですし。
どーしたもんか。

どうも、複合パスはMで始まりZで終わる点の集まりとして表現するみたいですね。例えばSVGファイル内で path d="M0,0L1,1L2,2ZM3,3L4,4L5,5L6,6Z" というように記されていると、(0,0)(1,1)(2,2)の直線と(3,3)(4,4)(5,5)の直線の2本の直線が複合パスとして記されていることとなるようです。

コメント ( 0 )|Trackback ( )
  ・