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



manim บทที่ ๑๙: การใส่ระบบพิกัดและแกนกราฟ
เขียนเมื่อ 2021/03/13 06:51
แก้ไขล่าสุด 2021/09/28 16:42

ต่อจาก บทที่ ๑๘

ในบทนี้จะเป็นเรื่องของการวางระบบพิกัดลงในภาพเพื่อใช้แสดงกราฟ




การสร้างแกนกราฟ

การใส่แกนกราฟลงในภาพทำได้โดยสร้างออบเจ็กต์คลาส Axes ส่วนตัวเลขแสดงพิกัดเติมได้โดยใช้เมธอด .add_coordinate_labels() ที่ตัวออบเจ็กต์กราฟ

ลองเริ่มจากสร้างแกนกราฟขึ้นมาเฉยๆโดยไม่ได้ปรับแต่งอะไรเลยดู
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        axes = mnm.Axes()
        axes.add_coordinate_labels()
        self.play(
            mnm.Write(axes),
            run_time=2
        )






การปรับแต่งแกนกราฟ

แกนกราฟมีค่าต่างๆที่สามารถปรับได้ เช่นตำแหน่งขีด ขนาดความกว้างและสูง ฯลฯ

สำหรับการปรับส่วนของเส้นแกนนั้นอาจปรับด้วยคีย์เวิร์ด axis_config เพื่อเป็นการปรับเส้นแกน x และ y ไปพร้อมๆกัน หรืออาจแยกเป็น x_axis_config กับ y_axis_config สำหรับส่วนที่ต้องการให้แกน x กับ y ต่างกัน

ส่วนตัวเลขแสดงพิกัดก็สามารถปรับได้โดยใส่คีย์เวิร์ดแบบเดียวกับที่ใช้สร้างออบเจ็กต์ DecimalNumber

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

class Manimala(mnm.Scene):
    def construct(self):
        axes = mnm.Axes(x_range=(-2,4,0.4), # ตำแหน่งขีดแกน x
                        y_range=(-1,3.1,0.5), # ตำแหน่งขีดแกน y
                        width=13, # ความกว้าง
                        height=7, # ความสูง
                        axis_config={'stroke_width':3}, # ความหนาเส้น
                        x_axis_config={'stroke_color':'#e7b0ef', # สีเส้น
                                       'line_to_number_direction':mnm.UP, # ตำแหน่งที่วางตัวเลข
                                       'include_tip':False}, # วาดลูกศรที่ปลายหรือไม่
                        y_axis_config={'stroke_color':'#bbefb0',
                                       'line_to_number_direction':mnm.RIGHT,
                                       'line_to_number_buff':1, # ระยะห่างระหว่างตัวเลขกับแกน
                                       'include_ticks':False}) # วาดขีดหรือไม่
        axes.add_coordinate_labels(font_size=25, # ขนาดอักษร
                                   num_decimal_places=1, # จำนวนเลขทศนิยม
                                   include_sign=True, # ใส่เครื่องหมาย + หรือไม่
                                   color='#b0dbef') # สีตัวหนังสือ
        self.play(
            mnm.Write(axes),
            run_time=1.5
        )
        self.wait(0.5)






การแปลงพิกัดจากระนาบแกนเป็นตำแหน่งในภาพ

หากต้องการจะวางวัตถุอะไรในระบบพิกัดแกนกราฟจะต้องทำการแปลงระบบพิกัดจากตำแหน่ง x,y ในระนาบแกนนั้นมาเป็นตำแหน่งภายในภาพ

การแปลงสามารถทำได้โดยใช้เมธอด .c2p() ที่ตัวกราฟ โดยใส่ค่าพิกัด x,y ลงไปแล้วจะได้ค่าพิกัดตำแหน่งภายในภาพ จากนั้นก็นำมาใช้เพื่อวางจุดตามที่ต้องการได้

ตัวอย่าง ลองวาดจุดขึ้นมาที่ตำแหน่งหนึ่งบนแกนกราฟ แล้วย้ายไปอีกตำแหน่ง
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        axes = mnm.Axes(x_range=(0,50,5),
                        y_range=(0,35,5))
        axes.add_coordinate_labels(font_size=32)
        p1 = axes.c2p(0,5) # ตำแหน่งจุดเริ่มต้น
        chut = mnm.Dot(p1) # วัตถุจุด
        p2 = axes.c2p(35,15) # ตำแหน่งจุดที่จะย้ายไป
        self.add(axes)
        self.play(
            chut.animate.move_to(p2),
            run_time=1.5
        )
        self.wait(0.5)






การแปลงตำแหน่งในภาพไปเป็นพิกัดระนาบแกน

ในทางตรงกันข้ามกับ .c2p() หากต้องการแปลงค่าตำแหน่งจากในภาพไปเป็นตำแหน่งในพิกัดระนาบแกนก็ทำได้โดยใช้เมธอด .p2c()

ตัวอย่างเช่น เมื่อต้องการใส่ตัวเลขที่แสดงตำแหน่งภายในระบบแกนกราฟก็อาจใช้ .c2p() ได้ เช่น
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        axes = mnm.Axes(x_range=(0,70,5),
                        y_range=(0,55,5))
        axes.add_coordinate_labels(font_size=28)
        p1 = axes.c2p(15,20) # จุดเริ่มต้น
        chut = mnm.Dot(p1) # วัตถุจุด
        # ฟังก์ชันสร้างเลขแสดงตำแหน่ง
        def sailek():
            # เอาค่าตำแหน่งจุดภายในภาพมาแปลงเป็นพิกัดในระนาบแกน
            x,y = axes.p2c(chut.get_center())
            xy = mnm.Text(f'({x:.0f},{y:.0f})')
            xy.next_to(chut,mnm.DOWN) # วางไว้ด้านล่างของจุด
            return xy
        # ตัวเลขแสดงตำแหน่ง ให้สร้างใหม่ทุกเฟรม
        text = mnm.always_redraw(sailek)
        p2 = axes.c2p(55,45) # จุดที่จะย้ายไป

        self.add(axes,text)
        self.play(
            chut.animate.move_to(p2),
            run_time=1.5
        )
        self.wait(0.5)






