title: How to make segments that preserve angles in different aspect ratios in ggplot2?
body: <p>I want to plot wind magnitude and direction as vectors. The problem is that the usual geoms recommended for vectors (<code>geom_segment()</code> or <code>geom_spoke()</code>) change angle if the axes have different ratios or are of different type (for example, x = date, y = height). My current workaround is using <code>geom_text(label = "→", ...)</code> per <a href="https://stackoverflow.com/questions/18103823/ggplot2-wind-time-series-with-arrows-vectors">this answer</a>.</p>
  
  <p>The problem is that this solution is slow and the size of the text based arrow is not well mapped to the magnitude of the wind. Also, importantly, for some reason it fails when exporting to PDF. I want a solution based on proper segments. Working within the <code>geom</code> call, I know I can work with the native coordinates of the plot to draw proper segments even if one axis is of different class than the other. My current attempt is this:</p>
  
  <p>
  <br/></p>
  
  <pre class="lang-r prettyprint-override"><code>library(ggplot2)
  
  geom_arrow2 &lt;- function(mapping = NULL, data = NULL, stat = "identity",
                                position = "identity", na.rm = FALSE, show.legend = NA,
                                inherit.aes = TRUE, scale = 1,...) {
      layer(geom = GeomArrow2,
            mapping = mapping,
            data = data,
            stat = stat,
            position = position,
            show.legend = show.legend,
            inherit.aes = inherit.aes,
            params = list(na.rm = na.rm, scale = scale, ...)
      )
  }
  GeomArrow2 &lt;- ggplot2::ggproto("GeomArrow2", Geom,
     required_aes = c("x", "y", "mag", "angle"),
     default_aes = ggplot2::aes(color = "black", scale = 1),
     draw_key = draw_key_polygon,
     draw_panel = function(data, panel_scales, coord, scale = 1) {
         coords &lt;- coord$transform(data, panel_scales)
  
         Mmag &lt;- max(coords$mag)
         coords$mag &lt;- with(coords, mag/Mmag*coords$scale)
  
         coords$dx &lt;- with(coords, cos(angle)*mag)*scale
         coords$dy &lt;- with(coords, sin(angle)*mag)*scale
  
         pol &lt;- grid::polylineGrob(x = c(coords$x,
                                          coords$x + coords$dx),
                                    y = c(coords$y,
                                          coords$y + coords$dy),
                                    default.units = "npc",
                                    arrow = grid::arrow(angle = 15, length = unit(0.5, "lines")),
                                    gp = grid::gpar(col = coords$colour),
                                    id = rep(seq(nrow(coords)), 2))
         pol
  
     })
  
  
  field &lt;- expand.grid(x = seq.Date(as.Date("2017-01-01"), as.Date("2017-01-31"), "2 days"),
                       y = 1:10)
  field$u &lt;- rnorm(nrow(field))
  field$v &lt;- rnorm(nrow(field))
  field$V &lt;- with(field, sqrt(u^2 + v^2))
  field$dir &lt;- with(field, atan2(v, u))*180/pi
  
  ggplot(field, aes(x, y)) +
      geom_point() +
      geom_arrow2(aes(mag = V, angle = dir), scale = 0.5)
  </code></pre>
  
  <p><img src="https://i.imgur.com/OveHAVW.png" alt=""></p>
  
  <p>But now the problem is back and different aspect ratios distort the actual angle of the arrows. I've been trying different things and found out that using <code>"snpc"</code> units instead of <code>"npc"</code> preserves angles, but the position is shifted, so that's no good. </p>
  
  <p><img src="https://i.imgur.com/WJenSNn.png" alt=""></p>
  
  <p>If I could get information of the aspect ratio of the plot inside the geom call that would be great.</p>
  
  <p>Any help will be very appreciated. </p>