20190730

fontファイルの文字データ(グリフ)を、matplotlib の path (Bezier 曲線の制御点) ではなくx, y 座標に直しplotする

このページの内容は

  1. フォントファイルの文字から、ベジェ曲線の制御ポイントを取りだして、matplotlibのpathに変換する。
  2. N次ベジェ曲線の制御点→x,y座標の配列に変換
→(matplotlib.pyployt.plotでフォントが描ける!)

やる前に、IPAフォントをインストールしてね。

IPAフォントのアドレス。これをインストールする。→'C:\WINDOWS\Fonts\IPAM.TTF'が保存される。これがなかったら、下のコードは動かない。

フォントファイルのグリフから、ベジェ曲線の制御ポイントを取り出し、matplotlibのpathに変換。

ベクターフォントのフォントファイルの各文字データ(グリフ)から、ベジェ曲線の制御ポイントを取り出す方法を知った。
これで、フォントの中の文字データ(グリフ)の、ベジェ曲線の制御ポイントを取り出して作図できる。
IPAフォントを作図した。


手順は、

  1. IPAフォントのインストール。
  2. フォントのベクターの制御点の座標を、fonttoolsのrecordingpenを使って取り出す。
  3. recordingpen をmatplotlibのpathに変換する関数を書く
  4. matplotlibのpath(ベジェ曲線を描く機能)を使ってプロットする。

手順2で作ったpathデータを、matplotlibにベジェ曲線を描く機能でそのまま使った。(matplotlibのpathを使うと、制御点を指定するだけで曲線が描ける。)
わざわざ、matplotlibで読める形に直す必要があったけど、ベジェ曲線の式を理解していなくてもベジェ曲線が描けてしまった。matplotlibすごい!

#!/usr/bin/env python
# -*- coding: cp932 -*-

import time
from datetime import datetime as dt

import numpy as np

import
matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'IPAGothic'

import matplotlib.path as mpath
import matplotlib.patches as mpatches
from fontTools.ttLib import TTFont

font = TTFont(r'C:\Windows\Fonts\ipamp.ttf')
glyph_set = font.getGlyphSet()
cmap = font.getBestCmap()

def get_glyph(glyph_set, cmap, char):
glyph_name = cmap[ord(char)]
return glyph_set[glyph_name]

iroha_1 = get_glyph(glyph_set, cmap, u'て')

from fontTools.pens.recordingPen import RecordingPen

recording_pen = RecordingPen()

iroha_1.draw(recording_pen)
print(recording_pen.value)

pathdt = recording_pen.value # path(bezier curve)

def pdTopd(pd,mtrx1=[[1,0],[0,1]]):
tmp1 = [[]]
tmp2 = [[]]
i2 = 0
for i in range(len(pd)):
if pd[i][0] == 'closePath':
tmp1.append([])
tmp2.append([])
i2+=1

if pd[i][0]=='moveTo':
tmp1[i2].append(mpath.Path.MOVETO)
tmp2[i2].append(np.dot(mtrx1, pd[i][1][0]))

elif pd[i][0]=='qCurveTo':
tmp1[i2].append(mpath.Path.CURVE3)
tmp2[i2].append(np.dot(mtrx1, pd[i][1][0]))
tmp1[i2].append(mpath.Path.CURVE3)
tmp2[i2].append(np.dot(mtrx1, pd[i][1][1]))
if pd[i+1][0]=='qCurveTo':
tmp1[i2].append(mpath.Path.LINETO)
tmp2[i2].append(np.dot(mtrx1, pd[i][1][1]))

elif pd[i][0]=='lineTo':
tmp1[i2].append(mpath.Path.LINETO)
tmp2[i2].append(np.dot(mtrx1, pd[i][1][0]))

elif pd[i][0] == 'curveTo':
tmp1[i2].append(mpath.Path.CURVE4)
tmp2[i2].append(np.dot(mtrx1, pd[i][1][0]))
tmp1[i2].append(mpath.Path.CURVE4)
tmp2[i2].append(np.dot(mtrx1, pd[i][1][1]))
tmp1[i2].append(mpath.Path.CURVE4)
tmp2[i2].append(np.dot(mtrx1, pd[i][1][2]))
if pd[i+1][0]=='qCurveTo':
tmp1[i2].append(mpath.Path.LINETO)
tmp2[i2].append(np.dot(mtrx1, pd[i][1][0]))
print("%s/%s"%(i,len(pd)))

