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

Python Matplotlib: วาด Polygon ใหญ่ที่สุดจากชุดจุด (Convex Hull)

บทนำ

การวาด polygon ใหญ่ที่สุดที่ครอบจุดทั้งหมด เรียกว่า Convex Hull ใน Matplotlib ใช้ Polygon patch จาก matplotlib.patches แต่อาจต้องคำนวณ hull ก่อนด้วย SciPy หรือการคำนวณเอง

ตัวอย่างโค้ด (ใช้จุดที่กำหนดเอง)


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

# กำหนดขนาดรูป
plt.rcParams["figure.figsize"] = [7.00, 3.50]
plt.rcParams["figure.autolayout"] = True

# จุดข้อมูล (ตัวอย่าง: จุดที่เป็นรูปห้าเหลี่ยม)
points = np.array([
    [1, 1],
    [0.5, 1.5],
    [2, 1],
    [1, 2],
    [2, 2]
])

# สร้าง Polygon patch
polygon = Polygon(points, facecolor='k')  # 'k' = black

# สร้าง figure และ axes
fig, ax = plt.subplots()

# เพิ่ม polygon ลง axes
ax.add_patch(polygon)

# กำหนดขอบเขตแกน
ax.set_xlim([0, 3])
ax.set_ylim([0, 3])

# ตกแต่ง
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
ax.set_title("Polygon from Points")

plt.show()

คำนวณ Convex Hull จริง (ด้วย SciPy)


from scipy.spatial import ConvexHull
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon

# จุดสุ่ม
np.random.seed(42)
points = np.random.rand(30, 2) * 10

# คำนวณ Convex Hull
hull = ConvexHull(points)

# จุดบน hull (เรียงตามลำดับรอบ)
hull_points = points[hull.vertices]

# วาด
fig, ax = plt.subplots(figsize=(7, 7))
ax.plot(points[:, 0], points[:, 1], 'o', alpha=0.5, label='Points')
ax.add_patch(Polygon(hull_points, fill=False, edgecolor='red', linewidth=2, label='Convex Hull'))
ax.set_aspect('equal')
ax.legend()
ax.grid(True, alpha=0.3)
plt.show()

คำนวณ Convex Hull เอง (ไม่ใช้ SciPy - Andrew's Monotone Chain)


def convex_hull(points):
    """Andrew's Monotone Chain Algorithm O(n log n)"""
    # เรียงจุดตาม x แล้ว y
    points = sorted(set(map(tuple, points)))
    
    if len(points) <= 1:
        return points
    
    def cross(o, a, b):
        return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
    
    # Lower hull
    lower = []
    for p in points:
        while len(lower) >= 2 and cross(lower[-2], lower[-1], p) <= 0:
            lower.pop()
        lower.append(p)
    
    # Upper hull
    upper = []
    for p in reversed(points):
        while len(upper) >= 2 and cross(upper[-2], upper[-1], p) <= 0:
            upper.pop()
        upper.append(p)
    
    # รวม (ลบจุดซ้ำปลาย)
    return lower[:-1] + upper[:-1]

# ทดสอบ
points = [(1,1), (0.5,1.5), (2,1), (1,2), (2,2), (1.5, 0.5)]
hull = convex_hull(points)
print("Hull vertices:", hull)

# วาด
fig, ax = plt.subplots()
ax.plot(*zip(*points), 'o')
ax.add_patch(Polygon(hull, fill=False, edgecolor='red', linewidth=2))
ax.set_aspect('equal')
plt.show()

กรณีใช้งานจริง

  • Computer vision: object boundary detection
  • GIS: เขตขอบพื้นที่
  • Robotics: path planning, collision avoidance
  • Data visualization: boundary ของ point cloud

สรุป

ใช้ matplotlib.patches.Polygon วาด polygon จากจุด สำหรับ Convex Hull จริง ใช้ scipy.spatial.ConvexHull หรือ implement Andrew's algorithm เอง (O(n log n)) แล้วสร้าง Polygon จาก hull vertices