アフィン変換行列(1/4)「点Aと点Bが、座標変換によって、点Cと点Dへ移動。１つづつ聞きました。点Eは?」をAI先生に聞きました。

・小見出し「座標変換コード」だそうです。(ChatGPT先生より)

:::note info
[4部作 アフィン変換行列](https://qiita.com/tags/%e3%82%a2%e3%83%95%e3%82%a3%e3%83%b3%e5%a4%89%e6%8f%9b%e8%a1%8c%e5%88%97) 上のタグと同じです。
:::
# 質問
・質問リストの追番は無視して下さい。１個ずつです。途中の回答表示は省略しています。
```
# 質問リスト
1. xy平面上の点Aと点Bが、座標変換によって、点Cと点Dへ移動しました。sympyのマトリックスのソースコードを教えて下さい。
2. 上記のソースコードの座標は変数でお願いします。
3. 上記の条件でスケーリングをするとなると、3行3列の行列になりませんか。
4. 上記の条件で、thetaとdx,dyの計算結果を、行列に代入して下さい。
5. 上記の条件で、sympyのユーザー定義関数でお願いします。
6. 上記の引数をsympyのPoint形式の4点でお願いします。
7. 上記のマトリックスで変換すると、Point(x_E, y_E)は、いくらになりますか。
8. 上記の引数のsx,syも関数内で、計算して下さい。
9. 結果を表示して下さい。
10. 上記をシンボリックのままでお願いします。
11. 上記のマトリックスは何と呼ばれていますか。呼び名を教えて下さい。
```
>(回答抜粋) 最後に
...この変換行列は **アフィン変換行列** と呼ばれ、回転、スケーリング、平行移動などの操作を同時に扱うことができる、非常に一般的な座標変換方法です。

(以下は未実行)　
**いい聞き方が、わかりませんでした。聞いていません。
アドバイスをいただけると幸いです。**
```
# 質問リスト
xy平面上の点Aと点Bが、**アフィン変換行列**によって、点Cと点Dへ移動しました。
アフィン変換行列の作成と点Eの変換後の座標計算。
sympyのマトリックスのソースコードを教えて下さい。
```







# ChatGPT先生へ

>ChatGPT の回答は必ずしも正しいとは限りません。重要な情報は確認するようにしてください。
>(回答抜粋)

・点A、点B → 点C,点D
・点E → 点E'
　...シンボリックのままでお願いします。
```python
import sympy as sp
from sympy.geometry import Point

def compute_transformation_matrix(A, B, C, D):
    """
    点A, Bの座標が点C, Dへ移動する際の2D座標変換行列（スケーリング・回転・平行移動）を求める関数
    
    引数:
        A, B : 移動前の2点（SymPyの Point オブジェクト）
        C, D : 移動後の2点（SymPyの Point オブジェクト）
    
    戻り値:
        transformation_matrix : 3×3の座標変換行列 (SymPy Matrix)
    """

    # 座標の取得
    x_A, y_A = A.coordinates
    x_B, y_B = B.coordinates
    x_C, y_C = C.coordinates
    x_D, y_D = D.coordinates

    # --- 1. スケーリング係数 sx, sy を計算（等方的スケール）---
    AB_length = sp.sqrt((x_B - x_A)**2 + (y_B - y_A)**2)  # |AB|
    CD_length = sp.sqrt((x_D - x_C)**2 + (y_D - y_C)**2)  # |CD|
    s = CD_length / AB_length  # スケール（sx = sy）

    # --- 2. 回転角 theta を計算 ---
    theta = sp.atan2(y_B - y_A, x_B - x_A) - sp.atan2(y_D - y_C, x_D - x_C)

    # --- 3. 平行移動 dx, dy を計算 ---
    dx = x_C - (s * sp.cos(theta) * x_A - s * sp.sin(theta) * y_A)
    dy = y_C - (s * sp.sin(theta) * x_A + s * sp.cos(theta) * y_A)

    # --- 4. 変換行列を作成 ---
    transformation_matrix = sp.Matrix([
        [s * sp.cos(theta), -s * sp.sin(theta), dx],
        [s * sp.sin(theta),  s * sp.cos(theta), dy],
        [0, 0, 1]
    ])

    return transformation_matrix

def transform_point(T, E):
    """
    変換行列Tを使って、点E(x_E, y_E)の新しい座標を求める関数

    引数:
        T : 3x3の座標変換行列 (SymPy Matrix)
        E : 変換前の点（SymPyの Point オブジェクト）

    戻り値:
        E' : 変換後の点（SymPyの Point オブジェクト）
    """

    x_E, y_E = E.coordinates
    E_h = sp.Matrix([x_E, y_E, 1])  # 同次座標 (x, y, 1)

    # 変換後の座標
    E_h_prime = T * E_h

    # 新しい座標を取得
    x_E_prime, y_E_prime = E_h_prime[:2]

    return Point(x_E_prime, y_E_prime)

# 使用例（シンボリック変数で定義）
x_A, y_A, x_B, y_B = sp.symbols('x_A y_A x_B y_B')
x_C, y_C, x_D, y_D = sp.symbols('x_C y_C x_D y_D')
x_E, y_E = sp.symbols('x_E y_E')

A = Point(x_A, y_A)
B = Point(x_B, y_B)
C = Point(x_C, y_C)
D = Point(x_D, y_D)
E = Point(x_E, y_E)

# 変換行列を計算
T = compute_transformation_matrix(A, B, C, D)

# 点Eの変換後の座標を計算
E_prime = transform_point(T, E)

# 結果をシンボリック形式で表示
sp.pprint(E_prime)
```




# Gemini先生へ


# copilot先生へ

# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

https://qiita.com/mrrclb48z/items/b6351b48e47bcf6265c0

# いつもと違うおすすめです。

#### wikipdia内

https://en.wikipedia.org/wiki/Affine_transformation

https://ja.wikipedia.org/wiki/アフィン写像

#### Qiit内
＞? OpenCVでの実装

https://qiita.com/koshian2/items/c133e2e10c261b8646bf

#### google検索
アフィン変換行列

https://www.google.com/search?q=%E3%82%A2%E3%83%95%E3%82%A3%E3%83%B3%E5%A4%89%E6%8F%9B%E8%A1%8C%E5%88%97+&sca_esv=a2e05d3851fdab60&rlz=1CAUHAM_enJP1105&sxsrf=AHTn8zrsqPeVfaRYm2rqZ6s9lcaa58ppNw%3A1740910855336&ei=BzHEZ5GRFKjp1e8P-M2goQY&ved=0ahUKEwjRsPioluuLAxWodPUHHfgmKGQQ4dUDCBA&uact=5&oq=%E3%82%A2%E3%83%95%E3%82%A3%E3%83%B3%E5%A4%89%E6%8F%9B%E8%A1%8C%E5%88%97+&gs_lp=Egxnd3Mtd2l6LXNlcnAiGeOCouODleOCo-ODs-WkieaPm-ihjOWIlyAyBBAjGCcyBBAAGB4yBBAAGB4yBBAAGB4yCBAAGIAEGKIEMggQABiABBiiBDIIEAAYgAQYogQyBhAAGAUYHkidHlCIBVjxEHABeACQAQCYAYgBoAHRCaoBBDAuMTC4AQPIAQD4AQGYAgqgAsQJwgIKEAAYsAMY1gQYR8ICCBAAGKIEGIkFwgIFEAAY7wWYAwCIBgGQBgqSBwMxLjmgB-At&sclient=gws-wiz-serp