How to draw 2d compass in 3d UIAxes

Is it possible to use the compass() function to draw a compass rose in a UIAxes object? I don't care about the function depicted by the compass, I just want the circles and degree text for other purposes. Here is my code:
function draw_compass(em)
th = linspace(0,.001,1000);
r = linspace(5000,384400,1000);
[u,v] = pol2cart(th,r);
pax = compass(em.UIAxes,u,v);
for i = 1:1000 % hide the arrows
pax(i).LineStyle = 'none';
end
end
If I run draw_compass() as a standalone function, it works just fine.
When I try to display this in my UIAxes, I get a "bowtie" effect from the hidden arrows, but no range circles or compass angle text. What gives?
I also tried polarplot(), but it doesn't like my Cartesian coordinate system. Also tried a flattened ellipse, but the range circles are uneven, and I would still have to add text for the angles.
If none of this works, I will have to hand-jam all the circles and radial lines and text the hard way.

 Accepted Answer

It is possible to place the compass rose in a 3D uiaxes. Did you want to plot something in addition to this? If so, you may have difficulties if you try plotting a 3D scatter on top with scatter3.
ax = uiaxes;
th = linspace(0,.001,1000);
r = linspace(5000,384400,1000);
[u,v] = pol2cart(th,r);
compass(ax,u,v)
for ii = 1:length(ax.Children)
delete(ax.Children(1))
end
view(3)

8 Comments

Kurt
Kurt on 7 Apr 2023
Edited: Kurt on 7 Apr 2023
Thanks. How do I rotate it so 0 degrees is up?
I also want to overlay it on other objects. This is an ecliptic plane, so the outer ring of the compass should match the dimensions of the edge of the ecliptic disk.
ax = uiaxes;
th = linspace(0,.001,1000);
r = linspace(5000,384400,1000);
[u,v] = pol2cart(th,r);
compass(ax,u,v)
for ii = 1:length(ax.Children)
delete(ax.Children(1))
end
You can add
ax.View = [-90 90];
or
view(ax,-90,90)
view(ax,-92,32)
You can stack two axes on top of eachother as such:
figure
ax = uiaxes;
th = linspace(0,.001,1000);
r = linspace(5000,384400,1000);
[u,v] = pol2cart(th,r);
compass(ax,u,v)
for ii = 1:length(ax.Children)
delete(ax.Children(1))
end
view(ax,-90,90)
ax2 = uiaxes;
th = linspace(0,.001,1000);
r = linspace(5000,384400,1000);
[u,v] = pol2cart(th,r);
compass(ax2,u,v)
for ii = 1:length(ax2.Children)
delete(ax2.Children(1))
end
view(ax2,-92,32)
Sill not quite there... Something's not working for me.
This standalone script works:
function draw_compass_standalone()
em = uiaxes;
th = linspace(0,.001,1000);
r = linspace(5000,384400,1000);
[u,v] = pol2cart(th,r);
pax = compass(em,u,v);
for i = 1:1000 % hide the arrows
pax(i).LineStyle = 'none';
end
end
However, when I try to incorporate my compass into an existing uiaxes, the circles and text all disappear and I'm left with just the "bowtie".
"em" is an "earthMoon" object, an instantiation of my EarthMoonGUI app:
classdef EarthMoonGUI < matlab.apps.AppBase
properties
EarthMoonUIFigure matlab.ui.Figure
UIAxes matlab.ui.control.UIAxes
.
.
.
earthMoon = app;
Somehow, when the earthMoon.UIAxes object finally reaches draw_compass(), they don't play nice. All I see is the bowtie function output, not the circles and text:
function draw_compass(em)
th = linspace(0,.001,1000);
r = linspace(5000,384400,1000);
[u,v] = pol2cart(th,r);
pax = compass(em.UIAxes,u,v); % nothing appears here but the bowtie
for i = 1:1000 % hide the arrows
pax.UIAxes(i).LineStyle = 'none';
end
end
(later): There is a problem with the statement:
pax = compass(em.UIAxes,u,v);
If I create a uiaxes in the function, it works. But if I try to pass it in as an extension of another object, compass() blows up.
The code above should throw an error.
pax should be a vector of line objects returned from compass().
In the loop, pax.UIAxes should throw an error. I assume pax.UIaxes(i) should be pax(i).
Secondly, I'm surprised you see a bowtie because the for-loop that sets the LineStyles to none should make all of the lines invisible. By the way, that for-loop can be replaced with set(pax,'LineStyle','none')
Are you holding the axes before calling draw_compass?
That helps. However, I'm still having trouble with this line. The compass part is still invisible, except for the bowtie function. This has been a problem since the beginning.
pax = compass(em.UIAxes,u,v);
When I try to add a compass to an already existing UIAxes, I can't see the compass.
By the way, when I tried this with your earlier "delete children" approach, I got an error message.
I need to attach this compass to an existing AppBase app - in this case, EarthMoon which is "em" here.
It works just fine if I create a new axes:
ax = uiaxes;
pax = compass(ax,u,v);
I have the same visibility problem if I use this approach:
function draw_compass(em)
ax = em.UIAxes;
pax = compass(ax,u,v);
I found the problem. "hold" was set. If I call
hold(em.UIAxes,'off')
the compass appears.
I dug into the compass() code and found that it really just calls polar(), so I can probably use that instead.
This also explains why running the compass function standalone worked: hold was off by default.
Kevin made an important point earlier. If you plot underneath this compass, you won't be able to see your data. compass(), which is really based around plot(), is opaque and does not respond to alpha transparancy settings either. So, if you want a compass you can see through, you will need to create it yourself from scratch.

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2022b

Asked:

on 7 Apr 2023

Commented:

on 11 Apr 2023

Community Treasure Hunt

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

Start Hunting!