# How can I specify the arrowhead size in printers points?

Is there any way to specify the size of an arrowhead in printer's points? I'm looking for something that would have similar functionality to AbsolutePointSize, AbsoluteThickness, or AbsoluteDashing, except for Arrowheads.

The best I have come up with is to use something like Arrowheads[1.5/???], where ??? is the width of the Graphics object. However, this doesn't work if I don't know the width of the graphic. I've played around with using Offset or Scaled, but I haven't been able to get them to work for this purpose.

Edit: Thanks for the suggestions so far. A few comments:

1. So far I have been using ImageSize combined with the Arrowheads[1.5/???], but this is annoying for two reasons. First, it makes it impossible to set the height of the graphic using ImageSize -> {{10000},{hmax}}. Second, it means that I have to pass the ImageSize as a parameter through a series of functions that I have written.

2. The sizes Tiny, Small, Medium, and Large are exactly what I'm looking for, except that they don't seem to work with custom arrowhead graphics. In particular, the specification

Arrowheads[{{Medium, 1/2, Graphics[Line[{{-1, 1}, {1, 0}, {-1, -1}}]]}}]

within a Graphics command followed by an Arrow produces the following mysterious error:

Encountered "Graphics[Line[{{-1, 1}, {1, 0}, {-1, -1}}]]" where a Graphics was expected in the value of option Arrowheads.

Edit 2: Problem solved! As Brett suggests below, it works to use offset coordinates:

    MyArrows = Arrowheads[{{0.000001, 0.5,
Graphics[Line[{Offset[{-4.5, 5.4}], Offset[{4.5, 0}], Offset[{-4.5, -5.4}]}]]
}}]


When using this approach, it seems to work better on curved lines to specify a very small arrowhead size such as 0.000001. Here is some sample output using the arrowhead style above:

-
I tried getting the arrow heads to automatically scale using CurrentValue[ImageSize], but failed. Has anyone else had luck with this approach? –  Simon Jan 27 '12 at 4:11

You could create a custom arrowhead using Offset coordinates, which are in terms of printer's points:

arrow = Graphics[
Polygon[{{0, 0}, Offset[{-10, 5}, {0, 0}], Offset[{-5, 0}, {0, 0}],
Offset[{-10, -5}, {0, 0}]}]];

Arrow[{{0, 0}, {1, 1}}]}, ImageSize -> s], {s, Range[25, 150, 25]}]


-
Good one. I didn't know this. It looks like this answered the OP's question, but what would you do if the requirement wasn't printer's points, but pixels? –  Sjoerd C. de Vries Jan 27 '12 at 8:35
@Sjoerd Mathematica assumes 72 dpi by default, so pixels and points are effectively the same for display in the front end. –  Szabolcs Jan 27 '12 at 10:41
@Brett Wow, that's really clever. Thanks! –  Jim Belk Jan 27 '12 at 17:57
Excellent. I have looked for this functionality before without success. –  Mr.Wizard Jan 28 '12 at 4:46

It won't give you full control over the size, but if you specify the size of the arrow heads as either Large, Medium, Small, or Tiny, the absolute size of the arrow heads will be independent of the width of the image. For example, if you evaluate

Graphics[{Arrowheads[ Medium], Arrow[{{0, 0}, {1, 1}}]}]


and rescale the image, the size of the arrow will stay the same:

As Szabolcs mentioned, you could use Text for the arrowhead specification to get a fixed size. You can actually wrap any Graphics inside Text, not just strings, so this would be a way to get an arrowhead with a custom shape and a fixed size independent of scaling. For example, to get an arrowhead with a length of 20 pixels you could do something like

size = 20;
Graphics[{
Graphics[Text[Graphics[Disk[], PlotRange -> All, ImageSize -> size]]]}}],
Arrow[{{0, 0}, {1, 1}}]}]

-
Thanks for the suggestion. Do you know if it's possible to use these size specifications with custom arrowheads? –  Jim Belk Jan 27 '12 at 2:08
@JimBelk I've tried but I failed so I fear that it might not be possible –  Heike Jan 27 '12 at 10:29

You don't know the graphics size? Well set it then at the size you want it to be using ImageSize:

imageSize = 200;
ImageSize -> imageSize]


imageSize = 200;
ImageSize -> imageSize,Background->LightYellow]


-
Thanks -- this has been my strategy so far, but it isn't working for a few reasons that I put in my edit above. The main problem is that I want to use ImageSize -> {{10000},{hmax}} to set the height of the graphic instead of the width. –  Jim Belk Jan 27 '12 at 2:09

To my knowlegde, it is not possible to specify the arrowhead size in printer's points because printer's points can't be used at arbitrary places in Mathematica. (I'd love to be proven wrong!)

But there's a hack you can use:

Graphics[{Arrowheads[{{1, 1,
Graphics@Style[Text["►", {0, 0}, {0, 0.15}], FontSize -> 24]}}],
Arrow[{{0, 0}, {1, 0}}]}]


Here I used normal text for the arrowhead, with a character that looks like a triangle. I needed to correct for the offset by 0.15 vertically to align the arrowhead on the line, but it appears to work robustly (independent of scaling). You can set the size using FontSize.

Update Unfortunately this is not robust to rotation. The head becomes slightly misplaced.

-
Thanks -- this is a neat idea. I'll try to work on fixing the rotation problem. –  Jim Belk Jan 27 '12 at 2:24