Simon
Simon

Reputation: 5039

Drawing a line of ones on a matrix

I have a matrix m = zeros(1000, 1000). Within this matrix I want to draw an estimate of the line which passes through 2 points from my matrix. Let's say x = [122 455]; and y = [500 500];.

How can I do this in Matlab? Are there any predefined functions to do this? I am using Matlab 2012b.

Upvotes: 5

Views: 4355

Answers (3)

Eitan T
Eitan T

Reputation: 32930

I'll denote the two endpoints as p1 and p2 because I'm planning to use x and y for something else. I'm also assuming that the first coordinate of p1 and p2 is x and the second is y. So here's a rather simple way to do it:

  1. Obtain the equation of the line y = ax + b. In MATLAB, this can be done by:

    x = p1(1):p2(1)
    dx = p2(1) - p1(1);
    dy = p2(2) - p1(2);
    y = round((x - p1(1)) * dy / dx + p1(2));
    
  2. Convert the values of x and y to indices of elements in the matrix, and set those elements to 1.

    idx = sub2ind(size(m), y, x);
    m(idx) = 1;
    

Example

Here's an example for a small 10-by-10 matrix:

%// This is our initial conditon
m = zeros(10);
p1 = [1, 4];
p2 = [5, 7];

%// Ensure the new x-dimension has the largest displacement
[max_delta, ix] = max(abs(p2 - p1));
iy = length(p1) - ix + 1;

%// Draw a line from p1 to p2 on matrix m
x = p1(ix):p2(ix);
y = round((x - p1(ix)) * (p2(iy) - p1(iy)) / (p2(ix) - p1(ix)) + p1(iy));
m(sub2ind(size(m), y, x)) = 1;
m = shiftdim(m, ix > iy); %// Transpose result if necessary

The result is:

m =
     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     0
     1     0     0     0     0     0     0     0     0     0
     0     1     0     0     0     0     0     0     0     0
     0     0     1     1     0     0     0     0     0     0
     0     0     0     0     1     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     0

Update: I have patched this algorithm to work when dy > dx by treating the dimension with the largest displacement as if it were the x-dimension, and then transposing the result if necessary.

Upvotes: 6

Giezi
Giezi

Reputation: 140

Neither of the provided answers work for displacements in y greater than in x (dy > dx). As pointed out, Bresenham's line algorithm is exactly meant for that.

The matlab file provided here works similarly than the examples provided in the other answers but covers all the use-cases. To relate to the previously provided example, the script can be used like this:

% initial conditions
m = zeros(10);
p1 = [1, 4];
p2 = [5, 10];% note dy > dx
% use file provided on file exchange
[x y] = bresenham(p1(1),p1(2),p2(1),p2(2));
% replace entries in matrix m
m(sub2ind(size(m), y, x)) = 1;

result looks like this:

m = 
    0     0     0     0     0     0     0     0     0     0
    0     0     0     0     0     0     0     0     0     0
    0     0     0     0     0     0     0     0     0     0
    1     0     0     0     0     0     0     0     0     0
    0     1     0     0     0     0     0     0     0     0
    0     1     0     0     0     0     0     0     0     0
    0     0     1     0     0     0     0     0     0     0
    0     0     0     1     0     0     0     0     0     0
    0     0     0     1     0     0     0     0     0     0
    0     0     0     0     1     0     0     0     0     0

Upvotes: 2

jetic
jetic

Reputation: 11

For me (matlab R2013b) following line did not work, when p1(1)>p2(2) (":" can not count backwards):

x = p1(1):p2(1);

E.G.:

1:10

1 2 3 4 5 6 7 8 9 10

10:1

Empty matrix: 1-by-0

But it worked when I used linspac instead:

x = linspace(p1(1), p2(1), abs(p2(1)-p1(1))+1);

Upvotes: 1

Related Questions