Files
mcm-26-b/scripts/matlab/fig_replay.m
T
2026-09-13 10:27:09 +08:00

110 lines
4.4 KiB
Matlab

function fig_replay(name)
%FIG_REPLAY 回放画布(点运动图):世界视图 + 事件流水 + 虚拟时间轴。
% name: 'replay_q3' 或 'replay_q4',对应 docs/figures/.data/<name>.mat。
% 本图是唯一保留自定义画布版式的图:三个区互不重叠,图例置于世界视图下方。
if nargin < 1
name = 'replay_q3';
end
S = fig_style();
D = load_data(S, name);
H = geom_helpers();
fig = figure('Color', 'w', 'Visible', 'off', 'Position', [100 100 1040 660]);
c_path = [0.35 0.35 0.35];
c_ray = pick_color(S, 'primary');
c_solved = pick_color(S, 'success');
c_unsolv = pick_color(S, 'accent');
c_head = pick_color(S, 'violet');
% ---------------- 世界视图 ----------------
ax = axes(fig, 'Position', [0.075 0.40 0.49 0.56]);
hold(ax, 'on');
H.circle(ax, [0 0], D.omega_r, pick_color(S, 'primary'), 1.2, '-');
h_path = plot(ax, D.path(:, 1), D.path(:, 2), 'Color', c_path, 'LineWidth', 0.9);
h_ray = plot(ax, nan, nan, 'Color', c_ray, 'LineWidth', 0.8);
for i = 1:size(D.rays, 1)
p0 = D.rays(i, 1:2);
p1 = p0 + D.rays(i, 3:4);
plot(ax, [p0(1) p1(1)], [p0(2) p1(2)], 'Color', c_ray, 'LineWidth', 0.8);
end
h_disk = gobjects(0);
for i = 1:size(D.half_disks, 1)
disk = squeeze(D.half_disks(i, :, :));
h_disk(end + 1) = patch(ax, 'XData', disk(:, 1), 'YData', disk(:, 2), ...
'FaceColor', c_head, 'FaceAlpha', 0.10, ...
'EdgeColor', c_head, 'LineWidth', 0.8); %#ok<AGROW>
end
for i = 1:size(D.headings, 1)
p0 = D.headings(i, 1:2);
p1 = p0 + D.headings(i, 3:4);
H.arrow(ax, p0, p1, c_head);
end
solved = D.truth_solved > 0.5;
h_solved = plot(ax, D.truth(solved, 1), D.truth(solved, 2), 'o', ...
'MarkerSize', 6, 'MarkerFaceColor', c_solved, 'MarkerEdgeColor', 'none');
h_unsolv = plot(ax, D.truth(~solved, 1), D.truth(~solved, 2), 'o', ...
'MarkerSize', 6, 'MarkerFaceColor', c_unsolv, 'MarkerEdgeColor', 'none');
label_color = repmat(c_unsolv, size(D.truth, 1), 1);
label_color(solved, :) = repmat(c_solved, nnz(solved), 1);
H.label_points(ax, D.truth, D.truth_labels, label_color);
plot(ax, D.clears(D.clears(:, 3) > 0.5, 1), D.clears(D.clears(:, 3) > 0.5, 2), ...
'x', 'MarkerSize', 7, 'LineWidth', 1.4, 'Color', c_solved);
plot(ax, D.clears(D.clears(:, 3) <= 0.5, 1), D.clears(D.clears(:, 3) <= 0.5, 2), ...
'o', 'MarkerSize', 6, 'MarkerEdgeColor', 'k', 'MarkerFaceColor', 'none');
hold(ax, 'off');
axis(ax, 'equal');
xlim(ax, [-D.half, D.half]);
ylim(ax, [-D.half, D.half]);
xlabel(ax, 'x / m');
ylabel(ax, 'y / m');
hleg = [h_path, h_ray];
if ~isempty(h_disk)
hleg(end + 1) = h_disk(1);
end
hleg = [hleg, h_solved, h_unsolv];
legend(ax, hleg, D.legend, 'Location', 'southoutside', 'Orientation', 'horizontal');
% ---------------- 事件流水 ----------------
ex = axes(fig, 'Position', [0.625 0.40 0.345 0.56], ...
'XLim', [0 1], 'YLim', [0 1], 'Visible', 'off');
hold(ex, 'on');
cols = [0.00 0.34 1.00];
align = {'left', 'left', 'right'};
head = {'动作', '参数', 't / s'};
for j = 1:3
text(ex, cols(j), 0.97, head{j}, 'FontWeight', 'bold', ...
'HorizontalAlignment', align{j});
end
for i = 1:size(D.events, 1)
y = 0.90 - (i - 1) * 0.088;
for j = 1:3
text(ex, cols(j), y, D.events{i, j}, 'HorizontalAlignment', align{j}, ...
'Interpreter', 'none');
end
end
hold(ex, 'off');
% ---------------- 虚拟时间轴 ----------------
tx = axes(fig, 'Position', [0.075 0.155 0.90 0.125]);
hold(tx, 'on');
rectangle(tx, 'Position', [0 0.34 D.total_s 0.32], ...
'FaceColor', pick_color(S, 'primary'), 'FaceAlpha', 0.12, ...
'EdgeColor', 'none');
for i = 1:size(D.marks, 1)
t = D.marks(i, 1);
if D.marks(i, 3) > 0.5
plot(tx, [t t], [0.05 0.95], 'Color', c_solved, 'LineWidth', 1.0);
elseif D.marks(i, 2) > 0.5
plot(tx, [t t], [0.22 0.78], 'Color', c_unsolv, 'LineWidth', 0.8);
end
end
hold(tx, 'off');
xlim(tx, [0 D.total_s]);
ylim(tx, [0 1]);
set(tx, 'YTick', []);
xlabel(tx, '虚拟时间 t / s');
fig_save(fig, S, D.out_png{1});
end