mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-15 18:39:09 +02:00
TAChart: Add TAGeometry.TPolygon utility object
git-svn-id: trunk@38575 -
This commit is contained in:
parent
df21315edc
commit
1a87d875b4
@ -24,6 +24,17 @@ uses
|
|||||||
TAChartUtils, Types;
|
TAChartUtils, Types;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
TPolygon = object
|
||||||
|
public
|
||||||
|
FPoints: TPointArray;
|
||||||
|
FCount: Integer;
|
||||||
|
public
|
||||||
|
constructor Init;
|
||||||
|
procedure Add(const APoint: TPoint);
|
||||||
|
function LastPoint: TPoint; inline;
|
||||||
|
function Purge: TPointArray; inline;
|
||||||
|
end;
|
||||||
|
|
||||||
TEllipse = object
|
TEllipse = object
|
||||||
public
|
public
|
||||||
FC: TDoublePoint;
|
FC: TDoublePoint;
|
||||||
@ -31,6 +42,8 @@ type
|
|||||||
constructor InitBoundingBox(AX1, AY1, AX2, AY2: Integer);
|
constructor InitBoundingBox(AX1, AY1, AX2, AY2: Integer);
|
||||||
public
|
public
|
||||||
function GetPoint(AParametricAngle: Double): TDoublePoint;
|
function GetPoint(AParametricAngle: Double): TDoublePoint;
|
||||||
|
procedure RadialPieToPolygon(
|
||||||
|
AAngleStart, AAngleLength: Double; AStep: Integer; var APoly: TPolygon);
|
||||||
function TesselateRadialPie(
|
function TesselateRadialPie(
|
||||||
AAngleStart, AAngleLength: Double; AStep: Integer): TPointArray;
|
AAngleStart, AAngleLength: Double; AStep: Integer): TPointArray;
|
||||||
end;
|
end;
|
||||||
@ -531,6 +544,33 @@ begin
|
|||||||
Result.Y := ASize.cy;
|
Result.Y := ASize.cy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TPolygon }
|
||||||
|
|
||||||
|
procedure TPolygon.Add(const APoint: TPoint);
|
||||||
|
begin
|
||||||
|
if FCount > High(FPoints) then
|
||||||
|
SetLength(FPoints, Max(2 * FCount, 16));
|
||||||
|
FPoints[FCount] := APoint;
|
||||||
|
FCount += 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TPolygon.Init;
|
||||||
|
begin
|
||||||
|
FCount := 0;
|
||||||
|
FPoints := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPolygon.LastPoint: TPoint;
|
||||||
|
begin
|
||||||
|
Result := FPoints[FCount - 1];
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TPolygon.Purge: TPointArray;
|
||||||
|
begin
|
||||||
|
SetLength(FPoints, FCount);
|
||||||
|
Result := FPoints;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TEllipse }
|
{ TEllipse }
|
||||||
|
|
||||||
function TEllipse.GetPoint(AParametricAngle: Double): TDoublePoint;
|
function TEllipse.GetPoint(AParametricAngle: Double): TDoublePoint;
|
||||||
@ -549,27 +589,15 @@ begin
|
|||||||
FR.Y := Abs(AY1 - AY2) / 2;
|
FR.Y := Abs(AY1 - AY2) / 2;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Represent the ellipse sector with a polygon on an integer grid.
|
procedure TEllipse.RadialPieToPolygon(
|
||||||
// Polygon vertices are no more then AStep pixels apart.
|
AAngleStart, AAngleLength: Double; AStep: Integer; var APoly: TPolygon);
|
||||||
function TEllipse.TesselateRadialPie(
|
|
||||||
AAngleStart, AAngleLength: Double; AStep: Integer): TPointArray;
|
|
||||||
var
|
var
|
||||||
resultPoints: TPointArray = nil;
|
|
||||||
cnt: Integer = 0;
|
|
||||||
lastAngle: Double;
|
lastAngle: Double;
|
||||||
|
|
||||||
procedure AddPoint(APoint: TPoint);
|
|
||||||
begin
|
|
||||||
if cnt > High(resultPoints) then
|
|
||||||
SetLength(resultPoints, 2 * cnt);
|
|
||||||
resultPoints[cnt] := Point(APoint.X, APoint.Y);
|
|
||||||
cnt += 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure SafeAddPoint(APoint: TPoint; AAngle: Double);
|
procedure SafeAddPoint(APoint: TPoint; AAngle: Double);
|
||||||
begin
|
begin
|
||||||
if resultPoints[cnt - 1] <> APoint then begin
|
if APoly.LastPoint <> APoint then begin
|
||||||
AddPoint(APoint);
|
APoly.Add(APoint);
|
||||||
lastAngle := AAngle;
|
lastAngle := AAngle;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -579,7 +607,7 @@ var
|
|||||||
pt: TPoint;
|
pt: TPoint;
|
||||||
begin
|
begin
|
||||||
pt := RoundPoint(GetPoint(AHi));
|
pt := RoundPoint(GetPoint(AHi));
|
||||||
if PointDist(resultPoints[cnt - 1], pt) <= Sqr(AStep) then
|
if PointDist(APoly.LastPoint, pt) <= Sqr(AStep) then
|
||||||
SafeAddPoint(pt, AHi)
|
SafeAddPoint(pt, AHi)
|
||||||
else begin
|
else begin
|
||||||
Rec(ALo, (ALo + AHi) / 2);
|
Rec(ALo, (ALo + AHi) / 2);
|
||||||
@ -599,15 +627,13 @@ var
|
|||||||
begin
|
begin
|
||||||
tprev := AAngleStart;
|
tprev := AAngleStart;
|
||||||
tlast := AAngleStart + AAngleLength;
|
tlast := AAngleStart + AAngleLength;
|
||||||
|
APoly.Add(RoundPoint(GetPoint(tprev)));
|
||||||
if (FR.X < 1) or (FR.Y < 1) then begin
|
if (FR.X < 1) or (FR.Y < 1) then begin
|
||||||
// Ellipse has degenerated into a line.
|
// Ellipse has degenerated into a line.
|
||||||
SetLength(resultPoints, 2);
|
|
||||||
AddPoint(RoundPoint(GetPoint(tprev)));
|
|
||||||
Add(tlast);
|
Add(tlast);
|
||||||
exit(resultPoints);
|
exit;
|
||||||
end;
|
end;
|
||||||
SetLength(resultPoints, 32);
|
APoly.Add(RoundPoint(GetPoint(tprev)));
|
||||||
AddPoint(RoundPoint(GetPoint(tprev)));
|
|
||||||
lastAngle := tprev;
|
lastAngle := tprev;
|
||||||
t := Ceil(tprev / HalfPi) * HalfPi;
|
t := Ceil(tprev / HalfPi) * HalfPi;
|
||||||
while t < tlast do begin
|
while t < tlast do begin
|
||||||
@ -619,8 +645,18 @@ begin
|
|||||||
Rec(tprev, tlast);
|
Rec(tprev, tlast);
|
||||||
Add(tlast);
|
Add(tlast);
|
||||||
SafeAddPoint(RoundPoint(FC), 0);
|
SafeAddPoint(RoundPoint(FC), 0);
|
||||||
SetLength(resultPoints, cnt);
|
end;
|
||||||
Result := resultPoints;
|
|
||||||
|
// Represent the ellipse sector with a polygon on an integer grid.
|
||||||
|
// Polygon vertices are no more then AStep pixels apart.
|
||||||
|
function TEllipse.TesselateRadialPie(
|
||||||
|
AAngleStart, AAngleLength: Double; AStep: Integer): TPointArray;
|
||||||
|
var
|
||||||
|
resultPoly: TPolygon;
|
||||||
|
begin
|
||||||
|
resultPoly.Init;
|
||||||
|
RadialPieToPolygon(AAngleStart, AAngleLength, AStep, resultPoly);
|
||||||
|
Result := resultPoly.Purge;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user