φυβλαςのβλογ
บล็อกของ phyblas



manim บทที่ ๓: การสร้างและจัดวางวัตถุในภาพ
เขียนเมื่อ 2021/03/12 00:03
แก้ไขล่าสุด 2021/09/28 16:42

ต่อจาก บทที่ ๒

หลังจากที่ได้แนะนำคำสั่งที่ใช้ในการสร้างภาพใน manim ไปแล้ว บทต่อจากนี้จะเป็นการลงลึกเรื่องส่วนประกอบต่างๆของภาพ

งานหลักของ manim คือการสร้างภาพเคลื่อนไหว แต่ก่อนจะไปถึงตรงนั้น ในบทนี้จะเริ่มที่เรื่องของพื้นฐานการสร้างและจัดวางวัตถุต่างๆในภาพ แล้วจึงค่อยเริ่มไปทำภาพเคลื่อนไหวในบทที่ ๕




การสร้างและใส่วัตถุ MObject

MObject (m ในที่นี้ย่อมาจาก math) คือวัตถุพื้นฐานที่เป็นองค์กระกอบหลักภายในภาพของ manim

MObject มีอยู่หลากหลายชนิด เช่นตัวหนังสือ สูตรคณิตศาสตร์ กราฟ รูปร่างต่างๆ ฯลฯ

ใน manim ถ้าพูดถึง "วัตถุ" โดยทั่วไปก็จะหมายถึง MObject นี้ดังนั้นต่อไปจะเรียกง่ายๆว่า "วัตถุ"

วัตถุเหล่านี้สร้างขึ้นทำได้โดยสร้างจากคลาส เช่นตัวหนังสือคือออบเจ็กต์คลาส Text สูตรคณิตศาสตร์เป็นออบเจ็กต์ของคลาส Tex และสี่เหลี่ยมจตุรัส สามเหลี่ยม วงกลม เป็นออบเจ็กต์ในคลาส Square Triangle Circle เป็นต้น

วัตถุต่างๆที่สร้างขึ้นมาจัดวางเป็นองค์ประกอบภายในภาพของ manim ล้วนเป็นออบเจ็กต์ที่สร้างจากคลาสย่อยของคลาส MObject

แต่แค่สร้างวัตถุขึ้นมาเฉยๆจะยังไม่ปรากฏให้เห็นได้ในภาพ แต่จะปรากฏขึ้นเมื่อมีคำสั่งหรือเหตุการณ์อะไรบางอย่างทำให้มันปรากฏขึ้นมา

วิธีการทำให้วัตถุปรากฏในภาพนั้นมีอยู่หลายวิธี สำหรับในบทนี้จะพูดถึงวิธีที่ง่ายที่สุดคือใส่ลงไปเฉยๆให้ปรากฏในทันที (ยังไม่ทำเป็นภาพเคลื่อนไหว) โดยใช้เมธอด self.add() โดยใส่วัตถุทั้งหมดที่ต้องการให้ปรากฏลงไปด้วยกันทีเดียวเลย

ตัวอย่าง ลองสร้างวัตถุแต่ละชนิดขึ้นมาแล้วใส่ลงในภาพทั้งหมด
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        samliam = mnm.Triangle(color='#FF6622')
        samakan = mnm.Tex(r'4 \times 3 = 12',color='#22FF99')
        khokhwam = mnm.Text('มณีมาลา',color='#8888FF')
        self.add(khokhwam,samliam,samakan)

ภาพที่ได้



จะเห็นว่าวัตถุถูกวาดทับลงไปเรื่อยๆ ลำดับการวาดก่อนหลังจะขึ้นอยู่กับลำดับที่ใส่ใน self.add() ในที่นี้คือ ข้อความ (Text) > สามเหลี่ยม (Triangle) > สมการ (Tex)

รายละเอียดของวัตถุแต่ละชนิดจะยังไม่พูดถึงตอนนี้ แต่จะค่อยๆอธิบายเพิ่มเติมในบทถัดๆไป ตอนนี้จะพูดถึงลักษณะโดยรวมของ MObject ก่อน

ปกติเมื่อใส่ลงไปวัตถุทั้งหมดจะอยู่ตรงกลางของภาพ คือตำแหน่ง x=0,y=0 ต้องทำการจัดเรียงหรือย้ายตำแหน่งจึงจะไปอยู่ตำแหน่งที่ต้องการ ซึ่งจะกล่าวถึงต่อไป




การกำหนดพิกัดตำแหน่งวัตถุด้วยเมธอด .move_to()

วิธีการจัดวางตำแหน่งของวัตถุนั้นมีอยู่หลายวิธี โดยพื้นฐานแล้วที่ง่ายที่สุดคือใช้เมธอด .set_x(), .set_y() หรือ .move_to() ที่ตัวออบเจ็กต์หลังจากที่สร้างขึ้นมาแล้ว

