Скачиваний:
5
Добавлен:
04.02.2020
Размер:
4.33 Кб
Скачать
from functools import reduce
from math import *
import matplotlib.pyplot as plt
import numpy as np


# рассчёт растояния между точками
def calc_r(x, y, point_x, point_y):
    return sqrt((point_x - x) ** 2 + (point_y - y) ** 2)


# рассчёт растояния между точками
def calc_alpha(x, y, point_x, point_y):
    dx = point_x - x
    dy = point_y - y
    alpha = 0

    if dy:
        alpha = atan(dx / dy)
    if dx < 0 and dy == 0:
        alpha += pi
    if dy < 0:
        alpha += pi
    if alpha > pi:
        alpha -= 2 * pi
    return alpha


# проверочная функция выхода за пределы поля электродов
def not_touch(x, y):
    if 0.4 * x + 6.2 > y and 0 < x < 14:
        return True
    else:
        return False


# расчёт напряжённости поля в точке
def calc_e(r, alpha, sign):
    if r == 0:
        return 0, 0

    return sign * sin(alpha) / r ** 2, sign * cos(alpha) / r ** 2


# расчёт линий
def calc_new_points(pos_line, s_p, s_n):
    line_points = [[] for el in pos_line]

    # цикл для каждого отрезка с зарядом
    for i, point in enumerate(pos_line):
        x = point[0]
        y = point[1] + 0.1

        res_x = [x]
        res_y = [y]

        # считаем пока не выйдем за пределы
        while not_touch(x, y):
            Ep = []
            En = []

            # расчёт плдя элементарных зарядов
            for dp, dn in list(zip(s_p, s_n)):
                r_p = calc_r(dp[0], dp[1], x, y)
                r_n = calc_r(dn[0], dn[1], x, y)

                alpha_p = calc_alpha(dp[0], dp[1], x, y)
                alpha_n = calc_alpha(dn[0], dn[1], x, y)

                Ep += [calc_e(r_p, alpha_p, 1)]
                En += [calc_e(r_n, alpha_n, -1)]

            # суммирование элементарных полей
            Ep = reduce(lambda el1, el2: (el1[0] + el2[0], el1[1] + el2[1]), Ep)
            En = reduce(lambda el1, el2: (el1[0] + el2[0], el1[1] + el2[1]), En)

            # новые координаты линии
            x += (Ep[0] + En[0]) * 0.0001
            y += (Ep[1] + En[1]) * 0.0001  # 0.00005
            res_x += [x]
            res_y += [y]

        print(f'progress {(i + 1) * 100 / len(pos_line)}')
        line_points[i] = (res_x[:len(res_x) - 1], res_y[:len(res_y) - 1])
    return line_points


# =========================================================================
N = 100
lines_count = 20
# линия с зарядом -Q
Qn_coord = [(2, 7), (12, 11)]
# половина окружности с зарядом +Q
Qз_r = 5
Qp_center = (7, 6)
Qp_angles = np.linspace(pi, 2 * pi, N)

dx = (Qn_coord[1][0] - Qn_coord[0][0]) / N
dy = (Qn_coord[1][1] - Qn_coord[0][1]) / N

sQp = []
sQn = []

# Разбиение электрода на элементарные заряды
for i in range(N):
    sQn += [(Qn_coord[0][0] + dx * i, Qn_coord[0][1] + dy * i)]

for angle in Qp_angles:
    sQp += [(Qp_center[0] + Qз_r * cos(angle), Qp_center[1] + Qз_r * sin(angle))]

# выберем сколько элментарных отрезков приходиться на линию
dq_to_line = np.array_split(sQp, lines_count)
# выберем средний отрезок
line_pos = [x[len(x) // 2] for x in dq_to_line]

# вызовем функцию расчёта линий
lines_points = calc_new_points(line_pos, sQp, sQn)

# отображение линий
for line in lines_points:
    plt.plot(line[0], line[1], '--', color="gray")
    dx = line[0][len(line[0]) // 2 + 1] - line[0][len(line[0]) // 2]
    dy = line[1][len(line[1]) // 2 + 1] - line[1][len(line[1]) // 2]
    plt.arrow(line[0][len(line[0]) // 2], line[1][len(line[1]) // 2], dx * 10, dy * 10, head_width=0.2, head_length=0.3,
              color="gray")

# данные для окружности
circle_plot_x = [i[0] for i in sQp]
circle_plot_y = [i[1] for i in sQp]

# печать линий зарядов
plt.plot(circle_plot_x, circle_plot_y, linewidth=2, label='+Q', color='red')
plt.plot([Qn_coord[0][0], Qn_coord[1][0]], [Qn_coord[0][1], Qn_coord[1][1]], linewidth=2, label='-Q', color='black')
plt.savefig("graf.jpg")
plt.show()
Соседние файлы в папке lab3