return tmp1, tmp2

a2,b2 = pdTopd(pathdt)# x,y(bezier)
a,b = pdTopd(pathdt,mtrx1=[[1,2],[0,1]])#(x,y(translated bezier))

f,(ax1) = plt.subplots(1,1)

for i in range(len(a)-1):
c = mpath.Path(b[i],a[i])
d = mpatches.PathPatch(c, facecolor='white', edgecolor="gray", lw=2, clip_on=False)
ax1.add_patch(d)
c = mpath.Path(b2[i],a2[i])
d = mpatches.PathPatch(c, facecolor='white', lw=2, clip_on=False)
ax1.add_patch(d)

ax1.set_aspect('equal')
ax1.grid(which="major", color="k", linestyle="--")
ax1.hlines(0, -3000,3000)
ax1.vlines(0, -3000,3000)
ax1.set_xlim(-2000, 2000)
ax1.set_ylim(-2000, 2000)
ax1.set_title(ur"Font", fontsize=30)
ax1.set_xlabel(ur"横 [px]", fontsize=30)
ax1.set_ylabel(ur"縦 [px]", fontsize=30)

tdatetime = dt.now()
itext = tdatetime.strftime('%Y%m%d'+ time.ctime()[11:13] + time.ctime()[14:16] + time.ctime()[17:19])
f.set_size_inches(19.2,10.8)
f.savefig("%s.png"%(itext))

20190727190844.png

N次ベジェ曲線

まずはベジェ曲線のプログラムから。

ベジェ曲線の説明には、このサイトが詳しい

あとベジェ曲線のwikipedia

二項定理とか出てきたので難しかった。
3次と4次しか使わないが、N次ベジェ曲線のx,y座標を取得するプログラムができた。

このコードは、

  1. 適当なベジェ曲線の制御点のx座標配列、y座標配列を取得して
  2. 関数部分でN次ベジェ曲線の制御ポイントをx,y座標に変換して
  3. matplotlib.pyplot.plotのx,y座標に入れる。

という作業をやっています。

N次ベジェ曲線の関数の引数は、x(N個の制御点x座標), y(N個の制御点y座標), と制御点間の補間数。(tを何分割するか。tが何なのかは、ほかのサイトを参照してください。)
当然ですが、x,yは、同じ長さにしてください。x,yの長さで、何次のベジェ曲線になるかが決まります。

x,y求めてプロット

曲線の間の補間がいまいちだとカクカクになる。

このカクカク感がたまんない!ベジェ曲線だが、ここまで間引くと、もはや曲線っぽくない。

20190601124605.png

#!/usr/bin/env python
# -*- coding: cp932 -*-

import
math
import time
from datetime import datetime as dt
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'IPAGothic'
from fontTools.ttLib import TTFont
from fontTools.pens.recordingPen import RecordingPen

def Nbezier(x1, y1, N=100):
if len(x1)!=len(y1):
print("Two lists must be the same 1-d list.")
return
if len(x1)<=2:
print("Length of the list must be grater than 2.")
return
t=np.linspace(0,1,N)
x2, y2 = [], []
for i in range(N):
tmpx, tmpy = 0, 0
n = len(x1)
for j in range(n):
tmpx = tmpx +(1-t[i])**(n-j-1)*t[i]**(j)*x1[j]*math.factorial(n-1)/(math.factorial(j)*math.factorial(n-j-1))
tmpy = tmpy + (1-t[i])**(n-j-1)*t[i]**(j)*y1[j]*math.factorial(n-1)/(math.factorial(j)*math.factorial(n-j-1))
x2.append(tmpx)
y2.append(tmpy)
return x2, y2

font = TTFont(r'C:\WINDOWS\Fonts\IPAM.TTF')#windowsのフォントファイル
glyph_set = font.getGlyphSet()
cmap = font.getBestCmap()

