ภาคตัดกรวย (Conics) ด้วยภาษา Python ตอนที่ 1

ภาคตัดกรวย (conics) [2] เป็นเรื่องการเดินทางของจุดที่ทำให้เกิดเส้นโค้งตามแนวที่ได้จากการตัดกรวยกลม เริ่มต้นมาตั้งแต่ประมาณ 200 ปีก่อนคริสต์กาลโดย Apollonius [1]  จนกลายมาเป็นพื้นฐานขของค้นพบอีกหลายต่อหลายเรื่อง เช่น การเคลื่อนที่ของดาวเคราะห์ จานรับสัญญาณดาวเทียม ฯลฯ




จากภาพแสดงให้เห็นชนิดของ conics มี 4 ชนิดคือ

Circle  คือ เซตของจุดที่อยู่ห่างจากจุดคงที่จุดหนึ่งเป็นระยะทางเท่ากัน จุดคงที่จุดนั้นเรียกว่า จุดศูนย์กลาง นิยมเขียนแทนด้วย C และระยะทางคงที่นั้นเรียกว่า รัศมี (radius) นิยมเขียนแทนด้วย r

Ellipse คือ เซตของจุดที่อยู่ห่างจากจุดคงที่สองจุด (F, G) โดยผลรวมของระยะห่างระหว่างจุดกับจุดคงที่ทั้งสองมีค่าคงที่

Parabola  คือเซตของจุดที่อยู่ห่างจากสิ่งสองสิ่งเป็นระยะทางเท่ากัน สองสิ่งที่ว่าคือ
  • จุดคงที่เรียกว่า Focus 
  • เส้นตรงเรียกว่า Directrix


Hyperbola [3] เกิดจากการตัดกรวยสองกรวยที่ยอดมาชนกัน ดังภาพ

By Melikamp - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=25108128

การทำความเข้าใจเรื่องภาคตัดกรวยหรือ conics ที่ง่ายและรวดเร็วทางหนึ่งก็คือการวาดรูปขึ้นมาประกอบการจดจำนิยามและสมการ ในตอนนี้จะใช้ Python library ชื่อ matplolib [4] มาช่วยสร้างรูปร่างต่าง ๆ ที่เกิดจากสมการ conics  ทั้งนี้ก็เพื่อให้การเขียน Python script สั้นและง่ายจนไม่น่าจะเป็นภาระ อีกทั้งทำให้เกิดการเรียนรู้แบบ interactive อีกด้วย

ติดตั้ง matplotlib 

1. Raspberry Pi 3 Model B ติดตั้ง Raspbian  และอุปกรณ์อื่นให้พร้อมใช้งาน
2. ใช้ python 3.5
3. ติดตั้ง matplotlib [4] ใช้คำสั่ง

$ sudo apt-get install python3-matplotlib

วงกลมและวงรี





หากพิจารณาจากรูปแล้ววงกลมและวงรีแทบจะเหมือนกันทุกประการ ดังนั้นเราจึงใช้สมการเดียวกันได้ คือ

x 2 a 2 + y 2 b 2 = r 2

เมื่อ a,b คือ scale factor [7]  สำหรับแกน x และ y ตามลำดับ และ r คือระยะห่างจากจุดศูนย์กลาง


เขียน Python script


ขั้นตอนที่ 1 นำเข้า module ที่ต้องใช้


import matplotlib.pyplot as plt
import numpy as np

เรานำ module เข้ามาในโปรแกรม (script) 2 modules คือ pyplot จาก matplotlib  แล้วกำหนดชื่ออ้างอิงใน script เป็น plt  (matplotlib เป็นกลุ่มของ module หลาย module  และ pyplot เป็นหนึ่งในนั้น)  และ numpy และกำหนดชื่อเป็น np (ไม่อยากเขียนยาว) เป็น module ที่ช่วยอำนวยความสะดวกในการทำงานกับตัวแปรที่มีหลายค่า (array)

ขั้นตอนที่ 2  สร้างตัวแปรและขอบเขตข้อมูล

x = np.linspace(-20,20,400)
y = np.linspace(-20,20,400)
x,y = np.meshgrid(x,y)


คำสั่ง np.linspace(-20,20,400) เป็นการสั่งให้ numpy ช่วยสร้างตัวแปรแบบ array ให้ โดยค่าเริ่มต้นคือ -20 ไปจนถึง 20 โดยมีสมาชิกทั้งหมด 400 ตัว  หากแสดงค่าของสมาชิกของ x หรือ y จะได้ดังภาพ จะเห็นได้ว่าค่าของ x, y เป็น array ของจำนวนจริง



x,y = np.meshgrid(x,y) เป็นคำสั่งที่ให้ numpy สร้างโครงสร้างข้อมูลแบบ grid หรือ coordinate หรือ คู่อันดับ ขึ้นมา โดยใช้ข้อมูลจาก x, y ไปสร้าง ผลที่ได้จากคำสั่งนี้คือจะได้ คู่อันดับจำนวน 400 x 400  = 160,000 คู่อันดับ (หากเขียนด้วยมือคงไม่ไหวแน่)
ทำไมต้องทำเป็นคู่อันดับ ก็เพราะเรากำลังนำข้อมูลไปเขียนกราฟหรือแสดงความสัมพันธ์ระหว่างตัวแปรสองตัว ในที่นี้แทนด้วย x และ y

