mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-12 15:51:12 +02:00
TAChart: Extract TAGeometry unit
git-svn-id: trunk@29797 -
This commit is contained in:
parent
304a45372e
commit
26ac2c3d21
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -2433,6 +2433,7 @@ components/tachart/tadraweraggpas.pas svneol=native#text/pascal
|
|||||||
components/tachart/tadraweropengl.pas svneol=native#text/pascal
|
components/tachart/tadraweropengl.pas svneol=native#text/pascal
|
||||||
components/tachart/tadrawutils.pas svneol=native#text/pascal
|
components/tachart/tadrawutils.pas svneol=native#text/pascal
|
||||||
components/tachart/tafuncseries.pas svneol=native#text/pascal
|
components/tachart/tafuncseries.pas svneol=native#text/pascal
|
||||||
|
components/tachart/tageometry.pas svneol=native#text/pascal
|
||||||
components/tachart/tagraph.lrs svneol=native#text/pascal
|
components/tachart/tagraph.lrs svneol=native#text/pascal
|
||||||
components/tachart/tagraph.pas svneol=native#text/plain
|
components/tachart/tagraph.pas svneol=native#text/plain
|
||||||
components/tachart/talegend.pas svneol=native#text/plain
|
components/tachart/talegend.pas svneol=native#text/plain
|
||||||
|
@ -278,7 +278,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
LResources, Math, PropEdits, TASources;
|
LResources, Math, PropEdits, TAGeometry, TASources;
|
||||||
|
|
||||||
type
|
type
|
||||||
TAxisDataExtent = record
|
TAxisDataExtent = record
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
for details about the copyright.
|
for details about the copyright.
|
||||||
"/>
|
"/>
|
||||||
<Version Major="1"/>
|
<Version Major="1"/>
|
||||||
<Files Count="20">
|
<Files Count="21">
|
||||||
<Item1>
|
<Item1>
|
||||||
<Filename Value="tagraph.pas"/>
|
<Filename Value="tagraph.pas"/>
|
||||||
<HasRegisterProc Value="True"/>
|
<HasRegisterProc Value="True"/>
|
||||||
@ -117,6 +117,10 @@
|
|||||||
<Filename Value="tacustomsource.pas"/>
|
<Filename Value="tacustomsource.pas"/>
|
||||||
<UnitName Value="TACustomSource"/>
|
<UnitName Value="TACustomSource"/>
|
||||||
</Item20>
|
</Item20>
|
||||||
|
<Item21>
|
||||||
|
<Filename Value="tageometry.pas"/>
|
||||||
|
<UnitName Value="TAGeometry"/>
|
||||||
|
</Item21>
|
||||||
</Files>
|
</Files>
|
||||||
<LazDoc Paths="$(LazarusDir)\components\tachart\fpdoc"/>
|
<LazDoc Paths="$(LazarusDir)\components\tachart\fpdoc"/>
|
||||||
<Type Value="RunAndDesignTime"/>
|
<Type Value="RunAndDesignTime"/>
|
||||||
|
@ -10,7 +10,7 @@ uses
|
|||||||
TAGraph, TAChartAxis, TAChartUtils, TACustomSeries, TASources, TADbSource,
|
TAGraph, TAChartAxis, TAChartUtils, TACustomSeries, TASources, TADbSource,
|
||||||
TASeries, TASeriesEditor, TASubcomponentsEditor, TATools, TATransformations,
|
TASeries, TASeriesEditor, TASubcomponentsEditor, TATools, TATransformations,
|
||||||
TATypes, TADrawUtils, TAMultiSeries, TALegend, TAStyles, TAFuncSeries,
|
TATypes, TADrawUtils, TAMultiSeries, TALegend, TAStyles, TAFuncSeries,
|
||||||
TALegendPanel, TARadialSeries, TACustomSource, LazarusPackageIntf;
|
TALegendPanel, TARadialSeries, TACustomSource, TAGeometry, LazarusPackageIntf;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
@ -214,8 +214,6 @@ const
|
|||||||
|
|
||||||
function BoundsSize(ALeft, ATop: Integer; ASize: TSize): TRect; inline;
|
function BoundsSize(ALeft, ATop: Integer; ASize: TSize): TRect; inline;
|
||||||
|
|
||||||
function DoublePoint(AX, AY: Double): TDoublePoint; inline;
|
|
||||||
function DoubleRect(AX1, AY1, AX2, AY2: Double): TDoubleRect; inline;
|
|
||||||
function DoubleInterval(AStart, AEnd: Double): TDoubleInterval; inline;
|
function DoubleInterval(AStart, AEnd: Double): TDoubleInterval; inline;
|
||||||
|
|
||||||
procedure EnsureOrder(var A, B: Integer); overload; inline;
|
procedure EnsureOrder(var A, B: Integer); overload; inline;
|
||||||
@ -227,50 +225,16 @@ procedure Exchange(var A, B: TDoublePoint); overload; inline;
|
|||||||
procedure Exchange(var A, B: String); overload; inline;
|
procedure Exchange(var A, B: String); overload; inline;
|
||||||
|
|
||||||
procedure ExpandRange(var ALo, AHi: Double; ACoeff: Double); inline;
|
procedure ExpandRange(var ALo, AHi: Double; ACoeff: Double); inline;
|
||||||
procedure ExpandRect(var ARect: TDoubleRect; const APoint: TDoublePoint); inline;
|
|
||||||
procedure ExpandRect(var ARect: TRect; const APoint: TPoint); inline;
|
|
||||||
procedure ExpandRect(
|
|
||||||
var ARect: TRect; const ACenter: TPoint; ARadius: Integer;
|
|
||||||
AAngle1, AAngle2: Double); inline;
|
|
||||||
|
|
||||||
function GetIntervals(AMin, AMax: Double; AInverted: Boolean): TDoubleDynArray;
|
function GetIntervals(AMin, AMax: Double; AInverted: Boolean): TDoubleDynArray;
|
||||||
|
|
||||||
function InterpolateRGB(AColor1, AColor2: Integer; ACoeff: Double): Integer;
|
function InterpolateRGB(AColor1, AColor2: Integer; ACoeff: Double): Integer;
|
||||||
|
|
||||||
function IsPointOnLine(const AP, A1, A2: TPoint): Boolean; inline;
|
|
||||||
function IsPointInPolygon(
|
|
||||||
const AP: TPoint; const APolygon: array of TPoint): Boolean;
|
|
||||||
function IsPointInRect(const AP, A1, A2: TPoint): Boolean; inline; overload;
|
|
||||||
function IsPointInRect(const AP: TPoint; const AR: TRect): Boolean; inline; overload;
|
|
||||||
function IsRectInRect(const AInner, AOuter: TRect): Boolean; inline;
|
|
||||||
function IsLineIntersectsLine(const AA, AB, AC, AD: TPoint): Boolean;
|
|
||||||
function IsPolygonIntersectsPolygon(const AP1, AP2: array of TPoint): Boolean;
|
|
||||||
function LineIntersectsRect(
|
|
||||||
var AA, AB: TDoublePoint; const ARect: TDoubleRect): Boolean;
|
|
||||||
|
|
||||||
function MeasureRotatedRect(const ASize: TPoint; AAngle: Double): TSize;
|
|
||||||
|
|
||||||
procedure NormalizeRect(var ARect: TRect); overload;
|
|
||||||
procedure NormalizeRect(var ARect: TDoubleRect); overload;
|
|
||||||
|
|
||||||
function OrientToRad(AOrient: Integer): Double; inline;
|
function OrientToRad(AOrient: Integer): Double; inline;
|
||||||
|
|
||||||
function PointDist(const A, B: TPoint): Integer; inline;
|
|
||||||
function PointDistX(const A, B: TPoint): Integer; inline;
|
|
||||||
function PointDistY(const A, B: TPoint): Integer; inline;
|
|
||||||
|
|
||||||
function ProjToRect(
|
|
||||||
const APt: TDoublePoint; const ARect: TDoubleRect): TDoublePoint;
|
|
||||||
|
|
||||||
function RadToDeg16(ARad: Double): Integer; inline;
|
function RadToDeg16(ARad: Double): Integer; inline;
|
||||||
function RadToOrient(ARad: Double): Integer; inline;
|
function RadToOrient(ARad: Double): Integer; inline;
|
||||||
|
|
||||||
function RectIntersectsRect(
|
|
||||||
var ARect: TDoubleRect; const AFixed: TDoubleRect): Boolean;
|
|
||||||
|
|
||||||
function RotatePoint(const APoint: TDoublePoint; AAngle: Double): TDoublePoint; overload;
|
|
||||||
function RotatePoint(const APoint: TPoint; AAngle: Double): TPoint; overload;
|
|
||||||
function RotateRect(const ASize: TPoint; AAngle: Double): TPointArray;
|
|
||||||
function RoundChecked(A: Double): Integer; inline;
|
function RoundChecked(A: Double): Integer; inline;
|
||||||
|
|
||||||
function SafeInfinity: Double; inline;
|
function SafeInfinity: Double; inline;
|
||||||
@ -285,22 +249,7 @@ procedure UpdateMinMax(AValue: Integer; var AMin, AMax: Integer); overload;
|
|||||||
|
|
||||||
function WeightedAverage(AX1, AX2, ACoeff: Double): Double; inline;
|
function WeightedAverage(AX1, AX2, ACoeff: Double): Double; inline;
|
||||||
|
|
||||||
operator +(const A: TPoint; B: TSize): TPoint; overload; inline;
|
|
||||||
operator +(const A, B: TPoint): TPoint; overload; inline;
|
|
||||||
operator +(const A, B: TDoublePoint): TDoublePoint; overload; inline;
|
|
||||||
operator -(const A: TPoint): TPoint; overload; inline;
|
|
||||||
operator -(const A, B: TPoint): TPoint; overload; inline;
|
|
||||||
operator -(const A, B: TDoublePoint): TDoublePoint; overload; inline;
|
|
||||||
operator div(const A: TPoint; ADivisor: Integer): TPoint; inline;
|
|
||||||
operator *(const A: TPoint; AMultiplier: Integer): TPoint; inline;
|
|
||||||
operator *(const A, B: TPoint): TPoint; inline;
|
|
||||||
operator *(const A, B: TDoublePoint): TDoublePoint; overload; inline;
|
|
||||||
operator /(const A, B: TDoublePoint): TDoublePoint; overload; inline;
|
|
||||||
operator =(const A, B: TMethod): Boolean; overload; inline;
|
operator =(const A, B: TMethod): Boolean; overload; inline;
|
||||||
operator <= (const A, B: TDoublePoint): Boolean; overload; inline;
|
|
||||||
|
|
||||||
operator :=(const APoint: TPoint): TSize; inline;
|
|
||||||
operator :=(const ASize: TSize): TPoint; inline;
|
|
||||||
|
|
||||||
var
|
var
|
||||||
DrawData: TDrawDataRegistry;
|
DrawData: TDrawDataRegistry;
|
||||||
@ -317,8 +266,6 @@ uses
|
|||||||
const
|
const
|
||||||
ORIENTATION_UNITS_PER_DEG = 10;
|
ORIENTATION_UNITS_PER_DEG = 10;
|
||||||
|
|
||||||
function PointLineSide(AP, A1, A2: TPoint): TValueSign; forward;
|
|
||||||
|
|
||||||
function BoundsSize(ALeft, ATop: Integer; ASize: TSize): TRect; inline;
|
function BoundsSize(ALeft, ATop: Integer; ASize: TSize): TRect; inline;
|
||||||
begin
|
begin
|
||||||
Result := Bounds(ALeft, ATop, ASize.cx, ASize.cy);
|
Result := Bounds(ALeft, ATop, ASize.cx, ASize.cy);
|
||||||
@ -394,20 +341,6 @@ begin
|
|||||||
end; {case AxisScale}
|
end; {case AxisScale}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function DoublePoint(AX, AY: Double): TDoublePoint; inline;
|
|
||||||
begin
|
|
||||||
Result.X := AX;
|
|
||||||
Result.Y := AY;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function DoubleRect(AX1, AY1, AX2, AY2: Double): TDoubleRect; inline;
|
|
||||||
begin
|
|
||||||
Result.a.X := AX1;
|
|
||||||
Result.a.Y := AY1;
|
|
||||||
Result.b.X := AX2;
|
|
||||||
Result.b.Y := AY2;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function DoubleInterval(AStart, AEnd: Double): TDoubleInterval;
|
function DoubleInterval(AStart, AEnd: Double): TDoubleInterval;
|
||||||
begin
|
begin
|
||||||
Result.FStart := AStart;
|
Result.FStart := AStart;
|
||||||
@ -471,35 +404,6 @@ begin
|
|||||||
AHi += d * ACoeff;
|
AHi += d * ACoeff;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure ExpandRect(var ARect: TDoubleRect; const APoint: TDoublePoint);
|
|
||||||
begin
|
|
||||||
UpdateMinMax(APoint.X, ARect.a.X, ARect.b.X);
|
|
||||||
UpdateMinMax(APoint.Y, ARect.a.Y, ARect.b.Y);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure ExpandRect(var ARect: TRect; const APoint: TPoint);
|
|
||||||
begin
|
|
||||||
UpdateMinMax(APoint.X, ARect.Left, ARect.Right);
|
|
||||||
UpdateMinMax(APoint.Y, ARect.Top, ARect.Bottom);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure ExpandRect(
|
|
||||||
var ARect: TRect; const ACenter: TPoint; ARadius: Integer;
|
|
||||||
AAngle1, AAngle2: Double);
|
|
||||||
var
|
|
||||||
p: TPoint;
|
|
||||||
i, j: Integer;
|
|
||||||
begin
|
|
||||||
p := Point(ARadius, 0);
|
|
||||||
EnsureOrder(AAngle1, AAngle2);
|
|
||||||
ExpandRect(ARect, RotatePoint(p, AAngle1) + ACenter);
|
|
||||||
ExpandRect(ARect, RotatePoint(p, AAngle2) + ACenter);
|
|
||||||
j := Floor(AAngle1 / Pi * 2);
|
|
||||||
for i := j to j + 4 do
|
|
||||||
if InRange(Pi / 2 * i, AAngle1, AAngle2) then
|
|
||||||
ExpandRect(ARect, RotatePoint(p, Pi / 2 * i) + ACenter);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GetIntervals(AMin, AMax: Double; AInverted: Boolean): TDoubleDynArray;
|
function GetIntervals(AMin, AMax: Double; AInverted: Boolean): TDoubleDynArray;
|
||||||
const
|
const
|
||||||
INV_TO_SCALE: array [Boolean] of TAxisScale = (asIncreasing, asDecreasing);
|
INV_TO_SCALE: array [Boolean] of TAxisScale = (asIncreasing, asDecreasing);
|
||||||
@ -556,205 +460,11 @@ begin
|
|||||||
r[i] := Round(c1[i] + (c2[i] - c1[i]) * ACoeff);
|
r[i] := Round(c1[i] + (c2[i] - c1[i]) * ACoeff);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function IsPointOnLine(const AP, A1, A2: TPoint): Boolean;
|
|
||||||
begin
|
|
||||||
Result := IsPointInRect(AP, A1, A2) and (PointLineSide(AP, A1, A2) = 0);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function IsPointInPolygon(
|
|
||||||
const AP: TPoint; const APolygon: array of TPoint): Boolean;
|
|
||||||
var
|
|
||||||
i, count: Integer;
|
|
||||||
p1, p2: TPoint;
|
|
||||||
s1, s2: TValueSign;
|
|
||||||
begin
|
|
||||||
if Length(APolygon) = 0 then exit(false);
|
|
||||||
p1 := APolygon[High(APolygon)];
|
|
||||||
for i := 0 to High(APolygon) do begin
|
|
||||||
p2 := APolygon[i];
|
|
||||||
if IsPointOnLine(AP, p1, p2) then exit(true);
|
|
||||||
p1 := p2;
|
|
||||||
end;
|
|
||||||
count := 0;
|
|
||||||
p1 := APolygon[High(APolygon)];
|
|
||||||
for i := 0 to High(APolygon) do begin
|
|
||||||
p2 := APolygon[i];
|
|
||||||
s1 := Sign(p1.Y - AP.Y);
|
|
||||||
s2 := Sign(p2.Y - AP.Y);
|
|
||||||
case s1 * s2 of
|
|
||||||
-1: count += Ord(PointLineSide(AP, p1, p2) = Sign(p1.Y - p2.Y));
|
|
||||||
0: if s1 + s2 = 1 then begin
|
|
||||||
if s1 = 0 then
|
|
||||||
count += Ord(p1.X >= AP.X)
|
|
||||||
else
|
|
||||||
count += Ord(p2.X >= AP.X)
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
p1 := p2;
|
|
||||||
end;
|
|
||||||
Result := count mod 2 = 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function IsPointInRect(const AP, A1, A2: TPoint): Boolean;
|
|
||||||
begin
|
|
||||||
Result := SafeInRange(AP.X, A1.X, A2.X) and SafeInRange(AP.Y, A1.Y, A2.Y);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function IsPointInRect(const AP: TPoint; const AR: TRect): Boolean;
|
|
||||||
begin
|
|
||||||
Result :=
|
|
||||||
SafeInRange(AP.X, AR.Left, AR.Right) and
|
|
||||||
SafeInRange(AP.Y, AR.Top, AR.Bottom);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function IsRectInRect(const AInner, AOuter: TRect): Boolean;
|
|
||||||
begin
|
|
||||||
Result :=
|
|
||||||
IsPointInRect(AInner.TopLeft, AOuter) and
|
|
||||||
IsPointInRect(AInner.BottomRight, AOuter);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function IsLineIntersectsLine(const AA, AB, AC, AD: TPoint): Boolean;
|
|
||||||
var
|
|
||||||
sa, sb, sc, sd: TValueSign;
|
|
||||||
begin
|
|
||||||
sa := PointLineSide(AA, AC, AD);
|
|
||||||
sb := PointLineSide(AB, AC, AD);
|
|
||||||
if (sa = 0) and (sb = 0) then
|
|
||||||
// All points are on the same infinite line.
|
|
||||||
Result :=
|
|
||||||
IsPointInRect(AA, AC, AD) or IsPointInRect(AB, AC, AD) or
|
|
||||||
IsPointInRect(AC, AA, AB) or IsPointInRect(AD, AA, AB)
|
|
||||||
else begin
|
|
||||||
sc := PointLineSide(AC, AA, AB);
|
|
||||||
sd := PointLineSide(AD, AA, AB);
|
|
||||||
Result := (sa * sb <= 0) and (sc * sd <= 0);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function IsPolygonIntersectsPolygon(const AP1, AP2: array of TPoint): Boolean;
|
|
||||||
var
|
|
||||||
i, j: Integer;
|
|
||||||
p1, p2: TPoint;
|
|
||||||
begin
|
|
||||||
if (Length(AP1) = 0) or (Length(AP2) = 0) then exit(false);
|
|
||||||
if IsPointInPolygon(AP1[0], AP2) or IsPointInPolygon(AP2[0], AP1) then
|
|
||||||
exit(true);
|
|
||||||
for i := 0 to High(AP1) do begin
|
|
||||||
p1 := AP1[i];
|
|
||||||
p2 := AP1[(i + 1) mod Length(AP1)];
|
|
||||||
for j := 0 to High(AP2) do
|
|
||||||
if IsLineIntersectsLine(p1, p2, AP2[j], AP2[(j + 1) mod Length(AP2)]) then
|
|
||||||
exit(true);
|
|
||||||
end;
|
|
||||||
Result := false;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function LineIntersectsRect(
|
|
||||||
var AA, AB: TDoublePoint; const ARect: TDoubleRect): Boolean;
|
|
||||||
var
|
|
||||||
dx, dy: Double;
|
|
||||||
|
|
||||||
procedure AdjustX(var AP: TDoublePoint; ANewX: Double); inline;
|
|
||||||
begin
|
|
||||||
AP.Y += dy / dx * (ANewX - AP.X);
|
|
||||||
AP.X := ANewX;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure AdjustY(var AP: TDoublePoint; ANewY: Double); inline;
|
|
||||||
begin
|
|
||||||
AP.X += dx / dy * (ANewY - AP.Y);
|
|
||||||
AP.Y := ANewY;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
dx := AB.X - AA.X;
|
|
||||||
dy := AB.Y - AA.Y;
|
|
||||||
case CASE_OF_TWO[AA.X < ARect.a.X, AB.X < ARect.a.X] of
|
|
||||||
cotFirst: AdjustX(AA, ARect.a.X);
|
|
||||||
cotSecond: AdjustX(AB, ARect.a.X);
|
|
||||||
cotBoth: exit(false);
|
|
||||||
end;
|
|
||||||
case CASE_OF_TWO[AA.X > ARect.b.X, AB.X > ARect.b.X] of
|
|
||||||
cotFirst: AdjustX(AA, ARect.b.X);
|
|
||||||
cotSecond: AdjustX(AB, ARect.b.X);
|
|
||||||
cotBoth: exit(false);
|
|
||||||
end;
|
|
||||||
case CASE_OF_TWO[AA.Y < ARect.a.Y, AB.Y < ARect.a.Y] of
|
|
||||||
cotFirst: AdjustY(AA, ARect.a.Y);
|
|
||||||
cotSecond: AdjustY(AB, ARect.a.Y);
|
|
||||||
cotBoth: exit(false);
|
|
||||||
end;
|
|
||||||
case CASE_OF_TWO[AA.Y > ARect.b.Y, AB.Y > ARect.b.Y] of
|
|
||||||
cotFirst: AdjustY(AA, ARect.b.Y);
|
|
||||||
cotSecond: AdjustY(AB, ARect.b.Y);
|
|
||||||
cotBoth: exit(false);
|
|
||||||
end;
|
|
||||||
Result := true;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function MeasureRotatedRect(const ASize: TPoint; AAngle: Double): TSize;
|
|
||||||
var
|
|
||||||
pt1, pt2: TPoint;
|
|
||||||
begin
|
|
||||||
pt1 := RotatePoint(ASize, AAngle);
|
|
||||||
pt2 := RotatePoint(Point(ASize.X, -ASize.Y), AAngle);
|
|
||||||
Result.cx := Max(Abs(pt1.X), Abs(pt2.X));
|
|
||||||
Result.cy := Max(Abs(pt1.Y), Abs(pt2.Y));
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure NormalizeRect(var ARect: TRect);
|
|
||||||
begin
|
|
||||||
with ARect do begin
|
|
||||||
EnsureOrder(Left, Right);
|
|
||||||
EnsureOrder(Top, Bottom);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure NormalizeRect(var ARect: TDoubleRect); overload;
|
|
||||||
begin
|
|
||||||
with ARect do begin
|
|
||||||
EnsureOrder(a.X, b.X);
|
|
||||||
EnsureOrder(a.Y, b.Y);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function OrientToRad(AOrient: Integer): Double;
|
function OrientToRad(AOrient: Integer): Double;
|
||||||
begin
|
begin
|
||||||
Result := DegToRad(AOrient / ORIENTATION_UNITS_PER_DEG);
|
Result := DegToRad(AOrient / ORIENTATION_UNITS_PER_DEG);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function PointDist(const A, B: TPoint): Integer;
|
|
||||||
begin
|
|
||||||
Result := Min(Sqr(Int64(A.X) - B.X) + Sqr(Int64(A.Y) - B.Y), MaxInt);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function PointDistX(const A, B: TPoint): Integer;
|
|
||||||
begin
|
|
||||||
Result := Min(Abs(Int64(A.X) - B.X), MaxInt);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function PointDistY(const A, B: TPoint): Integer; inline;
|
|
||||||
begin
|
|
||||||
Result := Min(Abs(Int64(A.Y) - B.Y), MaxInt);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function PointLineSide(AP, A1, A2: TPoint): TValueSign;
|
|
||||||
var
|
|
||||||
a1x, a1y: Int64;
|
|
||||||
begin
|
|
||||||
a1x := A1.X;
|
|
||||||
a1y := A1.Y;
|
|
||||||
Result := Sign((AP.X - a1x) * (A2.Y - a1y) - (AP.Y - a1y) * (A2.X - a1x));
|
|
||||||
end;
|
|
||||||
|
|
||||||
function ProjToRect(
|
|
||||||
const APt: TDoublePoint; const ARect: TDoubleRect): TDoublePoint;
|
|
||||||
begin
|
|
||||||
Result.X := EnsureRange(APt.X, ARect.a.X, ARect.b.X);
|
|
||||||
Result.Y := EnsureRange(APt.Y, ARect.a.Y, ARect.b.Y);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function RadToDeg16(ARad: Double): Integer;
|
function RadToDeg16(ARad: Double): Integer;
|
||||||
begin
|
begin
|
||||||
Result := Round(RadToDeg(ARad) * 16);
|
Result := Round(RadToDeg(ARad) * 16);
|
||||||
@ -765,56 +475,6 @@ begin
|
|||||||
Result := Round(RadToDeg(ARad)) * ORIENTATION_UNITS_PER_DEG;
|
Result := Round(RadToDeg(ARad)) * ORIENTATION_UNITS_PER_DEG;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function RectIntersectsRect(
|
|
||||||
var ARect: TDoubleRect; const AFixed: TDoubleRect): Boolean;
|
|
||||||
|
|
||||||
function RangesIntersect(L1, R1, L2, R2: Double; out L, R: Double): Boolean;
|
|
||||||
begin
|
|
||||||
EnsureOrder(L1, R1);
|
|
||||||
EnsureOrder(L2, R2);
|
|
||||||
L := Max(L1, L2);
|
|
||||||
R := Min(R1, R2);
|
|
||||||
Result := L <= R;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
with ARect do
|
|
||||||
Result :=
|
|
||||||
RangesIntersect(a.X, b.X, AFixed.a.X, AFixed.b.X, a.X, b.X) and
|
|
||||||
RangesIntersect(a.Y, b.Y, AFixed.a.Y, AFixed.b.Y, a.Y, b.Y);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function RotatePoint(const APoint: TDoublePoint; AAngle: Double): TDoublePoint;
|
|
||||||
var
|
|
||||||
sa, ca: Extended;
|
|
||||||
begin
|
|
||||||
SinCos(AAngle, sa, ca);
|
|
||||||
Result.X := ca * APoint.X - sa * APoint.Y;
|
|
||||||
Result.Y := sa * APoint.X + ca * APoint.Y;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function RotatePoint(const APoint: TPoint; AAngle: Double): TPoint;
|
|
||||||
var
|
|
||||||
sa, ca: Extended;
|
|
||||||
begin
|
|
||||||
SinCos(AAngle, sa, ca);
|
|
||||||
Result.X := Round(ca * APoint.X - sa * APoint.Y);
|
|
||||||
Result.Y := Round(sa * APoint.X + ca * APoint.Y);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function RotateRect(const ASize: TPoint; AAngle: Double): TPointArray;
|
|
||||||
var
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
SetLength(Result, 4);
|
|
||||||
Result[0] := -ASize div 2;
|
|
||||||
Result[2] := Result[0] + ASize;
|
|
||||||
Result[1] := Point(Result[2].X, Result[0].Y);
|
|
||||||
Result[3] := Point(Result[0].X, Result[2].Y);
|
|
||||||
for i := 0 to High(Result) do
|
|
||||||
Result[i] := RotatePoint(Result[i], AAngle);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function RoundChecked(A: Double): Integer;
|
function RoundChecked(A: Double): Integer;
|
||||||
begin
|
begin
|
||||||
Result := Round(EnsureRange(A, -MaxInt, MaxInt));
|
Result := Round(EnsureRange(A, -MaxInt, MaxInt));
|
||||||
@ -866,94 +526,11 @@ begin
|
|||||||
Result := AX1 * (1 - ACoeff) + AX2 * ACoeff;
|
Result := AX1 * (1 - ACoeff) + AX2 * ACoeff;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
operator + (const A: TPoint; B: TSize): TPoint;
|
|
||||||
begin
|
|
||||||
Result.X := A.X + B.cx;
|
|
||||||
Result.Y := A.Y + B.cy;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator + (const A, B: TPoint): TPoint;
|
|
||||||
begin
|
|
||||||
Result.X := A.X + B.X;
|
|
||||||
Result.Y := A.Y + B.Y;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator + (const A, B: TDoublePoint): TDoublePoint;
|
|
||||||
begin
|
|
||||||
Result.X := A.X + B.X;
|
|
||||||
Result.Y := A.Y + B.Y;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator - (const A: TPoint): TPoint;
|
|
||||||
begin
|
|
||||||
Result.X := - A.X;
|
|
||||||
Result.Y := - A.Y;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator - (const A, B: TPoint): TPoint;
|
|
||||||
begin
|
|
||||||
Result.X := A.X - B.X;
|
|
||||||
Result.Y := A.Y - B.Y;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator - (const A, B: TDoublePoint): TDoublePoint;
|
|
||||||
begin
|
|
||||||
Result.X := A.X - B.X;
|
|
||||||
Result.Y := A.Y - B.Y;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator div(const A: TPoint; ADivisor: Integer): TPoint;
|
|
||||||
begin
|
|
||||||
Result.X := A.X div ADivisor;
|
|
||||||
Result.Y := A.Y div ADivisor;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator * (const A: TPoint; AMultiplier: Integer): TPoint;
|
|
||||||
begin
|
|
||||||
Result.X := A.X * AMultiplier;
|
|
||||||
Result.Y := A.Y * AMultiplier;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator * (const A, B: TPoint): TPoint;
|
|
||||||
begin
|
|
||||||
Result.X := A.X * B.X;
|
|
||||||
Result.Y := A.Y * B.Y;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator * (const A, B: TDoublePoint): TDoublePoint;
|
|
||||||
begin
|
|
||||||
Result.X := A.X * B.X;
|
|
||||||
Result.Y := A.Y * B.Y;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator / (const A, B: TDoublePoint): TDoublePoint;
|
|
||||||
begin
|
|
||||||
Result.X := A.X / B.X;
|
|
||||||
Result.Y := A.Y / B.Y;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator = (const A, B: TMethod): Boolean;
|
operator = (const A, B: TMethod): Boolean;
|
||||||
begin
|
begin
|
||||||
Result := (A.Code = B.Code) and (A.Data = B.Data);
|
Result := (A.Code = B.Code) and (A.Data = B.Data);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
operator <= (const A, B: TDoublePoint): Boolean;
|
|
||||||
begin
|
|
||||||
Result := (A.X <= B.X) and (A.Y <= B.Y);
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator := (const APoint: TPoint): TSize;
|
|
||||||
begin
|
|
||||||
Result.cx := APoint.X;
|
|
||||||
Result.cy := APoint.Y;
|
|
||||||
end;
|
|
||||||
|
|
||||||
operator := (const ASize: TSize): TPoint;
|
|
||||||
begin
|
|
||||||
Result.X := ASize.cx;
|
|
||||||
Result.Y := ASize.cy;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TIndexedComponentList }
|
{ TIndexedComponentList }
|
||||||
|
|
||||||
procedure TIndexedComponentList.ChangeNamePrefix(
|
procedure TIndexedComponentList.ChangeNamePrefix(
|
||||||
|
@ -217,7 +217,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, PropEdits, Types;
|
Math, PropEdits, TAGeometry, Types;
|
||||||
|
|
||||||
{ TCustomChartSeries }
|
{ TCustomChartSeries }
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, TAChartUtils;
|
Math, TAChartUtils, TAGeometry;
|
||||||
|
|
||||||
{ TAggPasDrawer }
|
{ TAggPasDrawer }
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ procedure PrepareXorPen(ACanvas: TCanvas);
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, TAChartUtils;
|
Math, TAChartUtils, TAGeometry;
|
||||||
|
|
||||||
const
|
const
|
||||||
LINE_INTERVAL = 2;
|
LINE_INTERVAL = 2;
|
||||||
|
@ -140,7 +140,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, SysUtils, TAGraph;
|
Math, SysUtils, TAGeometry, TAGraph;
|
||||||
|
|
||||||
function DoublePointRotated(AX, AY: Double): TDoublePoint;
|
function DoublePointRotated(AX, AY: Double): TDoublePoint;
|
||||||
begin
|
begin
|
||||||
|
450
components/tachart/tageometry.pas
Normal file
450
components/tachart/tageometry.pas
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
*****************************************************************************
|
||||||
|
* *
|
||||||
|
* See the file COPYING.modifiedLGPL.txt, included in this distribution, *
|
||||||
|
* for details about the copyright. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||||
|
* *
|
||||||
|
*****************************************************************************
|
||||||
|
|
||||||
|
Authors: Alexander Klenin
|
||||||
|
|
||||||
|
}
|
||||||
|
unit TAGeometry;
|
||||||
|
|
||||||
|
{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
TAChartUtils, Types;
|
||||||
|
|
||||||
|
function DoublePoint(AX, AY: Double): TDoublePoint; inline;
|
||||||
|
function DoubleRect(AX1, AY1, AX2, AY2: Double): TDoubleRect; inline;
|
||||||
|
procedure ExpandRect(var ARect: TDoubleRect; const APoint: TDoublePoint); inline;
|
||||||
|
procedure ExpandRect(var ARect: TRect; const APoint: TPoint); inline;
|
||||||
|
procedure ExpandRect(
|
||||||
|
var ARect: TRect; const ACenter: TPoint; ARadius: Integer;
|
||||||
|
AAngle1, AAngle2: Double); inline;
|
||||||
|
function IsPointOnLine(const AP, A1, A2: TPoint): Boolean; inline;
|
||||||
|
function IsPointInPolygon(
|
||||||
|
const AP: TPoint; const APolygon: array of TPoint): Boolean;
|
||||||
|
function IsPointInRect(const AP, A1, A2: TPoint): Boolean; inline; overload;
|
||||||
|
function IsPointInRect(const AP: TPoint; const AR: TRect): Boolean; inline; overload;
|
||||||
|
function IsRectInRect(const AInner, AOuter: TRect): Boolean; inline;
|
||||||
|
function IsLineIntersectsLine(const AA, AB, AC, AD: TPoint): Boolean;
|
||||||
|
function IsPolygonIntersectsPolygon(const AP1, AP2: array of TPoint): Boolean;
|
||||||
|
function LineIntersectsRect(
|
||||||
|
var AA, AB: TDoublePoint; const ARect: TDoubleRect): Boolean;
|
||||||
|
procedure NormalizeRect(var ARect: TRect); overload;
|
||||||
|
procedure NormalizeRect(var ARect: TDoubleRect); overload;
|
||||||
|
function MeasureRotatedRect(const ASize: TPoint; AAngle: Double): TSize;
|
||||||
|
function PointDist(const A, B: TPoint): Integer; inline;
|
||||||
|
function PointDistX(const A, B: TPoint): Integer; inline;
|
||||||
|
function PointDistY(const A, B: TPoint): Integer; inline;
|
||||||
|
function ProjToRect(
|
||||||
|
const APt: TDoublePoint; const ARect: TDoubleRect): TDoublePoint;
|
||||||
|
function RectIntersectsRect(
|
||||||
|
var ARect: TDoubleRect; const AFixed: TDoubleRect): Boolean;
|
||||||
|
function RotatePoint(const APoint: TDoublePoint; AAngle: Double): TDoublePoint; overload;
|
||||||
|
function RotatePoint(const APoint: TPoint; AAngle: Double): TPoint; overload;
|
||||||
|
function RotateRect(const ASize: TPoint; AAngle: Double): TPointArray;
|
||||||
|
|
||||||
|
operator +(const A: TPoint; B: TSize): TPoint; overload; inline;
|
||||||
|
operator +(const A, B: TPoint): TPoint; overload; inline;
|
||||||
|
operator +(const A, B: TDoublePoint): TDoublePoint; overload; inline;
|
||||||
|
operator -(const A: TPoint): TPoint; overload; inline;
|
||||||
|
operator -(const A, B: TPoint): TPoint; overload; inline;
|
||||||
|
operator -(const A, B: TDoublePoint): TDoublePoint; overload; inline;
|
||||||
|
operator div(const A: TPoint; ADivisor: Integer): TPoint; inline;
|
||||||
|
operator *(const A: TPoint; AMultiplier: Integer): TPoint; inline;
|
||||||
|
operator *(const A, B: TPoint): TPoint; inline;
|
||||||
|
operator *(const A, B: TDoublePoint): TDoublePoint; overload; inline;
|
||||||
|
operator /(const A, B: TDoublePoint): TDoublePoint; overload; inline;
|
||||||
|
operator <= (const A, B: TDoublePoint): Boolean; overload; inline;
|
||||||
|
operator :=(const APoint: TPoint): TSize; inline;
|
||||||
|
operator :=(const ASize: TSize): TPoint; inline;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
Math;
|
||||||
|
|
||||||
|
function PointLineSide(AP, A1, A2: TPoint): TValueSign; forward;
|
||||||
|
|
||||||
|
function DoublePoint(AX, AY: Double): TDoublePoint; inline;
|
||||||
|
begin
|
||||||
|
Result.X := AX;
|
||||||
|
Result.Y := AY;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function DoubleRect(AX1, AY1, AX2, AY2: Double): TDoubleRect; inline;
|
||||||
|
begin
|
||||||
|
Result.a.X := AX1;
|
||||||
|
Result.a.Y := AY1;
|
||||||
|
Result.b.X := AX2;
|
||||||
|
Result.b.Y := AY2;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ExpandRect(var ARect: TDoubleRect; const APoint: TDoublePoint);
|
||||||
|
begin
|
||||||
|
UpdateMinMax(APoint.X, ARect.a.X, ARect.b.X);
|
||||||
|
UpdateMinMax(APoint.Y, ARect.a.Y, ARect.b.Y);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ExpandRect(var ARect: TRect; const APoint: TPoint);
|
||||||
|
begin
|
||||||
|
UpdateMinMax(APoint.X, ARect.Left, ARect.Right);
|
||||||
|
UpdateMinMax(APoint.Y, ARect.Top, ARect.Bottom);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure ExpandRect(
|
||||||
|
var ARect: TRect; const ACenter: TPoint; ARadius: Integer;
|
||||||
|
AAngle1, AAngle2: Double);
|
||||||
|
var
|
||||||
|
p: TPoint;
|
||||||
|
i, j: Integer;
|
||||||
|
begin
|
||||||
|
p := Point(ARadius, 0);
|
||||||
|
EnsureOrder(AAngle1, AAngle2);
|
||||||
|
ExpandRect(ARect, RotatePoint(p, AAngle1) + ACenter);
|
||||||
|
ExpandRect(ARect, RotatePoint(p, AAngle2) + ACenter);
|
||||||
|
j := Floor(AAngle1 / Pi * 2);
|
||||||
|
for i := j to j + 4 do
|
||||||
|
if InRange(Pi / 2 * i, AAngle1, AAngle2) then
|
||||||
|
ExpandRect(ARect, RotatePoint(p, Pi / 2 * i) + ACenter);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function IsPointOnLine(const AP, A1, A2: TPoint): Boolean;
|
||||||
|
begin
|
||||||
|
Result := IsPointInRect(AP, A1, A2) and (PointLineSide(AP, A1, A2) = 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function IsPointInPolygon(
|
||||||
|
const AP: TPoint; const APolygon: array of TPoint): Boolean;
|
||||||
|
var
|
||||||
|
i, count: Integer;
|
||||||
|
p1, p2: TPoint;
|
||||||
|
s1, s2: TValueSign;
|
||||||
|
begin
|
||||||
|
if Length(APolygon) = 0 then exit(false);
|
||||||
|
p1 := APolygon[High(APolygon)];
|
||||||
|
for i := 0 to High(APolygon) do begin
|
||||||
|
p2 := APolygon[i];
|
||||||
|
if IsPointOnLine(AP, p1, p2) then exit(true);
|
||||||
|
p1 := p2;
|
||||||
|
end;
|
||||||
|
count := 0;
|
||||||
|
p1 := APolygon[High(APolygon)];
|
||||||
|
for i := 0 to High(APolygon) do begin
|
||||||
|
p2 := APolygon[i];
|
||||||
|
s1 := Sign(p1.Y - AP.Y);
|
||||||
|
s2 := Sign(p2.Y - AP.Y);
|
||||||
|
case s1 * s2 of
|
||||||
|
-1: count += Ord(PointLineSide(AP, p1, p2) = Sign(p1.Y - p2.Y));
|
||||||
|
0: if s1 + s2 = 1 then begin
|
||||||
|
if s1 = 0 then
|
||||||
|
count += Ord(p1.X >= AP.X)
|
||||||
|
else
|
||||||
|
count += Ord(p2.X >= AP.X)
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
p1 := p2;
|
||||||
|
end;
|
||||||
|
Result := count mod 2 = 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function IsPointInRect(const AP, A1, A2: TPoint): Boolean;
|
||||||
|
begin
|
||||||
|
Result := SafeInRange(AP.X, A1.X, A2.X) and SafeInRange(AP.Y, A1.Y, A2.Y);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function IsPointInRect(const AP: TPoint; const AR: TRect): Boolean;
|
||||||
|
begin
|
||||||
|
Result :=
|
||||||
|
SafeInRange(AP.X, AR.Left, AR.Right) and
|
||||||
|
SafeInRange(AP.Y, AR.Top, AR.Bottom);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function IsRectInRect(const AInner, AOuter: TRect): Boolean;
|
||||||
|
begin
|
||||||
|
Result :=
|
||||||
|
IsPointInRect(AInner.TopLeft, AOuter) and
|
||||||
|
IsPointInRect(AInner.BottomRight, AOuter);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function IsLineIntersectsLine(const AA, AB, AC, AD: TPoint): Boolean;
|
||||||
|
var
|
||||||
|
sa, sb, sc, sd: TValueSign;
|
||||||
|
begin
|
||||||
|
sa := PointLineSide(AA, AC, AD);
|
||||||
|
sb := PointLineSide(AB, AC, AD);
|
||||||
|
if (sa = 0) and (sb = 0) then
|
||||||
|
// All points are on the same infinite line.
|
||||||
|
Result :=
|
||||||
|
IsPointInRect(AA, AC, AD) or IsPointInRect(AB, AC, AD) or
|
||||||
|
IsPointInRect(AC, AA, AB) or IsPointInRect(AD, AA, AB)
|
||||||
|
else begin
|
||||||
|
sc := PointLineSide(AC, AA, AB);
|
||||||
|
sd := PointLineSide(AD, AA, AB);
|
||||||
|
Result := (sa * sb <= 0) and (sc * sd <= 0);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function IsPolygonIntersectsPolygon(const AP1, AP2: array of TPoint): Boolean;
|
||||||
|
var
|
||||||
|
i, j: Integer;
|
||||||
|
p1, p2: TPoint;
|
||||||
|
begin
|
||||||
|
if (Length(AP1) = 0) or (Length(AP2) = 0) then exit(false);
|
||||||
|
if IsPointInPolygon(AP1[0], AP2) or IsPointInPolygon(AP2[0], AP1) then
|
||||||
|
exit(true);
|
||||||
|
for i := 0 to High(AP1) do begin
|
||||||
|
p1 := AP1[i];
|
||||||
|
p2 := AP1[(i + 1) mod Length(AP1)];
|
||||||
|
for j := 0 to High(AP2) do
|
||||||
|
if IsLineIntersectsLine(p1, p2, AP2[j], AP2[(j + 1) mod Length(AP2)]) then
|
||||||
|
exit(true);
|
||||||
|
end;
|
||||||
|
Result := false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function LineIntersectsRect(
|
||||||
|
var AA, AB: TDoublePoint; const ARect: TDoubleRect): Boolean;
|
||||||
|
var
|
||||||
|
dx, dy: Double;
|
||||||
|
|
||||||
|
procedure AdjustX(var AP: TDoublePoint; ANewX: Double); inline;
|
||||||
|
begin
|
||||||
|
AP.Y += dy / dx * (ANewX - AP.X);
|
||||||
|
AP.X := ANewX;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure AdjustY(var AP: TDoublePoint; ANewY: Double); inline;
|
||||||
|
begin
|
||||||
|
AP.X += dx / dy * (ANewY - AP.Y);
|
||||||
|
AP.Y := ANewY;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
dx := AB.X - AA.X;
|
||||||
|
dy := AB.Y - AA.Y;
|
||||||
|
case CASE_OF_TWO[AA.X < ARect.a.X, AB.X < ARect.a.X] of
|
||||||
|
cotFirst: AdjustX(AA, ARect.a.X);
|
||||||
|
cotSecond: AdjustX(AB, ARect.a.X);
|
||||||
|
cotBoth: exit(false);
|
||||||
|
end;
|
||||||
|
case CASE_OF_TWO[AA.X > ARect.b.X, AB.X > ARect.b.X] of
|
||||||
|
cotFirst: AdjustX(AA, ARect.b.X);
|
||||||
|
cotSecond: AdjustX(AB, ARect.b.X);
|
||||||
|
cotBoth: exit(false);
|
||||||
|
end;
|
||||||
|
case CASE_OF_TWO[AA.Y < ARect.a.Y, AB.Y < ARect.a.Y] of
|
||||||
|
cotFirst: AdjustY(AA, ARect.a.Y);
|
||||||
|
cotSecond: AdjustY(AB, ARect.a.Y);
|
||||||
|
cotBoth: exit(false);
|
||||||
|
end;
|
||||||
|
case CASE_OF_TWO[AA.Y > ARect.b.Y, AB.Y > ARect.b.Y] of
|
||||||
|
cotFirst: AdjustY(AA, ARect.b.Y);
|
||||||
|
cotSecond: AdjustY(AB, ARect.b.Y);
|
||||||
|
cotBoth: exit(false);
|
||||||
|
end;
|
||||||
|
Result := true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function MeasureRotatedRect(const ASize: TPoint; AAngle: Double): TSize;
|
||||||
|
var
|
||||||
|
pt1, pt2: TPoint;
|
||||||
|
begin
|
||||||
|
pt1 := RotatePoint(ASize, AAngle);
|
||||||
|
pt2 := RotatePoint(Point(ASize.X, -ASize.Y), AAngle);
|
||||||
|
Result.cx := Max(Abs(pt1.X), Abs(pt2.X));
|
||||||
|
Result.cy := Max(Abs(pt1.Y), Abs(pt2.Y));
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure NormalizeRect(var ARect: TRect);
|
||||||
|
begin
|
||||||
|
with ARect do begin
|
||||||
|
EnsureOrder(Left, Right);
|
||||||
|
EnsureOrder(Top, Bottom);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure NormalizeRect(var ARect: TDoubleRect); overload;
|
||||||
|
begin
|
||||||
|
with ARect do begin
|
||||||
|
EnsureOrder(a.X, b.X);
|
||||||
|
EnsureOrder(a.Y, b.Y);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function PointLineSide(AP, A1, A2: TPoint): TValueSign;
|
||||||
|
var
|
||||||
|
a1x, a1y: Int64;
|
||||||
|
begin
|
||||||
|
a1x := A1.X;
|
||||||
|
a1y := A1.Y;
|
||||||
|
Result := Sign((AP.X - a1x) * (A2.Y - a1y) - (AP.Y - a1y) * (A2.X - a1x));
|
||||||
|
end;
|
||||||
|
|
||||||
|
function PointDist(const A, B: TPoint): Integer;
|
||||||
|
begin
|
||||||
|
Result := Min(Sqr(Int64(A.X) - B.X) + Sqr(Int64(A.Y) - B.Y), MaxInt);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function PointDistX(const A, B: TPoint): Integer;
|
||||||
|
begin
|
||||||
|
Result := Min(Abs(Int64(A.X) - B.X), MaxInt);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function PointDistY(const A, B: TPoint): Integer; inline;
|
||||||
|
begin
|
||||||
|
Result := Min(Abs(Int64(A.Y) - B.Y), MaxInt);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function ProjToRect(
|
||||||
|
const APt: TDoublePoint; const ARect: TDoubleRect): TDoublePoint;
|
||||||
|
begin
|
||||||
|
Result.X := EnsureRange(APt.X, ARect.a.X, ARect.b.X);
|
||||||
|
Result.Y := EnsureRange(APt.Y, ARect.a.Y, ARect.b.Y);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RectIntersectsRect(
|
||||||
|
var ARect: TDoubleRect; const AFixed: TDoubleRect): Boolean;
|
||||||
|
|
||||||
|
function RangesIntersect(L1, R1, L2, R2: Double; out L, R: Double): Boolean;
|
||||||
|
begin
|
||||||
|
EnsureOrder(L1, R1);
|
||||||
|
EnsureOrder(L2, R2);
|
||||||
|
L := Max(L1, L2);
|
||||||
|
R := Min(R1, R2);
|
||||||
|
Result := L <= R;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
with ARect do
|
||||||
|
Result :=
|
||||||
|
RangesIntersect(a.X, b.X, AFixed.a.X, AFixed.b.X, a.X, b.X) and
|
||||||
|
RangesIntersect(a.Y, b.Y, AFixed.a.Y, AFixed.b.Y, a.Y, b.Y);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RotatePoint(const APoint: TDoublePoint; AAngle: Double): TDoublePoint;
|
||||||
|
var
|
||||||
|
sa, ca: Extended;
|
||||||
|
begin
|
||||||
|
SinCos(AAngle, sa, ca);
|
||||||
|
Result.X := ca * APoint.X - sa * APoint.Y;
|
||||||
|
Result.Y := sa * APoint.X + ca * APoint.Y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RotatePoint(const APoint: TPoint; AAngle: Double): TPoint;
|
||||||
|
var
|
||||||
|
sa, ca: Extended;
|
||||||
|
begin
|
||||||
|
SinCos(AAngle, sa, ca);
|
||||||
|
Result.X := Round(ca * APoint.X - sa * APoint.Y);
|
||||||
|
Result.Y := Round(sa * APoint.X + ca * APoint.Y);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function RotateRect(const ASize: TPoint; AAngle: Double): TPointArray;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
SetLength(Result, 4);
|
||||||
|
Result[0] := -ASize div 2;
|
||||||
|
Result[2] := Result[0] + ASize;
|
||||||
|
Result[1] := Point(Result[2].X, Result[0].Y);
|
||||||
|
Result[3] := Point(Result[0].X, Result[2].Y);
|
||||||
|
for i := 0 to High(Result) do
|
||||||
|
Result[i] := RotatePoint(Result[i], AAngle);
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator + (const A: TPoint; B: TSize): TPoint;
|
||||||
|
begin
|
||||||
|
Result.X := A.X + B.cx;
|
||||||
|
Result.Y := A.Y + B.cy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator + (const A, B: TPoint): TPoint;
|
||||||
|
begin
|
||||||
|
Result.X := A.X + B.X;
|
||||||
|
Result.Y := A.Y + B.Y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator + (const A, B: TDoublePoint): TDoublePoint;
|
||||||
|
begin
|
||||||
|
Result.X := A.X + B.X;
|
||||||
|
Result.Y := A.Y + B.Y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator - (const A: TPoint): TPoint;
|
||||||
|
begin
|
||||||
|
Result.X := - A.X;
|
||||||
|
Result.Y := - A.Y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator - (const A, B: TPoint): TPoint;
|
||||||
|
begin
|
||||||
|
Result.X := A.X - B.X;
|
||||||
|
Result.Y := A.Y - B.Y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator - (const A, B: TDoublePoint): TDoublePoint;
|
||||||
|
begin
|
||||||
|
Result.X := A.X - B.X;
|
||||||
|
Result.Y := A.Y - B.Y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator div(const A: TPoint; ADivisor: Integer): TPoint;
|
||||||
|
begin
|
||||||
|
Result.X := A.X div ADivisor;
|
||||||
|
Result.Y := A.Y div ADivisor;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator * (const A: TPoint; AMultiplier: Integer): TPoint;
|
||||||
|
begin
|
||||||
|
Result.X := A.X * AMultiplier;
|
||||||
|
Result.Y := A.Y * AMultiplier;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator * (const A, B: TPoint): TPoint;
|
||||||
|
begin
|
||||||
|
Result.X := A.X * B.X;
|
||||||
|
Result.Y := A.Y * B.Y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator * (const A, B: TDoublePoint): TDoublePoint;
|
||||||
|
begin
|
||||||
|
Result.X := A.X * B.X;
|
||||||
|
Result.Y := A.Y * B.Y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator / (const A, B: TDoublePoint): TDoublePoint;
|
||||||
|
begin
|
||||||
|
Result.X := A.X / B.X;
|
||||||
|
Result.Y := A.Y / B.Y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator <= (const A, B: TDoublePoint): Boolean;
|
||||||
|
begin
|
||||||
|
Result := (A.X <= B.X) and (A.Y <= B.Y);
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator := (const APoint: TPoint): TSize;
|
||||||
|
begin
|
||||||
|
Result.cx := APoint.X;
|
||||||
|
Result.cy := APoint.Y;
|
||||||
|
end;
|
||||||
|
|
||||||
|
operator := (const ASize: TSize): TPoint;
|
||||||
|
begin
|
||||||
|
Result.X := ASize.cx;
|
||||||
|
Result.Y := ASize.cy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -102,7 +102,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, SysUtils, TAGraph;
|
Math, SysUtils, TAGeometry, TAGraph;
|
||||||
|
|
||||||
{ TBubbleSeries }
|
{ TBubbleSeries }
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Math,
|
Math,
|
||||||
TACustomSource, TAGraph;
|
TACustomSource, TAGeometry, TAGraph;
|
||||||
|
|
||||||
{ TCustomPieSeries }
|
{ TCustomPieSeries }
|
||||||
|
|
||||||
|
@ -312,7 +312,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
GraphMath, LResources, Math, PropEdits, SysUtils,
|
GraphMath, LResources, Math, PropEdits, SysUtils,
|
||||||
TAGraph;
|
TAGeometry, TAGraph;
|
||||||
|
|
||||||
{ TLineSeries }
|
{ TLineSeries }
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
ComponentEditors, Forms, GraphMath, Math, PropEdits, SysUtils,
|
ComponentEditors, Forms, GraphMath, Math, PropEdits, SysUtils,
|
||||||
TACustomSeries, TADrawUtils, TASubcomponentsEditor;
|
TACustomSeries, TADrawUtils, TAGeometry, TASubcomponentsEditor;
|
||||||
|
|
||||||
type
|
type
|
||||||
{ TToolsComponentEditor }
|
{ TToolsComponentEditor }
|
||||||
|
@ -23,7 +23,7 @@ Authors: Luнs Rodrigues, Philippe Martinole, Alexander Klenin
|
|||||||
}
|
}
|
||||||
unit TATypes;
|
unit TATypes;
|
||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$H+}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@ -314,7 +314,7 @@ type
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
TACustomSource;
|
TACustomSource, TAGeometry;
|
||||||
|
|
||||||
{ TChartPen }
|
{ TChartPen }
|
||||||
|
|
||||||
|
@ -68,6 +68,9 @@ type
|
|||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
TAGeometry;
|
||||||
|
|
||||||
{ TIntervalListTest }
|
{ TIntervalListTest }
|
||||||
|
|
||||||
procedure TIntervalListTest.Basic;
|
procedure TIntervalListTest.Basic;
|
||||||
|
Loading…
Reference in New Issue
Block a user