|


Drawing an ArrowDate: 05/11/2000 at 03:38:13 From: Johan Sageryd Subject: Drawing an Arrow Hi. I've come across a math problem while building my pascal program. I need to draw an arrow relative to a user-drawn baseline. For example, the user draws a line from point (X1,Y1) to point (X2,Y2). At point (X2,Y2) I want an arrowhead to be drawn. The question I have is; what are the coordinates of the edges of the arrow? I want the angle between the baseline and arrow side to be 30 degrees, and the length of the arrow side 15 pixels. I would really appreciate it if you could give me a hand on this. Thanks! Sincerely, - Johan Sageryd
Date: 05/11/2000 at 12:13:14
From: Doctor Peterson
Subject: Re: Drawing an Arrow
Hi, Johan.
I'll assume you understand a bit of trigonometry, in order to follow
this. If the line is at an angle A degrees to the x-axis, the two
sides of the arrowhead should be at angles A+30 and A-30 degrees. The
slope is the tangent of this angle, so the slope of the two sides will
be:
tan(A) + tan(30)
m1 = tan(A+30) = ------------------
1 - tan(A) tan(30)
tan(A) - tan(30)
m2 = tan(A-30) = ------------------
1 + tan(A) tan(30)
You can easily find tan(A), which is the slope of the original line;
tan(30) is 1/sqrt(3). Using these two slopes, you can draw the lines
you need. Let me know if you need more help.
- Doctor Peterson, The Math Forum
http://mathforum.org/dr.math/
Date: 05/11/2000 at 13:57:17 From: Johan Sageryd Subject: Re: Drawing an Arrow Thanks for the quick answer! Maybe I didn't express it clear enough to be understandable, but what I really need is a formula for calculating the coordinates of the two outer points of the arrowhead. We can call them (X3,Y3) and (X4,Y4). Thanks again! - Johan Sageryd Date: 05/11/2000 at 14:53:25 From: Doctor Peterson Subject: Re: Drawing an Arrow Hi, Johan. I understand what you are asking for; but we like to give students a chance to do as much of the work as they can, so we prefer to give help rather than complete answers. You'll be able to use a formula better if you understand where it comes from, so you can make adjustments for yourself if you find a need to do so. I did the first hard part, the trigonometry, for you. The next step is either to use vectors, if you have learned about them, to find the point a given distance in the direction of slope m1 from your end point; or if you can't do that, to write the equation of the line with that slope and solve an equation to find the point. One of us has to do that work (I don't know of a standard off-the-shelf equation for this), and it's best if you can do it. If you still want more help, just write back and tell me what you have done and where you have trouble, so I can help further. - Doctor Peterson, The Math Forum http://mathforum.org/dr.math/
Date: 05/12/2000 at 17:03:22
From: Doctor Peterson
Subject: Re: Drawing an Arrow
Hi, Johan.
Now that I've given you a chance to work this problem out, I want to
let you know what I came up with, because I recognize it may be
difficult for you to do on your own. It's an interesting problem.
We have a line segment from A(x0,y0) to B(x1,y1), and want to draw
segments BC and BD of length d, at a t degree angle on either side of
the segment at (x1,y1):
B
d ---o
------ //
D o-- t / /
/ t/ d
/ /
/ /
/ o
/ C
/
slope m /
/
/
/
/ s
o - - - - - - -
A
As before, we can pre-calculate a few numbers to make things easier:
m = (y1-y0)/(x1-x0) = tan(s)
n = tan(t)
The vector from B to C will have a slope that is the tangent of s+t.
(For the vector BD, we can replace t with -t everywhere.) This makes
its slope:
tan(s) + tan(t) m + n
----------------- = ------
1 - tan(s) tan(t) 1 - mn
One possible vector in this direction will be (1 - mn, m + n). We can
make a unit vector by dividing this by its length, which is:
sqrt((1 - mn)^2 + (m + n)^2)
= sqrt(1 + m^2n^2 + m^2 + n^2)
= sqrt((1 + m^2)(1 + n^2))
Adding d times this unit vector to the position vector of point B, we
find:
1 - mn m + n
C = (x1 + ------------------------ d, y1 + ------------------------ d)
sqrt((1 + m^2)(1 + n^2)) sqrt((1 + m^2)(1 + n^2))
I've left out one detail, which is that there are actually TWO points
that are d units away from B on the line with the correct slope; how
can we ensure that this segment is drawn toward A rather than away
from it? If we go back to vector (1 - mn, m + n), we can tell whether
it points the right way by taking the scalar (dot) product with the
vector (x1 - x0, y1 - y0), which we want to be negative, so that it
will be pointing backward:
(1 - mn, m + n) dot (x1-x0, y1-y0)
= (1 - mn)(x1 - x0) + (m + n)(y1 - y0)
= (1 - mn)(x1 - x0) + (m + n)m(x1 - x0)
= [(1 - mn) + (m + n)m] (x1 - x0)
= (1 + m^2)(x1 - x0)
Since 1 + m^2 is always positive, this will have the same sign as
x1 - x0; so if x1 > x0, we want to replace d with -d to make it
negative.
So there's your formula:
(1 - mn)
x = x1 + ------------------------ d
sqrt((1 + m^2)(1 + n^2))
(m + n)
y = y1 + ------------------------ d
sqrt((1 + m^2)(1 + n^2))
Again, if x1 > x0, replace d with -d, and for point D, replace n with
-n. In your case, t = 30 degrees and n = 1/sqrt(3).
Please let me know if there are any parts of this you don't follow; I
don't know whether you know anything about vectors, but they are very
useful for any kind of graphic programming.
- Doctor Peterson, The Math Forum
http://mathforum.org/dr.math/
Date: 05/14/2000 at 09:57:09 From: Johan Sageryd Subject: Re: Drawing an Arrow Hi! Thanks VERY much for the explanation! I have implemented your formula into a program and I have found an error, or what seems like an error to me anyway: the angle, t, doesn't seem to be an angle, rather some sort of... um... well something else. Thanks! - Johan Sageryd
Date: 05/14/2000 at 22:51:35
From: Doctor Peterson
Subject: Re: Drawing an Arrow
Hi, Johan.
Before I sent you the formula, I implemented it (not as a program, but
using Geometer's Sketchpad, which let me plot the point and see how it
worked for different lines), and it worked for me in that form. I was
playing with the formula yesterday and made an improved version. My
concern was that what I gave you did not work if m is undefined (or
too large to compute); so I wrote m as (y1-y0)/(x1-x0) and simplified
the expression. It turns out that since I multiplied by x1-x0, I also
eliminated the problem with the direction of the arrowhead if x1 < x0.
Here's the improved formula:
(x1-x0) - n(y1-y0) d
x = x1 - ------------------ * ---
sqrt(1 + n^2) l
(y1-y0) + n(x1-x0) d
y = y1 - ------------------ * ---
sqrt(1 + n^2) l
where d is the length of the arrowhead line, n is the tangent of t,
and l is the length of the line AB = sqrt((x1-x0)^2 + (y1-y0)^2). For
the other side of the arrowhead, the sign of n is reversed, so the
+ and - are swapped. This form is much more symmetrical, isn't it?
Perhaps you can show me the source of your program (or at least the
relevant section) so I can see how you are using t. It should work,
but there may be a subtlety to its use in your program that I didn't
anticipate. I assume you are taking the tangent of the angle expressed
in radians, not degrees.
- Doctor Peterson, The Math Forum
http://mathforum.org/dr.math/
Date: 05/15/2000 at 01:55:52 From: Johan Sageryd Subject: Re: Drawing an Arrow Hi! I think what you're saying might be the problem, the program uses radians instead of degrees. Is there someway to convert values between these two? Anyway, thanks for the new formula, I will try it A.S.A.P. - Johan Sageyrd
Date: 05/15/2000 at 09:06:51
From: Doctor Peterson
Subject: Re: Drawing an Arrow
Hi, Johan.
Yes, if t is in degrees you will want to use
n = tan(t*pi/180)
to convert it to radians first. If you don't do this, large angles in
degrees will probably seem to give random results.
It occurred to me last night that, in trying to guide you to a simple
solution initially, without knowing whether you've had any
trigonometry or vectors, I blinded myself to the standard way to solve
this, which uses matrices. You can simply rotate the vector BA by t
degrees and scale it to the right length, and you will get exactly the
final formula I gave you, as long as t is less than 90 degrees. Here's
a version that should be completely general:
x = x1 - [(x1-x0)cos(t) - (y1-y0)sin(t)]*d/l
y = y1 - [(y1-y0)cos(t) + (x1-x0)sin(t)]*d/l
It's definitely worth learning about matrices if you are going to do
much with graphics; I've taught my 15-year-old son the basics.
- Doctor Peterson, The Math Forum
http://mathforum.org/dr.math/
Date: 05/15/2000 at 12:46:12
From: Johan Sageryd
Subject: Re: Drawing an Arrow
Okay, thanks. I've written a new version now with the degrees problem
fixed.
- Johan
|
Search the Dr. Math Library: |
[Privacy Policy] [Terms of Use]


Ask Dr. MathTM
© 1994-2013 The Math Forum
http://mathforum.org/dr.math/