Reputation: 1925
So we're reading a matrix and saving it in an array sequentially. We read the matrix from a starting [x,y] point which is provided. Here's an example of some code I wrote to get the values of [x-1,y] [x+1,y] [x,y-1] [x,y+1], which is a cross.
for(i = 0, n = -1, m = 0, array_pos = 0; i < 4; i++, n++, array_pos++) {
if(x+n < filter_matrix.src.columns && x+n >= 0 )
if(y+m < filter_matrix.src.lines && y+m >= 0){
for(k = 0; k < numpixels; k++) {
arrayToProcess[array_pos].rgb[h] = filter_matrix.src.points[x+n][y+m].rgb[h];
}
}
m = n;
m++;
}
(The if's are meant to avoid reading null positions, since it's an image we're reading the origin pixel can be located in a corner. Not relevant to the issue here.)
Now is there a similar generic algorithm which can read ALL the elements around as a square (not just a cross) based on a single parameter, which is the size of the square's side squared? If it helps, the only values we're dealing with are 9, 25 and 49 (a 3x3 5x5 and 7x7 square).
Upvotes: 0
Views: 617
Reputation: 753785
Given:
static inline int min(int x, int y) { return (x < y) ? x : y; }
static inline int max(int x, int y) { return (x > y) ? x : y; }
or equivalent macros, and given that:
2 * size + 1
) (so size
is 1, 2, or 3 for the 3x3, 5x5, and 7x7 cases; or if you prefer to have sq_side = one of 3, 5, 7
, then size = sq_side / 2
),x - size
can produce a negative value; if they're unsigned, you will get the wrong result using the expressions shown),then you can ensure that you are within bounds by setting:
x_lo = max(x - size, 0);
x_hi = min(x + size, x_max);
y_lo = max(y - size, 0);
y_hi = min(y + size, y_max);
for (x_pos = x_lo; x_pos <= x_hi; x_pos++)
{
for (y_pos = y_lo; y_pos <= y_hi; y_pos++)
{
// Process the data at array[x_pos][y_pos]
}
}
Basically, the initial assignments determine the bounds of the the array from [x-size][y-size]
to [x+size][y+size]
, but bounded by 0 on the low side and the maximum sizes on the high end. Then scan over the relevant rectangular (usually square) sub-section of the matrix. Note that this determines the valid ranges once, outside the loops, rather than repeatedly within the loops.
If the integer types are signed, you have ensure you never try to create a negative number during subtraction. The expressions could be rewritten as:
x_lo = x - min(x, size);
x_hi = min(x + size, x_max);
y_lo = y - min(y, size);
y_hi = min(y + size, y_max);
which isn't as symmetric but only uses the min
function.
Upvotes: 2
Reputation: 6246
Here is a generalized code for reading the square centered at (x,y) of size n
int startx = x-n/2;
int starty = y-n/2;
for(int u=0;u<n;u++) {
for(int v=0;v<n;v++) {
int i = startx + u;
int j = starty + v;
if(i>=0 && j>=0 && i<N && j<M) {
printf(Matrix[i][j]);
}
}
}
Explanation: Start from top left value which is (x - n/2, y-n/2)
now consider that you are read a normal square matrix from where i
and j
are indices of Matrix[i][j]
. So we just added startx & starty to shift the matrix at (0,0)
to (x-n/2,y-n/2)
.
Upvotes: 2
Reputation: 1
make use of this:
while(int i<=0 && int j<=0)
for (i = x-1; i <= x+1; i++) {
for (j = y-1; j <= y+1; j++) {
int elem = square[i][j];
}
}
}
Upvotes: 0
Reputation: 2876
Given the coordinates (x,y)
, you first need to find the surrounding elements. You can do that with a double for loop, like this:
for (int i = x-1; i <= x+1; i++) {
for (int j = y-1; j <= y+1; j++) {
int elem = square[i][j];
}
}
Now you just need to do a bit of work to make sure that 0 <= i,j < n
, where n
is the length of a side;
Upvotes: 1
Reputation: 1
I don't know whether the (X,Y) in your code is the center of the square. I assume it is.
If the side of the square is odd. generate the coordinates of the points on the square. I assume the center is (0,0). Then the points on the squares are (-side/2, [-side/2,side/2 - 1]); ([-side/2 + 1,side/2], -side/2); (side/2,[side/2 - 1,-side/2]);([side/2 - 1, side/2],-side/2);
side is the length of the square
Upvotes: 0