# Generating a circle matrix image

#### markovchain

##### New Member
Hi all,
Code:
# Suppose I have a 200 by 200 matrix with zeros entry
a<- matrix(0,nrow=200,ncol=200)

#I want to draw a shaded circle on this matrix using binary 1 and 0.

# Defining a coordinate as my centre of the circle, e.g.(100,100)
y.cent <- 100
x.cent <- 100

#Suppose I want my radius be 10 unit.
r=10

#I do the following,
xx <- x.cent + r*cos( seq(0,2*pi, length.out=360) )
yy <- y.cent + r*sin( seq(0,2*pi, length.out=360) )
a[xx,yy]=1
image(a)
I can't seem to arrive at my desired result. I got a rectangle instead.

Anyone can share your thoughts ?
Any methods will do as long as the shaded circle appears on this simulated grid matrix a.

Last edited by a moderator:

#### bryangoodrich

##### Probably A Mammal
Maybe it has something to do with image? I would test by creating an actual circle (simplified example) and see if it does what you want it to do. Then you can generalize your approach. I'd also create a function to perform the actions like,

Code:
drawImage <- function(mat, center, radius) {
grid <- mat
x.index <- center + radius * cos(seq(0, 2*pi, length = 360))
y.index <- center + radius * sin(seq(0, 2*pi, length = 360))
grid[x.index, y.index] <- 1
image(grid)
}  # end drawImage

drawImage(matrix(0, 200, 200), 100, 10)  # call example
Though, if your matrix is 200 cells across (100 from radius), aren't your indexes meaningless when indicating 360 different values? Granted, the index has to be a whole number, so many of them will overlap, no doubt. I wonder if your algorithm is making enough "curving" to make a "smoother" transition around the edges of the "circle" you want to make.

#### bryangoodrich

##### Probably A Mammal
Well, your algorithm produces a circle.

Code:
drawCircle <- function(center, radius) {
j <- center + radius * cos(seq(0, 10*pi, length = 360))
k <- center + radius * sin(seq(0, 10*pi, length = 360))
plot(NULL, type = "n", xlab = "", ylab = "", xlim = range(j, k), ylim = range(j, k))
matlines(j, k)
}
drawCircle(100, 10)
Therefore, my guess is that it has to do with either the way things are indexed in the grid or with the way image interprets your grid. My guess is the latter. Maybe image isn't the right function, or you need to play with its parameters. I've never even seen the function before today, so look into it.

#### Dason

No. It has everything to do with this line:
Code:
a[xx, yy] <- 1
R takes the cartesian product of the elements in xx and yy and uses every index in there.

Just like how if you say something like:
Code:
a <- matrix(1:4, 2, 2)
a[1:2, 1:2]
You get all of "a" back (not just the elements a[1,1], a[2,2]).

Doing a simple loop fixes the problem:
Code:
for(i in 1:length(xx)){
a[xx[i], yy[i]] <- 1
}

#### bryangoodrich

##### Probably A Mammal
Oh snap, that does work:

Code:
drawImage <- function(mat, center, radius) {
grid <- mat
x.index <- center + radius * cos(seq(0, 2*pi, length = 360))
y.index <- center + radius * sin(seq(0, 2*pi, length = 360))

for (i in seq(x.index))
grid[x.index[i], y.index[i]] <- 1

image(grid)
}  # end drawImage

drawImage(matrix(0, 200, 200), 100, 10)  # call example
But what if we wanted to fill the circle?

#### Dason

At that point I'd probably just write a loop to figure out the edge of the circle in terms of the x axis and then loop through and fill in the appropriate y values with a 1.

Yeah that was very non specific but essentially it's easy to figure out the edge of the circle (center - radius, center + radius). For a given x value it's easy to figure out which y values fall inside the circle. Fill all of those pairs in with a 1.

#### markovchain

##### New Member
Thanks all!

Doing a simple loop fixes the problem:
Code:
for(i in 1:length(xx)){
a[xx[i], yy[i]] <- 1
}
Like what bryangoodrich has stated. Now I gonna figure out how to input 1 into the circle now.

#### bryangoodrich

##### Probably A Mammal
Well, Dason aptly described the logic to filling in the circle. What I wonder is if there's a vectorized way to do it--say, use the boundaries at a given x/y value and extract the appropriate vector. It might require a loop through one dimension with a condition for checking what vector subset to extract from the cross-dimension; repeat for each point along the segment of the dimension.

#### TheEcologist

##### Global Moderator
if there's a vectorized way to do it--say
What do you mean?

Something like this?

Code:
# Circle outline only
DrawMeACircle= function(x, y, r, col) {
lines( (cos(seq(0, 2*pi, pi/180)) * r) + x, (sin(seq(0, 2*pi, pi/180)) *
r) + y , col=col )
}

# blank canvas
plot(0,0,col="white",xlim=c(-40,40),ylim=c(-40,40))
# Bob Ross with R: making a happy circle
DrawMeACircle(0,0,20,col='red')

# Filled circle
DrawMeAFilledCircle= function(x, y, r, col) {
polygon( (cos(seq(0, 2*pi, pi/180)) * r) + x, (sin(seq(0, 2*pi, pi/180)) *
r) + y , col=col )
}

# blank canvas
plot(0,0,col="white",xlim=c(-40,40),ylim=c(-40,40))
# Bob Ross with R: making a happy circle
DrawMeAFilledCircle(0,0,20,col='red')

#### TheEcologist

##### Global Moderator
I can't seem to arrive at my desired result. I got a rectangle instead.

Anyone can share your thoughts ?
Any methods will do as long as the shaded circle appears on this simulated grid matrix a.
Why dont you just do this?

Code:
x=1:200;y=x;x.cent=100;y.cent=100;r=10
A=outer(x,y,function(x,y) sqrt(((x-x.cent)^2)+((y-y.cent)^2)))
image(x,y,A<r)
Credit for the formula goes to our good friend Euclid of Alexandria (+- 300 BC)

#### markovchain

##### New Member
Code:
x=1:200;y=x;x.cent=100;y.cent=100;r=10
A=outer(x,y,function(x,y) sqrt(((x-x.cent)^2)+((y-y.cent)^2)))
image(x,y,A<r)

My priority of doing this is to set a matrix of 1 and 0 with 1 falling in the circle.

I guess this will help me

Code:
circle<-ifelse((A<r),1,0)

Last edited:

#### TheEcologist

##### Global Moderator
Sure the data is distances to the circle center and this is stored in object A. You can change this to 'ones and zeros' by doing this;

Code:
as.numeric(A<r)
#where r is an arbitrary circle radius
Then just store it as an object.