16

Does anyone have an algorithm for drawing an arrow in the middle of a given line. I have searched for google but haven't found any good implementation.

P.S. I really don't mind the language, but it would be great if it was Java, since it is the language I am using for this.

Thanks in advance.

nunos
  • 20,479
  • 50
  • 119
  • 154

2 Answers2

22

Here's a function to draw an arrow with its head at a point p. You would set this to the midpoint of your line. dx and dy are the line direction, which is given by (x1 - x0, y1 - y0). This will give an arrow that is scaled to the line length. Normalize this direction if you want the arrow to always be the same size.

private static void DrawArrow(Graphics g, Pen pen, Point p, float dx, float dy)
{
    const double cos = 0.866;
    const double sin = 0.500;
    PointF end1 = new PointF(
        (float)(p.X + (dx * cos + dy * -sin)),
        (float)(p.Y + (dx * sin + dy * cos)));
    PointF end2 = new PointF(
        (float)(p.X + (dx * cos + dy * sin)),
        (float)(p.Y + (dx * -sin + dy * cos)));
    g.DrawLine(pen, p, end1);
    g.DrawLine(pen, p, end2);
}
bbudge
  • 1,127
  • 6
  • 7
  • 2
    How would one adjust the size of the arrowhead? I like having it based on the length of the line, but the current ratio of arrowhead size to line size is incorrect for my application. – renosis Feb 01 '13 at 18:49
14

Here's a method to add an arrow head to a line. You just have to give it the coordinates of your arrow tip and tail.

private static void drawArrow(int tipX, int tailX, int tipY, int tailY, Graphics2D g)
{
    int arrowLength = 7; //can be adjusted
    int dx = tipX - tailX;
    int dy = tipY - tailY;

    double theta = Math.atan2(dy, dx);

    double rad = Math.toRadians(35); //35 angle, can be adjusted
    double x = tipX - arrowLength * Math.cos(theta + rad);
    double y = tipY - arrowLength * Math.sin(theta + rad);

    double phi2 = Math.toRadians(-35);//-35 angle, can be adjusted
    double x2 = tipX - arrowLength * Math.cos(theta + phi2);
    double y2 = tipY - arrowLength * Math.sin(theta + phi2);

    int[] arrowYs = new int[3];
    arrowYs[0] = tipY;
    arrowYs[1] = (int) y;
    arrowYs[2] = (int) y2;

    int[] arrowXs = new int[3];
    arrowXs[0] = tipX;
    arrowXs[1] = (int) x;
    arrowXs[2] = (int) x2;

    g.fillPolygon(arrowXs, arrowYs, 3);
}
renosis
  • 2,702
  • 2
  • 19
  • 22
Komplot
  • 516
  • 5
  • 7