I am hoping that I am confused in some way. I am getting some inconsistent behavior with TRect.Intersect
and TRect.IntersectsWith
. Here is some code that demonstrates the problem.
program RectCheck;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Types,
Vcl.Dialogs;
var
rect1: TRect;
rect2: TRect;
combinedRect: TRect;
begin
Rect1 := Rect(0,0,200,101);
Rect2 := Rect(0,100,200,200);
if Rect1.IntersectsWith(Rect2) then
begin
// We have interesected, get the combined rect
combinedRect := TRect.Intersect(Rect1, Rect2);
if not combinedRect.IsEmpty then
ShowMessage(Format('Our new rect (%d, %d), (%d, %d)',
[combinedRect.Left, combinedRect.Top, combinedRect.Right, combinedRect.Bottom]))
else
raise Exception.Create('They were supposed to intersect!');
end;
Rect1 := Rect(0,0,200,100);
Rect2 := Rect(0,100,200,200);
if Rect1.IntersectsWith(Rect2) then
begin
// We have interesected, get the combined rect
combinedRect := TRect.Intersect(Rect1, Rect2);
if not combinedRect.IsEmpty then
ShowMessage(Format('Our new rect (%d, %d), (%d, %d)',
[combinedRect.Left, combinedRect.Top, combinedRect.Right, combinedRect.Bottom]))
else
raise Exception.Create('They were supposed to intersect!');
end;
end.
The second exception is raised. TRect.IntersectsWith
indicates that the rects intersect but when I call TRect.Intersect
to get the new intersected rect then it returns an empty rect.
The code in IntersectsWith (which isn't written very clearly) is returning true in the second case because Self.BottomRight.Y = R.TopLeft.Y (100).
function TRect.IntersectsWith(const R: TRect): Boolean;
begin
Result := not ( (Self.BottomRight.X < R.TopLeft.X) or
(Self.BottomRight.Y < R.TopLeft.Y) or
(R.BottomRight.X < Self.TopLeft.X) or
(R.BottomRight.Y < Self.TopLeft.Y) );
end;
The problem is that IsRectEmpty
which is called by Intersect
checks to see if either the top and bottom of the rect or the left and right of the rect have the same values and when that passes Intersect
sets the result to an empty rect.
function IsRectEmpty(const Rect: TRect): Boolean;
begin
Result := (Rect.Right <= Rect.Left) or (Rect.Bottom <= Rect.Top);
end;
Is this the expected behavior and if not what should be changed. My understanding is that TRects exclude the bottom and right "edges" and if that's the case shouldn't TRect.IntersectsWith
look something like this?
function TRect.IntersectsWith(const R: TRect): Boolean;
begin
Result := not ( (Self.BottomRight.X <= R.TopLeft.X) or
(Self.BottomRight.Y <= R.TopLeft.Y) or
(R.BottomRight.X <= Self.TopLeft.X) or
(R.BottomRight.Y <= Self.TopLeft.Y) );
end;