正弦定理の考え方
Exercise 1
\(BC = 30, \angle B = 70^\circ, \angle C = 63^\circ\) となるような \(\triangle ABC\) が与えられたとします.このとき,長さ \(AB\) を求めよ
設問の \(\triangle ABC\) を図示すると以下のようになります.\(B\) から \(AC\) に対して垂線を垂らし,その交点を \(BH\) とします.
Code
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
def plot_triangular(base_length: float, angles: tuple, fig_size=(6,6)):
# Given values
= 30 # Side BC
BC = np.radians(angles[0]) # Convert degrees to radians
angle_B = np.radians(angles[1]) # Convert degrees to radians
angle_C
# Calculate angle A
= np.radians(180 - sum(angles))
angle_A
# Use Law of Sines to find AB and AC
= BC * np.sin(angle_B) / np.sin(angle_A)
AB = BC * np.sin(angle_C) / np.sin(angle_A)
AC
# Set points in a 2D coordinate system
= np.array([0, 0]) # Point B at the origin
B = np.array([BC, 0]) # Point C on the x-axis
C
# Calculate A's coordinates using trigonometry
= BC - AC * np.cos(angle_B) # Projection of AC on x-axis
A_x = AC * np.sin(angle_B) # Height of A
A_y
= np.array([A_x, A_y])
A
# Plot the triangle using ax
= plt.subplots(figsize = fig_size)
fig, ax 0], B[0]], [A[1], B[1]], 'ko-') # Black line with circle markers
ax.plot([A[0], C[0]], [B[1], C[1]], 'ko-') # Black line with circle markers
ax.plot([B[0], A[0]], [C[1], A[1]], 'ko-') # Black line with circle markers
ax.plot([C[
# Annotate points
0], A[1], ' A', fontsize=12, verticalalignment='bottom')
ax.text(A[0], B[1], ' B', fontsize=12, verticalalignment='top', horizontalalignment='right')
ax.text(B[0], C[1], ' C', fontsize=12, verticalalignment='top', horizontalalignment='left')
ax.text(C[
# Add angles as arcs
= 5 # Radius for the arcs
arc_radius
# Angle at B
= patches.Arc(B, arc_radius, arc_radius, angle=0, theta1=0, theta2=np.degrees(angle_B), color='blue')
angle_B_arc
ax.add_patch(angle_B_arc)0] + arc_radius/2, B[1] + 1, f"{70}°", fontsize=12, color='blue')
ax.text(B[
# Angle at C
= patches.Arc(C, arc_radius, arc_radius, angle=0, theta1=180 - np.degrees(angle_C), theta2=180, color='red')
angle_C_arc
ax.add_patch(angle_C_arc)0] - arc_radius/2) - 2, C[1] + 1, f"{63}°", fontsize=12, color='red')
ax.text((C[
return fig, ax, (A, B, C)
# plot
= plot_triangular(30, (70, 63))
fig, ax, coordinates
# add BH
= -1/((coordinates[2][1] - coordinates[0][1])/(coordinates[2][0] - coordinates[0][0]))
slope 0, 26.5), (0, slope * 26.5))
ax.plot((26.5, slope * 26.5, ' H', fontsize=12, verticalalignment='top', horizontalalignment='left')
ax.text(
# add labels
15, -2, "BC = 30", fontsize=12, color='black', horizontalalignment='center')
ax.text(0, color='black',linewidth=0.5)
ax.axhline(0, color='black',linewidth=0.5)
ax.axvline(True, linestyle='--', alpha=0.6)
ax.grid(-5, 35)
ax.set_xlim(-5, 42)
ax.set_ylim("Triangle ABC")
ax.set_title( plt.show()
\(\triangle BCH, \triangle ABH\) を考えると,
\[ \begin{align} BH &= \sin( A) * AB\\ BH &= \sin( C) * BC \end{align} \]
これを整理すると
\[ \begin{align} AB &= \frac{\sin(C) * BC}{\sin A}\label{eq-law-of-sines-1}\\ &= \frac{30 \cdot \sin(63^\circ)}{\sin(47^\circ)}\label{eq-law-of-sines-2} \end{align} \]
従って,
Code
print(f"BC = {30 * np.sin(63/180 * np.pi)/np.sin(47/180 * np.pi):.4f}")
BC = 36.5489
と計算されます.
正弦定理の証明
\(\eqref{eq-law-of-sines-1}\), \(\eqref{eq-law-of-sines-2}\) を整理すると
\[ \frac{AB}{\sin A} = \frac{BC}{\sin C} \]
を得ます.同様の方法で \(AC\) を求めて整理すると,
\[ \frac{AB}{\sin A}= \frac{AC}{\sin B} = \frac{BC}{\sin C} \]
これは,\(\triangle ABC\) の外接円を考えたとき,その外接円の半径を \(R\) としたとき
\[ \frac{AB}{\sin A}= \frac{AC}{\sin B} = \frac{BC}{\sin C} = 2R \]
という正弦定理へ繋がります.
▶ 対辺と\(\sin\) の比率が直径 \(2R\)に一致する証明
Code
import numpy as np
import matplotlib.pyplot as plt
# 与えられた条件
= 30 # 辺BC
BC = np.radians(70) # 角B (ラジアン変換)
angle_B = np.radians(63) # 角C (ラジアン変換)
angle_C
# 角Aを計算
= np.radians(180 - (70 + 63))
angle_A
# 正弦定理を使ってABとACを求める
= BC * np.sin(angle_B) / np.sin(angle_A)
AB = BC * np.sin(angle_C) / np.sin(angle_A)
AC
# 頂点座標
= np.array([0, 0]) # Bを原点に配置
B = np.array([BC, 0]) # Cをx軸上に配置
C = BC - AC * np.cos(angle_B) # Aのx座標
A_x = AC * np.sin(angle_B) # Aのy座標
A_y = np.array([A_x, A_y])
A
# 垂直二等分線の交点(外心)を求める
def circumcenter(A, B, C):
= 2 * (A[0] * (B[1] - C[1]) + B[0] * (C[1] - A[1]) + C[0] * (A[1] - B[1]))
D = ((A[0]**2 + A[1]**2) * (B[1] - C[1]) + (B[0]**2 + B[1]**2) * (C[1] - A[1]) + (C[0]**2 + C[1]**2) * (A[1] - B[1])) / D
Ux = ((A[0]**2 + A[1]**2) * (C[0] - B[0]) + (B[0]**2 + B[1]**2) * (A[0] - C[0]) + (C[0]**2 + C[1]**2) * (B[0] - A[0])) / D
Uy return np.array([Ux, Uy])
= circumcenter(A, B, C)
circumcenter_point = np.linalg.norm(A - circumcenter_point) # 外接円の半径
radius
# 円周上の点P(円周角を示す)
= np.radians(120) # 任意の角度 (120°)
theta_P = circumcenter_point[0] + radius * np.cos(theta_P)
P_x = circumcenter_point[1] + radius * np.sin(theta_P)
P_y = np.array([0, 30/np.sin(angle_A) * np.sin(np.pi/2 - angle_A)])
P
# 図を作成
= plt.subplots(figsize=(6,6))
fig, ax
# 三角形ABCをプロット
0], B[0]], [A[1], B[1]], 'bo-', label="AB")
ax.plot([A[0], C[0]], [B[1], C[1]], 'ro-', label="BC")
ax.plot([B[0], A[0]], [C[1], A[1]], 'go-', label="CA")
ax.plot([C[
# 外接円をプロット
= plt.Circle(circumcenter_point, radius, color='cyan', fill=False, linestyle='dashed', label="Circumcircle")
circle
ax.add_patch(circle)
# 円周角を示す点Pと三角形BPC
0], P[0]], [B[1], P[1]], 'purple', linestyle='dotted', label="BP")
ax.plot([B[0], P[0]], [C[1], P[1]], 'purple', linestyle='dotted', label="CP")
ax.plot([C[
# 点のラベル
0], A[1], ' A', fontsize=12, verticalalignment='bottom')
ax.text(A[0], B[1], ' B', fontsize=12, verticalalignment='top', horizontalalignment='right')
ax.text(B[0], C[1], ' C', fontsize=12, verticalalignment='top', horizontalalignment='left')
ax.text(C[0], P[1], ' P', fontsize=12, verticalalignment='bottom', horizontalalignment='right', color='purple')
ax.text(P[0], circumcenter_point[1], color='black') # 外心O
ax.scatter(circumcenter_point[
# グリッドと範囲設定
0, color='black', linewidth=0.5)
ax.axhline(0, color='black', linewidth=0.5)
ax.axvline(True, linestyle='--', alpha=0.6)
ax.grid(-radius-5, BC+radius+5)
ax.set_xlim(-radius-5, radius+AC+5)
ax.set_ylim(
ax.legend()"Triangle ABC with Circumcircle and Inscribed Angle")
ax.set_title(
# 図を表示
plt.show()
例題: 山の高さを求める
Exercise 2
とある山へハイキングにいくとします.
- 山頂をC
- 山の麓のA地点から同じ標高で直線距離で1000m離れている地点をB
- A地点からCを見たときの仰角は \(30^\circ\)
- \(\triangle ABC\) について,\(\angle CAB = 75^\circ, \angle ABC = 45^\circ\)
ということがわかっているとします.このとき,Cの標高を求めよ.なお,\(A, B\) の標高は 0m とする.
Code
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
# Given angles and side lengths
= np.radians(75)
angle_A = np.radians(45)
angle_B = 1000 # Given
AB
# Compute angle C
= np.radians(180 - 75 - 45) # C = 60 degrees
angle_C
# Compute sides using the Law of Sines
= AB * np.sin(angle_A) / np.sin(angle_C)
BC = AB * np.sin(angle_B) / np.sin(angle_C)
AC
# Compute coordinates of A, B, and C
= np.array([0, 0, 0]) # A is the origin
A = np.array([AB, 0, 0]) # B is along the x-axis
B = 0 # Projection of AC on x-axis
C_x = AC * np.cos(np.radians(30))
C_y = AC * np.sin(np.radians(30)) # Projection on y-axis
C_z = np.array([0, C_y, C_z]) # C remains in the XY plane
C
# Triangle ACH: Given CAH = 30°, CHA = 90° (Right Triangle)
= np.radians(30)
angle_CAH
# H's coordinates (directly above C in the Z direction)
= np.array([0, C_y, 0])
H
# Create 3D plot
= plt.figure(figsize=(8, 8))
fig = fig.add_subplot(111, projection='3d')
ax
# Plot edges of tetrahedron
= [
edges # Triangle ABC
(A, B), (B, C), (C, A), # Connecting H to A, C, and B
(A, H), (C, H), (B, H)
]
for edge in edges:
*zip(*edge), 'k-')
ax.plot(
# Define faces for tetrahedron visualization
= [
faces # Base ABC
[A, B, C], # Side ACH
[A, C, H], # Side CBH
[C, B, H], # Side AHB
[A, H, B]
]
# Add face shading
=0.3, color='cyan'))
ax.add_collection3d(Poly3DCollection(faces, alpha
# Annotate points
*A, " A", color='black', fontsize=12)
ax.text(*B, " B", color='black', fontsize=12)
ax.text(*C, " C", color='black', fontsize=12)
ax.text(*H, " H", color='black', fontsize=12)
ax.text(
# Labels and grid
"X-axis")
ax.set_xlabel("Y-axis")
ax.set_ylabel("Z-axis")
ax.set_zlabel("3D Tetrahedron CAHB")
ax.set_title(True)
ax.grid(
=20, azim=-55)
ax.view_init(elev
# Show the plot
plt.show()