MATLAB Answers

Can you plot polarplots so that theta zero location is at any arbitrary angle or are top left bottom right the only options?

67 views (last 30 days)
Ryan Rose
Ryan Rose on 28 Sep 2020
Edited: Adam Danz on 29 Sep 2020
I would like to plot a polar plot so that the top angle is the heading of a vehicle like you would see in a navigation display. Is there a way to do this? I tried using the view function to change the angle but it failed. Is there a way to change ax.ThetaZeroLocation to an angle instead of the four options listed?

Accepted Answer

Adam Danz
Adam Danz on 28 Sep 2020
Edited: Adam Danz on 29 Sep 2020
Here's a demo showing how to rotate line objects and theta ticks on polar axes. The orientation of the polar axes is controlled by a uislider within a UIFigure. The slider's callback function updates the "ThetaData" property for all objects on the axes.
Restrictions and notes of caution:
  1. If there are any plotted objects whose angular positions are not controlled by the "ThetaData" property (ie, text objects), this will have to be adapted to work with their positional properties.
  2. Since the ThetaData values are updated for all objects, they will no longer retain their original values. For example, if the original theta value was 0 and it was rotated by 15 deg, then its new theta value will be 15. To get the original theta values back, see the slider's UserData property which stores the current orientation of the polar axes relative to the ThetaZeroLocation.
See inline comments for details.
% Create data for polar plot
th1 = linspace(0,pi*11/6,12);
r1 = cos(th1);
th2 = linspace(5*pi/6,9*pi/6,20);
r2 = linspace(1,.1,20);
% Create the polar plot
% For this demo, this plot can only contain objects whose
% angular position is controlled by the 'ThetaData' property.
fig = uifigure();
ax = polaraxes(fig);
polarplot(ax, th1, r1, 'b-','LineWidth',2);
polarplot(ax, th2, r2, 'ro','MarkerFaceColor', 'r');
polarplot(ax, 0, .9, 'kp', 'MarkerSize', 16, 'MarkerFaceColor', 'y')
titleHandle = title(ax,'Orientation: 0 deg');
% Add slider & label
ax.Position([2,4]) = ax.Position([2,4])+[.15,-.15];
uilabel(fig, 'position', [20 60, 400,20], 'Text', 'Adjust orientation of polar axes (deg from ThetaZeroLocation)');
% You can substitute "ValueChangingFcn" and "ValueChangedFcn" for the same callback function.
sldr = uislider(fig, 'Position', [20, 50, 520, 3], 'Value', 0, 'Limits', [-180,180],...
'MajorTicks', -180:30:180, 'MinorTicks', [], 'UserData', 0, ... % UserData stores current rotation
'ValueChangingFcn', @(sldr,event)updatePolarTicks(sldr,event,ax,titleHandle));
drawnow(); pause(0.05)
% Define slider's callback function to update the orientation of the polar axes
% relative to the TheatZeroLocation.
function updatePolarTicks(sldr,event,ax,titleHandle)
% Update title and compute rotation amount; store new orientation in memory.
titleHandle.String = sprintf('Orientation: %.0f deg', event.Value);
rotation = event.Value - sldr.UserData; %(+=CCW, -=CW)
sldr.UserData = event.Value;
% Convert rotation angle to radians, wrapped to [0,2pi]
dwrap = @(d)mod(d,360) + (d>0 & mod(d,360)==0).*360; %wrap degrees to 0:360
deg = dwrap(rotation);
rad = pi/180*deg;
% Rotate line objects
chil = ax.Children;
thData = get(chil, 'ThetaData');
thDataRot = cellfun(@(c){c+rad},thData);
set(chil, {'ThetaData'}, thDataRot)
% Update ticks
origTickLabs = ax.ThetaTickLabel;
[newTicks, tickLabIdx] = unique(dwrap(unique(mod(ax.ThetaTick,360),'stable') + deg));
ax.ThetaTick = newTicks;
ax.ThetaTickLabel = origTickLabs(tickLabIdx);


Show 2 older comments
Adam Danz
Adam Danz on 29 Sep 2020
With data cursor, but it's not perfect.
For example, if the original theta data exceed 360 deg their data cursor values will be wrapped to 360.
The answer still doesn't handle objects such as text that does not have ThetaData but I had to prevent myself from letting it snowball into a week's project 🤓
% Set up on data cursor
dcm = datacursormode(fig);
dcm.Enable = 'on';
dcm.UpdateFcn = @(h,info)updateDCvalues(h,info,sldr);
function txt = updateDCvalues(~,info,sldr)
th = mod(180/pi*info.Position(1) - sldr.UserData, 360);
if th>359.99
txt = {['Theta \color[rgb]{0 0.6 1}\bf',sprintf('%.2f',th),'\color[rgb]{.25 .25 .25}\rm'], ...
['R \color[rgb]{0 0.6 1}\bf',sprintf('%.2g',info.Position(2)),'\color[rgb]{.25 .25 .25}\rm'],...
'Good idea WR!'};
Ryan Rose
Ryan Rose on 29 Sep 2020
Wow! this was way more than I was hoping for! Thank you!
I use matlab everyday but its nice to know theres lots more to learn.
Adam Danz
Adam Danz on 29 Sep 2020
Ryan, if you want to recreate the radio magnetic indicator (or whatever it is) in the image you shared, you can fairly easily overlay the outline of an aircraft using image, imagesc, or imshow, after scaling it properly and you can also replace the ThetaTickLabels with compass directions ('N', 'E', etc..) which will be maintained as the polar axes are rotated.

Sign in to comment.

More Answers (1)

Sindar on 28 Sep 2020
something like this:
top_angle = 24;
% get current labels
tt = thetaticks;
% rotate angles so top_angle takes place of 90
tt_2 = mod(tt - 90 + top_angle,360);

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!