TAChart: Add IsLineIntersectsLine and IsPointInRect utility functions

git-svn-id: trunk@26690 -
This commit is contained in:
ask 2010-07-16 17:50:16 +00:00
parent 3a4d1d6c19
commit c786d4253b
3 changed files with 62 additions and 5 deletions

View File

@ -188,7 +188,9 @@ procedure ExpandRect(var ARect: TDoubleRect; const APoint: TDoublePoint); inline
function GetIntervals(AMin, AMax: Double; AInverted: Boolean): TDoubleDynArray;
function IsPointOnLine(const AP, A1, A2: TPoint): Boolean;
function IsPointOnLine(const AP, A1, A2: TPoint): Boolean; inline;
function IsPointInRect(const AP, A1, A2: TPoint): Boolean; inline;
function IsLineIntersectsLine(const AA, AB, AC, AD: TPoint): Boolean;
function LineIntersectsRect(
var AA, AB: TDoublePoint; const ARect: TDoubleRect): Boolean;
@ -221,6 +223,8 @@ operator =(const A, B: TMethod): Boolean; overload; inline;
implementation
function PointLineSide(AP, A1, A2: TPoint): TValueSign; forward;
function BoundsSize(ALeft, ATop: Integer; ASize: TSize): TRect; inline;
begin
Result := Bounds(ALeft, ATop, ASize.cx, ASize.cy);
@ -418,10 +422,30 @@ end;
function IsPointOnLine(const AP, A1, A2: TPoint): Boolean;
begin
Result :=
SafeInRange(AP.X, A1.X, A2.X) and
SafeInRange(AP.Y, A1.Y, A2.Y) and
((AP.X - A1.X) * (A2.Y - A1.Y) = (AP.Y - A1.Y) * (A2.X - A1.X));
Result := IsPointInRect(AP, A1, A2) and (PointLineSide(AP, A1, A2) = 0);
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 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 LineIntersectsRect(
@ -498,6 +522,15 @@ begin
Result := Abs(A.Y - B.Y);
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 RectIntersectsRect(
var ARect: TDoubleRect; const AFixed: TDoubleRect): Boolean;

View File

@ -46,6 +46,7 @@ type
private
procedure AssertEquals(const Expected, Actual: TDoublePoint); overload;
published
procedure TestLineIntersectsLine;
procedure TestLineIntersectsRect;
procedure TestPointOnLine;
end;
@ -128,6 +129,23 @@ begin
AssertEquals(Expected.Y, Actual.Y);
end;
procedure TGeometryTest.TestLineIntersectsLine;
var
p1, p2: TPoint;
begin
p1 := Point(0, 0);
p2 := Point(1, 1);
AssertTrue(IsLineIntersectsLine(Point(1, 0), Point(0, 1), p1, p2));
AssertTrue(IsLineIntersectsLine(Point(1, 0), Point(0, 0), p1, p2));
AssertTrue(IsLineIntersectsLine(Point(1, 1), Point(2, 2), p1, p2));
AssertFalse(IsLineIntersectsLine(Point(2, 2), Point(3, 3), p1, p2));
AssertTrue(IsLineIntersectsLine(Point(2, 0), Point(0, 2), p1, p2));
AssertFalse(IsLineIntersectsLine(Point(3, 0), Point(0, 3), p1, p2));
p2 := Point(1, 0);
AssertTrue(IsLineIntersectsLine(Point(0, 0), Point(2, 0), p1, p2));
AssertFalse(IsLineIntersectsLine(Point(0, 1), Point(1, 1), p1, p2));
end;
procedure TGeometryTest.TestLineIntersectsRect;
var
r: TDoubleRect = (a: (X: 0; Y: 0); b: (X: 20; Y: 10));

View File

@ -62,6 +62,12 @@
<IncludeFiles Value="$(ProjOutDir)\"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<CodeGeneration>
<Checks>
<RangeChecks Value="True"/>
<OverflowChecks Value="True"/>
</Checks>
</CodeGeneration>
<Other>
<CompilerMessages>
<UseMsgFile Value="True"/>