Получите местоположения линии границы (mgp) в пользовательских координатах

Я пытаюсь сделать какую-то нестандартную маркировку сюжета и хотел бы преобразовать line параметр в mtext а также axis к пользовательским координатам.

Другими словами, я хотел бы преобразовать значения в par()$mgp к пользовательским координатам.

Это иллюстрирует проблему:

setup_plot <- function() {
  par(mar = c(2, 10, 2, 2), oma = rep(2, 4))
  plot.new()
  plot.window(xlim = c(0, 1), ylim = c(0, 1))
  box(which = "plot", lwd = 2, col = "gray40")
  box(which = "figure", lwd = 2, col = "darkred")
  box(which = "outer", lwd = 2, col = "darkgreen")
  text(x = 0.5, y = 0.5, 
       labels = "Plot Region", 
       col = "gray40", font = 2)
  mtext(side = 3, text = "Figure region", line = 0.5, col = "darkred", font = 2)
  mtext(side = 3, text = "Device region", line = 2.5, col = "darkgreen", font = 2)
  for (i in 0:9) {
    mtext(side = 2, col = "darkred", text = paste0("Line", i), line = i)
  }
}

Я пробовал два разных подхода.

## Try one approach where a line is the string height of "M"
setup_plot()
xline = strheight("M", units = "user")
abline(v =  par()$usr[1] - 0:9*xline, 
       xpd = TRUE, lty = "dashed", col = "gray40")

Строки не совпадают с текстом

## Try a second approach defining a line using par()$mai & par()$mar
setup_plot()
xline = abs(grconvertX(unique(par()$mai/par()$mar), "inches", "user"))
abline(v =  par()$usr[1] - 0:9*xline, 
       xpd = TRUE, lty = "dashed", col = "gray40")

Рисуется только одна линия

Как вы получаете позиции линии в пользовательских координатах?

ПРИМЕЧАНИЕ: цифры здесь 4 на 6 дюймов. Изменение размера вывода изменяет способ рисования линий, что также не имеет смысла для меня.

1 ответ

Решение

Следующее должно сделать трюк:

setup_plot()
abline(v=par('usr')[1] - (0:9) * 
         diff(grconvertX(0:1, 'inches', 'user')) * 
         par('cin')[2] * par('cex') * par('lheight'), 
       xpd=TRUE, lty=2)

margin_lines

par('cin')[2] * par('cex') * par('lheight') возвращает текущую высоту строки в дюймах, которую мы конвертируем в пользовательские координаты путем умножения на diff(grconvertX(0:1, 'inches', 'user'))длина дюйма в пользовательских координатах (в данном случае по горизонтали - если нас интересует вертикальная высота линии в пользовательских координатах, мы бы использовали diff(grconvertY(0:1, 'inches', 'user'))).

Для удобства это можно обернуть в функцию следующим образом:

line2user <- function(line, side) {
  lh <- par('cin')[2] * par('cex') * par('lheight')
  x_off <- diff(grconvertX(0:1, 'inches', 'user'))
  y_off <- diff(grconvertY(0:1, 'inches', 'user'))
  switch(side,
         `1` = par('usr')[3] - line * y_off * lh,
         `2` = par('usr')[1] - line * x_off * lh,
         `3` = par('usr')[4] + line * y_off * lh,
         `4` = par('usr')[2] + line * x_off * lh,
         stop("side must be 1, 2, 3, or 4", call.=FALSE))
}

setup_plot()
abline(v=line2user(line=0:9, side=2), xpd=TRUE, lty=2)

РЕДАКТИРОВАТЬ: обновленная версия функции, которая работает с зарегистрированными осями, доступна здесь.

Другие вопросы по тегам