def get_glyph(glyph_set, cmap, char):
glyph_name = cmap[ord(char)]
return glyph_set[glyph_name]

iroha_1 = get_glyph(glyph_set, cmap, u'い')

recording_pen = RecordingPen()

iroha_1.draw(recording_pen)
pathdt = recording_pen.value

# パスデータをx,y座標データに変換する関数。
# ベジェ曲線の関数はこの関数の中で使っている。

def
PdBzToPlt(pd, N=7):
x=[]
y=[]
j=-1
for i in range(len(pd)):
tmpx=[]
tmpy=[]
if pd[i][0] == 'moveTo':
x.append([pathdt[i][1][0][0]])
y.append([pathdt[i][1][0][1]])
j+=1
elif pd[i][0] == 'qCurveTo':
tmpx.append(x[j][-1])##最初の点は、xの最終点から借りてくる。
tmpx.append(pd[i][1][0][0])
tmpx.append(pd[i][1][1][0])
tmpy.append(y[j][-1])
tmpy.append(pd[i][1][0][1])
tmpy.append(pd[i][1][1][1])
tmpx2, tmpy2 = Nbezier(tmpx, tmpy ,N)
x[j].extend(tmpx2[1:])#最初の点は、xの最終点から借りてきた点なので[1:]。
y[j].extend(tmpy2[1:])
elif pd[i][0] == 'qCurveTo':
tmpx.append(x[j][-1])
tmpx.append(pd[i][1][0][0])
tmpx.append(pd[i][1][1][0])
tmpx.append(pd[i][1][2][0])
tmpy.append(y[j][-1])
tmpy.append(pd[i][1][0][1])
tmpy.append(pd[i][1][1][1])
tmpy.append(pd[i][1][2][1])
tmpx2, tmpy2 = Nbezier(tmpx, tmpy ,N)
x[j].extend(tmpx2[1:])
y[j].extend(tmpy2[1:])
elif pd[i][0] == 'lineTo':
tmpx2 = [x[j][-1], pd[i][1][0][0]]
tmpy2 = [y[j][-1], pd[i][1][0][1]]
x[j].extend(tmpx2[1:])
y[j].extend(tmpy2[1:])
return x,y

x2,y2=PdBzToPlt(pathdt, N=7)

f,(ax1) = plt.subplots(1,1)

for i in range(len(x2)):
ax1.plot(x2[i],y2[i])
ax1.scatter(x2[i],y2[i],facecolor=[0,0,0,0.3],edgecolor=[0,0,0])#plt.show()

tdatetime = dt.now()
timtext = tdatetime.strftime('%Y%m%d'+ time.ctime()[11:13] + time.ctime()[14:16] + time.ctime()[17:19])
fname = "%s.png"%(timtext)
plt.savefig(fname)
plt.close()


来月は、フォントファイルを、x,y座標に変換し、せん断変形した後で、
x,y座標から、面積を求めようと思います。
x,y座標から、面積だけでなく、断面二次モーメントも求めようと思います。

先月に書いたシンプソン則云々は、断面二次モーメントのところで使う。8月の記事までには形にしたい。
続きを読む
posted by yuchan at 00:00 | Comment(340) | python

20190630

いろいろ考えていたが

色々考えて、途中まで書いたものもたくさんある。
しかし、(期限までに)完成させられなかった。

x,y座標で指定された、閉じた図形の断面二次モーメントを、
数値計算的に出そうとしたら、合わなかった。
原因は、全部台形則で済まそうとしていたからだと思う。
来月までには、simpson則をちゃんと勉強する。

とりあえず、5月にアップできたオイラーの動画でも載せておく。
posted by yuchan at 20:16 | Comment(0) | 日記

20190527

matplotlibのpyplot.plotで地図を描く方法

20190526185456.png

地図を描くスタンダードな方法

mpl_toolkits.basemapというのが、スタンダード。
しかし、pyplotで何とか地図を描けないだろうか。

このサイトから地図データがダウンロードできる。

