2
$\begingroup$

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.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$?

$\endgroup$
2
  • 1
    $\begingroup$ Why do you recompute phi when you have angle on hand ? $\endgroup$ – Yves Daoust Dec 9 '16 at 14:33
  • $\begingroup$ 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. $\endgroup$ – sigsegv Dec 9 '16 at 14:50
0
$\begingroup$

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.

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

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}$$

$\endgroup$
1
$\begingroup$

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}.$$

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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