Einzelnen Beitrag anzeigen

Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.429 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Zwei Vier-Ecke subtrahieren

  Alt 1. Mär 2017, 15:51
Hab ein bischen Zeit gehabt und meine Idee umgesetzt und erfolgreich getestet.
Auf vordefinierte Funktionen wurde verzichtet, der Austausch von TRect durch eine eigene Klasse sollte also kein Problem sein.
Delphi-Quellcode:
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.
  Mit Zitat antworten Zitat