アフィン変換行列(3/4)「(AI先生へ)正三角形の頂点求め方について、多くの解法を教えて下さい。」を聞きました。

:::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) 上のタグと同じです。
:::


# ChatGPT先生へ
・質問リストの追番は無視して下さい。１個ずつです。途中の回答表示は省略しています。
```
# 質問リスト
1. 正三角形の2つの頂点(Ax,Ay)と(Bx,By)がわかっていて、第3の頂点を求めたい。多くの解法を教えて下さい。  
2. 上記のまとめの表の1列目に、方法の追番を追加して下さい。  
3. 上記の表の見出しを、 # →方法 へ 方法→名称 に変更して下さい。  
4. 上記の表を、Markdown形式のソースコードを教えて下さい。  
5. 私の質問をMarkdown形式でリスト化して出力して。Markdown形式でリストからアスタリスクは削除して。1行目に、# 質問リスト の文字を出力して。  
```
```
上記の5つの方法を、sympyのソースコードで教えて下さい。
```
・(枝分かれ?) 以下１~５を順番に繰り返しました。
```
上記の方法1を、sympyのソースコードで教えて下さい。
```

# 目次

| 方法 | 名称 | 概要 | 特徴 |
|------|------|------|------|
| **1** | **ベクトル回転** | \( AB \) を \( 60^\circ \) 回転 | 計算が直感的でプログラムしやすい |
| **2** | **中点と高さ** | 中点から垂直方向に高さを加える | 幾何的に分かりやすい |
| **3** | **極座標** | 角度を利用して回転 | 三角関数を使うがシンプル |
| **4** | **複素数** | 複素数の回転を利用 | 数式が簡潔で実装しやすい |
| **5** | **連立方程式** | 距離条件から求める | 計算が長いが理論的に確実 |

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

#### 方法1.ベクトル回転
```python
import sympy as sp

def rotate_point(x, y, cx, cy, angle):
    """
    点(x, y)を(cx, cy)を中心にangleだけ回転する。
    """
    angle = sp.rad(angle)  # 角度をラジアンに変換
    cos_theta = sp.cos(angle)
    sin_theta = sp.sin(angle)
    
    x_new = cx + (x - cx) * cos_theta - (y - cy) * sin_theta
    y_new = cy + (x - cx) * sin_theta + (y - cy) * cos_theta
    
    return sp.simplify(x_new), sp.simplify(y_new)

def equilateral_triangle_vertices(ax, ay, bx, by):
    """
    正三角形の3つ目の頂点を求める。
    """
    # 60度回転（反時計回り）
    cx1, cy1 = rotate_point(bx, by, ax, ay, 60)
    
    # -60度回転（時計回り）
    cx2, cy2 = rotate_point(bx, by, ax, ay, -60)
    
    return (cx1, cy1), (cx2, cy2)

# シンボリック変数の定義
Ax, Ay, Bx, By = sp.symbols('Ax Ay Bx By')
C1, C2 = equilateral_triangle_vertices(Ax, Ay, Bx, By)

# 結果を表示
print("第3の頂点（反時計回り）:", C1)
print("第3の頂点（時計回り）:", C2)
```
#### 方法2.中点と高さ
```python
import sympy as sp

def find_equilateral_triangle_vertices(A, B):
    x1, y1 = A
    x2, y2 = B
    
    # 中点 M
    Mx, My = (x1 + x2) / 2, (y1 + y2) / 2
    
    # AB の長さ
    d = sp.sqrt((x2 - x1)**2 + (y2 - y1)**2)
    
    # 正三角形の高さ h
    h = (sp.sqrt(3) / 2) * d
    
    # AB に垂直なベクトル (u, v)
    u, v = -(y2 - y1) / d, (x2 - x1) / d
    
    # 2つの C の座標を求める
    C1 = (Mx + h * u, My + h * v)
    C2 = (Mx - h * u, My - h * v)
    
    return C1, C2

# 例: A(0, 0), B(2, 0) の場合
A = (0, 0)
B = (2, 0)
C1, C2 = find_equilateral_triangle_vertices(A, B)

print("第3の頂点の候補:")
print("C1:", C1)
print("C2:", C2)
```

#### 方法3.極座標
```python
from sympy import symbols, cos, sin, atan2, pi, simplify

# 点 A, B の座標
x1, y1 = symbols('x1 y1')
x2, y2 = symbols('x2 y2')

# AB の長さ
d = ((x2 - x1)**2 + (y2 - y1)**2)**0.5

# AB の傾き
theta = atan2(y2 - y1, x2 - x1)

# 第3の頂点 C の座標（反時計回り）
x3_1 = x1 + d * cos(theta + pi/3)
y3_1 = y1 + d * sin(theta + pi/3)

# 第3の頂点 C の座標（時計回り）
x3_2 = x1 + d * cos(theta - pi/3)
y3_2 = y1 + d * sin(theta - pi/3)

# 結果を簡単にする
x3_1, y3_1 = simplify(x3_1), simplify(y3_1)
x3_2, y3_2 = simplify(x3_2), simplify(y3_2)

# 出力
(x3_1, y3_1), (x3_2, y3_2)
```

#### 方法4.複素数
```python
from sympy import symbols, I, exp, pi, simplify

# A, B の座標をシンボルとして定義
Ax, Ay, Bx, By = symbols('Ax Ay Bx By')

# A, B を複素数として表現
zA = Ax + Ay * I
zB = Bx + By * I

# 60度回転の複素数表現
rotation = exp(I * pi / 3)  # e^(iπ/3) = cos(60°) + i*sin(60°)

# C の座標を計算（時計回りと反時計回り）
zC1 = zA + (zB - zA) * rotation  # 反時計回り
zC2 = zA + (zB - zA) * exp(-I * pi / 3)  # 時計回り

# 実数部分と虚数部分を取り出して C の座標を求める
C1x, C1y = simplify(zC1.expand().as_real_imag())  # 反時計回り
C2x, C2y = simplify(zC2.expand().as_real_imag())  # 時計回り

# 結果を表示
print(f"反時計回りの C の座標: ({C1x}, {C1y})")
print(f"時計回りの C の座標: ({C2x}, {C2y})")
```

#### 方法5.連立方程式
```python
from sympy import symbols, Eq, solve
from sympy.geometry import Point, Triangle

# 頂点A, Bの座標を定義
A_x, A_y = 1, 2  # Aの座標
B_x, B_y = 4, 6  # Bの座標

# Cの座標を変数として定義
x, y = symbols('x y')

# 点A, B, Cの距離が等しいという条件
eq1 = Eq((x - A_x)**2 + (y - A_y)**2, (x - B_x)**2 + (y - B_y)**2)

# 正三角形なので、面積が一致することも考慮して、ABの長さを計算
# 点A, Bの距離
AB = ((B_x - A_x)**2 + (B_y - A_y)**2)**0.5
# ABを底辺とした三角形の高さを求める（面積から高さを求める）
height = (3**0.5 / 2) * AB

# 中点Mを求める
M_x = (A_x + B_x) / 2
M_y = (A_y + B_y) / 2

# Cの座標が中点Mから垂直方向に高さだけずれることを考慮
# Cの座標を求めるために、この垂直方向ベクトルを求める
eq2 = Eq((x - M_x)**2 + (y - M_y)**2, height**2)

# 連立方程式を解く
solutions = solve((eq1, eq2), (x, y))

# 解を表示
print(solutions)
```

# Gemini先生へ


# copilot先生へ

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

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

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

#### wikipdia内
#### Qiit内
#### google検索