โดย .set_x() จะเป็นการกำหนดตำแหน่งในแนวนอน .set_y() กำหนดตำแหน่งแนวตั้ง ส่วน .move_to() จะกำหนดตำแหน่งทั้งสองแนวไปพร้อมกัน

ค่าที่ต้องใส่ใน .move_to() คืออาเรย์ที่มีเลข ๓ ตัว ซึ่งแสดงถึงพิกัดในสามมิติ แต่ในที่นี้จะเริ่มจากภาพสองมิติ ซึ่งก็จะใช้แค่ x,y คือ ๒ ตัวแรก ส่วนอีกตัวคือค่าแกน z ในที่นี้ยังไม่ใช้จึงอาจใส่เป็น 0 ไว้ก็ได้

ตัวอย่างการใช้ .set_x(), .set_y() และ .move_to()
import manimlib as mnm
import numpy as np

class Manimala(mnm.Scene):
    def construct(self):
        text1 = mnm.Text('ก',color='#e0afdd')
        text1.set_x(5)
        text2 = mnm.Text('ข',color='#afd3e0')
        text2.set_y(-2)
        text3 = mnm.Text('ค',color='#b5e0af')
        text3.move_to(np.array([-5,2,0]))
        text4 = mnm.Text('ง',color='#e0c9af')
        self.add(text1,text2,text3,text4)



อนึ่ง ขนาดภาพนั้นโดยค่าตั้งต้นแล้วคือกว้าง 14.2 หน่วย สูง 8 หน่วยพิกัดแกน x คือ -7.1 ถึง 7.1 แกน y คือ -4 ถึง 4




การเลื่อนตำแหน่งวัตถุด้วยเมธอด .shift()

อีกวิธีที่ใช้มากในการเปลี่ยนตำแหน่งของวัตถุก็คือเลื่อนโดยอ้างอิงจากจุดเดิม โดยใช้เมธอด .shift()

ตัวอย่าง ลองสร้างวัตถุข้อความขึ้นมา ๕ ตัว แล้วจัดวางให้ไปอยู่ในตำแหน่งต่างๆ
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        text1 = mnm.Text('ก',color='#FF6666')
        text1.shift(mnm.RIGHT*6)
        text2 = mnm.Text('ข',color='#88FF22')
        text2.shift(mnm.UP*3)
        text3 = mnm.Text('ค',color='#88FFBB')
        text3.shift(mnm.LEFT*6+mnm.DOWN*3)
        text4 = mnm.Text('ง',color='#FFAA66')
        text4.shift([1,-2,0])
        text5 = mnm.Text('จ',color='#AACCEE')
        self.add(text1,text2,text3,text4,text5)



เพื่อความเข้าใจง่าย ในที่นี้ใช้ค่าอาเรย์ที่ manim ได้เตรียมไว้สำหรับแทนตำแหน่งต่างๆซึ่งเอาไว้ใส่แทนที่จะสร้างอาเรย์หรือลิสต์โดยตรง

หลักๆที่ใช้กำหนดทิศทางมี ๘ ตัว คือ บน (UP) ล่าง (DOWN) ซ้าย (LEFT) ขวา (RIGHT) แล้วก็ทิศเฉียงที่เกิดจากการผสมกัน คือบนซ้าย (UL) บนขวา (DR) ล่างซ้าย (DL) ล่างขวา (DR)
print(mnm.LEFT) # ได้ [-1.  0.  0.]
print(mnm.RIGHT) # ได้ [1. 0. 0.]
print(mnm.UP) # ได้ [0. 1. 0.]
print(mnm.DOWN) # ได้ [ 0. -1.  0.]
print(mnm.UL) # ได้ [-1.  1.  0.]
print(mnm.UR) # ได้ [1. 1. 0.]
print(mnm.DL) # ได้ [-1. -1.  0.]
print(mnm.DR) # ได้ [ 1. -1.  0.]




การย้ายวัตถุไปติดขอบหรือมุมด้วยเมธอด .to_edge() หรือ .to_corner()

เมธอด .to_edge() และ .to_corner() ใช้สำหรับเลื่อนวัตถุไปสุดขอบหรือไว้ที่มุม โดยค่าที่ต้องใส่คืออาเรย์แสดงทิศที่ต้องการย้ายไป

ข้อแตกต่างของ .to_edge() กับ .to_corner() คือค่าตั้งต้น โดยถ้าไม่กำหนดทิศ .to_edge() จะเป็นการย้ายไปติดขอบซ้าย (LEFT) ส่วน .to_corner() จะเป็นการย้ายไปติดขอบซ้ายล่าง (UL) แต่หากกำหนดทิศลงไปไม่ว่าจะใช้เมธอดไหนผลก็จะเหมือนกัน

