from cmath import sin

import matplotlib.pyplot as plt


def plot_logistic_map(r, x0, num_iterations):
    x = [x0]
    for _ in range(num_iterations):
        x0 = logistic_map(r, x0)
        x.append(x0)

    plt.plot(range(num_iterations + 1), x, marker='o', linestyle='-')
    plt.xlabel("Národy")
    plt.ylabel("Hodnota x")
    plt.title(f"Logistická mapa (r = {r})")
    plt.show()


def logistic_map(r, x):
    # return r * x * (1 - x) * (- x + 1)
    return r * x * (1 - x)


def bifurcation_diagram(r_values, x0, num_iterations, num_transient, num_points):
    all_x = []
    all_r = []

    for r in r_values:
        x = x0
        transient = []
        stable = []

        for i in range(num_iterations):
            x = logistic_map(r, x)

            if i >= num_transient:
                transient.append(r)
                stable.append(x)

        all_x.extend(stable)
        all_r.extend(transient)

    plt.scatter(all_r, all_x, s=1, marker=".")
    plt.xlabel("r")
    plt.ylabel("Hodnota x")
    plt.title("Bifurkační diagram")
    plt.show()


def create_diagrams():
    # Parametry
    r = 6
    r_values = [i / 1000 for i in range(1000, 6000)]  # Rozsah hodnot r
    x0 = 0.2  # Počáteční hodnota
    num_iterations = 1000
    num_transient = 100  # Počet přechodných iterací
    num_points = 10000  # Počet bodů v diagramu

    bifurcation_diagram(r_values, x0, num_iterations, num_transient, num_points)
    plot_logistic_map(r, x0, 100)


def midpoint(point1, point2):
    return ((point1[0] + point2[0]) / 2, (point1[1] + point2[1]) / 2)


def sierpinski_triangle(ax, depth, p1, p2, p3):
    if depth == 0:
        ax.plot(*p1, 'ro')
        ax.plot(*p2, 'ro')
        ax.plot(*p3, 'ro')
    else:
        p12 = midpoint(p1, p2)
        p23 = midpoint(p2, p3)
        p31 = midpoint(p3, p1)

        sierpinski_triangle(ax, depth - 1, p1, p12, p31)
        sierpinski_triangle(ax, depth - 1, p12, p2, p23)
        sierpinski_triangle(ax, depth - 1, p31, p23, p3)


def main():
    fig, ax = plt.subplots()
    p1 = (0, 0)
    p2 = (1, 0)
    p3 = (0.5, (3 ** 0.5) / 2)
    depth = 5  # Změňte tuto hodnotu pro různé úrovně fraktálu

    sierpinski_triangle(ax, depth, p1, p2, p3)
    ax.set_aspect('equal', adjustable='box')
    plt.show()


if __name__ == "__main__":
    main()
