SE_BOKUのまとめノート的ブログ

SE_BOKUが知ってること・勉強したこと・考えたことetc

Pythonの再帰処理を使って描く「C曲線」と「樹形図」

f:id:arakan_no_boku:20210912183619p:plain

目次

Python再帰処理を使って描く「C曲線」と「樹形図」

今回は、図形「C曲線」と「樹木曲線」をPythonで実装します。

matplotlibのグラフの機能を利用して描画しています。

再帰処理を使います。

再帰処理とは、関数の中で自分自身を呼び出すようなやり方のことです。

 

C曲線

 

C曲線とは、このような図形です。

f:id:arakan_no_boku:20210918192118p:plain

なんとなく可愛くて、僕はこの図形が結構好きです。

これを描くソースコードはこちらです。

class_graphics.py

from matplotlib import pyplot as plt


class Ccurve():
    def __init__(self):
        self.__tx = [1.0]
        self.__ty = [2.0]
        self.__title = "C曲線を描く"

    def __move(self, lpx, lpy, dx, dy):
        self.__tx.append(lpx + dx)
        self.__ty.append(lpy + dy)

    def __draw(self, st_len=10.0, lpx=0.0, lpy=0.0, dx=2.0, dy=0.0):
        leng = st_len
        if(leng <= 0.0):
            self.__move(lpx, lpy, dx, dy)
        else:
            self.__draw(leng - 1.0,
                        self.__tx[-1],
                        self.__ty[-1],
                        (dx + dy) / 2,
                        (dy - dx) / 2)
            self.__draw(leng - 1.0,
                        self.__tx[-1],
                        self.__ty[-1],
                        (dx - dy) / 2,
                        (dy + dx) / 2)
        return self.__tx, self.__ty

    def draw(self):
        x, y = self.__draw()
        plt.plot(x, y)
        plt.title(self.__title)
        plt.show()

 

再帰処理です。

__draw()の中でパラメータを少しずつ小さくしながら、__draw()自身を再帰的に呼び出しています。

使うときは。

from class_graphics import Ccurve

Ccurve().draw()

とすると、上記の図形を表示します。

 

樹形図(樹木曲線)

ブロッコリーみたいだと自分は思ってますが・・樹形図です。

描いた図形はこんな感じです。

f:id:arakan_no_boku:20210918195209p:plain

これを描くソースコードです。

Numpyが必要なので、importを追加しています。

同じファイルにクラスを追記しています。

class_graphics.py

import matplotlib.pyplot as plt
import numpy as np

class TreeCurve():
    def __init__(self):
        self.__tx = [320.0]
        self.__ty = [380.0]
        self.__title = "樹形図(樹木曲線)を描く"

    def __move(self, leng, lpx, lpy, angle):
        x = lpx + leng * np.cos(angle * np.pi / 180.0)
        y = lpy + leng * np.sin(angle * np.pi / 180.0)
        self.__tx.append(x)
        self.__ty.append(y)
        return x, y

    def __draw(self, leng=120.0, lpx=320.0, lpy=380.0, angle=90.0, scale=0.7):
        if(leng >= 5.0):
            self.__tx.append(lpx)
            self.__ty.append(lpy)
            lpx, lpy = self.__move(leng, lpx, lpy, angle)
            self.__draw(leng * scale, lpx, lpy, angle + 20.0)
            self.__draw(leng * scale, lpx, lpy, angle - 20.0)
        return self.__tx, self.__ty

    def draw(self):
        x, y = self.__draw()
        plt.plot(x, y)
        plt.title(self.__title)
        plt.show()

 

これも再帰処理しています。

__drawe()のパラメータを変化させながら、20度ずつ角度を変えて__draw()自身を再帰呼出ししています。 

ポイントは、__draw()の中で、一度原点に戻ってから、ラインを引く位置に移動(__move())していることで、この動きによって、樹形図っぽい図形になります。

使うときは。

from class_graphics import TreeCurve

TreeCurve().draw()

です。

ちなみに。

move()の中の以下の部分

y = lpy + leng * np.sin(angle * np.pi / 180.0)

これを、以下のように「-」に変更すると

y = lpy - leng * np.sin(angle * np.pi / 180.0)

上下逆転した図形になります。

f:id:arakan_no_boku:20181207000134j:plain

ではでは。