Changeset 36


Ignore:
Timestamp:
May 10, 2015, 1:41:11 AM (9 years ago)
Author:
chronos
Message:
  • Modified: Improved positioning of metro lines which are go in parallel so they should not overlay each other.
Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/BigMetro.lpi

    r29 r36  
    8080        <HasResources Value="True"/>
    8181        <ResourceBaseClass Value="Form"/>
    82         <UnitName Value="UFormMain"/>
    8382      </Unit1>
    8483      <Unit2>
    8584        <Filename Value="UEngine.pas"/>
    8685        <IsPartOfProject Value="True"/>
    87         <UnitName Value="UEngine"/>
    8886      </Unit2>
    8987      <Unit3>
    9088        <Filename Value="UGeometric.pas"/>
    9189        <IsPartOfProject Value="True"/>
    92         <UnitName Value="UGeometric"/>
    9390      </Unit3>
    9491      <Unit4>
    9592        <Filename Value="UTrack.pas"/>
    9693        <IsPartOfProject Value="True"/>
    97         <UnitName Value="UTrack"/>
    9894      </Unit4>
    9995      <Unit5>
    10096        <Filename Value="UMetaCanvas.pas"/>
    10197        <IsPartOfProject Value="True"/>
    102         <UnitName Value="UMetaCanvas"/>
    10398      </Unit5>
    10499    </Units>
  • trunk/UEngine.pas

    r35 r36  
    2222  TTrackPoints = class;
    2323  TTrack = class;
     24  TTrackLink = class;
    2425  TTrackLinks = class;
    2526
     
    6970    LineStation: TLineStation;
    7071    Position: TPoint;
    71     PositionShift: TPoint;
     72    //PositionShift: TPoint;
    7273    PositionDesigned: TPoint;
    7374    Pending: Boolean;
     
    7576    NeighPoints: TTrackPoints;
    7677    NeighLinks: TTrackLinks;
     78    LinkUp: TTrackLink;
     79    LinkDown: TTrackLink;
    7780    procedure Connect(TrackPoint: TTrackPoint);
    7881    procedure Disconnect(TrackPoint: TTrackPoint);
     
    8184    function GetNeighDown: TTrackPoint;
    8285    function GetNeighUp: TTrackPoint;
     86    function GetLinkDown: TTrackLink;
     87    function GetLinkUp: TTrackLink;
    8388    // Move to TTrackLink later
    8489    function GetDistance: Integer;
     
    133138  TTrackPointsAngle = class
    134139    Angle: Double;
    135     Tracks: TTracks;
     140    TrackLinks: TTrackLinks;
    136141    constructor Create;
    137142    destructor Destroy; override;
     
    536541constructor TTrackPointsAngle.Create;
    537542begin
    538   Tracks := TTracks.Create;
    539   Tracks.OwnsObjects := False;
     543  TrackLinks := TTrackLinks.Create;
     544  TrackLinks.OwnsObjects := False;
    540545end;
    541546
    542547destructor TTrackPointsAngle.Destroy;
    543548begin
    544   Tracks.Free;
     549  TrackLinks.Free;
    545550  inherited Destroy;
    546551end;
     
    624629    if NewIndex < Track.Points.Count then Result := TTrackPoint(Track.Points[NewIndex]);
    625630  end;
     631end;
     632
     633function TTrackPoint.GetLinkDown: TTrackLink;
     634begin
     635  if Assigned(LinkDown) then Result := LinkDown
     636    else begin
     637      LinkDown := TTrackLink.Create;
     638      LinkDown.Points.Add(GetNeighDown);
     639      LinkDown.Points.Add(Self);
     640      Result := LinkDown;
     641      GetNeighDown.LinkUp := LinkDown;
     642    end;
     643end;
     644
     645function TTrackPoint.GetLinkUp: TTrackLink;
     646begin
     647  if Assigned(LinkUp) then Result := LinkUp
     648    else begin
     649      LinkUp := TTrackLink.Create;
     650      LinkUp.Points.Add(Self);
     651      LinkUp.Points.Add(GetNeighUp);
     652      Result := LinkUp;
     653      GetNeighUp.LinkDown := LinkUp;
     654    end;
    626655end;
    627656
     
    794823    end;
    795824
    796     Angle := arctan2((TTrackPoint(Track.Points[2]).Position.Y - TTrackPoint(Track.Points[1]).Position.Y),
    797       (TTrackPoint(Track.Points[2]).Position.X - TTrackPoint(Track.Points[1]).Position.X));
    798     EndPoint := Point(Round(TTrackPoint(Track.Points[1]).Position.X - EndStationLength * Cos(Angle)),
    799       Round(TTrackPoint(Track.Points[1]).Position.Y - EndStationLength * Sin(Angle)));
     825    Angle := ArcTan2((TTrackPoint(Track.Points[2]).PositionDesigned.Y - TTrackPoint(Track.Points[1]).PositionDesigned.Y),
     826      (TTrackPoint(Track.Points[2]).PositionDesigned.X - TTrackPoint(Track.Points[1]).PositionDesigned.X));
     827    EndPoint := Point(Round(TTrackPoint(Track.Points[1]).PositionDesigned.X - EndStationLength * Cos(Angle)),
     828      Round(TTrackPoint(Track.Points[1]).PositionDesigned.Y - EndStationLength * Sin(Angle)));
     829    TTrackPoint(Track.Points.First).PositionDesigned := EndPoint;
    800830    TTrackPoint(Track.Points.First).Position := EndPoint;
    801     TTrackPoint(Track.Points.First).PositionDesigned := EndPoint;
    802 
    803     Angle := arctan2((TTrackPoint(Track.Points[Track.Points.Count - 2]).Position.Y - TTrackPoint(Track.Points[Track.Points.Count - 3]).Position.Y),
    804       (TTrackPoint(Track.Points[Track.Points.Count - 2]).Position.X - TTrackPoint(Track.Points[Track.Points.Count - 3]).Position.X));
    805     EndPoint := Point(Round(TTrackPoint(Track.Points[Track.Points.Count - 2]).Position.X + EndStationLength * Cos(Angle)),
    806       Round(TTrackPoint(Track.Points[Track.Points.Count - 2]).Position.Y + EndStationLength * Sin(Angle)));
     831
     832    Angle := ArcTan2((TTrackPoint(Track.Points[Track.Points.Count - 2]).PositionDesigned.Y - TTrackPoint(Track.Points[Track.Points.Count - 3]).PositionDesigned.Y),
     833      (TTrackPoint(Track.Points[Track.Points.Count - 2]).PositionDesigned.X - TTrackPoint(Track.Points[Track.Points.Count - 3]).PositionDesigned.X));
     834    EndPoint := Point(Round(TTrackPoint(Track.Points[Track.Points.Count - 2]).PositionDesigned.X + EndStationLength * Cos(Angle)),
     835      Round(TTrackPoint(Track.Points[Track.Points.Count - 2]).PositionDesigned.Y + EndStationLength * Sin(Angle)));
     836    TTrackPoint(Track.Points.Last).PositionDesigned := EndPoint;
    807837    TTrackPoint(Track.Points.Last).Position := EndPoint;
    808     TTrackPoint(Track.Points.Last).PositionDesigned := EndPoint;
    809838  end;
    810839end;
     
    939968  Index1 := Points.IndexOf(TP1);
    940969  Index2 := Points.IndexOf(TP2);
    941   P1 := TTrackPoint(Points[Index1]).Position;
    942   P2 := TTrackPoint(Points[Index2]).Position;
     970  P1 := TTrackPoint(Points[Index1]).PositionDesigned;
     971  P2 := TTrackPoint(Points[Index2]).PositionDesigned;
    943972  NewTrackPoint := Points.AddNew;
    944973  Delta := Point(P2.X - P1.X, P2.Y - P1.Y);
    945974  if Abs(Delta.X) > Abs(Delta.Y) then begin
    946     NewTrackPoint.Position := Point(P2.X - Sign(Delta.X) * Abs(Delta.Y), P1.Y);
    947     NewTrackPoint.PositionDesigned := NewTrackPoint.Position;
     975    NewTrackPoint.PositionDesigned := Point(P2.X - Sign(Delta.X) * Abs(Delta.Y), P1.Y);
     976    NewTrackPoint.Position := NewTrackPoint.PositionDesigned;
    948977  end else begin
    949     NewTrackPoint.Position := Point(P1.X, P2.Y - Sign(Delta.Y) * Abs(Delta.X));
    950     NewTrackPoint.PositionDesigned := NewTrackPoint.Position;
     978    NewTrackPoint.PositionDesigned := Point(P1.X, P2.Y - Sign(Delta.Y) * Abs(Delta.X));
     979    NewTrackPoint.Position := NewTrackPoint.PositionDesigned;
    951980  end;
    952981  Points.Insert(Index1 + 1, NewTrackPoint);
     
    10991128procedure TMapStation.ShiftTrackPoints;
    11001129var
    1101   Tracks: TTracks;
     1130  TrackLinks: TTrackLinks;
    11021131  I: Integer;
    11031132  J: Integer;
     
    11061135  LS: TLineStation;
    11071136  Line: TMetroLine;
    1108   Angle: Double;
     1137  Angle: Float;
    11091138  TPAngleGroup: TTrackPointsAngleGroup;
    11101139  GroupItem: TTrackPointsAngle;
    1111   NewTrack: TTrackLink;
     1140  NewTrackLink: TTrackLink;
    11121141  HAngle: Double;
    1113   PairTrack: TTrackLink;
    1114   NewPoint: TPoint;
    1115 begin
    1116   Tracks := TTracks.Create;
    1117 
    1118   // Collect all near track points as track
     1142  P1, P2: TPoint;
     1143  NewShift: TPoint;
     1144begin
     1145  TrackLinks := TTrackLinks.Create;
     1146  TrackLinks.OwnsObjects := False;
     1147
     1148  // Collect all near track points as track links
    11191149  SortLines;
    11201150  for I := 0 to Lines.Count - 1 do begin
     
    11241154    Index := Line.Track.Points.IndexOf(TP);
    11251155    if Index > 0 then begin
    1126       NewTrack := TTrackLink.Create;
    1127       NewTrack.Points.Count := 2;
    1128       NewTrack.Points[0] := TTrackPoint(Line.Track.Points[Index - 1]);
    1129       NewTrack.Points[1] := TTrackPoint(Line.Track.Points[Index]);
    1130       Tracks.Add(NewTrack);
     1156      NewTrackLink := TTrackPoint(Line.Track.Points[Index]).GetLinkDown;
     1157      TrackLinks.Add(NewTrackLink);
    11311158    end;
    11321159    if Index < (Line.Track.Points.Count - 1) then begin
    1133       NewTrack := TTrackLink.Create;
    1134       NewTrack.Points.Count := 2;
    1135       NewTrack.Points[0] := TTrackPoint(Line.Track.Points[Index + 1]);
    1136       NewTrack.Points[1] := TTrackPoint(Line.Track.Points[Index]);
    1137       Tracks.Add(NewTrack);
    1138     end;
    1139   end;
    1140 
    1141   // Make groups of tracks with same angle
     1160      NewTrackLink := TTrackPoint(Line.Track.Points[Index]).GetLinkUp;
     1161      TrackLinks.Add(NewTrackLink);
     1162    end;
     1163    if Line.IsCircular and (Self = TLineStation(Line.LineStations.First).MapStation) and
     1164    (Self = TLineStation(Line.LineStations.Last).MapStation) then begin
     1165      LS := TLineStation(Line.LineStations.Last);
     1166      TP := LS.TrackPoint;
     1167      Index := Line.Track.Points.IndexOf(TP);
     1168      if Index > 0 then begin
     1169        NewTrackLink := TTrackPoint(Line.Track.Points[Index]).GetLinkDown;
     1170        TrackLinks.Add(NewTrackLink);
     1171      end;
     1172      if Index < (Line.Track.Points.Count - 1) then begin
     1173        NewTrackLink := TTrackPoint(Line.Track.Points[Index]).GetLinkUp;
     1174        TrackLinks.Add(NewTrackLink);
     1175      end;
     1176    end;
     1177  end;
     1178
     1179  // Make groups of TrackLinks with same angle
    11421180  TPAngleGroup := TTrackPointsAngleGroup.Create;
    1143   for I := 0 to Tracks.Count - 1 do begin
    1144     Angle := ArcTan2(TTrackPoint(TTrackLink(Tracks[I]).Points[0]).PositionDesigned.Y - Position.Y,
    1145       TTrackPoint(TTrackLink(Tracks[I]).Points[0]).PositionDesigned.X - Position.X);
     1181  for I := 0 to TrackLinks.Count - 1 do begin
     1182    P1 := TTrackPoint(TTrackLink(TrackLinks[I]).Points[0]).PositionDesigned;
     1183    P2 := TTrackPoint(TTrackLink(TrackLinks[I]).Points[1]).PositionDesigned;
     1184    if ComparePoint(P1, Position) and not ComparePoint(P2, Position) then begin
     1185      Angle := ArcTan2(P2.Y - Position.Y, P2.X - Position.X);
     1186    end else
     1187    if ComparePoint(P2, Position) and not ComparePoint(P1, Position) then begin
     1188      Angle := ArcTan2(P1.Y - Position.Y, P1.X - Position.X);
     1189    end else Angle := 0;// else raise Exception.Create('TrackLink angle rrror');
     1190
    11461191    GroupItem := TPAngleGroup.SearchAngle(Angle);
    11471192    if not Assigned(GroupItem) then begin
     
    11501195      TPAngleGroup.Add(GroupItem);
    11511196    end;
    1152     GroupItem.Tracks.Add(TTrackLink(Tracks[I]))
    1153   end;
    1154 
    1155   // Shift tracks according number of lines in group
     1197    GroupItem.TrackLinks.Add(TTrackLink(TrackLinks[I]))
     1198  end;
     1199
     1200  // Shift TrackLinks according number of lines in group
    11561201  for I := 0 to TPAngleGroup.Count - 1 do
    11571202  with TTrackPointsAngle(TPAngleGroup[I]) do begin
    1158     for J := 0 to Tracks.Count - 1 do
    1159       with TTrackLink(Tracks[J]) do begin
     1203    for J := 0 to TrackLinks.Count - 1 do
     1204      with TTrackLink(TrackLinks[J]) do begin
    11601205        // Get orthogonal angle
    11611206        HAngle := Angle + Pi / 2;
    1162         if HAngle > Pi then HAngle := Hangle - Pi;
    1163         Shift.X := Trunc(MetroLineThickness * Cos(HAngle) * (J - (Tracks.Count - 1) / 2));
    1164         Shift.Y := Trunc(MetroLineThickness * Sin(HAngle) * (J - (Tracks.Count - 1) / 2));
    1165         TTrackPoint(Points[0]).PositionShift := Shift;
    1166         TTrackPoint(Points[1]).PositionShift := Shift;
     1207        if HAngle > Pi then HAngle := HAngle - Pi;
     1208        NewShift.X := Trunc(MetroLineThickness * Cos(HAngle) * (J - (TrackLinks.Count - 1) / 2));
     1209        NewShift.Y := Trunc(MetroLineThickness * Sin(HAngle) * (J - (TrackLinks.Count - 1) / 2));
     1210        //NewShift.X := TrackLinks.Count;
     1211        Shift := NewShift;
    11671212      end;
    11681213  end;
    11691214
    11701215  TPAngleGroup.Free;
    1171   Tracks.Free;
     1216  TrackLinks.Free;
    11721217end;
    11731218
     
    17471792  for L := 0 to Lines.Count - 1 do
    17481793  with TMetroLine(Lines[L]) do begin
    1749     if Track.Points.Count > 0 then
     1794    if Track.Points.Count > 1 then begin
    17501795      TTrackPoint(Track.Points[0]).Position := AddPoint(TTrackPoint(Track.Points[0]).PositionDesigned,
    1751         TTrackPoint(Track.Points[0]).PositionShift);
     1796        TTrackPoint(Track.Points[0]).LinkUp.Shift);
     1797    end;
    17521798    for I := 1 to Track.Points.Count - 1 do
    1753     with TTrackPoint(Track.Points[I]) do begin
    1754       Link1 := SubPoint(AddPoint(TTrackPoint(Track.Points[I]).PositionDesigned, TTrackPoint(Track.Points[I]).PositionShift),
    1755         AddPoint(TTrackPoint(Track.Points[I - 1]).PositionDesigned, TTrackPoint(Track.Points[I - 1]).PositionShift));
     1799    with TTrackPoint(Track.Points[I]) do
     1800    if Assigned(TTrackPoint(Track.Points[I]).LinkDown) and Assigned(TTrackPoint(Track.Points[I]).LinkUp) then begin
     1801      Link1 := SubPoint(AddPoint(TTrackPoint(Track.Points[I]).PositionDesigned, TTrackPoint(Track.Points[I]).LinkDown.Shift),
     1802        AddPoint(TTrackPoint(Track.Points[I - 1]).PositionDesigned, TTrackPoint(Track.Points[I]).LinkDown.Shift));
    17561803      if (I + 1) < Track.Points.Count then
    1757         Link2 := SubPoint(AddPoint(TTrackPoint(Track.Points[I + 1]).PositionDesigned, TTrackPoint(Track.Points[I + 1]).PositionShift),
    1758           AddPoint(TTrackPoint(Track.Points[I]).PositionDesigned, TTrackPoint(Track.Points[I]).PositionShift))
     1804        Link2 := SubPoint(AddPoint(TTrackPoint(Track.Points[I + 1]).PositionDesigned, TTrackPoint(Track.Points[I]).LinkUp.Shift),
     1805          AddPoint(TTrackPoint(Track.Points[I]).PositionDesigned, TTrackPoint(Track.Points[I]).LinkUp.Shift))
    17591806        else Link2 := Link1;
    17601807
    17611808      if ArcTanPoint(Link1) = ArcTanPoint(Link2) then begin
    17621809        // Parallel lines
    1763         TTrackPoint(Track.Points[I]).Position := AddPoint(TTrackPoint(Track.Points[I]).PositionDesigned,
    1764           TTrackPoint(Track.Points[I]).PositionShift);
     1810        NewPoint := AddPoint(TTrackPoint(Track.Points[I]).PositionDesigned,
     1811          TTrackPoint(Track.Points[I]).LinkDown.Shift);
     1812        TTrackPoint(Track.Points[I]).Position := NewPoint;
    17651813      end else begin
    17661814        // Intersected lines
    1767         NewPoint := LineIntersect(AddPoint(TTrackPoint(Track.Points[I - 1]).PositionDesigned, TTrackPoint(Track.Points[I - 1]).PositionShift),
    1768           AddPoint(TTrackPoint(Track.Points[I]).PositionDesigned, TTrackPoint(Track.Points[I]).PositionShift),
    1769           AddPoint(TTrackPoint(Track.Points[I]).PositionDesigned, TTrackPoint(Track.Points[I]).PositionShift),
    1770           AddPoint(TTrackPoint(Track.Points[I + 1]).PositionDesigned, TTrackPoint(Track.Points[I + 1]).PositionShift));
     1815        NewPoint := LineIntersect(AddPoint(TTrackPoint(Track.Points[I - 1]).PositionDesigned,
     1816          TTrackPoint(Track.Points[I]).LinkDown.Shift),
     1817          AddPoint(TTrackPoint(Track.Points[I]).PositionDesigned, TTrackPoint(Track.Points[I]).LinkDown.Shift),
     1818          AddPoint(TTrackPoint(Track.Points[I]).PositionDesigned, TTrackPoint(Track.Points[I]).LinkUp.Shift),
     1819          AddPoint(TTrackPoint(Track.Points[I + 1]).PositionDesigned, TTrackPoint(Track.Points[I]).LinkUp.Shift));
    17711820        TTrackPoint(Track.Points[I]).Position := NewPoint;
    17721821      end;
     
    17741823  end;
    17751824
     1825  // Remove all temporal links
     1826  for I := 0 to Lines.Count - 1 do
     1827  with TMetroLine(Lines[I]) do
     1828    for J := 0 to Track.Points.Count - 1 do
     1829    if Assigned(TTrackPoint(Track.Points[J]).LinkUp) then begin
     1830      TTrackPoint(Track.Points[J]).LinkUp.Free;
     1831      TTrackPoint(Track.Points[J]).LinkUp := nil;
     1832      TTrackPoint(Track.Points[J + 1]).LinkDown := nil;
     1833    end;
    17761834end;
    17771835
     
    22422300      end;}
    22432301    end;
     2302(*    Canvas.Pen.Color := Color;
     2303    Canvas.Pen.Style := psSolid;
     2304    Canvas.Pen.Width := MetroLineThickness div 2;
     2305    if Track.Points.Count > 0 then Canvas.MoveTo(TTrackPoint(Track.Points[0]).PositionDesigned);
     2306    for S := 1 to Track.Points.Count - 1 do begin
     2307      Canvas.LineTo(TTrackPoint(Track.Points[S]).PositionDesigned);
     2308{      if (S = TrackPoints.Count - 1) then begin
     2309        Canvas.Pen.EndCap := pecSquare;
     2310        Angle := arctan2((TTrackPoint(TrackPoints[S]).Position.Y - TTrackPoint(TrackPoints[S - 1]).Position.Y),
     2311          (TTrackPoint(TrackPoints[S]).Position.X - TTrackPoint(TrackPoints[S - 1]).Position.X));
     2312        EndPoint := Point(Round(TTrackPoint(TrackPoints[S]).Position.X + EndStationLength * Cos(Angle)),
     2313          Round(TTrackPoint(TrackPoints[S]).Position.Y + EndStationLength * Sin(Angle)));
     2314        Canvas.LineTo(EndPoint);
     2315        Canvas.MoveTo(Point(Round(EndPoint.X + Cos(Angle + Pi / 2) * EndStationLength / 3),
     2316          Round(EndPoint.Y + Sin(Angle + Pi / 2) * EndStationLength / 3)));
     2317        Canvas.LineTo(Point(Round(EndPoint.X + Cos(Angle - Pi / 2) * EndStationLength / 3),
     2318          Round(EndPoint.Y + Sin(Angle - Pi / 2) * EndStationLength / 3)));
     2319        Canvas.Pen.EndCap := pecRound;
     2320      end;}
     2321    end;
    22442322    {
    22452323    if (TrackPoints.Count > 1) then begin
     
    22572335      Canvas.Pen.EndCap := pecRound;
    22582336    end;  }
    2259   end;
    2260 
     2337    *)
     2338  end;
    22612339  // Draw design time lines
    22622340  if Assigned(TrackStationDown) and Assigned(TrackStationDown.LineStation) then begin
Note: See TracChangeset for help on using the changeset viewer.