Rumi P.
Rumi P.

Reputation: 1737

Strante interpretation of unit expression in grid

I am making a graphic using grid, and want to draw some text. I ran into an issue when specifying the coordinates of the text.

Specifically, I found out that I can use both a straight unit, such as unit(1, "native") and an expression that evaluates to a unit, such as unit(1, "native") + unit(1, "mm"). But as soon as I have two native units in the expression, the text is plotted not where I expect it, but in a position which might be using npc units.

In the following MWE, I would expect "3" to be printed to the right of the middle (0 in native units), but it is printed far to the left.

 require(grid)

grid.newpage()
vp.data.region <- viewport(x = unit(0.5, "npc"), y = unit(0.5, "npc"), width = unit(0.8, "npc"), height = unit(0.8, "npc"), xscale=c(-1,1), yscale=c(-1,1), name = "data region")
pushViewport(vp.data.region)
grid.xaxis()
grid.yaxis()

grid.text("1", unit(0, "native"),unit(0, "native")) #places the text where it should be
grid.text("2", unit(0, "native") + unit(10, "mm"), unit(0, "native")) # it is possible to use an expression adding mixed units 
grid.text("3", unit(0.6, "native") - unit(0.5, "native") + unit(1, "mm") , unit(0, "native")) # suddenly, it looks like the unit expression is being interpreted as npc?

enter image description here

What causes this problem, and how can I avoid it? Note that it would be very difficult to specify the unit with a single expression, because I start with a point already specified as native units plus some millimeters, and have to position the text a certain distance from it, which I have to again calculate using both native units and millimeters.

Upvotes: 1

Views: 68

Answers (1)

MrFlick
MrFlick

Reputation: 206177

Basically the primary units for the calculation are the npc units. When addition/subtraction occurs, each value is convert to npc units. We can use the convertX function to see how these values pan out. When you use native units, those values are mapped to npc units via the xscale= values. Note that

convertX(unit(0.6, "native"), "npc")
# [1] 0.8npc
convertX(unit(0.5, "native"), "npc")
# [1] 0.75npc
convertX(unit(0.6, "native") - unit(0.5, "native"), "npc")
# [1] 0.0499999999999999npc

compared to

convertX(unit(0.1, "native"), "npc")
# [1] 0.55npc

You can't do atritmetic in native space using npc coordinates. If you need to calculate 0.5 native units to the left of 0.6, then you need to do that arithmatic in native space

convertX(unit(0.6 - 0.5, "native"), "npc")
# [1] 0.55npc

If for some reason you can't do that, then you can make a function that takes a unit and a shift and does the arithmetic on that scale. For example

nativeShift <- function(unit, shift) {
  stopifnot(class(unit)=="unit")
  stopifnot(attr(unit, "unit")=="native")
  stopifnot(is.numeric(shift))
  unit(unclass(unit) + shift, "native")
}

convertX(nativeShift(unit(.6, "native"), -.5), "npc")
# [1] 0.55npc

With your plotting example that would look like

grid.text("3", nativeShift(unit(0.6, "native"), -0.5) + unit(1, "mm") , unit(0, "native"))

Upvotes: 1

Related Questions