ขั้นตอนที่ 3 กำหนด parameter อื่นที่เกี่ยวข้อง

a = 1
b = 1
r = 1
ct = (0,0)


จากสมการจะเห็นว่านอกจาก x และ y ซึ่งจะถูกนำไป plot แล้ว ก็ยังต้องมี a, b, r อีก และเพิ่มมาอีกหนึ่งคือ ct หรือ ตำแหน่งของ จุดศูนย์กลาง (นึกถึงนิยามวงกลม)

ขั้นตอนที่ 4  สร้างพื้นที่สำหรับการ plot

ax = plt.axes()
ax.axis('equal')
ax.grid()


ax  = plt.axes() เป็นคำสั่งบอกให้ pyplot สร้างพื้นที่สำหรับ plot ขึ้นมา โดย ax จะเป็นตัวแปรในการอ้างถึงแกน x และ แกน y ซึ่งเราจะสามารถปรับแต่งได้ต่อไป

ax.axis('equal')  เป็นคำสั่งให้ pyplot สร้างแกนนอนและแกนตั้งด้วยอัตราส่วนที่เท่ากัน

ax.grid() เป็นคำสั่งให้ pyplot สร้างเส้น grid ให้ด้วย ผลออกมาจะคล้ายกับการใช้กระดาษกร๊าฟ

ขั้นตอนที่ 5  การกำหนดความสัมพันธ์ด้วยสมการ

ax.contour(x,y,(x**2/a**2 + y**2/b**2),[r**2],color='green')


ดูเหมือนจะวุ่นวายสักหน่อยสำหรับคำสั่งนี้ แต่ไม่มีอะไรพิเศษ เป็นการสั่งให้ pyplot ทำการวาดเส้น contour [5] บนเงื่อนไขที่กำหนดให้ ซึ่งเงื่อนไขก็คือสมการแสดงความสัมพันธ์ระหว่างตัวแปรที่จะนำไป plot ในกรณีนี้ก็คือนำเอาสมการวงกลมหรือวงรีมาใส่ไว้นั่นเอง



ขั้นตอนที่ 6 สั่งวาดภาพ

plt.show()


ผลที่ได้คือ วงกลมที่มีรัศมี (r) 1 หน่วย เป็นวงกลมเพราะกำหนด scale ของ X และ Y ผ่านตัวแปร a, b ให้มีค่าเท่ากัน



script ที่เต็มรูปคือ

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-20,20,400)
y = np.linspace(-20,20,400)
x,y = np.meshgrid(x,y)

a = 1
b = 1
r = 1
ct =(0,0)

ax = plt.axes()
ax.grid()
ax.axis('equal')

ax.contour(x+ct[0],y+ct[1],x**2/a**2 + y**2/b**2, [r**2],color='green')

plt.show()



สั้นมาก ไม่มีอะไรซับซ้อน !


ทำการทดลองเปลี่ยนค่า parameter


1. เพิ่มค่า r เป็น r = 5 scale ของ X และ Y เท่ากัน แสดงความเร็วในการเปลี่ยนแปลงเท่ากัน


2.  a = 3  b = 1 เพิ่ม scale ของค่า X แสดงว่า ค่า X จะเปลี่ยนเร็วกว่าค่า Y


3.  a = 1, b = 3 เพิ่ม scale ของค่า Y แสดงว่าค่า Y จะเปลี่ยนเร็วกว่าค่า X




4. เปลี่ยนตำแหน่ง  ct = (3,3) เนื่องจากการเปลี่ยนตำแหน่งจุดศูนย์กลางจะมีผลในขั้นตอนของการวาด แต่รูปแบบความสัมพันธ์ยังคงเหมือนเดิม เราจึงไปแก้ไขในคำสั่ง contour เป็น

ax.contour(x+ct[0],y+ct[1],x**2/a**2 + y**2/b**2, [r**2],color='green')



5. อ้างอิงสมการ 2D rotation [6] ทดลองทำการหมุนภาพไป 30 องศา


theta = [np.pi/6] 

กำหนดองศาที่จะหมุน เนื่องจาก function geometry ใน Python ใช้มุมในหน่วยของ radian จึงต้องแปลงหน่วยให้เรียบร้อยก่อน

ax.contour(x*np.cos(theta) - y*np.sin(theta),
           x*np.sin(theta)+y*np.cos(theta),
           x**2/a**2 + y**2/b**2, 
           [r**2],
           color='green')


ทำการหมุนจุดทุกจุดก่อนการ plot



เราจะเรียนรู้ไม่ได้เต็มที่หากไม่ได้ทดลองเปลี่ยนแปลงอะไร ดังนั้นผู้อ่านควรไปทดลองเปลี่ยนแปลงค่า parameter ต่าง ๆแล้วดูผลลัพธ์ที่เปลี่ยนไป  ในตอนต่อไปจะกล่าวถึงเรื่องของ parabola และ hyperbola กันครับ


อกสารอ้างอิง

[1] https://en.wikipedia.org/wiki/Apollonius_of_Perga
[2] https://en.wikipedia.org/wiki/Conic_section
[3] https://en.wikipedia.org/wiki/Hyperbola
[4] https://matplotlib.org/
[5] https://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.contour
[6] https://somchaisom.blogspot.com/2018/03/computer-graphics-2-d-rotation.html
[7] https://somchaisom.blogspot.com/2018/03/computer-graphics-2d-scaling.html

Previous
Next Post »