国土数値情報ダウンロードサービスで、
“N03-110331_28_EC01.shp”というのを、ダウンロードしてみた。

shapeファイルをプロットしてみた

これでできた。変数eは変換行列になっているので、いろいろ試すといいかもしれない。

必要なファイル。
カレントフォルダに、”N03-110331_28_EC01.shp”

windows 日本語使用のコード

#!/usr/bin/env python
# -*- coding: cp932 -*-

import time
from datetime import datetime as dt

import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'IPAGothic'

import shapefile

#下の文字列に、シェイプファイルのアドレスを入力する。
sf = shapefile.Reader(r"N03-110331_28_EC01.shp",encoding='SHIFT-JIS') #,encoding='SHIFT-JIS'必須

f,(ax1) = plt.subplots(1,1)
e = [[1, 0], [0, 1]]#変換行列
a = 133.5

try:
i = 0
while True:
shape = sf.shape(i)
x = []
y = []
x2 = []
y2 = []
for i2 in range(len(shape.points)):
x.append(shape.points[i2][0])
y.append(shape.points[i2][1])
b = shape.points[i2]
c = [a, 0]
d = [b[0] - c[0], b[1] - c[1]]
#e = [[1, 0], [0, 1]]
f2 = np.dot(d, e)
c2 = [a, 0]
f2 = [f2[0] + c2[0], f2[1] + c2[1]]
x2.append(f2[0])
y2.append(f2[1])
#ax1.plot(x, y, color="k")
ax1.plot(x, y, color="k", linestyle="--")
ax1.plot(x2, y2, color="k", clip_on=False)
i += 1
except IndexError or UnicodeDecodeError or TypeError:
pass

ax1.set_aspect('equal')
ax1.grid(which="major", color="black", linestyle="--")
ax1.plot([a,a], [25,40], color="k", linestyle="dashdot" ,clip_on=False)

ax1.set_xlim(130, 137)
ax1.set_ylim(30, 37)

ax1.set_title(ur"兵庫県の地図")
ax1.set_xlabel(ur"経度(度)")
ax1.set_ylabel(ur"緯度(度)")
#plt.show()

tdatetime = dt.now()
itext = tdatetime.strftime('%Y%m%d'+ time.ctime()[11:13] + time.ctime()[14:16] + time.ctime()[17:19])
f.set_size_inches(19.2,10.8)

f.savefig("%s.png"%(itext))
posted by yuchan at 07:00 | Comment(0) | python

20190415

回転行列の求め方

タグ:回転行列

回転行列がなぜあの形なのか気になった

2×2の回転行列は

$$\begin{bmatrix}\cos{\theta} & -\sin{\theta} \\ sin{\theta} & \cos{\theta}\end{bmatrix}$$

なぜこの形をしているのか、wikipediaでは省略されていた。能力が不足しているのか、省略されているのにわからなかった。

図形的考察または三角関数の加法定理より、x ', y ' は以下のように表されることが分かる。

とWikipediaには書かれていた。しかし、自分は分からなかった。


前々から気にはなっていたが、ヒントがwebサイト以外何もなかったのでわからなかった。

今月、「行列とベクトルのはなし 改訂版」を読み始めて、一次変換の章(4版の119Pあたり)の式から(回転行列については書かれていないように思う。)、「こんな感じのノリでx,yを求めればいいのかぁ」と思いやってみた。

こんな感じのノリ部分を、太い赤文字にしておく。

頑張って、自分が納得のいく説明を考えてみた。

2.回転行列の使い方。

先ずは、回転行列の使い方を書いておく。

回転変換したい点の座標(インプット)は、

$$\begin{Bmatrix}x_{\rm{i}}\\y_{\rm{i}}\end{Bmatrix}$$

ここには具体的な座標が入る。

回転変換後の座標(xo,yo)は、

$$\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix}\cos{\theta}&-\sin{\theta} \\ \sin{\theta} & \cos{\theta}\end{bmatrix}\times\begin{Bmatrix}x_{\rm{i}}\\y_{\rm{i}}\end{Bmatrix}$$

行列のかけ算で、変換後の座標xo,yoが手に入る。

