procedure TFmArrowHead.ReDraw;
var
Box : array [0..1] of TArrayOfFloatPoint;
Poly, ArrowPts: TArrayOfFloatPoint;
StartPoint, EndPoint, StartOffsetPt, EndOffsetPt: TFloatPoint;
Delta: TFloatPoint;
Arrow: TArrowHeadAbstract;
GradientFiller: TLinearGradientPolygonFiller;
const
StartArrowColor: TColor32 = $60009900;
StartArrowPenColor: TColor32 = $FF339900;
EndArrowColor: TColor32 = $600000AA;
EndArrowPenColor: TColor32 = $FF0033AA;
begin
ImgView32.Bitmap.Clear(clWhite32);
case RgpArrowStyle.ItemIndex of
1: Arrow := TArrowHeadSimple.Create(ArrowSize);
2: Arrow := TArrowHeadFourPt.Create(ArrowSize);
3: Arrow := TArrowHeadDiamond.Create(ArrowSize);
4: Arrow := TArrowHeadCircle.Create(ArrowSize);
else Arrow := nil;
end;
Box[0] := MakeBox(FBoxCenter[0], CBoxSize);
Box[1] := MakeBox(FBoxCenter[1], CBoxSize);
FBitmapFiller.Pattern := FPattern[0];
DashLineFS(ImgView32.Bitmap, Box[0], FDashes, FBitmapFiller, EndArrowPenColor,
True, CBorderSize, 1.5);
FBitmapFiller.Pattern := FPattern[1];
DashLineFS(ImgView32.Bitmap, Box[1], FDashes, FBitmapFiller, EndArrowPenColor,
True, CBorderSize, 1.5);
// now accommodate for CBorderSize width as above ...
Box[0] := MakeBox(FBoxCenter[0], CBoxSizePlus);
Box[1] := MakeBox(FBoxCenter[1], CBoxSizePlus);
if BoxesOverlap(FBoxCenter[0], FBoxCenter[1], CBoxSizePlus) then
begin
StartPoint := FBoxCenter[0];
EndPoint := FBoxCenter[1];
end else
begin
StartPoint := GetNearestPointOnBox(FBoxCenter[1], FBoxCenter[0], Box[0]);
EndPoint := GetNearestPointOnBox(FBoxCenter[0], FBoxCenter[1], Box[1]);
end;
Delta.X := StartPoint.X - FBoxCenter[0].X;
Delta.Y := StartPoint.Y - FBoxCenter[0].Y;
if Abs(Delta.X) > Abs(Delta.Y) then
StartOffsetPt := FloatPoint(StartPoint.X + Delta.X * 2, StartPoint.Y)
else
StartOffsetPt := FloatPoint(StartPoint.X, StartPoint.Y + Delta.Y *2);
Delta.X := EndPoint.X - FBoxCenter[1].X;
Delta.Y := EndPoint.Y - FBoxCenter[1].Y;
if Abs(Delta.X) > Abs(Delta.Y) then
EndOffsetPt := FloatPoint(EndPoint.X + Delta.X * 2, EndPoint.Y)
else
EndOffsetPt := FloatPoint(EndPoint.X, EndPoint.Y + Delta.Y * 2);
Poly := BuildPolygonF([StartPoint.X, StartPoint.Y,
StartOffsetPt.X, StartOffsetPt.Y,
EndOffsetPt.X, EndOffsetPt.Y,
EndPoint.X, EndPoint.Y]);
Poly := MakeBezierCurve(Poly);
if Assigned(Arrow) then
begin
// shorten path at specified end(s) and draw ...
case RgpPosition.ItemIndex of
0: Poly := Shorten(Poly, ArrowSize, lpStart);
1: Poly := Shorten(Poly, ArrowSize, lpEnd);
2: Poly := Shorten(Poly, ArrowSize, lpBoth);
end;
// draw the connecting line ...
GradientFiller := TLinearGradientPolygonFiller.Create;
try
GradientFiller.SimpleGradient(Poly[0], StartArrowPenColor,
Poly[High(Poly)], EndArrowPenColor);
PolylineFS(ImgView32.Bitmap, Poly, GradientFiller, False,
TbrLineWidth.Position);
finally
GradientFiller.Free;
end;
// draw specified arrows ...
if RgpPosition.ItemIndex 1 then
begin
ArrowPts := Arrow.GetPoints(Poly, False);
PolygonFS(ImgView32.Bitmap, ArrowPts, StartArrowColor);
PolylineFS(ImgView32.Bitmap, ArrowPts, StartArrowPenColor, True,
TbrLineWidth.Position);
end;
if RgpPosition.ItemIndex 0 then
begin
ArrowPts := Arrow.GetPoints(Poly, True);
PolygonFS(ImgView32.Bitmap, ArrowPts, EndArrowColor);
PolylineFS(ImgView32.Bitmap, ArrowPts, EndArrowPenColor, True,
TbrLineWidth.Position);
end;
end else
PolylineFS(ImgView32.Bitmap, Poly, clBlack32, False,
TbrLineWidth.Position);
end;