2014-09-19 50 views
9

我希望我有些困惑。我收到一些與TRect.IntersectTRect.IntersectsWith不一致的行爲。以下是一些演示問題的代碼。TRect.Intersect and TRect.IntersectsWith Inconsistencies

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獲取新的相交矩形時,它將返回一個空矩形。

由於Self.BottomRight.Y = R.TopLeft.Y(100),IntersectsWith中的代碼(不會非常清晰地寫入)在第二種情況下返回true。

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; 

的問題是,IsRectEmpty其通過Intersect檢查稱爲以查看是否RECT的任一的頂部和底部或矩形的左和右具有相同的值和通過當Intersect設置結果到一個空的rect。

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; 

回答

6

這是一個錯誤;這不可能是預期的行爲。在當前的實現中,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()的重載同樣被打破。

+0

謝謝,我已經添加了一些你的信息(http://qc.embarcadero.com/wc/qcmain.aspx?d=127696) – Graymatter 2014-09-19 07:02:58

+0

嗯......兩個空的rec是相同的,所以當然他們相交,國際海事組織。當然,交叉點是空矩形。但是'Rect(0,0,100,200)'和'Rect(0,100,200,200)'不應該相交,即使它們名義上具有'(0,100)'共同點(但實際上並不是這樣,因爲這一點在Windows中不屬於第一條約束)。 – 2014-09-20 10:50:23

+0

@Rudy - 一個空矩形不是一個矩形。它不能與任何東西相交,甚至沒有內部/區域。 – 2014-09-20 11:08:09