unit MathRect;
interface
uses
Types;
type
TRectArray =
array of TRect;
function Subtract(
const R1, R2: TRect): TRectArray;
implementation
function Min(A, B: Integer): Integer;
begin
if A < B
then
Result := A
else
Result := B;
end;
function Max(A, B: Integer): Integer;
begin
if A > B
then
Result := A
else
Result := B;
end;
function IntersectRect(
out Rect: TRect;
const R1: TRect;
const R2: TRect): Boolean;
begin
Result :=
(R2.Top < R1.Bottom)
and (R1.Top < R2.Bottom)
and
(R2.Left < R1.Right)
and (R1.Left < R2.Right);
if Result
then
begin
Rect.Top := Max(R1.Top, R2.Top);
Rect.Left := Max(R1.Left, R2.Left);
Rect.Bottom := Min(R1.Bottom, R2.Bottom);
Rect.Right := Min(R1.Right, R2.Right);
end;
end;
function IsRectEmpty(
const Rect: TRect): Boolean;
begin
Result := (Rect.Left >= Rect.Right)
or (Rect.Top >= Rect.Bottom);
end;
procedure AddRect(
var RectArr: TRectArray;
const Rect: TRect);
var
n: Integer;
begin
if IsRectEmpty(Rect)
then
Exit;
{anfügen}
for n := 0
to High(RectArr)
do
begin
{selbe Zeile}
if (RectArr[n].Top = Rect.Top)
and
(RectArr[n].Bottom = Rect.Bottom)
then
begin
{rechts}
if RectArr[n].Right = Rect.Left
then
begin
RectArr[n].Right := Rect.Right;
Exit;
end;
{links - derzeit auf Grund der Reihenfolge nicht verwendet}
if RectArr[n].Left = Rect.Right
then
begin
RectArr[n].Left := Rect.Left;
Exit;
end;
end;
{selbe Spalte}
if (RectArr[n].Left = Rect.Left)
and
(RectArr[n].Right = Rect.Right)
then
begin
{unten}
if RectArr[n].Bottom = Rect.Top
then
begin
RectArr[n].Bottom := Rect.Bottom;
Exit;
end;
{oben - derzeit auf Grund der Reihenfolge nicht verwendet}
if RectArr[n].Top = Rect.Bottom
then
begin
RectArr[n].Top := Rect.Top;
Exit;
end;
end;
end;
{eigenständiges Recheck hinzufügen}
n := Length(RectArr);
SetLength(RectArr, n + 1);
RectArr[n] := Rect;
end;
function Subtract(
const R1, R2: TRect): TRectArray;
var
A:
array[0..2, 0..2]
of TRect;
B: TRect;
x, y: Integer;
begin
Result :=
nil;
{Das tatsächliche Überschneidungsrechteck B ermitteln}
if not IntersectRect(B, R1, R2)
then
begin
{keine Überschneidung}
AddRect(Result, R1);
Exit;
end;
{Zeilen}
for y := 0
to 2
do
begin
A[0, y].Left := R1.Left;
A[0, y].Right := B.Left;
A[1, y].Left := B.Left;
A[1, y].Right := B.Right;
A[2, y].Left := B.Right;
A[2, y].Right := R1.Right;
end;
{Spalten}
for x := 0
to 2
do
begin
A[x, 0].Top := R1.Top;
A[x, 0].Bottom := B.Top;
A[x, 1].Top := B.Top;
A[x, 1].Bottom := B.Bottom;
A[x, 2].Top := B.Bottom;
A[x, 2].Bottom := R1.Bottom;
end;
{benachbarte Rechtecke zusammenfassen}
for y := 0
to 2
do
for x := 0
to 2
do
if not ((y = 1)
and (x = 1))
then
AddRect(Result, A[x, y]);
end;
end.