การลากเส้นจากจุดไปยังแกน

ออบเจ็กต์แกนมีเมธอด .get_h_line() และ .get_v_line() ซึ่งใช้ลากเส้นแนวนอนและแนวตั้งจากจุดที่กำหนดไปยังแกน

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

class Manimala(mnm.Scene):
    def construct(self):
        axes = mnm.Axes(x_range=(-30,25,5),
                        y_range=(0,25,5),
                        axis_config={'stroke_width':5,'color':'#908ecb'})
        axes.add_coordinate_labels(font_size=36,color='#908ecb')
        p1 = axes.c2p(15,20)
        chut = mnm.Dot(p1,radius=0.2,color='#82c5b8')
        
        def f_non():
            return axes.get_h_line(chut.get_center(),color='#dfb0ef',stroke_width=4)
        sen_non = mnm.always_redraw(f_non)
        def f_tang():
            return axes.get_v_line(chut.get_center(),color='#efd7b0',stroke_width=3)
        sen_tang = mnm.always_redraw(f_tang)
        
        p2 = axes.c2p(-20,5)
        self.add(axes,sen_non,sen_tang)
        self.play(
            chut.animate.move_to(p2),
            run_time=1.5
        )






การวาดเส้นแสดงพิกัดระนาบของตำแหน่งภายในภาพ

หากต้องการแสดงระบบพิกัดของตำแหน่งภายในภาพก็สามารถทำได้โดยสร้างออบเจ็กต์คลาส NumberPlane

ตัวอย่าง ลองใส่กราฟแสดงพิกัดของตำแหน่งในภาพขึ้นมา
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        axes = mnm.NumberPlane()
        axes.add_coordinate_labels()
        self.play(
            mnm.Write(axes),
            run_time=1.5
        )
        self.wait(0.5)



NumberPlane ประกอบไปด้วยเส้นตาราง โดยเส้นหลักที่ขีดที่ค่าจำนวนเต็มจะอยู่ที่ .background_lines เส้นรองอยู่ที่ .faded_lines สามารถปรับแต่งขนาดหรือสีของเส้นได้เหมือนกับวัตถุคลาส Line

ลองปรับแต่งดู
import manimlib as mnm

class Manimala(mnm.Scene):
    def construct(self):
        axes = mnm.NumberPlane()
        axes.add_coordinate_labels(font_size=36,color='#908ecb')
        # ปรับเส้นหลัก
        axes.background_lines.set_style(stroke_color='#bcd6a6',
                                        stroke_width=7)
        # ปรับเส้นรอง
        axes.faded_lines.set_style(stroke_color='#ebb4d6',
                                   stroke_width=4)
        
        self.add(axes)
        # ลบเส้นรอง
        self.play(
            mnm.Uncreate(axes.faded_lines),
            run_time=1
        )
        self.wait(0.25)
        # ลบเส้นหลัก
        self.play(
            mnm.FadeOut(axes.background_lines),
            run_time=0.5
        )
        self.wait(0.25)



เมื่อใช้ NumberPlane พิกัดของแกนกราฟตรงกับพิกัดในภาพ ดังนั้นหากวางวัตถุอะไรลงในภาพก็จะตรงกับตำแหน่งในระบบแกนนี้โดยไม่ต้องทำการแปลงใดๆ

ตัวอย่างเช่น
import manimlib as mnm
import numpy as np

class Manimala(mnm.Scene):
    def construct(self):
        axes = mnm.NumberPlane()
        axes.add_coordinate_labels(font_size=32,color='#e5abd8')
        haliam = mnm.Polygon(np.array([-5,0,0]),
                             np.array([-1,3,0]),
                             np.array([1,3,0]),
                             np.array([5,0,0]),
                             np.array([0,-3,0]),
                             color='#bce5ab',
                             stroke_width=30)
        self.add(axes)
        self.play(
            mnm.Write(haliam),
            run_time=0.5
        )






ระนาบเชิงซ้อน

ComplexPlane เป็นคลาสย่อยของ NumberPlane โดยจะต่างจาก NumberPlane ตรงที่จะสร้างเป็นระบบพิกัดเชิงซ้อน

ตัวอย่างการใช้
import manimlib as mnm
import numpy as np

class Manimala(mnm.Scene):
    def construct(self):
        axes = mnm.ComplexPlane()
        axes.add_coordinate_labels()
        chut = mnm.Dot(np.array([3,2,0]))
        text = mnm.Text('3+2i')
        text.next_to(chut,mnm.UP)
        self.add(axes)
        self.play(
            mnm.FadeIn(chut),
            mnm.Write(text),
            run_time=1.5
        )





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





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

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

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

หมวดหมู่

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

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

สารบัญ

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

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

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



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

  ค้นหาบทความ

  บทความแนะนำ

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

บทความแต่ละเดือน

2024年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2023年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2022年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2021年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

2020年

1月 2月 3月 4月
5月 6月 7月 8月
9月 10月 11月 12月

ค้นบทความเก่ากว่านั้น

ไทย

日本語

中文