Polarplot draws unwanted lines to origin when envelope is not full circle (0–360°)

34 visualizaciones (últimos 30 días)
Hi everyone,
I'm creating a polar plot that visualizes measured values (like power) depending on wind direction and wind speed. I also overlay an envelope curve to define the acceptable range. When this envelope covers the full 360°, everything works as expected – I get a clean, closed curve.
However, when the envelope data only spans a partial angular range (e.g. 0° to 180°), MATLAB draws unwanted radial lines from the origin (0,0) to each point in the polarplot. These lines distort the visualization and are not part of the envelope.
I want the envelope to be a clean, curved line only between the actual data points. It should look like this:
I'm using the following helper function to prepare the data for polarplot:
What I tried so far:
[theta_rad, r_final] = prepareClosedPolarLine(envelope1.WindDirectionDeg, envelope1.WindSpeed);
function [theta_rad_final, r_final] = prepareClosedPolarLine(windDir_deg, windSpeed)
%PREPARECLOSEDPOLARLINE Creates a closed line in polar plot.
% It connects wind direction and wind speed data into a clean line,
% even when the angle range is incomplete (e.g., only 0°–180%).
% Ensure column vectors
theta_deg = windDir_deg(:);
r = windSpeed(:);
% Filter valid values
validIdx = ~isnan(theta_deg) & ~isnan(r);
theta_deg = theta_deg(validIdx);
r = r(validIdx);
% Normalize angles to [0, 360)
theta_deg = mod(theta_deg, 360);
% Sort by angle
[theta_deg_sorted, sortIdx] = sort(theta_deg);
r_sorted = r(sortIdx);
% Close the loop by adding first point at the end
theta_deg_closed = [theta_deg_sorted; theta_deg_sorted(1)];
r_closed = [r_sorted; r_sorted(1)];
% Convert to radians for polarplot
theta_rad_final = deg2rad(theta_deg_closed);
r_final = r_closed;
end
envelopeName = "Test";
polarplot(theta_rad, r_final, 'k-', 'MarkerSize', 8, 'LineWidth', 1, 'DisplayName', envelopeName);
Unfortunately neither GPT-4 nor Qwen3-Coder had any good ideas for this. The problem seems to be caused by the envelope not going through all for sections of the plot. Thanks so much for helping:
Data:
% It works for this type of data, covering all of the 360° range
envelope1 = table( ...
[40; 40; 40; 40; 35; 35; 25; 25; 10; 10; 10; 10; 10; 10; 10; 5; 5; 5; 5; 5; ...
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 10; 20; 20; 20; 25; ...
25; 30; 30; 55; 55; 60; 60], ...
[0; 10; 10; 15; 15; 20; 20; 30; 30; 40; 50; 60; 70; 80; 90; 90; 100; 110; ...
120; 130; 140; 150; 160; 170; 180; 190; 200; 210; 220; 230; 240; 250; ...
260; 270; 280; 280; 290; 300; 300; 310; 320; 320; 330; 330; 335; 335; ...
340; 340; 350], ...
'VariableNames', {'WindSpeed', 'WindDirectionDeg'});
% but not for this
envelope2 = table( ...
[60; 60; 40; 40; 25; 25; 20; 20; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; ...
10; 10; 15; 20; 20; 20; 25; 25; 30; 30; 50; 50; 55; 55; 55], ...
[0; 10; 10; 15; 15; 20; 20; 30; 30; 20; 10; 0; 350; 340; 330; 320; ...
310; 300; 290; 280; 280; 300; 300; 300; 310; 320; 320; 330; 330; ...
335; 335; 340; 340; 350; 0], ...
'VariableNames', {'WindSpeed', 'WindDirectionDeg'});

Respuesta aceptada

Mathieu NOE
Mathieu NOE el 14 de Oct. de 2025 a las 12:55
hello
seems to me that your data shoud NOT be sorted by angle. Of course this means you have to have the data ordered so that it indeed follows a nicely closed curve (if I randomise the data this will not be anymore true)
so your code without angle sorting works for both datas :
% It works for this type of data, covering all of the 360° range
envelope1 = table( ...
[40; 40; 40; 40; 35; 35; 25; 25; 10; 10; 10; 10; 10; 10; 10; 5; 5; 5; 5; 5; ...
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 10; 20; 20; 20; 25; ...
25; 30; 30; 55; 55; 60; 60], ...
[0; 10; 10; 15; 15; 20; 20; 30; 30; 40; 50; 60; 70; 80; 90; 90; 100; 110; ...
120; 130; 140; 150; 160; 170; 180; 190; 200; 210; 220; 230; 240; 250; ...
260; 270; 280; 280; 290; 300; 300; 310; 320; 320; 330; 330; 335; 335; ...
340; 340; 350], ...
'VariableNames', {'WindSpeed', 'WindDirectionDeg'});
envelopeName = "Test";
[theta_rad, r_final] = prepareClosedPolarLine(envelope1.WindDirectionDeg, envelope1.WindSpeed);
polarplot(theta_rad, r_final, 'k-', 'MarkerSize', 8, 'LineWidth', 1, 'DisplayName', envelopeName);
% but not for this
envelope2 = table( ...
[60; 60; 40; 40; 25; 25; 20; 20; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; ...
10; 10; 15; 20; 20; 20; 25; 25; 30; 30; 50; 50; 55; 55; 55], ...
[0; 10; 10; 15; 15; 20; 20; 30; 30; 20; 10; 0; 350; 340; 330; 320; ...
310; 300; 290; 280; 280; 300; 300; 300; 310; 320; 320; 330; 330; ...
335; 335; 340; 340; 350; 0], ...
'VariableNames', {'WindSpeed', 'WindDirectionDeg'});
envelopeName = "Test";
[theta_rad, r_final] = prepareClosedPolarLine(envelope2.WindDirectionDeg, envelope2.WindSpeed);
polarplot(theta_rad, r_final, 'k-', 'MarkerSize', 8, 'LineWidth', 1, 'DisplayName', envelopeName);
function [theta_rad_final, r_final] = prepareClosedPolarLine(windDir_deg, windSpeed)
%PREPARECLOSEDPOLARLINE Creates a closed line in polar plot.
% It connects wind direction and wind speed data into a clean line,
% even when the angle range is incomplete (e.g., only 0°–180%).
% Ensure column vectors
theta_deg = windDir_deg(:);
r = windSpeed(:);
% Filter valid values
validIdx = ~isnan(theta_deg) & ~isnan(r);
theta_deg = theta_deg(validIdx);
r = r(validIdx);
% Normalize angles to [0, 360)
theta_deg = mod(theta_deg, 360);
% % Sort by angle
% [theta_deg, sortIdx] = sort(theta_deg);
% r = r(sortIdx);
% Close the loop by adding first point at the end
theta_deg_closed = [theta_deg; theta_deg(1)];
r_closed = [r; r(1)];
%Convert to radians for polarplot
theta_rad_final = deg2rad(theta_deg_closed);
r_final = r_closed;
end

Más respuestas (0)

Categorías

Más información sobre Polar Plots en Help Center y File Exchange.

Productos


Versión

R2024a

Community Treasure Hunt

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

Start Hunting!

Translated by