この回転行列がなぜこの形になるのかわからなかった。
多分、一番わかりやすいサイトは、ここ。Gifアニメも充実しているし。
しかし、上記サイトでも何か納得いかなかった。

3.自分の考え

いろいろ図を描いてみて、下のやり方を考えた。

  1. インプットをx,y成分の単位行列に分ける
  2. xy成分毎に、円周上を通り回転させる式を考える。
    x成分の回転軌跡は、(x,y)=(1, 0)から始まる円で描く。
    y成分の回転軌跡は、(x,y)=(0, 1)から始まる円で描く。
  3. x,y成分別に出した式を足す。→係数のみ抽出して行列にする。→回転行列になってる

4.円を描く方法

例えばExcelの散布図で、円を描きたいとする。→円周上のx,y座標が必要。
x,y座標は、三角関数を使えば出せる。

しかし、x軸から回転が始まる場合と、y軸から回転が始まる場合で、円の書き方が違う。

4.1.x軸から回転を始める場合

円のx,y座標は (x,y) = (cosθ,sinθ)でだせる。

x軸から回転し始めるとすると。
→θ=0の時、(1,0)
(cos0 = 1, sin0 = 0)だし、あってる。


理屈
単位円なので、半径1
cosθ=x/1=x
sinθ=y/1=y



回転後の座標は、細かい数値なので書かない。

figure_2.png

x軸から出発した、角度0から60度回転させた弧が描けた。

xi=1じゃなくてもできそう。

xo = cosθ×xi
yo = sinθ×xi
x成分しか考えていないので、yiは出てこない。

行列にしておくと、

$$\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix}\cos{\theta}& 0 \\ \sin{\theta} & 0 \end{bmatrix}\times\begin{Bmatrix}x_{\rm{i}}\\0\end{Bmatrix}$$

例えば、

$$\theta = 60\\\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix}\cos{60}& 0 \\ \sin{60} & 0 \end{bmatrix}\times\begin{Bmatrix}x_{\rm{i}}\\0\end{Bmatrix}\\ = \begin{bmatrix}0.866\cdots & 0 \\ 0.5 & 0 \end{bmatrix}\times\begin{Bmatrix}x_{\rm{i}}\\0\end{Bmatrix}$$

cos60とかは、コンピュータで出しました↑三角関数は、マクローリン展開で作ってるらしいよ。

これで、x成分のみの場合は、回転させられるようになった。

4.2.y軸から回転を始める場合

円のx,y座標は (x,y) = (sin, cos)でも、出せる。

ふつうは、(x,y) = (cos,sin)だが、逆にしても描ける。描けるったら描けるのだ。


この円は、Y軸から回転し始める。
→θ=0の時、(0,1)
(sin0 = 0, cos0 = 1)だし、あってる。。。
と思いきや、進行方向の向きが違う。

figure_3.pngfigure_5.png

sinは非対称な関数なので、変数をプラスにするかマイナスにするかで、値が変わってくる。
sinθのままだと、θが増えると、xも増える。
→x+側(時計回り。)に回転する。→回転させたいのは反時計回り。

変数をマイナスにするのも変なので、sinθ×-1しておく。
という事で、円のx,y座標は (x,y) = (-sinθ, cos)でだせる。

figure_4.png

xo = -sinθ×yi
yo = cosθ×yi
yi成分しか考えていないので、xiは出てこない。

行列にしておくと、

$$\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix} 0 & -\sin{\theta} \\ 0 & \cos{\theta} \end{bmatrix}\times\begin{Bmatrix}0\\y_{\rm{i}}\end{Bmatrix}$$

例えば、

$$\theta = 60\\\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix}0 & -\sin{60}\\ 0 & \cos{60} \end{bmatrix}\times\begin{Bmatrix}0\\y_{\rm{i}}\end{Bmatrix}\\ = \begin{bmatrix} 0 & -0.5 \\ 0 & 0.866\cdots \end{bmatrix}\times\begin{Bmatrix}0\\y_{\rm{i}}\end{Bmatrix}$$

