I am trying draw an arrow from $\begin{bmatrix}x_1\\y_1\end{bmatrix}$ to $\begin{bmatrix}x_2\\y_2\end{bmatrix}$. Here is my work. If I draw an arrow rotating, then I can draw arrow pointing at any direction. Here is the Java code (full code). This section runs in infinite loop.

    x1 = 200; y1=200;
x2 = 200+150*cos(angle); y2 = 200-150*sin(angle);
a=20;
phi = (float)Math.atan2(y2-y1, x2-x1);

line(x1, y1, x2, y2);
triangle(x2, y2,
x2+a*(float)Math.cos(phi+2.88f),    // 165 deg = 2.88
y2+a*(float)Math.sin(phi+2.88f),
x2+a*(float)Math.cos(phi+3.4f),     // 195 deg = 3.4
y2+a*(float)Math.sin(phi+3.4f)
);

angle+=.01;


But when I run this code, I get the arrow head is flipped for left half quadrants like this. Please help me figure out where I am wrong. Why does the arrow head flip for left half quadrant, i.e. when $x2<x1$?

• Why do you recompute phi when you have angle on hand ? – Yves Daoust Dec 9 '16 at 14:33
• That is intentional. Replacing angle in place of phi works as intended. But this is a test code. I was rotating the line to see if the arrow works in all direction. But in the original project, the arrow is to be drawn from point A to point B. – sigsegv Dec 9 '16 at 14:50

Most likely your atan2() function isn't returning what you expect in that region. You may need to add $\pi$ to the result for those values (i.e., when $x_2<x_1$) to get the branch of $\tan^{-1}$ that you desire.

• Is the math alright? – sigsegv Dec 9 '16 at 14:26
• (Also addressed to @MPW) A general advise : prefer function called atan2 to atan. – Jean Marie Dec 9 '16 at 14:50
• @JeanMarie : Yes, I just mistyped – MPW Dec 9 '16 at 16:25

You don't actually need the angle at all.

If you calculate $$\begin{cases} x_n = \frac{x_2 - x_1}{\sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}} \\ y_n = \frac{y_2 - y_1}{\sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}} \end{cases}$$ then $\left [ \begin{array}{} x_n \\ y_n \end{array} \right ]$ is an unit vector in the direction of your arrow. If we rotate it 90° counterclockwise, we get $\left [ \begin{array}{} y_n \\ -x_n \end{array} \right ]$.

Let's say you want each edge of the arrowhead to be $L$ long, at angle $\varphi$ to the arrow body. If the arrow points to right, with the arrow point at origin, the endpoints of the arrowhead are at $\left [ \begin{array}{} -w \\ \pm h \end{array} \right ]$: $$\begin{cases} w = L \cos(\varphi) \\ h = L \sin(\varphi) \end{cases}$$ Instead of the length $L$ and angle $\varphi$, let's characterize the arrowhead you want in terms of $w$ and $h$.

If $\vec{p}_2$ is the endpoint of the arrow, $\hat{n}$ is the direction unit vector, and $\hat{c}$ is an unit vector perpendicular to $\hat{n}$, then the two endpoints of the arrowhead are $\vec{p}_2 - w \hat{n} \pm h \hat{c}$.

Let's say you calculate $$\begin{array}{} d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2} \\ x_n = \frac{x_2 - x_1}{d} \\ y_n = \frac{y_2 - y_1}{d} \\ x_c = y_n \\ y_c = -x_n \end{array}$$ With these, the two endpoints for the arrowhead are $$\begin{cases} x_3 = x_2 - w x_n - h x_c \\ y_3 = y_2 - w y_n - h y_c \\ \end{cases} \iff \begin{cases} x_3 = x_2 - w x_n - h y_n \\ y_3 = y_2 - w y_n + h x_n \\ \end{cases}$$ and $$\begin{cases} x_4 = x_2 - w x_n + h x_c \\ y_4 = y_2 - w y_n + h y_c \\ \end{cases} \iff \begin{cases} x_4 = x_2 - w x_n + h y_n \\ y_4 = y_2 - w y_n - h x_n \\ \end{cases}$$

The key to succeed in such geometry drawing code is

• to specify the coordinates in a simple reference position (say horizontal),

• to apply a rotation (computed once for all) to all vertices.

E.g. using complex numbers (a matrix/vector formulation is as good):

$$(0+i0)e^{i\phi},(\|p_1p_2\|+i0)e^{i\phi},(\|p_1p_2\|+ae^{i(180\pm15)°})e^{i\phi}.$$

• I swear I didn't see your answer before I submitted mine! We essentially describe the same steps .. :) – Nominal Animal Dec 9 '16 at 14:56
• @NominalAnimal: upvoted yours, for not using trigonometric functions. – Yves Daoust Dec 9 '16 at 15:57