function chladni_gui
% 创建主窗口
fig = figure('Name', 'Chladni Lab:克拉尼图形仿真与波动可视化', 'NumberTitle', 'off', ...
'Position', [100, 100, 1200, 800], 'Color', [0.1, 0.1, 0.15]);
% 预先计算贝塞尔函数零点表(用于圆形板)
zeros_table = compute_bessel_zeros(0:20, 1:20);
setappdata(fig, 'bessel_zeros', zeros_table);
% 创建标签
uicontrol('Style', 'text', 'String', 'Chladni Lab', ...
'Position', [50, 750, 300, 40], 'FontSize', 24, ...
'ForegroundColor', [0.96, 0.4, 0.62], 'BackgroundColor', [0.1, 0.1, 0.15]);
uicontrol('Style', 'text', 'String', '基于MATLAB的克拉尼图形仿真与波动可视化平台', ...
'Position', [350, 760, 500, 20], 'FontSize', 12, ...
'ForegroundColor', [0.7, 0.7, 0.9], 'BackgroundColor', [0.1, 0.1, 0.15]);
% 创建图形显示区域
ax1 = axes('Parent', fig, 'Position', [0.05, 0.35, 0.45, 0.55], ...
'Color', [0.18, 0.18, 0.23]);
title(ax1, '克拉尼图形仿真', 'Color', 'w', 'FontSize', 14);
axis(ax1, 'equal');
grid(ax1, 'on');
set(ax1, 'XColor', [0.8, 0.8, 0.8], 'YColor', [0.8, 0.8, 0.8], ...
'GridColor', [0.4, 0.4, 0.4]);
% 创建波动可视化区域
ax2 = axes('Parent', fig, 'Position', [0.55, 0.35, 0.45, 0.55], ...
'Color', [0.18, 0.18, 0.23]);
title(ax2, '沙粒波动可视化', 'Color', 'w', 'FontSize', 14);
axis(ax2, 'equal');
grid(ax2, 'on');
set(ax2, 'XColor', [0.8, 0.8, 0.8], 'YColor', [0.8, 0.8, 0.8], ...
'GridColor', [0.4, 0.4, 0.4]);
% 创建控制面板
control_panel = uipanel('Title', '参数控制', 'FontSize', 11, 'ForegroundColor', 'w', ...
'BackgroundColor', [0.2, 0.2, 0.25], ...
'Position', [0.05, 0.05, 0.9, 0.25]);
% 创建形状选择控件
uicontrol('Parent', control_panel, 'Style', 'text', 'String', '振动板形状:', ...
'Position', [20, 170, 100, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
shape_popup = uicontrol('Parent', control_panel, 'Style', 'popupmenu', ...
'String', {'方形板', '圆形板', '三角形板'}, ...
'Position', [20, 150, 120, 20], ...
'Callback', @updatePlot);
% 创建p滑块
uicontrol('Parent', control_panel, 'Style', 'text', 'String', 'p 值 (模态参数):', ...
'Position', [20, 120, 120, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
p_slider = uicontrol('Parent', control_panel, 'Style', 'slider', 'Min', 0, 'Max', 20, 'Value', 3, ...
'Position', [20, 100, 120, 20], ...
'Callback', @updatePlot);
p_text = uicontrol('Parent', control_panel, 'Style', 'text', 'String', '3', ...
'Position', [150, 100, 30, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
% 创建q滑块
uicontrol('Parent', control_panel, 'Style', 'text', 'String', 'q 值 (模态参数):', ...
'Position', [20, 70, 120, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
q_slider = uicontrol('Parent', control_panel, 'Style', 'slider', 'Min', 0, 'Max', 20, 'Value', 2, ...
'Position', [20, 50, 120, 20], ...
'Callback', @updatePlot);
q_text = uicontrol('Parent', control_panel, 'Style', 'text', 'String', '2', ...
'Position', [150, 50, 30, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
% 创建模式选择
uicontrol('Parent', control_panel, 'Style', 'text', 'String', '振动模式:', ...
'Position', [200, 170, 100, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
mode_popup = uicontrol('Parent', control_panel, 'Style', 'popupmenu', ...
'String', {'对称模式', '反对称模式'}, ...
'Position', [200, 150, 120, 20], ...
'Callback', @updatePlot);
% 创建网格分辨率控制
uicontrol('Parent', control_panel, 'Style', 'text', 'String', '网格分辨率:', ...
'Position', [200, 120, 120, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
res_popup = uicontrol('Parent', control_panel, 'Style', 'popupmenu', ...
'String', {'低 (100x100)', '中 (200x200)', '高 (300x300)'}, ...
'Value', 2, ...
'Position', [200, 100, 120, 20], ...
'Callback', @updatePlot);
% 创建频率显示
freq_text = uicontrol('Parent', control_panel, 'Style', 'text', 'String', '频率: 440 Hz', ...
'Position', [200, 50, 150, 30], ...
'FontSize', 12, 'ForegroundColor', [0.96, 0.4, 0.62], ...
'BackgroundColor', [0.2, 0.2, 0.25]);
% 创建波动控制按钮
uicontrol('Parent', control_panel, 'Style', 'pushbutton', 'String', '开始波动仿真', ...
'Position', [350, 150, 120, 30], 'FontSize', 10, ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.4, 0.6], ...
'Callback', @startWaveSimulation);
uicontrol('Parent', control_panel, 'Style', 'pushbutton', 'String', '暂停/继续', ...
'Position', [350, 110, 120, 30], 'FontSize', 10, ...
'ForegroundColor', 'w', 'BackgroundColor', [0.4, 0.4, 0.6], ...
'Callback', @togglePause);
uicontrol('Parent', control_panel, 'Style', 'pushbutton', 'String', '重置沙粒', ...
'Position', [350, 70, 120, 30], 'FontSize', 10, ...
'ForegroundColor', 'w', 'BackgroundColor', [0.6, 0.4, 0.4], ...
'Callback', @resetSandParticles);
% 沙粒数量控制
uicontrol('Parent', control_panel, 'Style', 'text', 'String', '沙粒数量:', ...
'Position', [500, 170, 100, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
sand_slider = uicontrol('Parent', control_panel, 'Style', 'slider', 'Min', 100, 'Max', 2000, ...
'Value', 800, 'Position', [500, 150, 150, 20]);
sand_text = uicontrol('Parent', control_panel, 'Style', 'text', 'String', '800', ...
'Position', [660, 150, 50, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
% 波动速度控制
uicontrol('Parent', control_panel, 'Style', 'text', 'String', '波动速度:', ...
'Position', [500, 120, 100, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
speed_slider = uicontrol('Parent', control_panel, 'Style', 'slider', 'Min', 0.1, 'Max', 5, ...
'Value', 1.5, 'Position', [500, 100, 150, 20]);
speed_text = uicontrol('Parent', control_panel, 'Style', 'text', 'String', '1.5', ...
'Position', [660, 100, 50, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
% 阻尼系数控制
uicontrol('Parent', control_panel, 'Style', 'text', 'String', '阻尼系数:', ...
'Position', [500, 70, 100, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
damping_slider = uicontrol('Parent', control_panel, 'Style', 'slider', 'Min', 0.01, 'Max', 0.2, ...
'Value', 0.08, 'Position', [500, 50, 150, 20]);
damping_text = uicontrol('Parent', control_panel, 'Style', 'text', 'String', '0.08', ...
'Position', [660, 50, 50, 20], ...
'ForegroundColor', 'w', 'BackgroundColor', [0.2, 0.2, 0.25]);
% 创建信息面板
info_panel = uipanel('Title', '物理信息', 'FontSize', 11, 'ForegroundColor', 'w', ...
'BackgroundColor', [0.2, 0.2, 0.25], ...
'Position', [0.05, 0.01, 0.9, 0.03]);
info_text = uicontrol('Parent', info_panel, 'Style', 'text', ...
'String', 'Chladni图案展示振动板在不同频率下的驻波节点分布。波动可视化模拟沙粒在振动板上的运动过程。', ...
'Position', [10, 5, 1080, 20], ...
'HorizontalAlignment', 'left', ...
'ForegroundColor', [0.8, 0.8, 0.9], ...
'BackgroundColor', [0.2, 0.2, 0.25], ...
'FontSize', 10);
% 存储GUI句柄
handles = struct('ax1', ax1, 'ax2', ax2, 'p_slider', p_slider, 'q_slider', q_slider, ...
'p_text', p_text, 'q_text', q_text, ...
'mode_popup', mode_popup, 'res_popup', res_popup, ...
'freq_text', freq_text, 'info_text', info_text, ...
'shape_popup', shape_popup, 'sand_slider', sand_slider, ...
'sand_text', sand_text, 'speed_slider', speed_slider, ...
'speed_text', speed_text, 'damping_slider', damping_slider, ...
'damping_text', damping_text);
% 初始化沙粒数据
sand_data = struct('particles', [], 'velocities', [], 'isSimulating', false, ...
'isPaused', false, 't', 0, 'Z', []);
guidata(fig, handles);
setappdata(fig, 'sand_data', sand_data);
% 初始绘图
updatePlot();
% 更新滑块文本的回调
set(p_slider, 'Callback', @(src,~) set(p_text, 'String', num2str(round(get(src, 'Value'))));
set(q_slider, 'Callback', @(src,~) set(q_text, 'String', num2str(round(get(src, 'Value'))));
set(sand_slider, 'Callback', @(src,~) set(sand_text, 'String', num2str(round(get(src, 'Value'))));
set(speed_slider, 'Callback', @(src,~) set(speed_text, 'String', num2str(get(src, 'Value'), '%.2f'));
set(damping_slider, 'Callback', @(src,~) set(damping_text, 'String', num2str(get(src, 'Value'), '%.2f'));
% 更新绘图函数
function updatePlot(~, ~)
handles = guidata(gcf);
zeros_table = getappdata(gcf, 'bessel_zeros');
% 获取参数值
p = round(get(handles.p_slider, 'Value'));
q = round(get(handles.q_slider, 'Value'));
mode_idx = get(handles.mode_popup, 'Value');
res_idx = get(handles.res_popup, 'Value');
shape_idx = get(handles.shape_popup, 'Value');
% 设置网格分辨率
resolutions = [100, 200, 300];
N = resolutions(res_idx);
% 创建网格
x = linspace(-0.5, 0.5, N);
y = linspace(-0.5, 0.5, N);
[X, Y] = meshgrid(x, y);
% 根据形状计算图案
if shape_idx == 1 % 方形板
% 计算频率
freq = 100 * (p + q);
% 更新信息文本
mode_str = {'对称模式', '反对称模式'};
info = sprintf('方形振动板\n振动模式: %s\n模态参数: m = %d, n = %d\n物理原理: z(x,y) = cos(mπx)cos(nπy) %s cos(nπx)cos(mπy)', ...
mode_str{mode_idx}, p, q, char(177));
% 计算波函数
psi1 = cos(p*pi*X) .* cos(q*pi*Y);
psi2 = cos(q*pi*X) .* cos(p*pi*Y);
% 根据模式组合
if mode_idx == 1 % 对称模式
Z = psi1 + psi2;
else % 反对称模式
Z = psi1 - psi2;
end
elseif shape_idx == 2 % 圆形板
% 确保q至少为1
q = max(1, q);
% 获取贝塞尔函数零点
if p+1 <= size(zeros_table, 1) && q <= size(zeros_table, 2)
k = zeros_table(p+1, q);
else
k = 1; % 默认值
end
% 修正频率计算
freq = 50 * k;
% 更新信息文本
mode_str = {'对称模式 (cos)', '反对称模式 (sin)'};
info = sprintf('圆形振动板\n振动模式: %s\n模态参数: n = %d (角向), m = %d (径向)\n物理原理: z(r,θ) = J_%d(k_{%d,%d}·r)·trig(%dθ)\n频率比例因子: 50', ...
mode_str{mode_idx}, p, q, p, p, q, p);
% 转换为极坐标
R = sqrt(X.^2 + Y.^2);
Theta = atan2(Y, X);
% 计算贝塞尔函数部分
J_part = besselj(p, k*R);
% 根据模式选择三角函数
if mode_idx == 1 % 对称模式
trig_part = cos(p*Theta);
else % 反对称模式
trig_part = sin(p*Theta);
end
% 组合得到振幅
Z = J_part .* trig_part;
% 将圆形外的区域设为NaN(不显示)
Z(R > 0.5) = NaN;
else % 三角形板 (shape_idx == 3)
% 计算频率
freq = 80 * (p + q);
% 更新信息文本
mode_str = {'对称模式', '反对称模式'};
info = sprintf('等边三角形振动板\n振动模式: %s\n模态参数: m = %d, n = %d\n物理原理: 基于重心坐标的特征函数', ...
mode_str{mode_idx}, p, q);
% 计算三角形特征函数
Z = triangular_plate_mode(X, Y, p, q, mode_idx);
% 标记三角形外的点
mask = triangular_mask(X, Y);
Z(~mask) = NaN;
end
% 更新频率显示
set(handles.freq_text, 'String', sprintf('频率: %.0f Hz', freq));
% 绘制克拉尼图形
axes(handles.ax1);
cla;
% 绘制等高线(节点线)
contour(X, Y, Z, [0, 0], 'LineWidth', 2, 'Color', [0.96, 0.4, 0.62]);
hold on;
% 添加中心点
plot(0, 0, 'ro', 'MarkerSize', 8, 'MarkerFaceColor', 'r');
% 绘制边界
if shape_idx == 2 % 圆形板
theta = linspace(0, 2*pi, 100);
plot(0.5*cos(theta), 0.5*sin(theta), 'w-', 'LineWidth', 1.5);
elseif shape_idx == 3 % 三角形板
[vx, vy] = equilateral_triangle_vertices();
plot([vx, vx(1)], [vy, vy(1)], 'w-', 'LineWidth', 1.5);
end
% 设置图形属性
shape_names = {'方形板', '圆形板', '三角形板'};
title(sprintf('克拉尼图案 (%s)', shape_names{shape_idx}), 'Color', 'w');
xlabel('x');
ylabel('y');
axis equal tight;
% 根据形状调整坐标轴范围
if shape_idx == 3
xlim([-0.6, 0.6]);
ylim([-0.6, 0.6]);
else
xlim([-0.55, 0.55]);
ylim([-0.55, 0.55]);
end
grid on;
box on;
set(gca, 'Color', [0.18, 0.18, 0.23], ...
'XColor', [0.8, 0.8, 0.8], 'YColor', [0.8, 0.8, 0.8]);
% 添加图例
if shape_idx == 1
legend('波节线', '固定点', 'Location', 'northeast', ...
'TextColor', 'w', 'Color', [0.25, 0.25, 0.3]);
else
legend('波节线', '中心点', '边界', 'Location', 'northeast', ...
'TextColor', 'w', 'Color', [0.25, 0.25, 0.3]);
end
% 存储Z值用于波动仿真
sand_data = getappdata(gcf, 'sand_data');
sand_data.Z = Z;
setappdata(gcf, 'sand_data', sand_data);
end
% 开始波动仿真
function startWaveSimulation(~, ~)
handles = guidata(gcf);
sand_data = getappdata(gcf, 'sand_data');
% 如果已经在仿真中,则停止之前的仿真
if sand_data.isSimulating
sand_data.isSimulating = false;
setappdata(gcf, 'sand_data', sand_data);
pause(0.1);
end
% 初始化沙粒数据
sand_data.isSimulating = true;
sand_data.isPaused = false;
sand_data.t = 0;
% 获取参数
num_particles = round(get(handles.sand_slider, 'Value'));
speed_factor = get(handles.speed_slider, 'Value');
damping = get(handles.damping_slider, 'Value');
% 获取当前形状
shape_idx = get(handles.shape_popup, 'Value');
% 根据形状初始化沙粒位置
particles = zeros(num_particles, 2);
velocities = zeros(num_particles, 2);
for i = 1:num_particles
if shape_idx == 1 % 方形板
particles(i,:) = [rand() - 0.5, rand() - 0.5];
elseif shape_idx == 2 % 圆形板
r = 0.45 * sqrt(rand());
theta = 2 * pi * rand();
particles(i,:) = [r*cos(theta), r*sin(theta)];
else % 三角形板
[vx, vy] = equilateral_triangle_vertices();
while true
x = 0.8 * (rand() - 0.5);
y = 0.8 * (rand() - 0.5);
if inpolygon(x, y, vx, vy)
particles(i,:) = [x, y];
break;
end
end
end
end
sand_data.particles = particles;
sand_data.velocities = velocities;
setappdata(gcf, 'sand_data', sand_data);
% 启动仿真循环
while sand_data.isSimulating
if ~sand_data.isPaused
% 更新沙粒位置
sand_data = updateSandParticles(sand_data, speed_factor, damping);
% 绘制沙粒
axes(handles.ax2);
cla;
% 绘制边界
shape_idx = get(handles.shape_popup, 'Value');
if shape_idx == 1 % 方形板
rectangle('Position', [-0.5, -0.5, 1, 1], 'EdgeColor', 'w', 'LineWidth', 1.5);
elseif shape_idx == 2 % 圆形板
theta = linspace(0, 2*pi, 100);
plot(0.5*cos(theta), 0.5*sin(theta), 'w-', 'LineWidth', 1.5);
else % 三角形板
[vx, vy] = equilateral_triangle_vertices();
plot([vx, vx(1)], [vy, vy(1)], 'w-', 'LineWidth', 1.5);
end
hold on;
% 绘制沙粒
scatter(sand_data.particles(:,1), sand_data.particles(:,2), 15, ...
'MarkerFaceColor', [0.96, 0.7, 0.3], 'MarkerEdgeColor', 'none');
% 添加中心点
plot(0, 0, 'ro', 'MarkerSize', 8, 'MarkerFaceColor', 'r');
% 设置图形属性
title('沙粒波动可视化', 'Color', 'w');
xlabel('x');
ylabel('y');
if shape_idx == 3
xlim([-0.6, 0.6]);
ylim([-0.6, 0.6]);
else
xlim([-0.55, 0.55]);
ylim([-0.55, 0.55]);
end
axis equal;
grid on;
box on;
set(gca, 'Color', [0.18, 0.18, 0.23], ...
'XColor', [0.8, 0.8, 0.8], 'YColor', [0.8, 0.8, 0.8]);
drawnow;
end
% 短暂暂停以控制速度
pause(0.02);
sand_data = getappdata(gcf, 'sand_data');
end
end
% 更新沙粒位置
function sand_data = updateSandParticles(sand_data, speed_factor, damping)
% 获取当前参数
p = round(get(handles.p_slider, 'Value'));
q = round(get(handles.q_slider, 'Value'));
mode_idx = get(handles.mode_popup, 'Value');
shape_idx = get(handles.shape_popup, 'Value');
% 时间步长
dt = 0.02 * speed_factor;
sand_data.t = sand_data.t + dt;
particles = sand_data.particles;
velocities = sand_data.velocities;
Z = sand_data.Z;
% 获取网格信息
[N, ~] = size(Z);
x = linspace(-0.5, 0.5, N);
y = linspace(-0.5, 0.5, N);
% 计算波函数的梯度
[dZdx, dZdy] = gradient(Z, x(2)-x(1), y(2)-y(1));
for i = 1:size(particles, 1)
px = particles(i, 1);
py = particles(i, 2);
% 检查粒子是否在边界内
if shape_idx == 1 % 方形板
in_bounds = (px >= -0.5) && (px <= 0.5) && (py >= -0.5) && (py <= 0.5);
elseif shape_idx == 2 % 圆形板
in_bounds = (sqrt(px^2 + py^2) <= 0.5);
else % 三角形板
[vx, vy] = equilateral_triangle_vertices();
in_bounds = inpolygon(px, py, vx, vy);
end
if in_bounds
% 找到最近的网格点
[~, idx_x] = min(abs(x - px));
[~, idx_y] = min(abs(y - py));
% 获取该点的梯度
gx = dZdx(idx_y, idx_x);
gy = dZdy(idx_y, idx_y);
% 计算力(指向波节线)
force_scale = 0.5;
force_x = -gx * force_scale;
force_y = -gy * force_scale;
% 添加一些随机扰动
rand_scale = 0.05;
force_x = force_x + rand_scale * (rand() - 0.5);
force_y = force_y + rand_scale * (rand() - 0.5);
% 更新速度
velocities(i, 1) = velocities(i, 1) * (1 - damping) + force_x * dt;
velocities(i, 2) = velocities(i, 2) * (1 - damping) + force_y * dt;
% 更新位置
particles(i, 1) = px + velocities(i, 1) * dt;
particles(i, 2) = py + velocities(i, 2) * dt;
else
% 如果粒子在边界外,将其重置到中心附近
particles(i, :) = [0.05*(rand()-0.5), 0.05*(rand()-0.5)];
velocities(i, :) = [0, 0];
end
end
sand_data.particles = particles;
sand_data.velocities = velocities;
setappdata(gcf, 'sand_data', sand_data);
end
% 暂停/继续波动仿真
function togglePause(~, ~)
sand_data = getappdata(gcf, 'sand_data');
if sand_data.isSimulating
sand_data.isPaused = ~sand_data.isPaused;
setappdata(gcf, 'sand_data', sand_data);
end
end
% 重置沙粒
function resetSandParticles(~, ~)
sand_data = getappdata(gcf, 'sand_data');
sand_data.isSimulating = false;
sand_data.isPaused = false;
% 清除波动可视化区域
axes(handles.ax2);
cla;
title('沙粒波动可视化', 'Color', 'w');
axis equal;
grid on;
set(gca, 'Color', [0.18, 0.18, 0.23], ...
'XColor', [0.8, 0.8, 0.8], 'YColor', [0.8, 0.8, 0.8]);
if get(handles.shape_popup, 'Value') == 3
xlim([-0.6, 0.6]);
ylim([-0.6, 0.6]);
else
xlim([-0.55, 0.55]);
ylim([-0.55, 0.55]);
end
setappdata(gcf, 'sand_data', sand_data);
end
end
% 计算贝塞尔函数零点的辅助函数
function zeros_table = compute_bessel_zeros(n_vals, m_vals)
max_n = max(n_vals);
max_m = max(m_vals);
zeros_table = zeros(max_n+1, max_m);
for n = n_vals
for m = m_vals
% 使用数值方法求解贝塞尔函数零点
fun = @(x) besselj(n, x);
guess = (m + 0.5*n - 0.25)*pi; % 初始猜测值
% 使用fzero查找零点
try
zero = fzero(fun, guess);
zeros_table(n+1, m) = zero;
catch
% 如果失败,使用更鲁棒的搜索方法
x = linspace(0, 100, 10000); % 限制搜索范围
y = fun(x);
inds = find(diff(sign(y)) ~= 0);
if length(inds) >= m
zero = x(inds(m));
zeros_table(n+1, m) = zero;
else
zeros_table(n+1, m) = 0;
end
end
end
end
end
% 生成等边三角形的顶点坐标
function [vx, vy] = equilateral_triangle_vertices()
% 等边三角形顶点 (中心在原点)
height = 0.9;
side = height / (sqrt(3)/2); % 边长
vx = [0, -side/2, side/2];
vy = [height/2, -height/2, -height/2];
end
% 创建三角形板的掩码
function mask = triangular_mask(X, Y)
% 获取三角形顶点
[vx, vy] = equilateral_triangle_vertices();
% 创建多边形掩码
mask = inpolygon(X, Y, vx, vy);
end
% 三角形板的振动模式函数
function Z = triangular_plate_mode(X, Y, m, n, mode_idx)
% 获取三角形顶点
[vx, vy] = equilateral_triangle_vertices();
A = [vx(1), vy(1)];
B = [vx(2), vy(2)];
C = [vx(3), vy(3)];
% 计算面积 (用于重心坐标)
total_area = abs((B(1)-A(1))*(C(2)-A(2)) - (C(1)-A(1))*(B(2)-A(2)))/2;
% 初始化Z矩阵
Z = zeros(size(X));
% 计算每个点的重心坐标
for i = 1:size(X,1)
for j = 1:size(X,2)
P = [X(i,j), Y(i,j)];
% 计算子三角形面积
area_A = abs((B(1)-P(1))*(C(2)-P(2)) - (C(1)-P(1))*(B(2)-P(2)))/2;
area_B = abs((A(1)-P(1))*(C(2)-P(2)) - (C(1)-P(1))*(A(2)-P(2)))/2;
area_C = abs((A(1)-P(1))*(B(2)-P(2)) - (B(1)-P(1))*(A(2)-P(2)))/2;
% 计算重心坐标
lambda1 = area_A / total_area;
lambda2 = area_B / total_area;
lambda3 = area_C / total_area;
% 确保重心坐标和为1
if abs(lambda1 + lambda2 + lambda3 - 1) > 1e-6
lambda3 = 1 - lambda1 - lambda2;
end
% 计算特征函数
if mode_idx == 1 % 对称模式
Z(i,j) = sin(2*pi*(2*m+n)*lambda1) + ...
sin(2*pi*(2*n+m)*lambda2) + ...
sin(2*pi*(m+n)*lambda3);
else % 反对称模式
Z(i,j) = cos(2*pi*(2*m+n)*lambda1) + ...
cos(2*pi*(2*n+m)*lambda2) + ...
cos(2*pi*(m+n)*lambda3);
end
end
end
end
上面这个代码中,文件: chladni_gui84.m 行: 177 列: 96
无效表达式。调用函数或对变量进行索引时,请使用圆括号。否则,请检查不匹配的分隔符。
Caught "std::exception" Exception message is:
Invalid character code sequence detected.请你帮我修改并给出正确的完整代码