Kvasir EnDevenir
Kvasir EnDevenir

Reputation: 927

Bid Rent Curves - Plotting Circles of Projected Radii from Another Dimension

The goal is to reproduce this Bid-Rent graph in R:

Bid Rent Graph

The challenge is to draw the projected circles. So far I got:

My 2D Plot

The 2D part is created by the R code below with the traditional graphic system in base R:

#Distance
X <- seq(0,7,1)

#Bid Rent Curves: Commercial, Industrial, Residential 
com <- -5*X + 10
ind <- -2*X + 7  
res <- -0.75*X + 4

graph <- plot(X, com, type="l", col="green", ylim=c(0,10), xlab="", ylab="", axes=FALSE)
lines(X, ind, col="red")
lines(X, res, col="blue")
abline(v=0, h=0)

segments(1,0, 1,5, lty=2)
segments(2.5,0, 2.5,2, lty=2)

title(main="Bid Rent Curves", sub="Alonso Model", 
      xlab="Distance from CBD", ylab="Rent per m2")

text(2.5,7.5, "Commercial", col="green")
text(3.5,4, "Industrial", col="red")
text(5.5,2, "Residential", col="blue")
  1. (Detail: Why the curves do not respect the ylim = 0 ?)
  2. How make the projection and draw the semi-circles?

It is not exactly a 3D plot. I have looked into plot3D and rgl. I am not sure which packages or strategy to use from here.

Upvotes: 2

Views: 2032

Answers (1)

IRTFM
IRTFM

Reputation: 263451

I'm taking you at your word that you want circles, so you need to push the plot area into the upper right corner:

outHalfCirc <- function(r,colr) {opar=par(xpd=TRUE, new=TRUE) #plot ouside plot area
   polygon(x=seq(r,-r,by=-0.1), 
          y= -sqrt(r^2 - seq(r,-r,by=-0.1)^2) , # solve r^2 = x^2 +y^2 for y
           xlim =c(0,7 ), ylim=c(0,10), col=colr,  # need xlim and ylim to match base plot ranges
           yaxs="i", yaxt="n", xaxs="i") # yaxis off; x and y axes meet at origin
  par(opar)}

Then push plot up and to the right: This will draw a colored half-circles (largest first so they overlap) below the y=0 line.

png()  # send to image file;  not needed for testing
opar <- par(mar=c(15, 15, 2,2) ) # default units are in widths of text-"line".
# the margins start at lower, then clockwise

# run your code

outHalfCirc(5.5, "blue")
outHalfCirc(2.5, "red")
outHalfCirc(1, "green")
dev.off()  # complete image production
par(opar)  # different than the 'opar' inside the function

Voila! Although not really circles because the aspect ratio is not 1. That can be fixed (or you could set the xlim and ylim to be equal. enter image description here

Upvotes: 3

Related Questions