Проектирование распределителей ДСТ
作者
using Plots
using Printf
plotlyjs() # Возвращаем PlotlyJS для идеального и неискаженного 3D-профиля
struct UniversalRegion
shape::String
length::Float64
radial_depth_start::Float64
radial_depth_end::Float64
width_start::Float64
width_end::Float64
r_edge::Float64
end
struct SpoolComponent
name::String
block_path::String
spool_diameter::Float64
rod_diameter::Float64
nslots::Int64
chamber_length_0::Float64
underlap::Float64
underlap_max_area::Float64
edge_to_edge::Float64
clearance::Float64
eccentricity_ratio::Float64
enable_annular_area::Bool
enable_pressure_force::Bool
couette_effect::Bool
regions::Vector{UniversalRegion}
end
# --- МИКРО-ФУНКЦИЯ 1: ИСТИННЫЙ ЦИЛИНДРИЧЕСКИЙ РАСЧЕТ ПРОФИЛЯ ВСЕХ КАНАВОК ---
function calculate_spool_matrices(comp::SpoolComponent, n_theta, n_z, z_max_body)
theta = range(0, 2π, length=n_theta)
z_spool_body = range(0.0, z_max_body, length=n_z)
r_spool = comp.spool_diameter / 2.0
total_notch_width = isempty(comp.regions) ? 6.0 : sum(reg.length for reg in comp.regions)
X = zeros(n_theta, n_z)
Y = zeros(n_theta, n_z)
Z = zeros(n_theta, n_z)
x_contour_top = fill(NaN, n_z)
y_contour_floor = fill(r_spool, n_z)
slot_centers = range(0, 2π - 2π/comp.nslots, length=comp.nslots)
rect_depth_end = length(comp.regions) >= 1 ? comp.regions[1].radial_depth_end : 1.0
for j in 1:n_z
zi = z_spool_body[j]
z_from_bottom = total_notch_width - zi
current_width_z = NaN
current_depth = 0.0
if z_from_bottom >= 0.0 && zi >= 0.0 && !isempty(comp.regions)
accum_length = 0.0
active_reg_idx = 1
local_z = z_from_bottom
for (idx, reg) in enumerate(comp.regions)
if z_from_bottom <= accum_length + reg.length
active_reg_idx = idx
local_z = z_from_bottom - accum_length
break
end
accum_length += reg.length
end
reg = comp.regions[active_reg_idx]
norm_z = reg.length > 0 ? local_z / reg.length : 0.0
if reg.shape == "rectangular"
current_width_z = reg.width_start
current_depth = reg.radial_depth_start + (reg.radial_depth_end - reg.radial_depth_start) * norm_z
elseif reg.shape in ["trapezoidal", "triangular"]
current_width_z = reg.width_start + (reg.width_end - reg.width_start) * norm_z
current_depth = reg.radial_depth_start + (reg.radial_depth_end - reg.radial_depth_start) * norm_z
elseif reg.shape == "circular"
current_width_z = reg.width_end * sqrt(max(0.0, 1.0 - (1.0 - norm_z)^2))
current_depth = reg.radial_depth_start
elseif reg.shape == "trapezoidal_rounded"
current_depth = rect_depth_end
R = reg.r_edge
h = reg.length
w1 = reg.width_start
w2 = reg.width_end
if R > 0.0 && h > 0.0
z_c_fixed = (h^2 + (w2/2.0)^2 - (w1/2.0)^2) / (2.0 * h) - (w2/2.0 - w1/2.0) / h * sqrt(max(0.0, R^2 - h^2/4.0 - (w2/2.0 - w1/2.0)^2/4.0))
x_c = (w1 / 2.0) + sqrt(max(0.0, R^2 - z_c_fixed^2))
half_w_circle = x_c - sqrt(max(0.0, R^2 - (local_z - z_c_fixed)^2))
current_width_z = half_w_circle * 2.0
else
current_width_z = reg.width_start + (reg.width_end - reg.width_start) * norm_z
end
end
end
x_contour_top[j] = isnan(current_width_z) ? NaN : current_width_z / 2.0
y_contour_floor[j] = r_spool - current_depth
half_w = isnan(current_width_z) ? 0.0 : current_width_z / 2.0
for i in 1:n_theta
t = theta[i]
x_glob = r_spool * cos(t)
y_glob = r_spool * sin(t)
if !isnan(current_width_z)
for center in slot_centers
x_local = x_glob * sin(center) - y_glob * cos(center)
y_local = x_glob * cos(center) + y_glob * sin(center)
y_floor = r_spool - current_depth
if abs(x_local) <= half_w
y_floor = max(0.0, y_floor)
if y_local > y_floor
x_glob = x_local * sin(center) + y_floor * cos(center)
y_glob = -x_local * cos(center) + y_floor * sin(center)
end
end
end
end
X[i, j] = x_glob
Y[i, j] = y_glob
Z[i, j] = -zi
end
end
return X, Y, Z, x_contour_top, y_contour_floor
end
# --- МИКРО-ФУНКЦИЯ 2: СБОРКА И ИДЕНТИЧНАЯ СИНХРОНИЗАЦИЯ ПРОЕКЦИЙ ---
function draw_spool_component_3d(comp::SpoolComponent)
n_theta, n_z = 360, 350
total_notch_width = isempty(comp.regions) ? 6.0 : sum(reg.length for reg in comp.regions)
z_max_body = max(25.0, total_notch_width + 5.0)
r_spool, r_rod = comp.spool_diameter / 2.0, comp.rod_diameter / 2.0
X, Y, Z, x_contour_top, y_contour_floor = calculate_spool_matrices(comp, n_theta, n_z, z_max_body)
z_shared_axis = [Z[1, k] for k in 1:n_z]
z_lim_min = -z_max_body
z_lim_max = 5.0
sleeve_edge = comp.underlap
title_text = string("3D-Модель: ", comp.name, " | Underlap: ", comp.underlap, " мм")
p3d = plot(title=title_text, xlabel="Z", ylabel="X", zlabel="Y", legend=false, camera=(45, 25), aspect_ratio=:equal)
surface!(p3d, Z, X, Y, color=:coolwarm, alpha=0.95, colorbar=false)
theta_rod, z_rod = range(0, 2π, length=40), range(0.0, z_max_body, length=10)
surface!(p3d, [-z for t in theta_rod, z in z_rod], [r_rod * cos(t) for t in theta_rod, z in z_rod], [r_rod * sin(t) for t in theta_rod, z in z_rod], color=:lightgray, alpha=0.7)
r_house_in, r_house_out = r_spool + 0.3, r_spool + 1.8
z_house_left = range(-z_max_body - 1.0, sleeve_edge, length=15)
surface!(p3d, [z for t in theta_rod, z in z_house_left], [r_house_in * cos(t) for t in theta_rod, z in z_house_left], [r_house_in * sin(t) for t in theta_rod, z in z_house_left], color=:gray, alpha=0.35)
surface!(p3d, [z for t in theta_rod, z in z_house_left], [r_house_out * cos(t) for t in theta_rod, z in z_house_left], [r_house_out * sin(t) for t in theta_rod, z in z_house_left], color=:gray, alpha=0.15)
plot!(p3d, fill(sleeve_edge, length(theta_rod)), [r_house_in * cos(t) for t in theta_rod], [r_house_in * sin(t) for t in theta_rod], color=:red, lw=3)
z_ch = range(sleeve_edge, sleeve_edge + max(4.0, comp.chamber_length_0), length=15)
surface!(p3d, [z for t in theta_rod, z in z_ch], [(r_spool + 2.2) * cos(t) for t in theta_rod, z in z_ch], [(r_spool + 2.2) * sin(t) for t in theta_rod, z in z_ch], color=:darkgray, alpha=0.25)
z_house_right = range(sleeve_edge + max(4.0, comp.chamber_length_0), 5.0, length=15)
surface!(p3d, [z for t in theta_rod, z in z_house_right], [r_house_in * cos(t) for t in theta_rod, z in z_house_right], [r_house_in * sin(t) for t in theta_rod, z in z_house_right], color=:gray, alpha=0.35)
# Проекция YZ (Продольный разрез дна паза)
p_yz = plot(title="Проекция YZ (Продольный разрез дна паза)", xlabel="Ось Z (мм)", ylabel="Радиус Y (мм)", grid=true, aspect_ratio=:equal, legend=false, xlims=(z_lim_min, z_lim_max), ylims=(0, r_spool + 3.0))
plot!(p_yz, z_shared_axis, y_contour_floor, fillrange=0, fillalpha=0.15, fillcolor=:blue, color=:blue, lw=2.5)
plot!(p_yz, [z_lim_min, sleeve_edge, sleeve_edge, sleeve_edge + comp.chamber_length_0, sleeve_edge + comp.chamber_length_0, z_lim_max], [r_spool, r_spool, r_spool + 2.0, r_spool + 2.0, r_spool, r_spool], color=:black, lw=2)
vline!(p_yz, [sleeve_edge], color=:red, style=:dash, lw=1.5)
# Проекция XZ (Развертка ширины паза)
p_xz = plot(title="Проекция XZ (Развертка ширины паза)", xlabel="Ось Z (мм)", ylabel="Ширина X (мм)", grid=true, aspect_ratio=:equal, legend=false, xlims=(z_lim_min, z_lim_max))
plot!(p_xz, z_shared_axis, x_contour_top, fillrange=-x_contour_top, fillalpha=0.15, fillcolor=:orange, color=:darkorange, lw=2.5)
vline!(p_xz, [sleeve_edge], color=:red, style=:dash, lw=1.5)
combined_plot = plot(p3d, p_yz, p_xz, layout=grid(3, 1, heights=[0.5, 0.25, 0.25]), link=:x, size=(900, 1000))
savefig(combined_plot, "final_spool_plot.png")
return combined_plot
end