25 December 2015

はじめに

PythonSf と名づけたエディタに組み込んで使う計算ソフトを開発しています。vim,emacs に pysf.vim, pysf.el といった小さな script を組み込んで使います。その PythonSf では one-liners での計算を多用します。通常の使用では 99% 以上が one-liners になると思います。を組み込んで計算させます。 こんな具合に カーソル下の計算式、または Python コード文字列を実行させます。

下の URL より PythonSf utf-8 版と shift-jis 版を入手できます。

  1. cps932版 PythonSf;;https://github.com/lobosKobayashi/PythonSfCp932
  2. utf-8版 PythonSf;;https://github.com/lobosKobayashi/PythonSfUtf8

Windows 限定ですが、ここから vim と Python も含んだポータブル版 zip ファイルを入手することもできます。bigCpPysf32_version97B.zip が cp932版であり、 bigUtPysf32_version97B.zip が utf-8 版です。Windows ではギリシャ漢字文字を含んだファイル変数を使うために cp932版を使うことを進めます。

この PythonSf one-liners で SVG 文字列を生成してやり、web page の作成で image file へのリンクを張ることなく、図形を表示しようとしています。少し動き始めてきたので、それについて書いてみます。

背景と XyPic(..) 関数

HTML5 の一般化に伴い SVG ファイルが使われるようになってきました。IE11 でも SVG ファイルを扱えるようになりました。SVG 規格は web page に二次元図形を描かせる規格です。2001 年に w3.org から勧告されました。ベクトル・グラフィック図形を XML テキスト文字で表現する規格です。それまでのグラフィック言語の経験を踏まえた旨く纏まった規格です。Tcl/Tk のような古臭い図形表示仕様と比較すると格段に進歩していると感じます。図形表示規格としては筋の良さを感じます。

一方で理系の記事を web page に書くには、図形を活用すべきです。図形は二次元情報を使うことで大量の情報を一度に伝達でき、読者の文章を読み取る労力を大幅にが軽減してくれます。でも文章を書くのに比べて図を作成するのには手間が掛かります。Drawing ソフトを立ち上げ、マウスで図を作成しなければなりません。png ファイルを作成し web page に そのファイルへのリンクを書き込まねばなりません。

私自身は LaTeX の XY-pic を使い PythonSf one-liner で図形を作成できるようにしています。下のような具合です。

PythonSf one-liner

XyPic(r"& O4\,Complex \ar[r]^{\tau_0} \ar[d]^{f_0} & O6\,Complex \ar[d]^{f_1}\\"+'\n'+ r"& O2\,Complex \ar[r]_{\tau_1} & O3\,Complex")

XY-pic による dvi 図形

既に LaTeX と XY-pic がインストールされているのならば、同様なことをしたかったら下の関数を sfCrrntiIni.py に書き込むだけで上の PythonSf one-liner が動くようになります。よろしければお使いください。

source(XyPic)
In file: sfCrrntIni.py

def XyPic(strAg):
    strHead=(
    r"""\documentclass{jarticle}
    \usepackage[all]{xy}
    \begin{document}
    \[\xymatrix{
    """
    )

    strTail=(r"""
    }\]
    \end{document}"""
    )

    fl=open('temp.tex','w')
    fl.write(strHead + strAg + strTail)
    fl.close()

    import os
    #os.system("platex temp.tex")
    if 0 != os.system("platex -halt-on-error temp.tex"):
        return
    os.system("start temp.dvi")

===============================
None

SVG text と kSvgTxt モジュール

でもこの XyPic(..) 関数のようなことを SVG で行えるようにできたら、png ファイルを作る手間も省けてしまうことになります。下のように SVG テキストを置いてやるだけで済みます。

SVG text

<svg width="320" height="60" viewBox="0 0 320 60">
<text font-family="MS gothic" font-size="50.0" x="30" y="50">a</text>
<text font-family="MS gothic" font-size="20.0" x="70" y="50">←</text>
<text font-family="MS gothic" font-size="50.0" x="110" y="50">X</text>
<text font-family="MS gothic" font-size="20.0" x="150" y="50">→</text>
<text font-family="MS gothic" font-size="50.0" x="180" y="50">b</text>
</svg>
a X b

