-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
92 lines (73 loc) · 2.93 KB
/
main.py
File metadata and controls
92 lines (73 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import numpy as np
import trimesh
from scipy.special import comb
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# ---------------------------
# Бернштейновы полиномы
# ---------------------------
def bernstein_basis(n, i, t):
return comb(n, i) * (t ** i) * ((1 - t) ** (n - i))
def fit_bernstein_surface(u, v, r, degree_u=6, degree_v=6):
A = np.zeros((len(u), (degree_u + 1) * (degree_v + 1)))
for k in range(len(u)):
row = []
for i in range(degree_u + 1):
for j in range(degree_v + 1):
row.append(bernstein_basis(degree_u, i, u[k]) * bernstein_basis(degree_v, j, v[k]))
A[k] = row
coeffs, _, _, _ = np.linalg.lstsq(A, r, rcond=None)
return coeffs.reshape((degree_u + 1, degree_v + 1))
def bernstein_surface(u, v, coeffs):
n, m = coeffs.shape[0] - 1, coeffs.shape[1] - 1
result = np.zeros_like(u)
for i in range(n + 1):
for j in range(m + 1):
result += coeffs[i, j] * bernstein_basis(n, i, u) * bernstein_basis(m, j, v)
return result
# ---------------------------
# Перевод декартовых координат в сферические
# ---------------------------
def cartesian_to_spherical(x, y, z):
print('x\n', x)
print('y\n', y)
print('z\n', z)
r = np.sqrt(x ** 2 + y ** 2 + z ** 2)
theta = np.arccos(z / r)
phi = np.arctan2(y, x)
return r, theta, phi
# ---------------------------
# Основная часть
# ---------------------------
def main():
# Путь к .obj
obj_path = 'bodies/2_norm.obj'
# Загружаем модель с учетом .mtl
mesh = trimesh.load(obj_path, force='mesh')
points = mesh.vertices
# Переход в сферические координаты
r, theta, phi = cartesian_to_spherical(points[:, 0], points[:, 1], points[:, 2])
# Нормализованные углы
u = theta / np.pi # θ ∈ [0, π] → u ∈ [0, 1]
v = (phi + np.pi) / (2 * np.pi) # φ ∈ [-π, π] → v ∈ [0, 1]
# Аппроксимация
degree_u, degree_v = 8, 8
coeffs = fit_bernstein_surface(u, v, r, degree_u, degree_v)
# Сетка для визуализации
U, V = np.meshgrid(np.linspace(0, 1, 150), np.linspace(0, 1, 300))
R = bernstein_surface(U, V, coeffs)
# Обратно в декартовы координаты
Theta = U * np.pi
Phi = V * 2 * np.pi - np.pi
X = R * np.sin(Theta) * np.cos(Phi)
Y = R * np.sin(Theta) * np.sin(Phi)
Z = R * np.cos(Theta)
# Визуализация
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z, color='lightblue', edgecolor='gray', linewidth=0.2, alpha=1.0)
ax.set_title("Аппроксимация полиномами Берштейна", fontsize=14)
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()