connect nodes (coordinates of a matrix rx3) with a line

3 views (last 30 days)
I am modifying the question because it was completely misunderstood.
I want to connect the coordinates in data.txt (representing the black * in the figure) with a line (red) in the following way:
I tried this code but it does not give the desired result.
data = readmatrix('data.txt');
figure
plot(data(:,1), data(:,2),'k*','Markersize',15)
hold on
plot(data(:,1), data(:,2),'-r','LineWidth',1)
hold off
grid off
xlabel('x')
ylabel('y')
  1 Comment
Alberto Acri
Alberto Acri on 24 Dec 2022
I have thought of something like this but at the moment it does not bring the desired result:
data = readmatrix('data.txt');
count_rows = height(data);
for i = 1:2:count_rows
odd_row = data(i,:);
for j = 2:2:count_rows
row_even = data(j,:);
line(odd_row, row_even)
end
end

Sign in to comment.

Accepted Answer

Voss
Voss on 24 Dec 2022
data = readmatrix('data.txt');
N = size(data,1);
% d: distance (squared) from each point to each other point
% (with the distance from a point to itself set to Inf,
% so that it won't be the minimum)
x = data(:,1);
y = data(:,2);
d = (x-x.').^2+(y-y.').^2;
d(1:N+1:end) = Inf;
% used_idx: indices of points used so far
% unused_idx: indices of points not used so far
% start with point 1
used_idx = 1;
unused_idx = 2:N;
% as long as there are some points not yet used
while ~isempty(unused_idx)
% find the unused point nearest to the last used one
[~,idx] = min(d(used_idx(end),unused_idx),[],2);
% add that index to the used_idx vector
used_idx(end+1) = unused_idx(idx);
% and remove it from the unused_idx vector
unused_idx(idx) = [];
end
% plot
plot(x,y,'*k')
hold on
% include the first point at the beginning and end ([1:end 1]),
% in order to close the loop
plot(x(used_idx([1:end 1])),y(used_idx([1:end 1])), ...
'LineWidth',3)
  2 Comments
Alberto Acri
Alberto Acri on 26 Dec 2022
Thank you for your response @Voss. In the case where I have two similar curves (see example.m) I don't understand why the line joining the final coordinate with the initial one is not created. I thank you if you can take a look at the code.
Voss
Voss on 26 Dec 2022
Edited: Voss on 26 Dec 2022
That happens because of the NaNs you put into x_sx and x_dx in an attempt to partition the dataset into the two separate curves. Basically, in between the last point and the first point of each curve, the entire other curve exists but its x-coordinates are all NaN's so you don't see it, but you also don't get the line connecting the last point back to the first.
You could modify the code to handle NaNs, but what makes more sense to me is, instead of using NaNs, separate the two curves completely:
data = readmatrix('te_300.txt');
x = data(:,1);
y = data(:,2);
threshold = 255;
idx = x > threshold;
x_sx = x(idx);
y_sx = y(idx);
coord_left = [x_sx, y_sx];
x_dx = x(~idx);
y_dx = y(~idx);
coord_right = [x_dx, y_dx];
And then, of course, the calculations of d_sx and d_dx have to use y_sx and y_dx, respectively, instead of y:
% ...
d_sx = (x_sx - x_sx.').^2 + (y_sx - y_sx.').^2;
% ...
d_dx = (x_dx-x_dx.').^2+(y_dx-y_dx.').^2;
% ...
And the rest stays the same.

Sign in to comment.

More Answers (3)

Karim
Karim on 24 Dec 2022
Edited: Karim on 24 Dec 2022
Note that the typical sorting trick using the angle won't work due to the shape of your curve. Hence the method below uses a loop over the points, looking for the closest neighbour until the order is found.
See below for a demonstration of the principle using your data points. Hope it helps.
data = readmatrix('data.txt');
% determine the order of the closest points for each point
idx = knnsearch(data,data,'K',size(data,1));
% create a vector to store the order of the points
order = zeros(size(data,1),1);
% we use point 1 as the starting point
order(1) = 1;
% loop over the other points
for i = 2:size(data,1)
% extract the indexes of the points closest to the current point
% these are ordered by distance vie the knnsearch
currPoints = idx(order(i-1),:);
% keep looking for the closest point we havent used so far
for j = 2:size(data,1)
if all(order(1:(i-1)) ~= currPoints(j))
% we found the next point, store in the order and stop the
% internal loop
order(i) = currPoints(j);
break
end
end
end
% sort the points using the order
data = data(order,:);
% make a figure
figure
plot(data(:,1),data(:,2),'LineWidth',1.5)
grid on
title('sorted points')

Image Analyst
Image Analyst on 23 Dec 2022
Edited: Image Analyst on 23 Dec 2022
Not sure how you define thickness but if it's the distance between the two points that are fartest away from each other, you can use pdist2 or bwferet
data = readmatrix('data.txt');
% FIGURE 1
figure
plot(data(:,1), data(:,2),'k*','Markersize',5)
hold on
plot(data(:,1), data(:,2),'-r','LineWidth',1)
hold off
grid off
xlabel('x')
ylabel('y')
% FIGURE 2
x = data(:,1);
y = data(:,2);
s = 1;
k = boundary(x,y,s);
figure
plot(x,y, 'k*', x(k), y(k), '-r')
grid off
xlabel('x')
ylabel('y')
% Get boundary points.
xb = x(k);
yb = y(k);
rows = max(y)
columns = max(x)
mask = poly2mask(xb, yb, rows, columns);
figure
imshow(mask)
axis('on', 'xy')
feretInfo = bwferet(mask)
% Use pdist2 to find out which points are farthest from each other.
distances = pdist2([xb, yb], [xb, yb]);
maxDistance = max(distances(:))
feretInfo =
1×3 table
MaxDiameter MaxAngle MaxCoordinates
________________ ________________ ______________
113.600176056202 170.371843871513 {2×2 double}
maxDistance =
113.282831885507
  5 Comments
Image Analyst
Image Analyst on 24 Dec 2022
You're going to need to sort your data in a clockwise manner instead of by x value. We talked about this in your prior question. Doesn't boundary do that for you?
Alberto Acri
Alberto Acri on 24 Dec 2022
No, the boundary function does not do that for me.

Sign in to comment.


Benjamin Kraus
Benjamin Kraus on 23 Dec 2022
You can specify the LineWidth when you call the plot command.
data = readmatrix('data.txt');
x = data(:,1);
y = data(:,2);
s = 1;
k = boundary(x,y,s);
plot(x,y, 'k*', x(k), y(k), '-r','LineWidth',3) % Specify Line Width here
grid off
xlabel('x')
ylabel('y')
  2 Comments
Benjamin Kraus
Benjamin Kraus on 23 Dec 2022
If you want a different line width for the line versus the markers, you need to use hold like this:
data = readmatrix('data.txt');
x = data(:,1);
y = data(:,2);
s = 1;
k = boundary(x,y,s);
plot(x,y, 'k*', 'MarkerSize',5)
hold on
plot(x(k), y(k), '-r','LineWidth',3) % Specify Line Width here
grid off
xlabel('x')
ylabel('y')
Alberto Acri
Alberto Acri on 24 Dec 2022
Read my question which I edited. I hope it is clearer than the previous one.

Sign in to comment.

Products


Release

R2021b

Community Treasure Hunt

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

Start Hunting!