I am trying to patch a color gradient of given angular data
Here is the data:
n = [263.6909 287.9987 262.1933 199.6890 128.5683 71.1718 34.6535 15.2568 6.2683 2.4868 0.9872 0.4063 0.1793 0.0876 0.0487 0.0315 0.0241 0.0221 0.0243 0.0319 0.0495 0.0895 0.1838 0.4174 1.0159 2.5605 6.4504 15.6740 35.5053 72.6566 130.6707 201.9328];
theta=0:(2*pi/32):(2*pi*(32-1)/32);
theta(theta>pi) = theta(theta>pi)-2*pi;
I use a patch command
figure
hold on
patch(cos(theta), sin(theta), n, 'EdgeColor', 'none');
quiver(0,0,-4.6492,-0.9099,0.5,'k','linewidth',3);
axis equal
** edit start 3/12/2024 **
The gradient is suppose to be perpendicular to the line between the peak of the concentration and the opposite point along the rim (i.e, from $\theta(n_{max})$ and $\theta(n_{max}+\pi)).
There are two options I'm trying to apply:
1.Assuming that there is an exponential decaying gradient where the gradient patch decays from n_max to zero in the vertical direction.
** edit end 3/12/2024 **
Here in the plot below is what I obtain, and what I wish to obtain
I highlight that the data is part of a dynamical simulation where the array n
changes every iteration, and therefore the gradient slope, and direction, must be according to the given n
Your vector n
is not smooth, and doesn't represent a parallel gradient to any vector direction. You can see this by just using plot(n)
, it aligns with the representation you get. This code shows how you can plot a gradient perpendicular to a given vector:
You can use atan2
to work out the direction of your vector aUV
, and set the colour equal to cos(theta + aUV + pi/2)
, since you want to start drawing the colours offset by aUV
from where you're drawing the circular patch
and the additional pi/2
makes the gradient perpendicular.
% Some setup values
N = 32; % Number of samples in array
U = -4.6492; % X displacement of vector
V = -0.9099; % Y displacement of vector
% Calculate circle drawing vectors
aUV = atan2(U,V); % Angle of UV vector
theta = linspace(0,2*pi,N); % Angle array for drawing patch
clr = cos(theta + aUV + pi/2); % Offset cyclic colour starting from aUV+pi/2
% Plot
figure(1); clf; hold on;
patch(cos(theta), sin(theta), clr, 'EdgeColor', 'none');
quiver(0,0,U,V,0.5,'k','linewidth',3);
axis equal; colormap spring
Output:
Edit with respect to question update...
If you do not have the angle or direction vector as an input we can determine it from the input n
by
See the code comments for details
% Sort theta so that we can interpolate with it as the axis
[theta,idx] = sort(theta);
n = n(idx); % Match the order of points in 'n' with sorted theta
% Upsample 'n' using piecewise cubic interpolation
theta_i = linspace(theta(1),theta(end),1000);
n_i = interp1( theta, n, theta_i, 'pchip' );
% Find the index for the max value of 'n'
[n_max,idx] = max(n_i);
aUV = theta_i(idx);
% Offset cyclic colour starting from aUV
clr = cos(theta - aUV);
% Plotting... side by side of input curve with gradient for comparison
label = sprintf('\\theta=%.3f',aUV); % helper for legend labelling
figure(1); clf;
subplot(1,3,1); hold on;
plot(theta,n,'displayname','Input "n"');
plot(theta_i,n_i,'displayname','Upsampled "n"');
plot(aUV,n_max,'kx','displayname',['Peak "n" at ' label]);
legend('show','location','south');
subplot(1,3,2:3); hold on;
patch(cos(theta), sin(theta), clr, 'EdgeColor', 'none','displayname','gradient');
line( [-1,1]*cos(aUV), [-1,1]*sin(aUV), 'color', 'k', 'displayname', ['Ref line at ' label]);
axis equal; colormap parula; legend show
Result: