我希望我在某种程度上感到困惑。我得到了一些与TRect.Intersect
和TRect.IntersectsWith
不一致的行为。以下是一些演示该问题的代码。
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.
引发了第二个异常。TRect.IntersectsWith
表示矩形相交,但当我调用TRect.Intersect
以获得新的相交矩形时,它返回一个空矩形。
IntersectsWith中的代码(写得不太清楚)在第二种情况下返回true,因为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;
问题是Intersect
调用的IsRectEmpty
检查矩形的顶部和底部或者矩形的左侧和右侧是否具有相同的值,并且当通过Intersect
时将结果设置为空矩形。
function IsRectEmpty(const Rect: TRect): Boolean;
begin
Result := (Rect.Right <= Rect.Left) or (Rect.Bottom <= Rect.Top);
end;
这是预期的行为吗?如果不是,应该改变什么。我的理解是,TRects排除了底部和右侧的"边缘",如果是这样的话,TRect.IntersectsWith
不应该是这样的吗?
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;
这是一个bug;这不可能是预期的行为。在当前的实现中,RTL认为两个空的矩形可以相交(例如(0,0,0,0)
、(0,0,0,0)
或一个非空的矩形与一个空的),这没有任何意义。
Assert(Rect(0, 0, 0, 0).IntersectsWith(Rect(0, 0, 0, 0)));
上述断言没有失败。
此外,它不符合Windows api。以下断言失败:winapi认为(0,0,200,100)
和(0,100,200,200)
不相交。
Assert(winapi.windows.IntersectRect(OutRect, Rect(0,0,200,100), Rect(0,100,200,200)));
返回布尔值的System.Types.IntersectRect()
的重载同样被破坏。