ตัวอย่าง
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        text1 = mnm.Text('ก')
        text1.to_edge(mnm.UP)
        text2 = mnm.Text('ข')
        text2.to_edge(mnm.DOWN)
        text3 = mnm.Text('ค')
        text3.to_edge(mnm.LEFT)
        text4 = mnm.Text('ง')
        text4.to_edge(mnm.RIGHT)
        text5 = mnm.Text('จ')
        text5.to_edge(mnm.UR)
        text6 = mnm.Text('ช')
        text6.to_corner()
        self.add(text1,text2,text3,text4,text5,text6)






การวางตำแหน่งโดยอิงจากวัตถุอื่นด้วยเมธอด .next_to()

อีกวิธีที่สะดวกในการวางวัตถุคือวางโดยอ้างอิงจากวัตถุอื่นที่ถูกวางไว้แล้ว

หากมีวัตถุหนึ่งถูกสร้างอยู่แล้ว และต้องการจะวางตำแหน่งวัตถุโดยขึ้นอยู่กับตำแหน่งวัตถุที่มีอยู่เดิมนั้นอาจใช้เมธอด .next_to() โดยใส่วัตถุที่ใช้อ้างอิงและใส่ทิศทางที่จะต่อ

ตัวอย่าง
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        text1 = mnm.Text('กลาง',color='#efb5e1')
        text2 = mnm.Text('ขวา',color='#a6dcc2')
        text2.next_to(text1,mnm.RIGHT)
        text3 = mnm.Text('ล่าง',color='#cdaf97')
        text3.next_to(text1,mnm.DOWN)
        text4 = mnm.Text('ขวาบน',color='#9e9f8f')
        text4.next_to(text2,mnm.UP)
        text5 = mnm.Text('ขวาบนขวา',color='#e5c6f0')
        text5.next_to(text4,mnm.RIGHT)
        text6 = mnm.Text('ขวาบนขวาบน',color='#dbe5ee')
        text6.next_to(text5,mnm.UP)
        self.add(text1,text2,text3,text4,text5,text6)



จะเห็นว่าวัตถุถูกวางต่อกันไปเรื่อยๆตามทิศที่กำหนด

หากต้องการเพิ่มระยะให้เว้นห่างออกไปก็ใส่คีย์เวิร์ด buff กำหนดระยะห่างตามที่ต้องการ เช่น
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        text1 = mnm.Text('กลาง',color='#cd88af')
        text2 = mnm.Text('ซ้าย',color='#efe1b5')
        text2.next_to(text1,mnm.LEFT,buff=3.5)
        text3 = mnm.Text('ขวาล่าง',color='#56ec2c')
        text3.next_to(text1,mnm.DR,buff=1.5)
        text4 = mnm.Text('ซ้ายบน',color='#9eef2f')
        text4.next_to(text2,mnm.UP,buff=2.5)
        self.add(text1,text2,text3,text4)



หากไม่ได้ใส่ค่า buff จะเป็นระยะห่างตั้งต้น คือเป็น buff=0.25




การคัดลอกวัตถุด้วยเมธอด .copy()

หากมีวัตถุอยู่ตัวหนึ่งแล้วต้องการสร้างอีกตัวให้เหมือนกันเลยก็ทำได้โดยใช้เมธอด .copy()

วัตถุที่สร้างโดย .copy() นั้นแค่หน้าตาเหมือนตัวต้นแบบเท่านั้น แต่ไม่ถือเป็นตัวเดียวกัน หลังจากสร้างแล้วจะนำไปทำอะไรก็ไม่มีผลต่อตัวต้นฉบับ

ตัวอย่าง ลองคัดลอกวัตถุมาแล้วย้ายไปวางตำแหน่งต่างไป
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        text = mnm.Text('สไลม์',color='#77aacc',size=2.9)
        text.shift(mnm.UL*2)
        textc = text.copy()
        textc.shift(mnm.RIGHT*5)
        textcc = textc.copy()
        textcc.shift(mnm.DOWN*4)
        self.add(text,textc,textcc)





อ่านบทถัดไป >> บทที่ ๔





-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> python >> manim

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

สารบัญ

รวมคำแปลวลีเด็ดจากญี่ปุ่น
มอดูลต่างๆ
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
การเรียนรู้ของเครื่อง
-- โครงข่าย
     ประสาทเทียม
ภาษา javascript
ภาษา mongol
ภาษาศาสตร์
maya
ความน่าจะเป็น
บันทึกในญี่ปุ่น
บันทึกในจีน
-- บันทึกในปักกิ่ง
-- บันทึกในฮ่องกง
-- บันทึกในมาเก๊า
บันทึกในไต้หวัน
บันทึกในยุโรปเหนือ
บันทึกในประเทศอื่นๆ
qiita
บทความอื่นๆ

บทความแบ่งตามหมวด



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  ค้นหาบทความ

  บทความแนะนำ

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ

ไทย

日本語

中文