95 lines
2.6 KiB
Python
95 lines
2.6 KiB
Python
from collections import defaultdict
|
||
from sys import argv
|
||
|
||
import matplotlib.pyplot as plt
|
||
import numpy as np
|
||
|
||
|
||
def read_points(filename: str) -> list[tuple[float, float, str]]:
|
||
points = []
|
||
with open(filename, "r", encoding="utf-8") as f:
|
||
for line in f:
|
||
line = line.strip()
|
||
if line and not line.startswith("#"):
|
||
parts = line.split()
|
||
if len(parts) >= 3:
|
||
x = float(parts[0])
|
||
y = float(parts[1])
|
||
label = parts[2]
|
||
points.append((x, y, label))
|
||
return points
|
||
|
||
|
||
def main() -> None:
|
||
points = read_points(argv[1])
|
||
|
||
plt.figure(figsize=(8.27, 11.69))
|
||
plt.xlim(0, 30)
|
||
plt.ylim(0, 20)
|
||
plt.gca().set_aspect("equal", adjustable="box")
|
||
plt.grid(True, linewidth=0.3)
|
||
plt.xticks(range(0, 31, 2))
|
||
plt.yticks(range(0, 21, 2))
|
||
|
||
grouped = defaultdict(list)
|
||
for x, y, phi in points:
|
||
grouped[phi].append((x, y))
|
||
|
||
for x, y, label in points:
|
||
plt.scatter(x, y, color="red", s=15)
|
||
plt.text(x + 0.3, y + 0.3, label, fontsize=9)
|
||
|
||
for phi, coords in grouped.items():
|
||
coords.sort(key=lambda p: p[1])
|
||
xs, ys = zip(*coords)
|
||
plt.plot(xs, ys, linewidth=0.8, label=f"φ={phi} В")
|
||
|
||
for i in range(len(coords) - 1):
|
||
x1, y1 = coords[i]
|
||
x2, y2 = coords[i + 1]
|
||
|
||
mid_x = (x1 + x2) / 2
|
||
mid_y = (y1 + y2) / 2
|
||
|
||
dx = x2 - x1
|
||
dy = y2 - y1
|
||
|
||
perp_dx = -dy
|
||
perp_dy = dx
|
||
|
||
length = np.sqrt(perp_dx**2 + perp_dy**2)
|
||
if length > 0:
|
||
arrow_length = 0.5
|
||
perp_dx = perp_dx / length * arrow_length
|
||
perp_dy = perp_dy / length * arrow_length
|
||
|
||
plt.arrow(
|
||
mid_x,
|
||
mid_y,
|
||
perp_dx,
|
||
perp_dy,
|
||
head_width=0.2,
|
||
head_length=0.15,
|
||
fc="green",
|
||
ec="green",
|
||
linewidth=1.5,
|
||
)
|
||
|
||
if int(argv[2]):
|
||
theta = np.linspace(0, 2 * np.pi, 200)
|
||
cx, cy = 15, 9
|
||
|
||
for r in [5, 6]:
|
||
x = cx + r * np.cos(theta)
|
||
y = cy + r * np.sin(theta)
|
||
plt.plot(x, y, color="blue", linewidth=1)
|
||
|
||
plt.xlabel("X (см)")
|
||
plt.ylabel("Y (см)")
|
||
plt.title("Эквипотенциальные линии с силовыми стрелками")
|
||
plt.savefig("points.png", dpi=300)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|