TAChart: Add clsRoundRect and clsRoundSides to TChartLabelShape enumeration

git-svn-id: trunk@38579 -
This commit is contained in:
ask 2012-09-08 11:24:09 +00:00
parent 5417050ae2
commit c7d446ef38
2 changed files with 82 additions and 25 deletions

View File

@ -31,6 +31,7 @@ type
public
constructor Init;
procedure Add(const APoint: TPoint);
procedure AddNoDup(const APoint: TPoint); inline;
function LastPoint: TPoint; inline;
function Purge: TPointArray; inline;
end;
@ -42,7 +43,7 @@ type
constructor InitBoundingBox(AX1, AY1, AX2, AY2: Integer);
public
function GetPoint(AParametricAngle: Double): TDoublePoint;
procedure RadialPieToPolygon(
procedure SliceToPolygon(
AAngleStart, AAngleLength: Double; AStep: Integer; var APoly: TPolygon);
function TesselateRadialPie(
AAngleStart, AAngleLength: Double; AStep: Integer): TPointArray;
@ -82,8 +83,10 @@ function RectIntersectsRect(
function RotatePoint(const APoint: TDoublePoint; AAngle: Double): TDoublePoint; overload;
function RotatePoint(const APoint: TPoint; AAngle: Double): TPoint; overload;
function RotatePointX(AX, AAngle: Double): TPoint;
function RotateRect(const ARect: TRect; AAngle: Double): TPointArray;
function RoundPoint(APoint: TDoublePoint): TPoint;
function TesselateRect(const ARect: TRect): TPointArray;
function TesselateEllipse(const ABounds: TRect; AStep: Integer): TPointArray;
function TesselateRoundRect(const ARect: TRect; ARadius, AStep: Integer): TPointArray;
operator +(const A: TPoint; B: TSize): TPoint; overload; inline;
operator +(const A, B: TPoint): TPoint; overload; inline;
@ -430,9 +433,13 @@ begin
Result.Y := Round(sa * AX);
end;
function RotateRect(const ARect: TRect; AAngle: Double): TPointArray;
var
i: Integer;
function RoundPoint(APoint: TDoublePoint): TPoint;
begin
Result.X := Round(APoint.X);
Result.Y := Round(APoint.Y);
end;
function TesselateRect(const ARect: TRect): TPointArray;
begin
SetLength(Result, 4);
with ARect do begin
@ -441,14 +448,54 @@ begin
Result[2] := BottomRight;
Result[3] := Point(Right, Top);
end;
for i := 0 to High(Result) do
Result[i] := RotatePoint(Result[i], AAngle);
end;
function RoundPoint(APoint: TDoublePoint): TPoint;
function TesselateEllipse(const ABounds: TRect; AStep: Integer): TPointArray;
var
e: TEllipse;
p: TPolygon;
begin
Result.X := Round(APoint.X);
Result.Y := Round(APoint.Y);
with ABounds do
e.InitBoundingBox(Left, Top, Right, Bottom);
p.Init;
e.SliceToPolygon(0, 2 * Pi, AStep, p);
Result := p.Purge;
end;
function TesselateRoundRect(
const ARect: TRect; ARadius, AStep: Integer): TPointArray;
var
e: TEllipse;
p: TPolygon;
begin
with ARect do begin
if Min(Right - Left, Bottom - Top) < 2 * ARadius then exit(nil);
p.Init;
e.FR := DoublePoint(ARadius, ARadius);
p.AddNoDup(Point(Right, Bottom - ARadius));
p.AddNoDup(Point(Right, Top + ARadius));
e.FC := DoublePoint(Right - ARadius, Top + ARadius);
e.SliceToPolygon(0, Pi / 2, AStep, p);
p.AddNoDup(Point(Right - ARadius, Top));
p.AddNoDup(Point(Left + ARadius, Top));
e.FC := DoublePoint(Left + ARadius, Top + ARadius);
e.SliceToPolygon(Pi / 2, Pi / 2, AStep, p);
p.AddNoDup(Point(Left, Top + ARadius));
p.AddNoDup(Point(Left, Bottom - ARadius));
e.FC := DoublePoint(Left + ARadius, Bottom - ARadius);
e.SliceToPolygon(Pi, Pi / 2, AStep, p);
p.AddNoDup(Point(Left + ARadius, Bottom));
p.AddNoDup(Point(Right - ARadius, Bottom));
e.FC := DoublePoint(Right - ARadius, Bottom - ARadius);
e.SliceToPolygon(Pi * 3/2, Pi / 2, AStep, p);
end;
Result := p.Purge;
end;
operator + (const A: TPoint; B: TSize): TPoint;
@ -554,6 +601,12 @@ begin
FCount += 1;
end;
procedure TPolygon.AddNoDup(const APoint: TPoint);
begin
if (FCount = 0) or (LastPoint <> APoint) then
Add(APoint);
end;
constructor TPolygon.Init;
begin
FCount := 0;
@ -589,7 +642,7 @@ begin
FR.Y := Abs(AY1 - AY2) / 2;
end;
procedure TEllipse.RadialPieToPolygon(
procedure TEllipse.SliceToPolygon(
AAngleStart, AAngleLength: Double; AStep: Integer; var APoly: TPolygon);
var
lastAngle: Double;
@ -644,7 +697,6 @@ begin
end;
Rec(tprev, tlast);
Add(tlast);
SafeAddPoint(RoundPoint(FC), 0);
end;
// Represent the ellipse sector with a polygon on an integer grid.
@ -655,7 +707,8 @@ var
resultPoly: TPolygon;
begin
resultPoly.Init;
RadialPieToPolygon(AAngleStart, AAngleLength, AStep, resultPoly);
SliceToPolygon(AAngleStart, AAngleLength, AStep, resultPoly);
resultPoly.AddNoDup(RoundPoint(FC));
Result := resultPoly.Purge;
end;

View File

@ -39,7 +39,7 @@ type
property Top default DEF_LABEL_MARGIN_Y;
end;
TChartLabelShape = (clsRectangle, clsEllipse);
TChartLabelShape = (clsRectangle, clsEllipse, clsRoundRect, clsRoundSide);
TChartTextElement = class(TChartElement)
strict private
@ -349,25 +349,29 @@ end;
function TChartTextElement.GetLabelPolygon(
ADrawer: IChartDrawer; ASize: TPoint): TPointArray;
const
STEP = 3;
var
e: TEllipse;
a: Double;
i: Integer;
b: TRect;
i: Integer;
begin
a := GetLabelAngle;
b := GetBoundingBox(ADrawer, ASize);
case Shape of
clsRectangle:
Result := RotateRect(b, a);
clsEllipse: begin
e.InitBoundingBox(b.Left, b.Top, b.Right, b.Bottom);
Result := e.TesselateRadialPie(0, 2 * Pi, 3);
SetLength(Result, Length(Result) - 1);
for i := 0 to High(Result) do
Result[i] := RotatePoint(Result[i], a);
end;
Result := TesselateRect(b);
clsEllipse:
Result := TesselateEllipse(b, STEP);
clsRoundRect:
Result := TesselateRoundRect(
b, Min(b.Right - b.Left, b.Bottom - b.Top) div 3, STEP);
clsRoundSide:
Result := TesselateRoundRect(
b, Min(b.Right - b.Left, b.Bottom - b.Top) div 2, STEP);
end;
a := GetLabelAngle;
for i := 0 to High(Result) do
Result[i] := RotatePoint(Result[i], a);
end;
function TChartTextElement.GetLinkPen: TChartPen;