漢字を利用することでテキストだけでも結構な図形を描けます。Font size を旨く選択してやれば、さらに図形らしくなってくれます。

調べてみると svgwrite package がありました。これを利用してやれば XyPic(..) に近いことができそうです。

そう考えて kSvgTxt.py の名前のモジュールを作っているところです。今現在下のようにテキストから SVG テキストへの変換ができるようになったところです。

PythonSf one-liner

ksv(); x=17mm; y=ksv.AlndEclsAr(krry(x*'abc\nAB', 5mm*'xy', dtype=ksv.Enclosure)); y.tostring()
===============================
<text font-family="MS gothic" font-size="60.0" x="0" y="0">abc</text>
<text font-family="MS gothic" font-size="60.0" x="0" y="60">AB</text>

<text font-family="MS gothic" font-size="18" x="90" y="18">xy</text>
abc AB xy

少しずつ動かしては修正していく形で、このプログラムを完成に近づけていきます。

ちなみに、このソースは下のようなコードです。

PythonSf one-liner

import pysf.kSvgTxt as md; source(md)

kSvgTxt モジュールの UML 図とプログラム解説

上のプログラム・コードの UML 図を下に示します


    ┌──────────┐
    │object              │
    └──────────┘
              △
              │
    ┌──────────┐
    │ClEnclosure         │  形あるもの一般の basic クラス ┌────────┐      
    ├──────────┤                                │SvSize          │
    │m_arInsert          │  配置位置                      ├────────┤
    │m_arSize            │  左上から右下までのベクトル    │m_strUnit       │
    │m_svwObj            │  SVG object                    │m_flUnit        │
    ├──────────┤                                ├────────┤
    │NE  N   NE  position│                                │__rmul__(.strAg)│
    │W   C   E attributes│                                └────────┘
    │SW  S   SE          │                                mm=SvSize('mm')
    ├──────────┤
    │                    │
    └──────────┘
              △
              ├──────────────────────┐
    ┌──────────┐                     ┌──────────┐
    │Text                │                     │AlndEclsAr          │ 形のある SVG 図形を行列状
    ├──────────┤                     ├──────────┤ に配置する
    │m_arInsert          │                     │m_mtElmnts          │
    │m_arSize            │                     │m_arSize            │
    │m_flFontSize        │                     │                    │
    │m_svwObj            │text 情報も保持する  │                    │
    ├──────────┤                     ├──────────┤
    │tostring()          │                     │tostring()          │SVG text を返す
    │                    │                     │                    │
    │                    │                     │                    │
    ├──────────┤                     ├──────────┤
    │                    │                     │                    │
    └──────────┘                     └──────────┘

AlndEclsAr クラスが Text など SVG 図形を行列配置させるクラスです。dx,dy 引数で配置隙間を指定します。ClEnclosure は SVG 図形一般の抽象クラスです。このクラス、または これを継承したクラス・インスタンスをAlndEclsAr クラスによって行列状に配置します。

SvSize クラスは SVG 図形の長さの単位を指定するクラスです。mm 単位で使います。one-liner を記述するとき ksv() 関数によって mm をグローバル変数に格上げしています。ですから 5mm*‘xy’ のような記述ができてしまいます。そして SvSize インスタンスに文字列を掛けるコードになったとき、それは Text クラスのインスタンスを返すようにしています。SVG のテキスト・グラフィックスを定める XML 文字列を作るためのクラスです。tostring() method が この XML 文字列を返します。

                                                  ↓長さ*文字列で Text class instance を生成する
ksv(); x=17mm; y=ksv.AlndEclsAr(krry(x*'abc\nAB', 5mm*'xy', dtype=ksv.Enclosure)); y.tostring()

もし、このような SVG XML テキスト生成プログラムを既に作られたかたがおられましたら教えてやってください。



blog comments powered by Disqus