The routine that I posted above doesn’t account for pen size. For a one or two point pen size it won’t be noticeable, but for a large pen size the arrowheads won’t look good. Rather than leave things half done, I revised the routine to compensate for pen size, and while I was at it, I decided to include several arrowhead styles. A new property mArrowType has a range of 0…3 and the corresponding styles are:
0 - Open style (like the one given by Eugene Dakin)
1 - Closed triangle
2 - Filled triangle
3 - Filled polygon (sharp point arrowhead)
Revised code:
Public Sub DrawArrow(extends g As Graphics, x1 As Double, y1 As Double, x2 As Double, y2 As Double)
'Draw a line with arrowhead at the end
'Calling parameters are the same as for DrawLine
'Arrowhead parameters are determined by properties arrowLength and arrowAngle
'
'*** Revised to compensate for large pen sizes
'
const deg2halfrad = 0.008726646259972
'Get angle of line
dim aLine As Double = ATan2(y2-y1,x2-x1)
'calculate angle of arrowhead lines
dim ahLineA As Double = aLine-mArrowAngle*deg2halfrad
dim ahLineB As Double = aLine+arrowAngle*deg2halfrad
'calculate x and y coordinates of the arrowhead points
dim ahLineAx As Double = x2-mArrowLength*cos(ahLineA)
dim ahLineBx As Double = x2-mArrowLength*cos(ahLineB)
dim ahLineAy As Double = y2-mArrowLength*sin(ahLineA)
dim ahLineBy As Double = y2-mArrowLength*sin(ahLineB)
'Pen size adjustment
dim dPH as Double = g.PenHeight/2
dim dPW as Double = g.PenWidth/2
dim poly() As Double =Array(0,x2+dPW,y2+dPH,ahLineAx+dPW,ahLineAy+dPH,ahLineBx+dPW,ahLineBy+dPH)
if mArrowType=0 then
'Draw the principal line
g.DrawLine(x1,y1,x2,y2)
Else
'Draw the principal line (only to the base of the arrowhead)
g.DrawLine(x1,y1,(ahLineAx+ahLineBx)/2,(ahLineAy+ahLineBy)/2)
end if
if mArrowType<3 then
'Draw two line segments for arrowhead
g.DrawLine(ahLineAx,ahLineAy,x2,y2)
g.DrawLine(ahLineBx,ahLineBy,x2,y2)
end if
if mArrowType=1 or mArrowType=2 then
'Add baseline for triangle arrowhead
g.DrawLine(ahLineAx,ahLineAy,ahLineBx,ahLineBy)
end if
if mArrowType=2 or mArrowType=3 then
'Fill the arrowhead
g.FillPolygon(poly)
end if
End Sub