I have a unit circle with n roots of unity marked. I would like to be able to rotate, translate, and scale a line resting on the x-axis (between -1 and 1) to connect any pair of marked roots. Currently my code can do this in some cases, but doesn't work in general. I want to avoid hard-coding how the line should move for each possible pair. Here's what I have so far:
clear
%% Roots of unity
n = 10;
roots = zeros(1, n);
for k = 1 : n
roots(k) = exp(2 * k* pi * 1i / n);
end
%% Move line
% Pair of roots the line should connect
point_1 = roots(2);
point_2 = roots(6);
% Coordinates of pair of roots
x1 = real(point_1);
x2 = real(point_2);
y1 = imag(point_1);
y2 = imag(point_2);
d = sqrt((x1-x2)^2 (y1-y2)^2); % Euclidean distance between pair of roots
m = (y1 - y2) / (x1 - x2); % Gradient of line connecting pair of roots
c = y1 - m * x1; % y-intercept of line
int = -c / m; % x-coordinate that the rotation should occur at
shift = [int; 0];
x = linspace(-1, 1, 10); % Initial line lying purely on x-axis
y = 0 * x;
v = [x; y];
theta = atan((y2-shift(2))/(x2-shift(1))); % Angle by which to rotate
rot = [cos(theta), -sin(theta); sin(theta), cos(theta)]; % Rotation matrix
u = v * (d / 2); % Scale initial line
if m < 1e-3 % Horizontal case
shift = [0; 0];
end
w = (rot * (u - shift)) shift; % Apply rotation
% Another shift that seems necessary
% This is definitely a problematic section
shift_x = w(1, 1) - x2;
shift_y = w(2, 1) - y2;
shift_2 = [shift_x; shift_y];
w = w - shift_2;
%% Plot
fig = figure;
fig.Units = 'inches';
fig.Position = [1, 1, 9, 9];
ax = gca;
tt = title(ax, 'Title');
tt.FontWeight = 'bold';
tt.FontSize = 20;
st = subtitle(ax, sprintf('More text here'));
st.FontAngle = 'italic';
st.FontSize = 15;
hold on
hCircle = viscircles([0, 0], 1, 'Color', 'k');
for i = 1 : n
x_point = real(roots(i));
y_point = imag(roots(i));
hPin = plot(x_point, y_point, 'Marker', 'o', 'MarkerSize', 20, 'MarkerfaceColor', 'red', ...
'MarkerEdgeColor', 'black');
end
% Plot original and shifted line, split into colours so direction is easier to see
plot(v(1,1:4), v(2,1:4), 'b');
plot(v(1,4:7), v(2,4:7), 'r');
plot(v(1,7:end), v(2,7:end), 'g');
plot(w(1,1:4), w(2,1:4), 'b');
plot(w(1,4:7), w(2,4:7), 'r');
plot(w(1,7:end), w(2,7:end), 'g');
For example, keeping point_1 = roots(2);
and changing only point_2 = roots(p);
works as intended for only p=3, 4, 6, 7, 8.
Any guidance on how to get this working would be greatly appreciated, thanks!
Edit:
To give some more details, basically I have an array of numbers between 0 and 1 (rather than just a line) which I want to plot on the line that would connect two roots. E.g. if my array is x=[0.2, 0.5, 0.9]
, then I want three points between point_1
and point_2
, the first being 0.2d down the connecting line away from point_1
, the second 0.5d (i.e. halfway), and the final being 0.9d away.
CodePudding user response:
First of all, since the points you want to connect are complex numbers, it is easier to work with complex coordinate directly.
Roots of unity
I have simplified your code a bit.
Some may raise a flag on naming a variable roots
since roots
is a built-in matlab function. I am fine with it, as long as the usage does not cause any confusion, namely, don't use roots
as a variable and as a function in the same context.
As matlab provides so many built-in functions, it is impossible to avoid name collision unless one knows them all by heart or searches before naming every single variable.
n = 10;
k = 1:n;
roots = exp(2 * k * pi * 1i / n);
Scaling, rotating, and translating
% Pair of roots the line should connect
point_1 = roots(2);
point_2 = roots(6);
d = abs(point_2 - point_1); % distance between pair of roots
theta = angle(point_2 - point_1); % rotation angle
p_on_line = linspace(-1, 1, 10); % Initial line lying on x-axis
p_on_line = p_on_line * d/2; % scale
p_on_line = p_on_line * exp(1i*theta); % rotate
p_on_line = p_on_line (point_1 - p_on_line(1)); % translate
Plot
I added some scatter points and removed irrevelant parts (e.g. title, fonts).
fig = figure;
fig.Units = 'inches';
fig.Position = [1, 1, 9, 9];
hold on
hCircle = viscircles([0, 0], 1, 'Color', 'k');
hPin = plot(roots, 'o', 'MarkerSize', 20, 'MarkerfaceColor', 'red', ...
'MarkerEdgeColor', 'black');
% Plot line connecting roots
plot(p_on_line(1:4), 'b.-', 'MarkerSize', 20);
plot(p_on_line(4:7), 'r.-', 'MarkerSize', 20);
plot(p_on_line(7:end), 'g.-', 'MarkerSize', 20);
% Plot original line
original_x = linspace(-1, 1, 10);
original_y = zeros(1, 10);
plot(original_x(1:4), original_y(1:4), 'b.-', 'MarkerSize', 20);
plot(original_x(4:7), original_y(4:7), 'r.-', 'MarkerSize', 20);
plot(original_x(7:end), original_y(7:end), 'g.-', 'MarkerSize', 20);
hold off
This should work for all combinations of root pairs.