····@ATHENA.MIT.EDU asked me to summarize:
> ) Given the terminal points of a line (x1,y1) and (x2,y2) is there an
> ) easy (integer if possible) way to figure out the coordinates of a
> ) triangle that forms the point of an arrow? (Well, I've already
> ) figured out one of them, (x2,y2) :-) What if the arrow is horizontal
> ) or vertical, i.e. dx = 0 or dy = 0, this could hurt for divisions?
> No. Only if BOTH are zero.
> ) The arrowhead need not be perfect, but more pointed than my sketch
> ) suggests, maybe about 15 degrees on each side of the line.
> )
> ) (x3,y3)__ (x2,y2)
> ) /|
> ) / (x4,y4) x3 = ? y3 = ?
> ) / x4 = ? y4 = ?
> ) /
> ) /
> ) (x1,y1)
> To do this exactly not only calls for real arithmetic, but also for
> computing a square root, which may be expensive/complicated. At the end I
> give some approximation methods that may be useful. To obtain integer
> arithmetic, you must do some scaling yourself (e.g., multiply everything by
> 10000, and divide the final result again).
> The exact procedure:
> Input: two points (x1,y1) and (x2,y2), the angle phi by which the
> "whiskers" must stand off the "shaft" (e.g., 15 degrees), and the desired
> length L of the whiskers.
> 1. Compute the distance between (x1,y1) and (x2,y2), which is
> sqrt((x1-x2)^2 + (y1-y2)^2). Call it R.
> 2. Set xx = (L/R)*(x1-x2), yy = (L/R)*(y1-y2).
> 3. Let c stand for cos(phi), and s for sin(phi). Then
> (x3,y3) = (x2 + c*xx + s*yy, y2 - s*xx + c*yy);
> (x4,y4) = (x2 + c*xx - s*yy, y2 + s*xx + c*yy).
> Approximation for computing the length of a line segment:
> Take the absolute values of the differences of the x-values and of the y-
> values. Call the smaller A and the larger B. Compute 0.3978*A + 0.9604*B.
> The result is off by less than 4% from sqrt(A^2 + B^2).
> Example: A = 5 and B = 12 gives the result 13.5138, while by Pythagoras
> the exact length is 13. Error: 3.95%.
> Approximations for cos(phi) and sin(phi):
> Let phi be given in degrees (i.e, a right angle = 90). (Note: phi is HALF
> the angle between the two whiskers. So for an equilateral triangle, which
> has angles of 30 degrees, we have phi = 15.)
> Compute: cos(phi) = 1 if phi <= 7.5
> cos(phi) = 1.0337 - 0.00452*phi if phi > 7.5;
> sin(phi) = 0.0059 + 0.01686*phi.
> Example: phi = 10 gives for the cosine the value 0.9885, and for the sine
> the value 0.1745. The exact values are 0.9848 and 0.1736.
> The approximations are reasonable for phi between 0 and 45 degrees, and
> best for phi between 7 and 23 degrees.
> If phi is fixed, you can of course look them up once.
> --Lambert Meertens, CWI, Amsterdam; ·······@cwi.nl
And here is how I've done it in LeLisp. dx and dy subsequently take
on the above A and B, L/R, xx and yy, sin(phi)*xx and sin(phi)*yy:
; draw an arrowhead
(setq dx (abs (- x1 x2))
dy (abs (- y1 y2)))
(psetq dx (min dx dy)
dy (max dx dy))
(setq dx (/ 10 (+ (* .3978 dx) (* .9604 dy))))
(psetq dx (* (- x1 x2) dx)
dy (* (- y1 y2) dx))
; (cos .3) and (sin .3)
(setq cx (* .9553 dx)
cy (* .9553 dy)
dx (* .2955 dx)
dy (* .2955 dy))
(draw-polyline 3
(vector (+ x2 (round (+ cx dy) 1))
x2
(+ x2 (round (- cx dy) 1)))
(vector (+ y2 (round (- cy dx) 1))
y2
(+ y2 (round (+ dx cy) 1))))
Someone also offered to send me an algo in Fortran, and someone else
later also sent me something similar looking in C, but since I didn't
yet have a request to summarize, I'm afraid I didn't keep any pointers.
+---------------+
| * * * |
| * * | Beware - polyglot esperantist
| * * |
| * * |
| * * * |
+---------------+
|
| Daniel Pfeiffer <········@cix.cict.fr>
| Tolosa (Toulouse), Midi-Pyrenees, Europe <········@irit.fr>
| <········@frcict81.bitnet>
|