我们最近研究出来了如何画方向线(我们也叫它矢量线)的算法,现在拿出来和大家共享。如果您有更好的算法,请教教我们,谢谢!
我们将给出这个算法的两个版本,Delphi版和C#版:
Delphi版:
-------------
procedure DrawVectorLine(ACanvas: TCanvas; const X1, Y1, X2, Y2: Integer;
const ArrowEdgeLength: Integer);
var
DeltaX, DeltaY : Integer;
Theta, AccumRadian: Extended; // radian
LineLength : Extended;
ArrowHeight : Extended;
HalfEdgeLength : Extended;
TailLength : Extended;
BasePoint : TPoint;
ArrowPolygon : array [0..2] of TPoint;
begin
if (X1 = X2) and (Y1 = Y2)
then Exit;
if ArrowEdgeLength < 1
then Exit;
DeltaX := X2 - X1;
DeltaY := Y2 - Y1;
Theta := ArcTan2(DeltaY, DeltaX);
LineLength := Sqrt(DeltaX * DeltaX + DeltaY * DeltaY);
HalfEdgeLength := ArrowEdgeLength / 2;
ArrowHeight := Sqrt(ArrowEdgeLength * ArrowEdgeLength - HalfEdgeLength * HalfEdgeLength);
TailLength := LineLength - ArrowHeight;
BasePoint.X := Round( X1 + TailLength * Cos(Theta) );
BasePoint.Y := Round( Y1 + TailLength * Sin(Theta) );
AccumRadian := Theta + Pi / 2;
ArrowPolygon[0].X := Round( BasePoint.X + HalfEdgeLength * Cos(AccumRadian) );
ArrowPolygon[0].Y := Round( BasePoint.Y + HalfEdgeLength * Sin(AccumRadian) );
AccumRadian := Theta - Pi / 2;
ArrowPolygon[1].X := Round( BasePoint.X + HalfEdgeLength * Cos(AccumRadian) );
ArrowPolygon[1].Y := Round( BasePoint.Y + HalfEdgeLength * Sin(AccumRadian) );
ArrowPolygon[2].X := X2;
ArrowPolygon[2].Y := Y2;
with ACanvas do
begin
MoveTo(X1, Y1);
LineTo(X2, Y2);
Polygon(ArrowPolygon);
end;
end;
C#版:
--------
void DrawVectorLine(Graphics graph, int x1, int y1, int x2, int y2, int arrowEdgeLength)
{
int deltaX, deltaY;
double theta, accumRadian;
double lineLength;
double arrowHeight;
double halfEdgeLength;
double tailLength;
Point basePoint = new Point(0, 0);
Point[] arrowPolygon = { new Point(0, 0), new Point(0, 0), new Point(0, 0) };
if ( (x1 == x2) && (y1 == y2) )
return;
if (arrowEdgeLength < 1)
return;
deltaX = x2 - x1;
deltaY = y2 - y1;
theta = Math.Atan2(deltaY, deltaX);
lineLength = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
halfEdgeLength = arrowEdgeLength / 2;
arrowHeight = Math.Sqrt(arrowEdgeLength * arrowEdgeLength - halfEdgeLength * halfEdgeLength);
tailLength = lineLength - arrowHeight;
basePoint.X = (int)( x1 + tailLength * Math.Cos(theta) );
basePoint.Y = (int)( y1 + tailLength * Math.Sin(theta) );
accumRadian = theta + Math.PI / 2;
arrowPolygon[0].X = (int)( basePoint.X + halfEdgeLength * Math.Cos(accumRadian) );
arrowPolygon[0].Y = (int)( basePoint.Y + halfEdgeLength * Math.Sin(accumRadian) );
accumRadian = theta - Math.PI / 2;
arrowPolygon[1].X = (int)( basePoint.X + halfEdgeLength * Math.Cos(accumRadian) );
arrowPolygon[1].Y = (int)( basePoint.Y + halfEdgeLength * Math.Sin(accumRadian) );
arrowPolygon[2].X = x2;
arrowPolygon[2].Y = y2;
graph.DrawLine(new Pen(new SolidBrush(Color.Black)), new Point(x1, y1), new Point(x2, y2));
graph.FillPolygon(new SolidBrush(Color.Black), arrowPolygon);
graph.DrawLine(new Pen(new SolidBrush(Color.Black)), arrowPolygon[0], arrowPolygon[1]);
graph.DrawLine(new Pen(new SolidBrush(Color.Black)), arrowPolygon[1], arrowPolygon[2]);
graph.DrawLine(new Pen(new SolidBrush(Color.Black)), arrowPolygon[2], arrowPolygon[0]);
}