Google で Python その2「アフィン変換」

これは既出「図形変形のためのアフィン変換」のGoogle Colaboratory 版です。ただし、パラメータの入れ直しや変換順の変更はできませんでした。お許しください。
Google で Python を実行する方法は、「Google で Python その1」の「まえがき」をご参照ください。
なお、本Google Colab版「図形変換のためのアフィン変換」はGoogle Colab専用です。通常のPython 開発環境では「Ipython がない」というエラーが出ます。

# 2次元図形「box」のアフィン変換。2023.01.11 by Kero
# modified for Google Colaboratory 2023.01.29 by Kero

import sys
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation, rc
from IPython.display import HTML

# アフィン変換の宣言。
print('2次元座標サンプル(台形)のアフィン変換を行列演算で実行します。')
print('座標行列 x に 変換処理(T) を Tx の形で行います。')
print('変換は、A:回転、B:拡大、C:せん断、D:鏡映、E:平行移動、です。')
print('各変換のパラメータ入力は、空リターンで標準値が入ります。')
print('変換順は、英記号で入力してください。空リターンでおわりです。')
print('表示に1分近くかかることがあります。ご了承ください。')
print('')

# プロットエリアの設定。xy軸は同じ長さ。
def gurafu():
    plt.xlim(-10.,10.)
    plt.ylim(-10.,10.)
    plt.xticks(np.arange(-10, 11, 2))
    plt.yticks(np.arange(-10, 11, 2))
    ax.set_aspect('equal', adjustable='box')
    plt.grid(which='major')

# 座標群を行列にします。一筆書きになります。szはすべて1。
def tensen(t):
    sx = np.array([])
    sy = np.array([])
    sz = np.array([])
    for i in range(t.shape[0]): # shape は配列の長さ。
        sx = np.append(sx, t[i,0])
        sy = np.append(sy, t[i,1])
        sz = np.append(sz, 1)
    return np.concatenate([[sx],[sy],[sz]])

# 入力値が数値かチェック。
def isnum(t: str) -> bool:
    try:
        float(t)
        return True
    except ValueError:
        return False

# 回転のマトリックス設定。
def A(drd,i):
    rd = drd * i
    Am = np.array([[np.cos(rd), -np.sin(rd), 0],
                  [np.sin(rd),  np.cos(rd), 0],
                  [0., 0., 1.]])
    return Am

# 拡大のマトリックス設定。
def B(dkax, dkay,i):
    Bm = np.array([[dkax * i + 1., 0, 0],
                   [0, dkay * i + 1., 0],
                   [0, 0, 1]])
    return Bm

# せん断のマトリックス設定。
def C(dsex, dsey, i):
    sex = dsex * i
    sey = dsey * i
    Cm = np.array([[1., np.tan(sex), 0.],
                   [np.tan(sey), 1., 0.],
                   [0., 0., 1.]])
    return Cm

# 鏡映のマトリックス設定
def D(dkyx, dkyy, i, kyx, kyy):
    if kyx == '1':
        a22 = dkyx * i * 2 + 1.
    else:
        a22 = 1.
    if kyy == '1':
        a11 = dkyy * i * 2 + 1.
    else:
        a11 = 1.
        
    Dm = np.array([[a11, 0., 0.],
                   [0., a22, 0.],
                   [0., 0., 1.]])
    return Dm

# 平行移動のマトリックス設定。
def E(didx, didy, i):
    idx = didx * i
    idy = didy * i
    Em = np.array([[1., 0., idx],
                   [0., 1., idy],
                   [0., 0., 1.]])
    return Em

# サンプルとしての形状座標群(台形)。
box = np.array([[0., 0.],
                [3., 0.],
                [3., 2.],
                [0., 3.],
                [0., 0.]])


# パラメータ入力。
print('【パラメータ入力】')
# 1.回転
do = input('A:回転:回転角度?(度):')
if (do == '') or (not(isnum(do))):
    drd = 0
else:
    drd = 0.01 * np.radians(float(do))

# 2.拡大
kax = input('B:拡大:xの拡大率? :')
if (kax == '') or (not(isnum(kax))):
    dkax = 0.
else:
    dkax = 0.01 * (float(kax) - 1.)
kay = input('B:拡大:yの拡大率? :')
if (kay == '') or (not(isnum(kay))):
    dkay = 0.
else:
    dkay = 0.01 * (float(kay) - 1.)

# 3.せん断
sex = input('C:せん断:y軸をx軸方向へ何度?:')
if (sex == '') or (not(isnum(sex))):
    dsex = 0.
else:
    dsex = 0.01 * np.radians(float(sex))
sey = input('C:せん断:x軸をy軸方向へ何度?:')
if (sey == '') or (not(isnum(sey))):
    dsey = 0.
else:
    dsey = 0.01 * np.radians(float(sey))

# 4.鏡映
kyx = input('D:鏡映:x軸対称(0/1)?:')
kyy = input('D:鏡映:y軸対称(0/1)?:')
if kyx == '1':
    dkyx = -0.01
else:
    dkyx = 0.01
    kyx = '0'
if kyy == '1':
    dkyy = -0.01
else:
    dkyy = 0.01
    kyy = '0'

# 5.平行移動
idx = input('E:平行移動:x方向?:')
if (idx == '') or (not(isnum(idx))):
    didx = 0.
else:
    didx = 0.01 * float(idx)
idy = input('E:平行移動:y方向?:')
if (idy == '') or (not(isnum(idy))):
    didy = 0.
else:
    didy = 0.01 * float(idy)

# 変換順の入力
print('')
print('【変換順(英記号)入力】')
jun = []
while True:
    hen = input('変換は?:')
    if hen == '':
        break
    jun.append(hen.upper())

# アニメ化。
fig, ax = plt.subplots()
artists = []
gurafu()
        
# 原型はブルーで表示。
boxline = tensen(box) # 座標行列を作成。
plt.plot(boxline[0], boxline[1], c='b')

# 入力順に変換の実行。
for j in jun:
    print(j)
    if j == 'A':
        for d in range(101):
            Am = A(drd,d)
            boxline2 = np.dot(Am, boxline)
            artist = ax.plot(boxline2[0], boxline2[1], c='r')
            artists.append(artist)

    elif j == 'B':
        for d in range(101):
            Bm = B(dkax,dkay,d)
            boxline2 = np.dot(Bm, boxline)
            artist = ax.plot(boxline2[0], boxline2[1], c='r')
            artists.append(artist)

    elif j == 'C':
        for d in range(101):
            Cm = C(dsex,dsey,d)
            boxline2 = np.dot(Cm, boxline)
            artist = ax.plot(boxline2[0], boxline2[1], c='r')
            artists.append(artist)

    elif j == 'D':
        for d in range(101):
            Dm = D(dkyx,dkyy,d, kyx, kyy)
            boxline2 = np.dot(Dm, boxline)
            artist = ax.plot(boxline2[0], boxline2[1], c='r')
            artists.append(artist)

    elif j == 'E':
        for d in range(101):
            Em = E(didx,didy,d)
            boxline2 = np.dot(Em, boxline)
            artist = ax.plot(boxline2[0], boxline2[1], c='r')
            artists.append(artist)

    boxline = boxline2
    
anim = animation.ArtistAnimation(fig, artists, interval=50)

rc('animation', html='jshtml')
plt.close()
anim

「Google で Python その2「アフィン変換」」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です