これで、y成分のみの場合にも、回転させられるようになった。


5.. 二つの式を組み合わせたら回転行列になった。

X成分にも、Y成分にも適用できるようにしたい。
(この間になんか欲しい。が、ない袖は振れない。)
X、Y両方を合わせてみたら、なんか回転行列の形になった。(ポカーン)
  1. x成分のみを回転させた場合
    xo = cosθ×xi
    yo = sinθ×xi
  2. y成分のみを回転させた場合
    xo = -sinθ×yi
    yo = cosθ×yi
  3. 1.2.を組み合わせた場合
    xo = cosθ×xi - sinθ×yi
    yo = sinθ×xi + cosθ×yi

上記3を行列に直すと、

$$\begin{Bmatrix}x_{\rm{o}}\\y_{\rm{o}}\end{Bmatrix} = \begin{bmatrix}\cos{\theta}&-\sin{\theta} \\ \sin{\theta} & \cos{\theta}\end{bmatrix}\times\begin{Bmatrix}x_{\rm{i}}\\y_{\rm{i}}\end{Bmatrix}$$

最初の式と全く同じだけど、書いちゃったぜ。

回転行列が取り出せましたね。

6.使用したpythonコード

最近気づいたのは(今思いついたのは)、他人のサイトにpythonコードがあっても、わざわざコピペして実行なんかしてない。試さない。
そもそも、見て勉強すらしてない。

「うんうん、できるんだね。」といった感想しか持てない。

なら、本文の前のほうでスペースを占めるより、最後に押し込めたほうが、読み手の立場に立っているのではないかと思いました。欲しい(見たい)のは絵やアニメ。
(本当は、文章全体の見通しが悪かったので、コードが邪魔になっただけ。)

なので、この位置。
来月には忘れているかもな。

import numpy as np
import matplotlib.pyplot as plt

N = 500

# gray: circle(360[deg])
theta1 = 2 * np.pi
n1 = np.linspace(0, theta1, N)
x1 = np.cos(n1)
y1 = np.sin(n1)
plt.plot(x1,y1, "-", c="gray")

# red: 60[deg]
theta2 = 1.0 / 6 * 2 * np.pi
n2 = np.linspace(0, theta2, N)
x2 = np.cos(n2) #x2 = np.sin(n2) #x2 = -np.sin(n2)
y2 = np.sin(n2) #y2 = np.cos(n2)
plt.plot(x2,y2, "-", c="red", lw=3)

# Appearance
plt.xlim(-1,1)
plt.ylim(-1,1)
plt.axes().set_aspect('equal')
plt.grid(which='major',color='gray',linestyle='-')
ax = plt.gca() # get current axis
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))

plt.show()

円の方程式は、$$x^2+y^2=r^2$$と習った。けど、この形ではx,y座標が出せなかったので、放っておいた。何か大切な議論が抜けている気がするが不明。なぜ、x成分とy成分に分けたら、ちゃんと考えられたのか今以て不明。


×(かける)の後にx(エックス)を平然と持ってくるあたり、何か欠けているのかもしれない。直すつもりはないが。

タグ:回転行列
posted by yuchan at 07:00 | Comment(306) | 数学

20190311

tcl/tkよく使うメモ

最近は、tcl/tkに手を出し始めた。
VBAも継続中。pythonも。
tcl/tkは、昔のスクリプト言語らしい。
もともと、pysideやってたのに、時代に逆行してる気がする。。。

tcl/tkの入手

Tcl/tkとして、 ActiveState ActiveTcl 8.5.18.0を使った。 DLして、インストールしたらできた。

これを、なるべく不自由なく使いたい。
pythonでできそうなことをやろうとしたらどんなことをすべきか書いたメモ。

基本的な文法をちょろっと書いた2000文字程度のページだったはずが、ActiveTclを調べてたら、パッケージ(ライブラリ)が気になって…文字数が肥大化した。

使用してみた感じ

ActiveTclのwindowsのスタート画面.png

windowsのcmd上から、

tclsh

