Bug: IntersectRect liefert falsche Resultate
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:
Korrekt wäre es m.E. zum Beispiel so
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;
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; |
AW: Bug: IntersectRect liefert falsche Resultate
Zitat:
Bei Dir wird false geliefert: Irgendwo müssen auch <= bzw >= im Vergleich auftauchen. Im Original wird das durch das not erschlagen. |
AW: Bug: IntersectRect liefert falsche Resultate
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Im anhängenden Bild ist A=Rect(35,5,65,35) B=Rect(5,5,35,35) A.Left = B.Right Und wo überschneiden sich die Rechtecke? Bedenke: B.Right liegt außerhalb der Fläche des Rechtecks B. So ist nun einmal TRect definiert. Left und Top liegen innerhalb der Fläche. Right und Bottom liegen außerhalb der Fläche. |
AW: Bug: IntersectRect liefert falsche Resultate
Ich denke, dass Du Recht hast (und frage mich, warum mir das nicht aufgefallen war - vielleicht ist das in XE3 schon gefixt? Ich schaue das heute Abend mal nach.)
|
AW: Bug: IntersectRect liefert falsche Resultate
Zitat:
|
AW: Bug: IntersectRect liefert falsche Resultate
Zitat:
|
AW: Bug: IntersectRect liefert falsche Resultate
Liste der Anhänge anzeigen (Anzahl: 1)
Das gelbe Rect1 ist Left=2 und Right=5.
Der Bereich ist dann real 2..4. Das blaue Rect2 ist dann Left=5 und Right=8. Der Bereich ist dann real 5..7. Die beiden Rects grenzen nur aneinander, aber es gibt keine Überschneidung. Dass die Rects Left und Top den realen Wert widerspiegeln und Right und Bottom 1 Pixel weiter außerhalb liegen hat mich auch schon einige graue Haare gekostet (trage jetzt Glatze ;-)) |
AW: Bug: IntersectRect liefert falsche Resultate
Zitat:
Delphi-Quellcode:
besagt aber gerade, daß die so geteilten Rechtecke eben nicht eine Seite gemeinsam haben. Die Trennlinie beschreibt zwar die rechte Kante des linken Rechtecks, gehört aber per Definition nicht dazu.
TRect
Anders ausgedrückt würde eine Schleife über die X-Werte eines Rechtecks so lauten:
Delphi-Quellcode:
for I := A.Left to A.Right - 1 do
Wie schon erwähnt, ist dies in späteren Delphi-Versionen gefixt. |
AW: Bug: IntersectRect liefert falsche Resultate
Zitat:
Bleiben wir trotzdem bei Deinem Beispiel. Wir haben also ein Rechteck. Der obere linke Eckpunkt soll bei 5,5 liegen und es soll 60 Pixel breit und 30 Pixel hoch sein. Nun trennen wir es in der Mitte durch eine senkrechte Linie und nennen den linken Teil B und den rechten Teil A. Da wir die beiden Rechtecke ja nicht nur denken sondern auch zeichnen wollen, brauchen wir die Koordinaten von A und B. Wenn wir die haben, zeichnen wir beide Rechtecke mit Canvas.Rectangle, wobei beide Rechtecke einen 1 Pixel breiten Rahmen haben sollen und die Rechtecke und Rahmen sichtbar unterschiedliche Farben haben sollen, damit wir genau sehen wo welches Rechteck beginnt und wo welches endet. Liefere du bitte die Koordinaten der beiden TRects A und B. |
AW: Bug: IntersectRect liefert falsche Resultate
Wenn man in der Mitte eine Linie zieht und diese beide Rects begrenzt überschneiden sich beide tatsächlich um ein Pixel.
Man muss also das rechte Rect noch um ein Pixel nach rechts verschieben und erhält die gegebene Situation (und in der Mitte eine 2 Pixel breite Linie). Ich sehe gerade, in XE3 ist die Funktion auch noch falsch und ich hatte auch eine eigene geschrieben. :roteyes: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:55 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz