Changeset 91 for trunk/UTrack.pas
- Timestamp:
- Sep 22, 2022, 10:57:26 PM (20 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/UTrack.pas
r86 r91 4 4 5 5 uses 6 Classes, SysUtils, Generics.Collections;6 Classes, SysUtils, Math, Generics.Collections; 7 7 8 8 type 9 9 TTrack = class; 10 10 TTrackPoints = class; 11 TTrackLink = class; 11 12 TTrackLinks = class; 12 13 … … 14 15 15 16 TTrackPoint = class 17 OwnerPoint: TObject; 18 Position: TPoint; 19 //PositionShift: TPoint; 20 PositionDesigned: TPoint; 21 Pending: Boolean; 16 22 Track: TTrack; 17 Position: TPoint;18 23 NeighPoints: TTrackPoints; 19 24 NeighLinks: TTrackLinks; 25 LinkUp: TTrackLink; 26 LinkDown: TTrackLink; 20 27 procedure Connect(TrackPoint: TTrackPoint); 21 28 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; 22 37 constructor Create; 23 38 destructor Destroy; override; … … 27 42 28 43 TTrackPoints = class(TObjectList<TTrackPoint>) 44 Track: TTrack; 45 function AddNew: TTrackPoint; 29 46 end; 30 47 … … 32 49 33 50 TTrackLink = class 34 Track: TTrack;35 51 Points: TTrackPoints; 52 Shift: TPoint; 36 53 constructor Create; 37 54 destructor Destroy; override; … … 42 59 TTrackLinks = class(TObjectList<TTrackLink>) 43 60 function SearchPoints(Point1, Point2: TTrackPoint): TTrackLink; 61 function AddNew: TTrackLink; 44 62 end; 45 63 … … 47 65 48 66 TTrack = class 49 public50 67 Points: TTrackPoints; 51 68 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); 53 73 constructor Create; 54 74 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; 56 90 end; 57 91 58 92 59 93 implementation 94 95 uses 96 UGeometric; 97 98 resourcestring 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'; 60 102 61 103 { TTrackLinks } … … 67 109 I := 0; 68 110 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)) do111 ((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 71 113 Inc(I); 72 114 if I < 0 then Result := Items[I] … … 74 116 end; 75 117 118 function TTrackLinks.AddNew: TTrackLink; 119 begin 120 Result := TTrackLink.Create; 121 end; 122 123 { TTrackPoints } 124 125 function TTrackPoints.AddNew: TTrackPoint; 126 begin 127 Result := TTrackPoint.Create; 128 Result.Track := Track; 129 end; 130 131 { TTrack } 132 133 constructor TTrack.Create; 134 begin 135 Points := TTrackPoints.Create; 136 Points.Track := Self; 137 Links := TTrackLinks.Create; 138 end; 139 140 destructor TTrack.Destroy; 141 begin 142 FreeAndNil(Points); 143 FreeAndNil(Links); 144 inherited; 145 end; 146 147 function TTrack.GetLength: Integer; 148 var 149 I: Integer; 150 begin 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); 155 end; 156 157 procedure TTrack.RouteTrack(TP1, TP2: TTrackPoint); 158 var 159 NewTrackPoint: TTrackPoint; 160 Delta: TPoint; 161 P1, P2: TPoint; 162 Index1, Index2: Integer; 163 begin 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); 179 end; 180 181 procedure TTrack.RemoveTrackBetween(TP1, TP2: TTrackPoint); 182 var 183 Index1, Index2: Integer; 184 Temp: Integer; 185 I: Integer; 186 begin 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); 200 end; 201 76 202 { TTrackLink } 77 203 … … 84 210 destructor TTrackLink.Destroy; 85 211 begin 86 Points.Free;212 FreeAndNil(Points); 87 213 inherited; 88 214 end; 89 215 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 218 function TTrackPointsAngleGroup.SearchAngle(Angle: Double): TTrackPointsAngle; 219 var 220 I: Integer; 221 begin 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; 226 end; 227 228 { TTrackPointsAngle } 229 230 constructor TTrackPointsAngle.Create; 231 begin 232 TrackLinks := TTrackLinks.Create; 233 TrackLinks.OwnsObjects := False; 234 end; 235 236 destructor TTrackPointsAngle.Destroy; 237 begin 238 FreeAndNil(TrackLinks); 239 inherited; 97 240 end; 98 241 … … 106 249 NeighPoints.Add(TrackPoint); 107 250 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; 110 254 NewLink.Points.Add(TrackPoint); 111 255 NewLink.Points.Add(Self); … … 113 257 TrackPoint.NeighLinks.Add(NewLink); 114 258 Track.Links.Add(NewLink); 115 end ;259 end else raise Exception.Create(SAlreadyConnectedTrackPoint); 116 260 end; 117 261 … … 125 269 NeighPoints.Delete(Index); 126 270 TrackPoint.NeighPoints.Remove(Self); 127 // Remove link 271 272 // Remove link from both track points 128 273 Link := NeighLinks.SearchPoints(Self, TrackPoint); 129 274 NeighLinks.Remove(Link); 130 275 TrackPoint.NeighLinks.Remove(Link); 131 276 Track.Links.Remove(Link); 132 end; 277 end else raise Exception.Create(SAlreadyDisconnectedTrackPoint); 278 end; 279 280 function TTrackPoint.GetDown: TTrackPoint; 281 var 282 I: Integer; 283 begin 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; 289 end; 290 291 function TTrackPoint.GetUp: TTrackPoint; 292 var 293 I: Integer; 294 begin 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; 300 end; 301 302 function TTrackPoint.GetNeighDown: TTrackPoint; 303 var 304 NewIndex: Integer; 305 begin 306 Result := nil; 307 NewIndex := Track.Points.IndexOf(Self) - 1; 308 if NewIndex >= 0 then Result := Track.Points[NewIndex]; 309 end; 310 311 function TTrackPoint.GetNeighUp: TTrackPoint; 312 var 313 NewIndex: Integer; 314 begin 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; 320 end; 321 322 function TTrackPoint.GetLinkDown: TTrackLink; 323 begin 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; 332 end; 333 334 function TTrackPoint.GetLinkUp: TTrackLink; 335 begin 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; 344 end; 345 346 function TTrackPoint.GetDistance: Integer; 347 var 348 Index: Integer; 349 begin 350 Index := Track.Points.IndexOf(Self); 351 Result := Distance(Track.Points[Index + 1].Position, Track.Points[Index].Position); 133 352 end; 134 353 … … 137 356 NeighPoints := TTrackPoints.Create; 138 357 NeighPoints.OwnsObjects := False; 358 NeighLinks := TTrackLinks.Create; 359 NeighLinks.OwnsObjects := False; 139 360 end; 140 361 141 362 destructor 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; 363 begin 364 FreeAndNil(NeighLinks); 365 FreeAndNil(NeighPoints); 150 366 inherited; 151 367 end; 152 368 153 { TTrack }154 155 constructor TTrack.Create;156 begin157 Points := TTrackPoints.Create;158 end;159 160 destructor TTrack.Destroy;161 begin162 Points.Free;163 inherited;164 end;165 166 procedure TTrack.RemoveTrackBetween(TP1, TP2: TTrackPoint);167 var168 Index1, Index2: Integer;169 Temp: Integer;170 I: Integer;171 begin172 Index1 := Points.IndexOf(TP1);173 Index2 := Points.IndexOf(TP2);174 if (Index1 = -1) then175 raise Exception.Create('TrackPoint1 not found');176 if (Index2 = -1) then177 raise Exception.Create('TrackPoint2 not found');178 if Index1 > Index2 then begin179 Temp := Index1;180 Index1 := Index2;181 Index2 := Temp;182 end;183 for I := 1 to Index2 - Index1 - 1 do184 Points.Delete(Index1 + 1);185 end;186 187 188 369 end. 189 370
Note:
See TracChangeset
for help on using the changeset viewer.