と入力すると、tclのあの%が表示される。 この画面を、「tclのシェルを起動した」というらしい。
「インタプリタ画面を出した」ではダメなんだろうか。
tclとだけ打っても無反応なのは注意したい。

名前説明
ActiveTclHelpは、コマンドリファレンスですな。
Licenseテキストファイルが出てくる。ライセンス関連。再配布なんかしないから関係ない。
Readmereadmeが入っている。
Tclshx.x(xには番号)シェルが立ち上がる。
Tkこれはすごくいい。Tkを使ったGUIの例と、そのコードが見れる。pyqtgraphのexampleみたい。
tkcontkのコンソールが開く。
uninstall ActiveTcl x.x.xx.xアンインストール
wishxxwishとは、「簡素なwindowingshell」らしい。使い方は、ここにあるように、ボタンを追加してみたら、ボタンが出てくるよ。

teacup

ライブラリのアップデートや追加に使う。

teacup update

teacup update

をtclshxx(xxはバージョン)で実行すると、下記のように最新?のライブラリの検索が始まる。

teacup update
Retrieving package logger 0.9.4 tcl ...@http://teapot.activestate.com... Ok
Retrieving package sqlite3 3.8.10.2 win32-ix86 ...@http://teapot.activestate.com... Ok
Retrieving package struct::pool 1.2.3 tcl ...@http://teapot.activestate.com... Ok
Retrieving package tls 1.6.7.1 win32-ix86 ...@http://teapot.activestate.com... Ok
.
.
.

これが延々続く。
これをしないと、mathが使えない。
pythonも環境設定大事だもんね。なんでもpython基準で申し訳ない。

最後にこれが表示される。

Installed 4 newer packages
Installed 695 unknown packages

新しいバージョンがあれば更新されるし、
最新バージョンなら"Ok"と表示される。
問題は、何も表示されない場合。
結局、mathは何も表示されていなかった。

これでインストールできるんじゃないの!?
文字通り、updateだけでした。

teacup install

mathが入っていなかったので、mathを使おうとしても

package require math
tcl can't find package math

となってしまう。
mathを入れたい。

% teacup install math
Resolving math ... [package math 1.2.5 tcl ... Already installed in repository, probing dependencies]
Resolving Tcl 8.0 -is package ... [package Tcl 8.5.18 _ ... Installed outside repository, probing dependencies]

そしたら、下記のように打てば、

package require math

下記のように表示される。

% package require math
1.2.5

早速入れたmathを使ってみる。

package require math

と入れただけじゃ使用できない。

package require math::statistics

ここまで打たないと、統計系のコマンドは使えない。

平均値を求めるコマンド。

package require math::statistics

math::statistics::mean "1 4 2";#1,4,2の平均値を求める。

% package require math::statistics
1.0
% math::statistics::mean "1 4 2"
2.3333333333333335

おー動いちゃいましたか。

math::constant定数 eやπ

定数は、コマンドではなく、定数がそのまま入っている。
だから、先頭に書いてしまうと「そんなコマンド無い」と返されてしまう。

package require math::statistics
math::constants::e
% puts $math::constants::e

% math::constants::e
invalid command name "math::constants::e"
% puts $math::constants::e
2.718281828459045
% puts $math::constants::pi
3.141592653589793

使用可能なライブラリの一覧

結局、目的のが入ったのかどうか分からない。

package names

と入力すると、package require できる一覧が表示されます。
ただ、長すぎるので、全部読み切れない。
テキスト長にコピーして目的の文字を検索するのが手っ取り早い。

下記部分を最初に書いていた。

最初は、ここより下の文章を書いていた。 いろいろできるようになっていったら、うれしくなって、どんどん肥大化していった。

tcl/tkよく使うメモ

プログラム言語は、pythonから入ったのでtcl/tkとかよく分からない。
基本的に、どの言語でも、np.linspaceのような等差数列を出すコマンドが欲しいと思ってしまう。
だから、下のほうに、tcl/tkでもnp.linspace風の等差数列を実現するfor構文を書いておいた。こういうときって、for書くしかないのね。procで自作関数かするしかないのか。"未開拓の土地に来"た感あるなぁ。

文字列の表示 puts

