Spero di essere confuso in qualche modo. Sto ottenendo alcuni comportamenti incoerenti con TRect.Intersect
e TRect.IntersectsWith
. Ecco un codice che dimostra il problema.TRect.Intersect e TRect.IntersectsWith Incoistenze
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.
La seconda eccezione viene sollevata. TRect.IntersectsWith
indica che i rects si intersecano ma quando chiamo TRect.Intersect
per ottenere il nuovo rect intersecato, restituisce un rect vuoto.
Il codice in IntersectsWith (che non è scritto in modo molto chiaro) restituisce true nel secondo caso perché 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;
Il problema è che IsRectEmpty
quale è invocato Intersect
verifica se sia nella parte superiore e inferiore del rettangolo o sinistra e destra del rettangolo hanno gli stessi valori e quando passa Intersect
imposta il risultato un rect vuoto.
function IsRectEmpty(const Rect: TRect): Boolean;
begin
Result := (Rect.Right <= Rect.Left) or (Rect.Bottom <= Rect.Top);
end;
È questo il comportamento previsto e, in caso contrario, quello che dovrebbe essere modificato. La mia comprensione è che i TRects escludono i "bordi" inferiori e quelli giusti e, in tal caso, non dovrebbe essere lo TRect.IntersectsWith
simile a questo?
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;
Grazie, ho aggiunto un controllo di qualità con alcune delle tue informazioni (http://qc.embarcadero.com/wc/qcmain.aspx?d=127696) – Graymatter
Hmmm ... Due recs vuoti sono identici, quindi ovviamente si intersecano, IMO. L'intersezione è, ovviamente, il rect vuoto. Ma 'Rect (0, 0, 100, 200)' e 'Rect (0, 100, 200, 200)' non dovrebbero intersecare, IMO, anche se, nominalmente, hanno il punto '(0, 100)' in comune (ma non in realtà, poiché quel punto è, in Windows, non parte del primo rect). –
@Rudy - Un rect vuoto è un rect che non lo è. Non può intersecare nulla, non ha nemmeno un interno/area. –