Einzelnen Beitrag anzeigen

Benutzerbild von timog
timog

Registriert seit: 26. Sep 2006
Ort: Landkreis Oldenburg (Oldb)
117 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#9

AW: Voronoi-Diagramme

  Alt 29. Mai 2019, 20:37
Dieser Ansatz dürfte langsamer als die Polygon Methode von RosettaCode.org sein, aber sie tut's - glaube ich

Delphi-Quellcode:
procedure TformMain.DrawVoronoi(AImage: TImage; const AP, ACells: Integer; ADistanceType: TDistanceType);
var
  px, py: array of Integer;
  LColor: array of TColor;
  LImg: TBitmap;
  n, i, x, y, j: Integer;
  d1, d2: Double;

  function GetDistance(const x1, x2, y1, y2, AP: Integer; const ADistanceType: TDistanceType): Double;
  begin
    case ADistanceType of
      dtManhattan: Result := Abs(x1 - x2) + Abs(y1 - y2);
      dtMinkovski: Result := Power(Power(Abs(x1 - x2), AP) + Power(Abs(y1 - y2), AP), (1 / AP));
    else
      Result := Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); // dtEuclidian
    end;
  end;

begin
  LImg := nil;
  try
    LImg := TBitmap.Create;
    LImg.Width := AImage.Width;
    LImg.Height := AImage.Height;

    SetLength(px, ACells);
    SetLength(py, ACells);
    SetLength(LColor, ACells);

    // Zufällige Zellen/Sites erzeugen
    for i := 0 to ACells - 1 do
    begin
      px[i] := RandomRange(1, AImage.Width-1); // nicht direkt auf dem Rand
      py[i] := RandomRange(1, AImage.Height-1);
      LColor[i] := GenerateRandomColor;
    end;

    // In x und y Richtung die Entfernungen ermitteln, Farbe der am nächsten liegenden Zelle bestimmen
    for x := 0 to AImage.Width - 1 do
    begin
      for y := 0 to AImage.Height - 1 do
      begin
        n := 0;
        for i := 0 to ACells - 1 do
        begin
          d1 := GetDistance(px[i], x, py[i], y, AP, ADistanceType);
          d2 := GetDistance(px[n], x, py[n], y, AP, ADistanceType);
          if d1 < d2 then n := i;
        end;
        LImg.Canvas.Pixels[x, y]:=LColor[n];
      end;
    end;

    // Zelle/Site zeichnen
    for j := 0 to ACells - 1 do
    begin
      LImg.Canvas.Pen.Color := clBlack;
      LImg.Canvas.Brush.Color := clBlack;
      LImg.Canvas.Rectangle(px[j] - 2, py[j] - 2, px[j] + 2, py[j] + 2);
    end;

    AImage.Picture.Assign(LImg);
  finally
    LImg.Free;
  end;
end;
Miniaturansicht angehängter Grafiken
voronoi.png  
Angehängte Dateien
Dateityp: 7z Voronoi.7z (52,4 KB, 13x aufgerufen)
Timo
Real Programmers are surprised when the odometers in their cars don't turn from 99999 to 9999A.
  Mit Zitat antworten Zitat