printじゃなくputs。 echoでも通ります。

##############
#文字列の表示#
##############

# 文字列は、""か{}で囲んだら、表示された。
puts "Hello world."
echo Hello

変数の代入 set,$

変数は、

set 変数名 値

その値をputsで表示したいのであれば、

puts $変数名

############
#変数の表示#
############
set a 1
puts $a

コメントアウト #もしくは;

すでに何か書いてある行にコメントアウトするのであれば、

○○ [×× ◇◇◇ △△△];# コメントアウトの#の前に;(セミコロン)が要る

何も書いてない行にコメントアウトを入れるのであれば、

#何も書かれていない行には、最初から#を書けばいい。

################
#コメントアウト#
################
#コメントアウト
puts "abc" ;#行末尾では、コメントアウトの仕方が変わる。セミコロンの後に#じゃないとダメ。

配列

配列。変数の中に複数の値を入れるあれ。 代入するとき、添字(index)を指定。 取り出すときも、そのindexを指定。

############
#配列の表示#
############
set b(0) 5
set b(1) 1
set b(2) 7
set b(3) 8

puts $b(2)

リスト

リストも、変数の中に、複数の値が入っている。
リストを作るには、

"1 10 100 1000"

のように、スペース区切りで入力する。

####################
#リストは配列じゃない#
################
#スペース区切りの文字列で、リスト。

set c "2 4 6 8 10"
#puts $c(2);#配列のようにindexingしてはいけない。
puts [lindex $c 3];#返り血は8。リストのindexingはlindexという専用の関数を使用する。
#ちなみに、[]はコマンドをくくるときに使う。

ちなみに、上記の、配列のように添え字付きで、putsすると、

puts $c(2)
can't read "a(1)": variable isn't array

と返ってくる。

繰返し構文

for、incr

###########
#for 構文 #
###########
for {set i 1} {$i <= 5} {incr i} {
puts $i
}

incrは、

incr i 2

とすれば、2ずつ増える。

pythonのnp.linspace風に、tcl/tkでも等差数列が欲しい。

incrは便利なようで不便。なぜなら、整数型しか使えないから。
自分は、numpyのlinspaceのような関数を見つけられていないから、for構文で小数点以下の数字を作りたいのだけれども、そういう時はincrを使わずに、

###########
#for 構文 #
###########
for {set i 0} {$i <= 5} {set i [expr {$i+0.1}] } {
puts $i
}

foreach

foreachで、for以外の変数で繰り返す。

forだと、整数で繰り返す。
foreachなら、文字列や小数点のある数値でも繰り返せる。

#########
#foreach#
#########
foreach i {A B C} {
puts $i
}

このforeachは、上記のリストとかで使う。

0埋め

ここでも連番画像やテキストファイルの取得をするかもしれないので、0埋めの方法を書いておく。

#######
#0埋め#
#######
puts [format "0 padding %0.5d" 1]

tk

tkで、GUIを作る。 工夫したのは、整数型しか入力しない点。

package require Tk

proc pushed {} {
puts $::eleID1
}

proc
exit {} {
destroy .
}

wm title . "Set and print integer" ;# タイトル設定

#準備して、
set eleID1 0
entry .entr1 -textvariable eleID1 -validate all -vcmd {string is int %P};# -validatecommand {if {[string first "%s" "1234567890."] == -1} {return 1} else {return 0}}
label .l1 -text "Enter intefer"
button .btn1 -text "OK." -command pushed
button .btn2 -text "Cancel." -command exit

#設置する。

pack .entr1 .l1 .btn1 .btn2 -side left

最後の空白行1行も、一応実行してね。
下のような感じになります。
tcl tk_実行.png


ちなみにマラソンは完走した。4:55くらいだった。サブ4までの道のりは長い。
(自分用メモ) マークダウンは、visual studio codeで書いて、Mark Rightのプレビューをさくらのブログにコピー→いったん保存→コードの改行を治す。→タグP、h3などの余計なスタイルを空白で置換して軽くするで作る事にする。
posted by yuchan at 07:00 | Comment(293) | tcl/tk