Что такое дюйм? Установка длины для стрелок

Несколько необъяснимо, параметр length в arrows указан в дюймах (от ?arrows):

length длина краев головки стрелки (в дюймах).

R-источник даже заходит так далеко, что явным образом отмечаю, что это измерение в дюймах в комментарии, подчеркивая, насколько свойственна эта конструкция.

Это означает, что относительный размер стрелок зависит от dev.size(). Непонятно, как перевести дюймы в осевые единицы (которые в любом случае бесконечно более полезны). Вот упрощенная версия:

h = c(1, 2, 3)
xs = barplot(h, space = 0, ylim = c(0, 4))
arrows(xs, h - .5, xs, h + .5,
       length = .5*mean(diff(xs)))

Как это отобразится, будет зависеть от устройства. Например. вот вывод на этом устройстве:

png('test.png', width = 5, height = 5)

введите описание изображения здесь

И здесь он находится на другом:

png('test.png', width = 8, height = 8)

введите описание изображения здесь

Это немного оптическая иллюзия, чтобы рассказать в поле зрения, но стрелки действительно имеют одинаковую ширину на двух графиках. Как я могу контролировать это так, чтобы обе графики (которые отображали одни и те же данные) отображались одинаково? Более конкретно, как я могу убедиться, что стрелки в точности равны .5 единицы измерения по ширине?

Ответы

Ответ 1

Я провел слишком много времени в кроличьей дыре, но здесь. Сначала я запишу немного о своем путешествии, чтобы помочь другим, которые случаются на этом в типах укромных уголков и трещин, чтобы искать, пытаясь подтянуть себя своими бутстрапами.

Я начал искать источник arrows, но безрезультатно, так как он быстро погружается во внутренний код. Поэтому я искал источник R для "C_arrows", чтобы узнать, что происходит; к счастью, не слишком эзотерический, поскольку внутренний код R идет. Кажется, что рабочая лошадка на самом деле GArrow, но это был тупик, так как кажется, что параметр length не является действительно преобразованный там (IIUC это означает, что преобразование в дюймы выполняется для других координат, а length нетронутым). Но я заметил несколько вызовов GConvert, которые были ближе к тому, что я хочу, и надеялись найти какую-то пользовательскую функцию, которая обращается к ним напрямую.

Это заставило меня вернуться к R и просто запустить гамму функций в том же пакете, что и arrows, ища все, что может быть полезно:

ls(envir = as.environment('package:grDevices'))
ls(envir = as.environment('package:graphics'))

Наконец, я нашел три функции в graphics: xinch, yinch и xyinch (все найденные на ?xinch) используются для противоположности моей цели здесь - а именно, они занимают дюймы и конвертировать их в единицы устройства (соответственно в направлениях x, y и x & y). К счастью, эти функции очень просты, например. рабочая лошадь xinch является коэффициентом пересчета:

diff(par("usr")[1L:2])/par("pin")[1L]

Изучая ?par (в течение 1,000,000-го раза), действительно pin и usr являются именно графическим параметром, который нам нужен (pin является новым для меня, usr появляется здесь и там):

pin Текущие размеры участка (ширина, высота) в дюймах.

usr Вектор формы c(x1, x2, y1, y2), дающий экстремумы пользовательских координат области построения.

Следовательно, мы можем преобразовать из единиц измерения в дюймы путем инвертирования этой функции:

xinch_inv = function(dev_unit) {
    dev_unit * par("pin")[1L]/diff(par("usr")[1L:2L])
}

h = c(1, 2, 3)
xs = barplot(h, space = 0, ylim = c(0, 4))
arrows(xs, h - .5, xs, h + .5,
       # just convert plot units to inches
       length = xinch_inv(.5*mean(diff(xs))))

Результат (5x5):

введите описание изображения здесь

И (8x8):

введите описание изображения здесь

Еще одно замечание: length - длина каждой стороны головы стрелки; при использовании length = xinch_inv(.5), code = 3, angle = 90 результаты охватывают сегменты шириной, равными ширине (например, 1).

В случае непредвиденных обстоятельств вас интересует, я упаковал их в пакет как xdev2in и т.д.; GitHub только сейчас.