Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Python

วิธีกำหนด Line Style แบบลูกศร (Arrow-like) ใน Matplotlib

การวาดเส้นที่มีลูกศรชี้ทิศทาง (Arrow-like Line Style) ใน Matplotlib ทำได้ด้วยเมธอด quiver() ซึ่งออกแบบมาสำหรับ Vector Field แต่ใช้วาดเส้นทางกับลูกศรได้ดี

หลักการ quiver()

quiver(X, Y, U, V) วาดลูกศรจากจุด (X, Y) ไปยัง (X+U, Y+V) โดย:

  • X, Y: ตำแหน่งเริ่มต้นลูกศร
  • U, V: เวกเตอร์ทิศทาง/ความยาว (Delta X, Delta Y)
  • angles='xy', scale_units='xy', scale=1: ใช้ Data Coordinates โดยตรง

ตัวอย่าง: วาดเส้นโค้งพร้อมลูกศรชี้ทิศทาง

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams["figure.figsize"] = [10, 6]
plt.rcParams["figure.autolayout"] = True

# ข้อมูลเส้นโค้ง
x = np.linspace(-5, 5, 50)
y = np.sin(x)

fig, ax = plt.subplots()

# วาดเส้นโค้งพื้นหลัง
ax.plot(x, y, 'k-', linewidth=1, alpha=0.3, label='Path')

# คำนวณ Vector สำหรับ quiver (ทิศทางเส้นโค้ง)
# ใช้จุดกึ่งกลางระหว่างจุดข้อมูล
x_mid = (x[:-1] + x[1:]) / 2
y_mid = (y[:-1] + y[1:]) / 2
u = x[1:] - x[:-1]  # Delta X
v = y[1:] - y[:-1]  # Delta Y

# วาดลูกศรทุก 3 จุด (ไม่หนาแน่นเกินไป)
step = 3
ax.quiver(x_mid[::step], y_mid[::step], 
          u[::step], v[::step],
          angles='xy', scale_units='xy', scale=1,
          color='red', width=0.005, headwidth=3, headlength=4,
          label='Direction')

ax.set_xlim(-5.5, 5.5)
ax.set_ylim(-1.5, 1.5)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_title('Arrow-like Line Style with quiver()', fontsize=14)
ax.legend()
ax.grid(True, alpha=0.3)

plt.show()

ตัวอย่าง: ลูกศรระหว่างจุดข้อมูล (Annotate Style)

import numpy as np
import matplotlib.pyplot as plt

plt.rcParams["figure.figsize"] = [10, 6]
plt.rcParams["figure.autolayout"] = True

x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 3, 1, 4, 2])

fig, ax = plt.subplots()
ax.plot(x, y, 'ko-', linewidth=2, markersize=8)

# วาดลูกศรระหว่างจุดต่อเนื่อง
for i in range(len(x) - 1):
    ax.annotate('',
                xy=(x[i+1], y[i+1]), xycoords='data',
                xytext=(x[i], y[i]), textcoords='data',
                arrowprops=dict(arrowstyle='->', color='blue', lw=2,
                                mutation_scale=15, shrinkA=5, shrinkB=5))

ax.set_title('Arrows Between Data Points (annotate)', fontsize=14)
ax.grid(True, alpha=0.3)
plt.show()

ตัวอย่าง: Fancy Arrow Patch (ควบคุมรายละเอียดสูง)

from matplotlib.patches import FancyArrowPatch
import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(figsize=(10, 6))
x = np.linspace(0, 10, 20)
y = np.sin(x)

ax.plot(x, y, 'k-', alpha=0.3)

# สร้าง FancyArrowPatch แบบกำหนดเอง
for i in range(0, len(x)-1, 2):
    arrow = FancyArrowPatch(
        posA=(x[i], y[i]),
        posB=(x[i+1], y[i+1]),
        arrowstyle='fancy,head_width=0.3,head_length=0.5,tail_width=0.1',
        color='crimson',
        linewidth=2,
        mutation_scale=20,
        shrinkA=3, shrinkB=3
    )
    ax.add_patch(arrow)

ax.set_title('FancyArrowPatch for Custom Arrow Styles', fontsize=14)
ax.grid(True, alpha=0.3)
plt.show()

สรุปวิธีการเลือกใช้

วิธีเหมาะสำหรับความยืดหยุ่น
quiver()Vector Field, หลายลูกศรพร้อมกัน, ข้อมูลเป็น Arrayสูง
annotate()ลูกศรเดี่ยว, ชี้จากจุดไปจุด, มีข้อความประกอบสูงมาก
FancyArrowPatchลูกศรโค้ง, รูปทรงซับซ้อน, Animationสูงสุด
Arrow (patches.Arrow)ลูกศรตรงง่ายๆต่ำ

คำแนะนำ

  • ใช้ angles='xy', scale_units='xy', scale=1 ใน quiver เพื่อให้ 1 Unit = 1 Data Unit
  • width ควบคุมความหนาเส้น, headwidth, headlength ควบคุมหัวลูกศร
  • สำหรับเส้นโค้ง ใช้ annotate กับ connectionstyle='arc3,rad=0.3' จะได้ลูกศรโค้งตามเส้น