Changeset 91 for trunk/UTrack.pas


Ignore:
Timestamp:
Sep 22, 2022, 10:57:26 PM (20 months ago)
Author:
chronos
Message:
  • Modified: More classes separated from UEngine unit.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/UTrack.pas

    r86 r91  
    44
    55uses
    6   Classes, SysUtils, Generics.Collections;
     6  Classes, SysUtils, Math, Generics.Collections;
    77
    88type
    99  TTrack = class;
    1010  TTrackPoints = class;
     11  TTrackLink = class;
    1112  TTrackLinks = class;
    1213
     
    1415
    1516  TTrackPoint = class
     17    OwnerPoint: TObject;
     18    Position: TPoint;
     19    //PositionShift: TPoint;
     20    PositionDesigned: TPoint;
     21    Pending: Boolean;
    1622    Track: TTrack;
    17     Position: TPoint;
    1823    NeighPoints: TTrackPoints;
    1924    NeighLinks: TTrackLinks;
     25    LinkUp: TTrackLink;
     26    LinkDown: TTrackLink;
    2027    procedure Connect(TrackPoint: TTrackPoint);
    2128    procedure Disconnect(TrackPoint: TTrackPoint);
     29    function GetDown: TTrackPoint;
     30    function GetUp: TTrackPoint;
     31    function GetNeighDown: TTrackPoint;
     32    function GetNeighUp: TTrackPoint;
     33    function GetLinkDown: TTrackLink;
     34    function GetLinkUp: TTrackLink;
     35    // Move to TTrackLink later
     36    function GetDistance: Integer;
    2237    constructor Create;
    2338    destructor Destroy; override;
     
    2742
    2843  TTrackPoints = class(TObjectList<TTrackPoint>)
     44    Track: TTrack;
     45    function AddNew: TTrackPoint;
    2946  end;
    3047
     
    3249
    3350  TTrackLink = class
    34     Track: TTrack;
    3551    Points: TTrackPoints;
     52    Shift: TPoint;
    3653    constructor Create;
    3754    destructor Destroy; override;
     
    4259  TTrackLinks = class(TObjectList<TTrackLink>)
    4360    function SearchPoints(Point1, Point2: TTrackPoint): TTrackLink;
     61    function AddNew: TTrackLink;
    4462  end;
    4563
     
    4765
    4866  TTrack = class
    49   public
    5067    Points: TTrackPoints;
    5168    Links: TTrackLinks;
    52     function AddNew: TTrackPoint;
     69    Owner: TObject;
     70    function GetLength: Integer;
     71    procedure RouteTrack(TP1, TP2: TTrackPoint);
     72    procedure RemoveTrackBetween(TP1, TP2: TTrackPoint);
    5373    constructor Create;
    5474    destructor Destroy; override;
    55     procedure RemoveTrackBetween(TP1, TP2: TTrackPoint);
     75  end;
     76
     77  { TTrackPointsAngle }
     78
     79  TTrackPointsAngle = class
     80    Angle: Double;
     81    TrackLinks: TTrackLinks;
     82    constructor Create;
     83    destructor Destroy; override;
     84  end;
     85
     86  { TTrackPointsAngleGroup }
     87
     88  TTrackPointsAngleGroup = class(TObjectList<TTrackPointsAngle>)
     89    function SearchAngle(Angle: Double): TTrackPointsAngle;
    5690  end;
    5791
    5892
    5993implementation
     94
     95uses
     96  UGeometric;
     97
     98resourcestring
     99  SAlreadyConnectedTrackPoint = 'Trying to connect already connected track point';
     100  SAlreadyDisconnectedTrackPoint = 'Trying to disconnect not connected track point';
     101  STrackPointNotFound = 'Track point %d not found';
    60102
    61103{ TTrackLinks }
     
    67109  I := 0;
    68110  while (I < 0) and
    69   ((Items[I].Points.First <> Point1) or (Items[I].Points.Last <> Point2))
    70   and ((Items[I].Points.First <> Point2) or (Items[I].Points.Last <> Point1)) do
     111    ((Items[I].Points.First <> Point1) or (Items[I].Points.Last <> Point2)) and
     112    ((Items[I].Points.First <> Point2) or (Items[I].Points.Last <> Point1)) do
    71113  Inc(I);
    72114  if I < 0 then Result := Items[I]
     
    74116end;
    75117
     118function TTrackLinks.AddNew: TTrackLink;
     119begin
     120  Result := TTrackLink.Create;
     121end;
     122
     123{ TTrackPoints }
     124
     125function TTrackPoints.AddNew: TTrackPoint;
     126begin
     127  Result := TTrackPoint.Create;
     128  Result.Track := Track;
     129end;
     130
     131{ TTrack }
     132
     133constructor TTrack.Create;
     134begin
     135  Points := TTrackPoints.Create;
     136  Points.Track := Self;
     137  Links := TTrackLinks.Create;
     138end;
     139
     140destructor TTrack.Destroy;
     141begin
     142  FreeAndNil(Points);
     143  FreeAndNil(Links);
     144  inherited;
     145end;
     146
     147function TTrack.GetLength: Integer;
     148var
     149  I: Integer;
     150begin
     151  Result := 0;
     152  for I := 0 to Points.Count - 1 do
     153  if I > 0 then
     154    Result := Result + Distance(Points[I].Position, Points[I - 1].Position);
     155end;
     156
     157procedure TTrack.RouteTrack(TP1, TP2: TTrackPoint);
     158var
     159  NewTrackPoint: TTrackPoint;
     160  Delta: TPoint;
     161  P1, P2: TPoint;
     162  Index1, Index2: Integer;
     163begin
     164  RemoveTrackBetween(TP1, TP2);
     165  Index1 := Points.IndexOf(TP1);
     166  Index2 := Points.IndexOf(TP2);
     167  P1 := Points[Index1].PositionDesigned;
     168  P2 := Points[Index2].PositionDesigned;
     169  NewTrackPoint := Points.AddNew;
     170  Delta := Point(P2.X - P1.X, P2.Y - P1.Y);
     171  if Abs(Delta.X) > Abs(Delta.Y) then begin
     172    NewTrackPoint.PositionDesigned := Point(P2.X - Sign(Delta.X) * Abs(Delta.Y), P1.Y);
     173    NewTrackPoint.Position := NewTrackPoint.PositionDesigned;
     174  end else begin
     175    NewTrackPoint.PositionDesigned := Point(P1.X, P2.Y - Sign(Delta.Y) * Abs(Delta.X));
     176    NewTrackPoint.Position := NewTrackPoint.PositionDesigned;
     177  end;
     178  Points.Insert(Index1 + 1, NewTrackPoint);
     179end;
     180
     181procedure TTrack.RemoveTrackBetween(TP1, TP2: TTrackPoint);
     182var
     183  Index1, Index2: Integer;
     184  Temp: Integer;
     185  I: Integer;
     186begin
     187  Index1 := Points.IndexOf(TP1);
     188  Index2 := Points.IndexOf(TP2);
     189  if (Index1 = -1) then
     190    raise Exception.Create(Format(STrackPointNotFound, [1]));
     191  if (Index2 = -1) then
     192    raise Exception.Create(Format(STrackPointNotFound, [2]));
     193  if Index1 > Index2 then begin
     194    Temp := Index1;
     195    Index1 := Index2;
     196    Index2 := Temp;
     197  end;
     198  for I := 1 to Index2 - Index1 - 1 do
     199    Points.Delete(Index1 + 1);
     200end;
     201
    76202{ TTrackLink }
    77203
     
    84210destructor TTrackLink.Destroy;
    85211begin
    86   Points.Free;
     212  FreeAndNil(Points);
    87213  inherited;
    88214end;
    89215
    90 { TTrackPoints }
    91 
    92 function TTrack.AddNew: TTrackPoint;
    93 begin
    94   Result := TTrackPoint.Create;
    95   Result.Track := Self;
    96   Points.Add(Result);
     216{ TTrackPointsAngleGroup }
     217
     218function TTrackPointsAngleGroup.SearchAngle(Angle: Double): TTrackPointsAngle;
     219var
     220  I: Integer;
     221begin
     222  I := 0;
     223  while (I < Count) and (Items[I].Angle <> Angle) do Inc(I);
     224  if I < Count then Result := Items[I]
     225    else Result := nil;
     226end;
     227
     228{ TTrackPointsAngle }
     229
     230constructor TTrackPointsAngle.Create;
     231begin
     232  TrackLinks := TTrackLinks.Create;
     233  TrackLinks.OwnsObjects := False;
     234end;
     235
     236destructor TTrackPointsAngle.Destroy;
     237begin
     238  FreeAndNil(TrackLinks);
     239  inherited;
    97240end;
    98241
     
    106249    NeighPoints.Add(TrackPoint);
    107250    TrackPoint.NeighPoints.Add(Self);
    108     // Add new link
    109     NewLink := TTrackLink.Create;
     251
     252    // Add new link to both self and connected track point
     253    NewLink := Track.Links.AddNew;
    110254    NewLink.Points.Add(TrackPoint);
    111255    NewLink.Points.Add(Self);
     
    113257    TrackPoint.NeighLinks.Add(NewLink);
    114258    Track.Links.Add(NewLink);
    115   end;
     259  end else raise Exception.Create(SAlreadyConnectedTrackPoint);
    116260end;
    117261
     
    125269    NeighPoints.Delete(Index);
    126270    TrackPoint.NeighPoints.Remove(Self);
    127     // Remove link
     271
     272    // Remove link from both track points
    128273    Link := NeighLinks.SearchPoints(Self, TrackPoint);
    129274    NeighLinks.Remove(Link);
    130275    TrackPoint.NeighLinks.Remove(Link);
    131276    Track.Links.Remove(Link);
    132   end;
     277  end else raise Exception.Create(SAlreadyDisconnectedTrackPoint);
     278end;
     279
     280function TTrackPoint.GetDown: TTrackPoint;
     281var
     282  I: Integer;
     283begin
     284  I := Track.Points.IndexOf(Self) - 1;
     285  while (I >= 0) and not Assigned(Track.Points[I].OwnerPoint) do
     286    Dec(I);
     287  if I >= 0 then Result := Track.Points[I]
     288    else Result := nil;
     289end;
     290
     291function TTrackPoint.GetUp: TTrackPoint;
     292var
     293  I: Integer;
     294begin
     295  I := Track.Points.IndexOf(Self) + 1;
     296  while (I < Track.Points.Count) and not Assigned(Track.Points[I].OwnerPoint) do
     297    Inc(I);
     298  if I < Track.Points.Count then Result := Track.Points[I]
     299    else Result := nil;
     300end;
     301
     302function TTrackPoint.GetNeighDown: TTrackPoint;
     303var
     304  NewIndex: Integer;
     305begin
     306  Result := nil;
     307  NewIndex := Track.Points.IndexOf(Self) - 1;
     308  if NewIndex >= 0 then Result := Track.Points[NewIndex];
     309end;
     310
     311function TTrackPoint.GetNeighUp: TTrackPoint;
     312var
     313  NewIndex: Integer;
     314begin
     315  Result := nil;
     316  if Assigned(Track) then begin
     317    NewIndex := Track.Points.IndexOf(Self) + 1;
     318    if NewIndex < Track.Points.Count then Result := Track.Points[NewIndex];
     319  end;
     320end;
     321
     322function TTrackPoint.GetLinkDown: TTrackLink;
     323begin
     324  if Assigned(LinkDown) then Result := LinkDown
     325    else begin
     326      LinkDown := TTrackLink.Create;
     327      LinkDown.Points.Add(GetNeighDown);
     328      LinkDown.Points.Add(Self);
     329      Result := LinkDown;
     330      GetNeighDown.LinkUp := LinkDown;
     331    end;
     332end;
     333
     334function TTrackPoint.GetLinkUp: TTrackLink;
     335begin
     336  if Assigned(LinkUp) then Result := LinkUp
     337    else begin
     338      LinkUp := TTrackLink.Create;
     339      LinkUp.Points.Add(Self);
     340      LinkUp.Points.Add(GetNeighUp);
     341      Result := LinkUp;
     342      GetNeighUp.LinkDown := LinkUp;
     343    end;
     344end;
     345
     346function TTrackPoint.GetDistance: Integer;
     347var
     348  Index: Integer;
     349begin
     350  Index := Track.Points.IndexOf(Self);
     351  Result := Distance(Track.Points[Index + 1].Position, Track.Points[Index].Position);
    133352end;
    134353
     
    137356  NeighPoints := TTrackPoints.Create;
    138357  NeighPoints.OwnsObjects := False;
     358  NeighLinks := TTrackLinks.Create;
     359  NeighLinks.OwnsObjects := False;
    139360end;
    140361
    141362destructor TTrackPoint.Destroy;
    142 var
    143   I: Integer;
    144 begin
    145   // Disconnect from all before destruction
    146   for I := NeighPoints.Count - 1 downto 0 do
    147     NeighPoints[I].Disconnect(Self);
    148   if Assigned(Track) then Track.Points.Remove(Self);
    149   NeighPoints.Free;
     363begin
     364  FreeAndNil(NeighLinks);
     365  FreeAndNil(NeighPoints);
    150366  inherited;
    151367end;
    152368
    153 { TTrack }
    154 
    155 constructor TTrack.Create;
    156 begin
    157   Points := TTrackPoints.Create;
    158 end;
    159 
    160 destructor TTrack.Destroy;
    161 begin
    162   Points.Free;
    163   inherited;
    164 end;
    165 
    166 procedure TTrack.RemoveTrackBetween(TP1, TP2: TTrackPoint);
    167 var
    168   Index1, Index2: Integer;
    169   Temp: Integer;
    170   I: Integer;
    171 begin
    172   Index1 := Points.IndexOf(TP1);
    173   Index2 := Points.IndexOf(TP2);
    174   if (Index1 = -1) then
    175     raise Exception.Create('TrackPoint1 not found');
    176   if (Index2 = -1) then
    177     raise Exception.Create('TrackPoint2 not found');
    178   if Index1 > Index2 then begin
    179     Temp := Index1;
    180     Index1 := Index2;
    181     Index2 := Temp;
    182   end;
    183   for I := 1 to Index2 - Index1 - 1 do
    184     Points.Delete(Index1 + 1);
    185 end;
    186 
    187 
    188369end.
    189370
Note: See TracChangeset for help on using the changeset viewer.