16

I am trying to make a simple illustration where a circle is plotted inside a square. I have used the rect() function from the grid package and the draw.circle() function from the plotrix package before so I thought this would be simple. But clearly I am missing something.

The following code seems to me like it should work:

require(plotrix)
require(grid)

plot(c(-1, 1), c(-1,1), type = "n")
rect( -.5, -.5, .5, .5) 
draw.circle( 0, 0, .5 )

however I end up with the circle lapping out of the square in the vertical dimension like this:

enter image description here

What in the heck am I missing?

If you have a simpler way of plotting circles and squares, I'd love to know about it. But I'd also like to know why my method above does not work.

Thanks!

JD Long
  • 59,675
  • 58
  • 202
  • 294

4 Answers4

22

You need to specify asp=1

require(plotrix)
require(grid)

plot(c(-1, 1), c(-1,1), type = "n", asp=1)
rect( -.5, -.5, .5, .5) 
draw.circle( 0, 0, .5 )

See also: Drawing non-intersecting circles This one got me too!

Community
  • 1
  • 1
  • well crud. In the back of my mind I thought this had something to do with aspect. I was grabbing the corner of the plot with the mouse and wiggling it around like an r-tard. Thank you for the help! – JD Long Mar 23 '11 at 21:30
  • The Devil's in little things, like `asp`. – Roman Luštrik Mar 24 '11 at 09:12
  • This post saved my life :D, i always assumed that every element in the plot scaled to the plotbox aspect, but the circles did not. Spent two hours trying to figure out why some points/circels didn't fit till i saw this. Thanks!! – Ghost Feb 15 '18 at 20:11
6

Here is a solution in base R:

x <- seq(-2, 2, 0.01)
y <- seq(-2, 2, 0.01)

plot(x,y, xlim = c(-2,2), ylim=c(-2,2), type='n', asp = 1)
curve((  1 * (4 - x^2)^0.5 ), add=TRUE, from=-2 , to =2)
curve(( -1 * (4 - x^2)^0.5 ), add=TRUE, from=-2 , to =2)
rect(-2,-2,2,2)

# to fill circle and square
plot(x,y, xlim = c(-2,2), ylim=c(-2,2), type='n', asp = 1)
x2 <- c(seq(-2, 2, 0.01), seq(-2, 2, 0.01))
y2 <- c((  1 * (4 - x2[1:401]^2)^0.5 ), ( -1 * (4 - x2[402:802]^2)^0.5 ))
rect(-2,-2,2,2, col = 'red')
polygon(x2,y2, col = 'green', border = NA)

enter image description here

EDIT

Just for fun, here is a function:

circle.square.function <- function(radius, x.midpoint, y.midpoint, 
                                   my.x.lim, my.y.lim) {

  x <- seq(x.midpoint-radius, x.midpoint+radius, 0.01)
  y <- seq(y.midpoint-radius, y.midpoint+radius, 0.01)

  plot(x,y, xlim = my.x.lim, ylim = my.y.lim, type='n', asp = 1)
  curve((  1 * (radius^2 - (x - x.midpoint)^2)^0.5 + y.midpoint), add=TRUE, 
                from = (x.midpoint-radius) , to = (x.midpoint+radius))
  curve(( -1 * (radius^2 - (x - x.midpoint)^2)^0.5 + y.midpoint), add=TRUE, 
                from = (x.midpoint-radius) , to = (x.midpoint+radius))
  rect((x.midpoint-radius),(y.midpoint-radius),
       (x.midpoint+radius),(y.midpoint+radius))

}

radius     <-  10          # radius of circle
x.midpoint <- 150          # center of circle on x-axis
y.midpoint <-  50          # center of circle on y-axis
my.x.lim   <- c(-100,200)  # x-axis to plot
my.y.lim   <- c(   0,200)  # y-axis to plot

circle.square.function(radius, x.midpoint, y.midpoint, my.x.lim, my.y.lim)
Mark Miller
  • 12,483
  • 23
  • 78
  • 132
6

You could use the my.symbols function in the TeachingDemos package:

library(TeachingDemos)
my.symbols(1,1,ms.polygon, n=360, add=FALSE)
my.symbols(1,1, cbind( c(-1,-1,1,1,-1), c(-1,1,1,-1,-1) ), add=TRUE)
Greg Snow
  • 48,497
  • 6
  • 83
  • 110
  • Thanks greg! I like that. I'm also glad you pointed out TeachingDemos as I had not looked at that package before. – JD Long Mar 24 '11 at 13:35
1

Another solution for plotting a circle inside a square in R in base R:

plot(c(-1, 1), c(-1,1), type = "n", asp=1)
symbols(x=0, y=0, squares=1, inches=F, add=T)
symbols(x=0, y=0, circles=.5, inches=F, add=T)

And a solution when asp!=1 using plotrix. When asp!=1 circles look like ellipses.

symbols(x=0, y=0, rectangles=matrix(c(1,1),ncol=2), inches=F)
library("plotrix")
draw.ellipse(x=0, y=0, a=.5, b=.5)

Or Mark Miller's base R solution which works also for asp!=1.

GKi
  • 37,245
  • 2
  • 26
  • 48