Can I assign values to an array in a diagonal direction from a reference point on that array?
4 次查看(过去 30 天)
显示 更早的评论
If I have an array of size NxN,called X, and I count through it using an (i,j) for loop like this
for i = 1:N
for j = 1:N
and im looking for a value in it like this
if(X(i,j) == 1)
I want to start where I find a 1 and change the diagonal lines around it to an 8. So far ive tried code similar to this and many things like it but it doesnt seem to work how I envision it
for i = 1:N
for j = 1:N
if(X(i,j) == 1)
X(i+1,j+1) = 8;
X(i-1,j-1) = 8;
X(i+1,j-1) = 8;
X(i-1,j+1) = 8;
end
end
end
I want the outcome to be something like
0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
this turns into this
8 0 0 0 8
0 8 0 8 0
0 0 1 0 0
0 8 0 8 0
8 0 0 0 8
0 个评论
采纳的回答
Stephen23
2017-9-17
编辑:Stephen23
2017-9-17
Perhaps:
X = [...
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 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 0 0 0 0
];
[R,C] = find(X);
for k = 1:numel(R)
r = R(k);
c = C(k);
X([r-1,r+1],[c-1,c+1]) = 8;
X([r-2,r+2],[c-2,c+2]) = 8;
end
giving:
>> X
X =
8 0 0 0 8 0
0 8 0 8 0 0
0 0 1 0 0 0
0 8 0 8 0 0
8 0 0 0 8 0
0 8 0 0 0 8
0 0 8 0 8 0
0 0 0 1 0 0
0 0 8 0 8 0
0 8 0 0 0 8
8 个评论
Stephen23
2017-9-18
编辑:Stephen23
2017-9-19
Given that you want to extend the eights all the way to the edge one easy strategy is to use linear indices, because it is easy to construct an vector of linear indices from the selected starting point: the trick is to remember that the step size is either N+1 for the diagonals, and N-1 for the antidiagonals. The end points are limited by 1 and end, and also by some mod-based limits to prevent the lines of eights wrapping around the top and bottom:
% Create a matrix:
N = 10;
X = zeros(N,N);
X([7,12,30,45,81,96]) = 1
% Fill with eights:
V = find(X);
for k = V(:).'
stp = N+1;
diagLo = k-stp*mod(k-1,N);
diagHi = k+stp*mod(N-k,N);
X(k-stp:-stp:max(diagLo,001)) = 8;
X(k+stp:+stp:min(diagHi,end)) = 8;
stp = N-1;
antiLo = k-stp*mod(N-k,N);
antiHi = k+stp*mod(k-1,N);
X(k-stp:-stp:max(antiLo,001)) = 8;
X(k+stp:+stp:min(antiHi,end)) = 8;
end
X
Giving:
X = % original matrix
0 0 0 0 0 0 0 0 1 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 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1
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 1 0 0 0 0 0 0 0
X = % filled matrix
8 0 8 0 8 0 8 0 8 0
0 8 0 0 0 8 0 8 0 8
8 0 8 0 8 0 8 0 0 8
0 0 0 8 0 8 0 8 8 0
0 0 8 0 8 0 0 8 8 0
0 8 0 8 0 8 8 0 0 1
1 0 8 0 0 8 8 0 8 0
8 8 0 0 8 0 0 8 0 0
8 8 8 8 0 0 8 0 8 0
0 0 1 8 0 8 0 0 0 8
Note that while it might look at bit imposing, actually this this code is quite efficient and should scale well to larger matrix sizes: it does not create any large intermediate matrices (the four limit values are scalars), does not require expanding or enlarging the matrix, uses efficient linear indexing, and it iterates just once for each non-zero element in the input matrix.
更多回答(4 个)
Guillaume
2017-9-18
Another option, with no issues near the edges. Requires the image processing toolbox:
se = min(1, eye(5) + fliplr(eye(5))); %The cross. Can be any pattern of 0s and 1s.
newX = 8 * imdilate(X, se); %replace each 1 by the se pattern and multiply by 8
newX(logical(X)) = 1; %set original 1s back to 1
0 个评论
Andrei Bobrov
2017-9-18
编辑:Andrei Bobrov
2017-9-19
s = size(X);
[~,d(:,2)] = spdiags(rot90(X));
[~,d(:,1)] = spdiags(X);
out = full(spdiags(ones(s(1),size(d,1)),d(:,1),s(1),s(2)) +...
rot90(spdiags(ones(s(2),size(d,1)),d(:,2),s(2),s(1)),-1));
k = max(out(:));
out(out < k & out > 0) = 8;
out(out == k) = 1;
or
[m,n] = size(X);
ii = find(X);
a = toeplitz(0:-1:1-m,0:n-1);
b = hankel(1:m,m + (0:n-1));
aa = a(ii);
bb = b(ii);
out = ((sum(reshape(aa,1,1,[]) == a,3) + ...
sum(reshape(bb,1,1,[]) == b,3)) > 0) + 7*X;
0 个评论
James Tursa
2017-9-18
Yet another method:
[M,N] = size(X);
n = min(M,N);
XXX = repmat(X,3,3); % work with a big matrix so we don't have to worry about edge cases
[R,C] = find(X);
for k = 1:numel(R) % replace the diagonal spots with 8's in the big matrix
r = R(k) + M;
c = C(k) + N;
x = sub2ind(size(XXX),r+[-n:-1,1:n],c+[-n:-1,1:n]); % upper left to lower right diagonal
XXX(x) = 8;
x = sub2ind(size(XXX),r+[n:-1:1,-1:-1:-n],c+[-n:-1,1:n]); % lower left to upper right diagonal
XXX(x) = 8;
end
X = XXX(M+1:M+M,N+1:N+N); % extract the "original" matrix from the middle
Works for any rectangular matrix X, and overwrites all 1's that are on a diagonal of other 1's with 8's.
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Operating on Diagonal Matrices 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!