Changeset 165 for trunk/UMap.pas


Ignore:
Timestamp:
Nov 22, 2017, 4:48:33 PM (7 years ago)
Author:
chronos
Message:
  • Added: Optimization phase for voronoi map generation.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UMap.pas

    r164 r165  
    271271  Intersection: TPoint;
    272272  CellDistance: TCellsDistance;
    273   R1, R2: TRect;
    274273  Cell: TCell;
    275   CellsAngle: TObjectList; // TObjecTList<TCellsDistance>
    276   CellAngle: TCellsDistance;
    277   NextCellAngle: TCellsDistance;
    278274  L1, L2: TLine;
    279275  MP: TPoint;
    280276  LinkLine: TLine;
    281277  Polygon: TPolygon;
     278  //LeftLink: TCellsDistance;
     279  //CenterLink: TCellsDistance;
     280  //RightLink: TCellsDistance;
     281  LeftClosingLine1: TLine;
     282  LeftClosingLine2: TLine;
     283  RightClosingLine1: TLine;
     284  RightClosingLine2: TLine;
     285  CurrentAngle: Double;
     286  LeftAngle: Double;
     287  RightAngle: Double;
     288  CenterCell: TCell;
     289  LeftCell: TCell;
     290  RightCell: TCell;
     291  LeftIndex: Integer;
     292  RightIndex: Integer;
     293  LeftCenterCell: TCell;
     294  RightCenterCell: TCell;
     295  ChangesCount: Integer;
     296  LeftCellCommon: TCell;
     297  RightCellCommon: TCell;
     298  LeftText: string;
     299  RightText: string;
    282300begin
    283301  Clear;
    284 
    285   // Allocate and init new
     302  RandSeed := 1234;
     303
     304  // Allocate and init new cells
    286305  Cells.Count := Size.Y * Size.X;
    287306  for Y := 0 to Size.Y - 1 do
     
    325344        TCellsDistance(SelectedCells[J]).Cell2.PosPx);
    326345      if LineIntersect(L1, L2, Intersection) then begin
    327           R1 := PointsToRect(TCellsDistance(CellsDistance[I]).Cell1.PosPx,
    328             TCellsDistance(CellsDistance[I]).Cell2.PosPx);
    329           R2 := PointsToRect(TCellsDistance(SelectedCells[J]).Cell1.PosPx,
    330             TCellsDistance(SelectedCells[J]).Cell2.PosPx);
    331           if PointInRect(Intersection, R1) and PointInRect(Intersection, R2) then begin
    332             Intersected := True;
    333             Break;
    334           end;
     346        if PointInRect(Intersection, L1.ToRect) and
     347        PointInRect(Intersection, L2.ToRect) then begin
     348          Intersected := True;
     349          Break;
    335350        end;
     351      end;
    336352    end;
    337353    if not Intersected then SelectedCells.Add(CellsDistance[I]);
     
    348364  FreeAndNil(SelectedCells);
    349365  FreeAndNil(CellsDistance);
     366  SortNeighborsByAngle;
     367
     368  while True do begin
     369  ChangesCount := 0;
     370  // Optimize link lines for lower angle
     371  for Cell in Cells do begin
     372    // Change link if lower angle can be achieved
     373    for I := 0 to Cell.Neighbors.Count - 1 do begin
     374      LeftCell := Cell.Neighbors[I];
     375      RightCell := Cell.Neighbors[(I + 1) mod Cell.Neighbors.Count];
     376      LeftText := LeftCell.Neighbors.ToString;
     377      RightText := RightCell.Neighbors.ToString;
     378      LeftIndex := LeftCell.Neighbors.IndexOf(Cell);
     379      RightIndex := RightCell.Neighbors.IndexOf(Cell);
     380      LeftCellCommon := LeftCell.Neighbors[(LeftIndex + LeftCell.Neighbors.Count - 1) mod LeftCell.Neighbors.Count];
     381      RightCellCommon := RightCell.Neighbors[(RightIndex + 1) mod RightCell.Neighbors.Count];
     382      if (LeftCellCommon = RightCell) and
     383      (RightCellCommon = LeftCell) then begin
     384        LeftCenterCell := LeftCell.Neighbors[(LeftIndex + LeftCell.Neighbors.Count - 2) mod LeftCell.Neighbors.Count];
     385        RightCenterCell := RightCell.Neighbors[(RightIndex + 2) mod RightCell.Neighbors.Count];
     386
     387        if LeftCenterCell = RightCenterCell then begin
     388          CenterCell := LeftCenterCell;
     389
     390          LeftClosingLine1 := TLine.Create(LeftCell.PosPx, Cell.PosPx);
     391          LeftClosingLine2 := TLine.Create(LeftCell.PosPx,
     392            CenterCell.PosPx);
     393          LeftAngle := SubAngle(LeftClosingLine1.GetAngle,
     394            LeftClosingLine2.GetAngle);
     395
     396          RightClosingLine1 := TLine.Create(RightCell.PosPx, Cell.PosPx);
     397          RightClosingLine2 := TLine.Create(RightCell.PosPx,
     398            CenterCell.PosPx);
     399          RightAngle := SubAngle(RightClosingLine2.GetAngle,
     400            RightClosingLine1.GetAngle);
     401
     402          LeftClosingLine1 := TLine.Create(Cell.PosPx, LeftCell.PosPx);
     403          RightClosingLine1 := TLine.Create(Cell.PosPx, RightCell.PosPx);
     404          CurrentAngle := SubAngle(RightClosingLine1.GetAngle,
     405            LeftClosingLine1.GetAngle);
     406          if (CurrentAngle > LeftAngle) and (CurrentAngle > RightAngle) then begin
     407            LeftCell.DisconnectFrom(RightCell);
     408            Cell.ConnectTo(CenterCell);
     409            SortNeighborsByAngle;
     410            Inc(ChangesCount);
     411          end;
     412        end;
     413        //end;
     414      end;
     415    end;
     416  end;
     417  if ChangesCount = 0 then Break;
     418  end;
    350419
    351420  // Compute polygon around cells with sequence sorted by link angle
    352421  for Cell in Cells do begin
    353     CellsAngle := TObjectList.Create;
    354     for I := 0 to Cell.Neighbors.Count - 1 do begin
    355       CellAngle := TCellsDistance.Create;
    356       CellAngle.Cell1 := Cell;
    357       CellAngle.Cell2 := TCell(Cell.Neighbors[I]);
    358       CellAngle.Distance := ArcTan2Point(Point(
    359         CellAngle.Cell2.PosPx.X - CellAngle.Cell1.PosPx.X,
    360         CellAngle.Cell2.PosPx.Y - CellAngle.Cell1.PosPx.Y));
    361       CellsAngle.Add(CellAngle);
    362     end;
    363     CellsAngle.Sort(CompareDistance);
    364 
    365422    // Use whole map first for cell polygon
    366     if CellsAngle.Count > 0 then begin
     423    if Cell.Neighbors.Count > 0 then begin
    367424      Polygon := TPolygon.Create(Rect(0, 0,
    368425        Size.X * DefaultCellSize.X, Size.Y * DefaultCellSize.Y));
    369       for I := 0 to CellsAngle.Count - 1 do begin
    370         CellAngle := TCellsDistance(CellsAngle[I]);
    371         LinkLine := TLine.Create(CellAngle.Cell1.PosPx,
    372           CellAngle.Cell2.PosPx);
     426      for I := 0 to Cell.Neighbors.Count - 1 do begin
     427        LinkLine := TLine.Create(Cell.PosPx,
     428          Cell.Neighbors[I].PosPx);
     429        LinkLine.Distance := LinkLine.Distance - 4;
    373430        MP := LinkLine.GetMiddle;
    374431        // Create half plane vector
    375         L1 := TLine.Create(MP, Point(MP.X + LinkLine.GetSize.X, MP.Y + LinkLine.GetSize.Y));
     432        L1 := TLine.Create(MP, Point(MP.X + LinkLine.GetSize.X,
     433          MP.Y + LinkLine.GetSize.Y));
    376434
    377435        Polygon.CutLine(L1, Cell.PosPx);
     
    379437      Cell.Polygon := Polygon.Points;
    380438    end else SetLength(Cell.Polygon, 0);
    381 
    382     FreeAndNil(CellsAngle);
    383439  end;
    384440
Note: See TracChangeset for help on using the changeset viewer.