φυβλαςのβλογ
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
蒙古语
语言学
maya
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



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

  查看日志

  推荐日志

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