24
$\begingroup$

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:

Sample picture

$\endgroup$
1
  • $\begingroup$ I tried getting the arrow heads to automatically scale using CurrentValue[ImageSize], but failed. Has anyone else had luck with this approach? $\endgroup$
    – Simon
    Commented Jan 27, 2012 at 4:11

4 Answers 4

19
$\begingroup$

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}]}]];

Table[Graphics[{Arrowheads[{{0.1, 1, arrow}}], 
   Arrow[{{0, 0}, {1, 1}}]}, ImageSize -> s], {s, Range[25, 150, 25]}]

enter image description here

$\endgroup$
5
  • $\begingroup$ 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? $\endgroup$ Commented Jan 27, 2012 at 8:35
  • $\begingroup$ @Sjoerd Mathematica assumes 72 dpi by default, so pixels and points are effectively the same for display in the front end. $\endgroup$
    – Szabolcs
    Commented Jan 27, 2012 at 10:41
  • $\begingroup$ @Brett Wow, that's really clever. Thanks! $\endgroup$
    – Jim Belk
    Commented Jan 27, 2012 at 17:57
  • $\begingroup$ Excellent. I have looked for this functionality before without success. $\endgroup$
    – Mr.Wizard
    Commented Jan 28, 2012 at 4:46
  • $\begingroup$ Am I using this wrong? I get free flying arrow heads (not connected to the line) when I try to use these. Not in the example but in other cases, sometimes upon rotating, for example in: Graphics3D[{Arrowheads[{{0.1, 1, arrow}}], Arrow[#] & /@ {{{0.213, 0.758, 0.857}, {0.217, 0.744, 0.861}}, {{0.217, 0.744, 0.861}, {0.23, 0.691, 0.876}}, {{0.23, 0.69, 0.876}, {0.223, 0.718, 0.869}}}}, ImageSize -> 1000] $\endgroup$
    – Kvothe
    Commented Mar 16, 2021 at 15:21
6
$\begingroup$

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:

Mathematica graphics Mathematica graphics

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[{
  Arrowheads[{{1, 1, 
    Graphics[Text[Graphics[Disk[], PlotRange -> All, ImageSize -> size]]]}}], 
  Arrow[{{0, 0}, {1, 1}}]}]
$\endgroup$
2
  • $\begingroup$ Thanks for the suggestion. Do you know if it's possible to use these size specifications with custom arrowheads? $\endgroup$
    – Jim Belk
    Commented Jan 27, 2012 at 2:08
  • $\begingroup$ @JimBelk I've tried but I failed so I fear that it might not be possible $\endgroup$
    – Heike
    Commented Jan 27, 2012 at 10:29
4
$\begingroup$

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

imageSize = 200;
headSize = 30;
Graphics[{Arrowheads[headSize/imageSize], Arrow[{{0, 0}, {2, 1}}]}, 
  ImageSize -> imageSize]

Mathematica graphics

imageSize = 200;
headSize = 200;
Graphics[{Arrowheads[headSize/imageSize], Arrow[{{0, 0}, {1, 0}}]}, 
  ImageSize -> imageSize,Background->LightYellow]

Mathematica graphics

$\endgroup$
1
  • $\begingroup$ 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. $\endgroup$
    – Jim Belk
    Commented Jan 27, 2012 at 2:09
3
$\begingroup$

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.

$\endgroup$
1
  • $\begingroup$ Thanks -- this is a neat idea. I'll try to work on fixing the rotation problem. $\endgroup$
    – Jim Belk
    Commented Jan 27, 2012 at 2:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.