Einzelnen Beitrag anzeigen

Blup

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

AW: Abschlussprojekt FIAE (Optimierung von Algorithmen) -> Vergleich von Polygonen

  Alt 21. Mär 2022, 13:30
Bitte für das Formular eine eigene Unit.
Damit kannst du dir eine Bibliothek schreiben, die wenger Abhängigkeiten hat.
Das erleichtert auch die Implementation von Testfällen.

Mal ein erster Ansatz:
Delphi-Quellcode:
unit CadVec3;

interface

uses
  Generics.Collections;

type
  TCadVec3 = record
    x: Integer;
    y: Integer;
    z: Integer;
  end;

  TCadVec3List = TList<TCadVec3>;

// Globale Methoden.
  procedure RemoveIdenticalFromList(AList: TCadVec3List; AOpen: Boolean);

  function IsListItemEqual(AItem1, AItem2: TCadVec3): Boolean;
  function IsListEqual(AList1, AList2: TCadVec3List; AOffset: Integer): Boolean;

  function CompareOpenPolygons(AFirstList, ASecondList: TCadVec3List): Boolean; overload;
  function CompareOpenPolygons(AFirstList, ASecondList: TCadVec3List; ADirectional: Boolean): Boolean; overload;
  function CompareClosedPolygon(AFirstList, ASecondList: TCadVec3List): Boolean; overload;
  function CompareClosedPolygon(AFirstList, ASecondList: TCadVec3List; ADirectional: Boolean): Boolean; overload;

  function CompareBothLists(AFirstList, ASecondList: TCadVec3List; ADirectional, AFirstListOpen, ASecondListOpen: Boolean): Boolean;

implementation


function CompareBothLists(AFirstList, ASecondList: TCadVec3List; ADirectional, AFirstListOpen, ASecondListOpen: Boolean): Boolean;
var
  LFirstTmpList, LSecondTmpList: TCadVec3List;
begin
// Vergleich der Listen bzw. der Polygone und ob diese geometrisch gleich, oder ungleich sind.
// Hierbei werden verschiedene Rahmenbedingungen und Szenarien aufgeführt -> geschlossene Polygone, offene Polygone, geschlossenes/offenes Polygon.
  if (AFirstList = nil) or (ASecondList = nil) then
    Exit(False);

  LFirstTmpList := TCadVec3List.Create;
  LSecondTmpList := TCadVec3List.Create;
  try
    LFirstTmpList.AddRange(AFirstList);
    LSecondTmpList.AddRange(ASecondList);
    RemoveIdenticalFromList(LFirstTmpList, AFirstListOpen);
    RemoveIdenticalFromList(LSecondTmpList, ASecondListOpen);

    if AFirstListOpen and ASecondListOpen then
    begin
      if LFirstTmpList.Count <> LSecondTmpList.Count then
        Exit(False);

      Result := CompareOpenPolygons(LFirstTmpList, LSecondTmpList, ADirectional)
    end
    else
    begin
      if AFirstListOpen then
      begin
        if not IsListItemEqual(LFirstTmpList.First, LFirstTmpList.Last) then
          Exit(False);

        LFirstTmpList.Delete(LFirstTmpList.Count - 1);
      end
      else if ASecondListOpen then
      begin
        if not IsListItemEqual(LSecondTmpList.First, LSecondTmpList.Last) then
          Exit(False);

        LSecondTmpList.Delete(LSecondTmpList.Count - 1);
      end
      else // if not AFirstListOpen and not ASecondListOpen then
      begin
        if LFirstTmpList.Count <> LSecondTmpList.Count then
          Exit(False);
      end;

      Result := CompareClosedPolygon(LFirstTmpList, LSecondTmpList, ADirectional);
    end;
  finally
    LSecondTmpList.Free;
    LFirstTmpList.Free;
  end;
end;

function CompareClosedPolygon(AFirstList, ASecondList: TCadVec3List): Boolean;
var
  i: Integer;
begin
  // Vergleich von geschlossenen Polygonen bzw. einem offenen und einem geschlossenen Polygon.
  for i := 0 to ASecondList.Count - 1 do
  begin
    if IsListItemEqual(AFirstList[0], ASecondList[i]) then
    begin
      if IsListEqual(AFirstList, ASecondList, i) then
        Exit(True);
    end;
  end;
  Result := False;
end;

function CompareClosedPolygon(AFirstList, ASecondList: TCadVec3List; ADirectional: Boolean): Boolean;
begin
  Result := CompareClosedPolygon(AFirstList, ASecondList);
  if (not Result) and ADirectional then
  begin
    ASecondList.Reverse;
    Result := CompareClosedPolygon(AFirstList, ASecondList);
    ASecondList.Reverse;
  end;
end;

function CompareOpenPolygons(AFirstList, ASecondList: TCadVec3List): Boolean;
begin
// Vegleich von zwei offenen Polygonen.
  Result := IsListEqual(AFirstList, ASecondList, 0);
end;

function CompareOpenPolygons(AFirstList, ASecondList: TCadVec3List;
  ADirectional: Boolean): Boolean;
begin
  Result := CompareOpenPolygons(AFirstList, ASecondList);
  if (not Result) and ADirectional then
  begin
    ASecondList.Reverse;
    Result := CompareOpenPolygons(AFirstList, ASecondList);
    ASecondList.Reverse;
  end;
end;

function IsListEqual(AList1, AList2: TCadVec3List; AOffset: Integer): Boolean;
var
  i1, i2, iCount: Integer;
begin
// AOffset .. StartIndex in List2,
  iCount := AList2.Count;
  i2 := AOffset;
  for i1 := 0 to AList1.Count - 1 do
  begin
    if not IsListItemEqual(AList1[i1], AList2[i2]) then
      Exit(False);

    i2 := (i2 + 1) mod iCount;
  end;
  Result := True;
end;

function IsListItemEqual(AItem1, AItem2: TCadVec3): Boolean;
begin
  Result := (AItem1.x = AItem2.x) and (AItem1.y = AItem2.y) and (AItem1.z = AItem2.z);
end;

procedure RemoveIdenticalFromList(AList: TCadVec3List; AOpen: Boolean);
var
  i: Integer;
begin
// Entferne doppelte, aufeinander Folgende Eintr�ge bzw. Elemente.
  for i := AList.Count - 1 downto 1 do
  begin
    if IsListItemEqual(AList[i], AList[i - 1]) then
      AList.Delete(i);
  end;

  if not AOpen then
  begin
    if IsListItemEqual(AList.First, AList.Last) then
      AList.Delete(AList.Count - 1);
  end;
  AList.TrimExcess;
end;

end.

Geändert von Blup (21. Mär 2022 um 22:15 Uhr) Grund: Fehler in IsListEqual
  Mit Zitat antworten Zitat