private void AddCoordinate(VertexInformation vertex, float xCoord, float yCoord) { int xc = (int)xCoord; int yc = (int)yCoord; if (!TrainCoordinates.ContainsKey(xc)) { TrainCoordinates.Add(xc, new SortedDictionary <int, VertexInformation>()); } if (!TrainCoordinates[xc].ContainsKey(yc)) { TrainCoordinates[xc].Add(yc, vertex); } }
/// <summary> /// Paint the control. /// </summary> /// <param name="e">The <see cref="PaintEventArgs"/> object encapsulating the drawing context.</param> protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); if (Model == null || Model.LocationList == null || Model.LocationList.Count == 0 || Model.TrainList == null || Model.TrainList.Count == 0 || e is null) { return; } e.Graphics.SmoothingMode = SmoothingMode.HighQuality; float leftLimit = Size.Width * LeftMarginPercent; float topLimit = Size.Height * TopMarginPercent; float bottomLimit = Size.Height * (1 - BottomMarginPercent); TrainCoordinates.Clear(); // Work out horizontal resolution List <TrainGraphAxisTickInfo> timeAxisInfo = Model.GetTimeAxisInformation().Select(i => { i.PopulateSize(e.Graphics, TimeAxisFont); return(i); }).ToList(); bottomLimit -= timeAxisInfo.Max(i => (float)i.Height.Value) + 5; using (Pen axisPen = new Pen(Color.Black, 1f)) { // Draw Y axis List <TrainGraphAxisTickInfo> locationAxisInfo = Model.GetDistanceAxisInformation().Select(i => { i.PopulateSize(e.Graphics, LocationAxisFont); return(i); }).ToList(); topLimit += (float)locationAxisInfo.Last().Height.Value / 2; LocationAxisXCoordinate = leftLimit += locationAxisInfo.Max(i => (float)i.Width) + 5; using (SolidBrush backColourBrush = new SolidBrush(GraphBackColour)) { e.Graphics.FillRectangle(backColourBrush, leftLimit, topLimit, MaximumXCoordinate - leftLimit, bottomLimit - topLimit); } e.Graphics.DrawLine(axisPen, leftLimit, bottomLimit, leftLimit, topLimit); e.Graphics.DrawLine(axisPen, MaximumXCoordinate, bottomLimit, MaximumXCoordinate, topLimit); using (SolidBrush blackBrush = new SolidBrush(Color.Black)) { foreach (TrainGraphAxisTickInfo tick in locationAxisInfo) { float y = CoordinateHelper.Stretch(topLimit, bottomLimit, 1 - tick.Coordinate); e.Graphics.DrawLine(axisPen, MaximumXCoordinate, y, leftLimit - 5, y); e.Graphics.DrawString(tick.Label, LocationAxisFont, blackBrush, (float)(leftLimit - (tick.Width.Value + 5)), (float)(y - tick.Height.Value / 2)); } // Draw X axis ticks / gridlines. foreach (TrainGraphAxisTickInfo tick in timeAxisInfo) { float x = CoordinateHelper.Stretch(leftLimit, MaximumXCoordinate, tick.Coordinate); float yTop = ShowVerticalGridLines ? topLimit : bottomLimit; e.Graphics.DrawLine(axisPen, x, yTop, x, bottomLimit + 5); e.Graphics.DrawString(tick.Label, TimeAxisFont, blackBrush, (float)(x - tick.Width.Value / 2), bottomLimit + 5); } } } // Draw trains List <TrainDrawingInfo> trainDrawingInfo = Model.GetTrainDrawingInformation().ToList(); List <Tuple <float, float> > selectedTrainCoordinates = new List <Tuple <float, float> >(); foreach (TrainDrawingInfo info in trainDrawingInfo) { using (Pen trainPen = new Pen(info.Properties.Colour, info.Properties.Width) { DashStyle = info.Properties.DashStyle }) { foreach (LineCoordinates lineData in info.Lines) { DrawLine(e.Graphics, trainPen, lineData.Vertex1, lineData.Vertex2, leftLimit, MaximumXCoordinate, topLimit, bottomLimit, selectedTrainCoordinates); } } if (Model.DisplayTrainLabels && !string.IsNullOrWhiteSpace(info.Headcode)) { SizeF headcodeDimensions = e.Graphics.MeasureString(info.Headcode.Trim(), TrainLabelFont); LineCoordinates longestLine = info.Lines[LineCoordinates.GetIndexOfLongestLine(info.Lines)]; float llX1 = CoordinateHelper.Stretch(leftLimit, MaximumXCoordinate, longestLine.Vertex1.X); float llX2 = CoordinateHelper.Stretch(leftLimit, MaximumXCoordinate, longestLine.Vertex2.X); float llY1 = CoordinateHelper.Stretch(topLimit, bottomLimit, 1 - longestLine.Vertex1.Y); float llY2 = CoordinateHelper.Stretch(topLimit, bottomLimit, 1 - longestLine.Vertex2.Y); PointF longestLineMidpoint = new PointF((llX1 + llX2) / 2, (llY1 + llY2) / 2); e.Graphics.TranslateTransform(longestLineMidpoint.X, longestLineMidpoint.Y); e.Graphics.RotateTransform((float)(Math.Atan2(llY1 - llY2, llX1 - llX2) * (180.0 / Math.PI) + 180.0)); e.Graphics.TranslateTransform(-headcodeDimensions.Width / 2, -headcodeDimensions.Height); e.Graphics.DrawString(info.Headcode.Trim(), TrainLabelFont, Brushes.Black, new PointF(0, 0)); e.Graphics.ResetTransform(); } } float handleOffset = ControlHandleSize / 2f; foreach (Tuple <float, float> controlHandleCoordinate in selectedTrainCoordinates) { e.Graphics.FillEllipse(Brushes.White, controlHandleCoordinate.Item1 - handleOffset, controlHandleCoordinate.Item2 - handleOffset, ControlHandleSize, ControlHandleSize); e.Graphics.DrawEllipse(Pens.Black, controlHandleCoordinate.Item1 - handleOffset, controlHandleCoordinate.Item2 - handleOffset, ControlHandleSize, ControlHandleSize); } // Draw vertex/train being dragged (if appropriate) if (InDragMode) { float x = CoordinateHelper.Stretch(leftLimit, MaximumXCoordinate, _nearestVertex.X + _nearestVertex.DragOffset) - handleOffset; float y = CoordinateHelper.Stretch(topLimit, bottomLimit, 1 - _nearestVertex.Y) - handleOffset; //_log.Trace("Drawing drag handle at {0}, {1}", x, y); e.Graphics.FillEllipse(Brushes.LightGray, x, y, ControlHandleSize, ControlHandleSize); e.Graphics.DrawEllipse(Pens.Black, x, y, ControlHandleSize, ControlHandleSize); } }