Ich hatte kürzlich in einem Programm unerwartete Fehler registriert und dann festgestellt, dass die Funktionen IntersectRect und Rect.IntersectsWith, beide in System.Types, falsche Resultate liefern, wenn die beiden Rechtecke direkt aneinander grenzen.
Beide Funktionen betrachten Rect.Right und Rect.Bottom als innerhalb der Fläche des Rechtecks.
Tatsächlich liegen Rect.Right und Rect.Bottom außerhalb der Fläche des Rechtecks.
Oder mache ich da einen Denkfehler?
Beschreibung aus
OH
TRect definiert ein Rechteck.
TRect repräsentiert die Abmessungen eines Rechtecks. Die Koordinaten werden entweder als vier einzelne Integerwerte angegeben, die den linken, oberen, rechten und unteren Rand definieren, oder als zwei Punkte, die die Position der linken, oberen sowie der rechten, unteren Ecke angeben.
Normalerweise repräsentieren TRect-Werte Pixel-Positionen, wobei der Ursprung des Koordinatensystems in der oberen, linken Ecke des Bildschirms (Bildschirmkoordinaten) oder in der oberen, linken Ecke des Client-Bereichs (Client-Koordinaten) eines Steuerelements liegt. Wenn ein TRect-Wert ein Rechteck auf dem Bildschirm darstellt,
liegen die oberen und die linken Ecken konventionsgemäß innerhalb des Rechtecks und die
unteren und rechten Ecken außerhalb des Rechtecks. Durch diese Konvention kann die Breite des Rechtecks mit Right – Left und die Höhe mit Bottom – Top ermittelt werden.
Delphi-Quellcode:
function IntersectRect(const Rect1, Rect2: TRect): Boolean;
begin
Result := (Rect1.Left <= Rect2.Right) and
(Rect1.Right >= Rect2.Left) and
(Rect1.Top <= Rect2.Bottom) and
(Rect1.Bottom >= Rect2.Top);
end;
Delphi-Quellcode:
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;
Korrekt wäre es m.E. zum Beispiel so
Delphi-Quellcode:
FUNCTION MyIntersectRect(const A,B:TRect):Boolean;
begin
Result:=(A.Left<B.Right) and (A.Right>B.Left) and (A.Top<B.Bottom) and (A.Bottom>B.Top);
end;