function animate_operating_zones
f = figure('Name', 'Operating Zones on Sphere', 'Position', [100 100 1000 600]);
ax = axes('Parent', f, 'Position', [0.35 0.1 0.6 0.8]);
xlabel('X'); ylabel('Y'); zlabel('Z');
uicontrol(f, 'Style', 'text', 'String', 'Characteristic Angle', 'Position', [20 520 200 20]);
uicontrol(f, 'Style', 'text', 'String', '0', 'Position', [20 500 30 20]);
angles.char = uicontrol(f, 'Style', 'slider', 'Min', 0, 'Max', 360, 'Value', charAngle, ...
'Position', [50 500 200 20], 'Callback', @(src,~) update());
uicontrol(f, 'Style', 'text', 'String', '360', 'Position', [250 500 30 20]);
labels.char = uicontrol(f, 'Style', 'text', 'String', num2str(charAngle), 'Position', [280 500 40 20]);
uicontrol(f, 'Style', 'text', 'String', 'Min Forward Angle', 'Position', [20 460 200 20]);
uicontrol(f, 'Style', 'text', 'String', '0', 'Position', [20 440 30 20]);
angles.fwdMin = uicontrol(f, 'Style', 'slider', 'Min', 0, 'Max', 90, 'Value', fwdMin, ...
'Position', [50 440 200 20], 'Callback', @(src,~) update());
uicontrol(f, 'Style', 'text', 'String', '90', 'Position', [250 440 30 20]);
labels.fwdMin = uicontrol(f, 'Style', 'text', 'String', num2str(fwdMin), 'Position', [280 440 40 20]);
uicontrol(f, 'Style', 'text', 'String', 'Max Forward Angle', 'Position', [20 400 200 20]);
uicontrol(f, 'Style', 'text', 'String', '0', 'Position', [20 380 30 20]);
angles.fwdMax = uicontrol(f, 'Style', 'slider', 'Min', 0, 'Max', 90, 'Value', fwdMax, ...
'Position', [50 380 200 20], 'Callback', @(src,~) update());
uicontrol(f, 'Style', 'text', 'String', '90', 'Position', [250 380 30 20]);
labels.fwdMax = uicontrol(f, 'Style', 'text', 'String', num2str(fwdMax), 'Position', [280 380 40 20]);
uicontrol(f, 'Style', 'text', 'String', 'Min Reverse Angle', 'Position', [20 340 200 20]);
uicontrol(f, 'Style', 'text', 'String', '0', 'Position', [20 320 30 20]);
angles.revMin = uicontrol(f, 'Style', 'slider', 'Min', 0, 'Max', 90, 'Value', revMin, ...
'Position', [50 320 200 20], 'Callback', @(src,~) update());
uicontrol(f, 'Style', 'text', 'String', '90', 'Position', [250 320 30 20]);
labels.revMin = uicontrol(f, 'Style', 'text', 'String', num2str(revMin), 'Position', [280 320 40 20]);
uicontrol(f, 'Style', 'text', 'String', 'Max Reverse Angle', 'Position', [20 280 200 20]);
uicontrol(f, 'Style', 'text', 'String', '0', 'Position', [20 260 30 20]);
angles.revMax = uicontrol(f, 'Style', 'slider', 'Min', 0, 'Max', 90, 'Value', revMax, ...
'Position', [50 260 200 20], 'Callback', @(src,~) update());
uicontrol(f, 'Style', 'text', 'String', '90', 'Position', [250 260 30 20]);
labels.revMax = uicontrol(f, 'Style', 'text', 'String', num2str(revMax), 'Position', [280 260 40 20]);
surf(ax, 0.1*X, 0.1*Y, 0.1*Z, 'FaceAlpha', 0.8, 'EdgeColor', 'none');
axis(ax, [-1 1 -1 1 -1 1]);
xlabel('X'); ylabel('Y'); zlabel('Z');
fmin = angles.fwdMin.Value;
fmax = angles.fwdMax.Value;
rmin = angles.revMin.Value;
rmax = angles.revMax.Value;
labels.char.String = sprintf('%.1f', ca);
labels.fwdMin.String = sprintf('%.1f', fmin);
labels.fwdMax.String = sprintf('%.1f', fmax);
labels.revMin.String = sprintf('%.1f', rmin);
labels.revMax.String = sprintf('%.1f', rmax);
mt_dir = rotate_vector([0 0 1], zt_axis, deg2rad(ca));
mt_dir = mt_dir / norm(mt_dir);
quiver3(0, 0, 0, mt_dir(1), mt_dir(2), mt_dir(3), 'r', 'LineWidth', 2, 'MaxHeadSize', 1);
text(mt_dir(1), mt_dir(2), mt_dir(3), 'Max Torque', 'Color', 'r');
quiver3(0, 0, 0, zt_axis(1), zt_axis(2), zt_axis(3), 'b', 'LineWidth', 2, 'MaxHeadSize', 1);
text(zt_axis(1), zt_axis(2), zt_axis(3), 'Zero Torque', 'Color', 'b');
quiver3(0, 0, 0, negZ(1), negZ(2), negZ(3), 'k', 'LineWidth', 2, 'MaxHeadSize', 1);
text(negZ(1), negZ(2), negZ(3), '-U_0', 'Color', 'k', 'VerticalAlignment', 'top');
plot_sector(mt_dir, zt_axis, -fmin, fmax, [0 1 0]);
plot_sector(-mt_dir, zt_axis, rmin, -rmax, [1 0.5 0]);
function v_rot = rotate_vector(v, axis, angle)
axis = axis / norm(axis);
v_rot = v*cos(angle) + cross(axis, v)*sin(angle) + axis*dot(axis, v)*(1 - cos(angle));
function plot_sector(mt_dir, zt_dir, minAngle, maxAngle, color)
u = mt_dir / norm(mt_dir);
v = zt_dir - dot(zt_dir, u)*u;
theta = deg2rad(linspace(minAngle, maxAngle, N));
arc(i, :) = cos(theta(i))*u + sin(theta(i))*v;
arc(i, :) = arc(i, :) / norm(arc(i, :));
fill3([0; arc(:,1)], [0; arc(:,2)], [0; arc(:,3)], color, ...
'FaceAlpha', 0.4, 'EdgeColor', 'none');