/// <inheritdoc /> public Visual Draw() { if (Network == null) throw new Exception("Network is Null"); //Create drawing target DrawingVisual drawingVisual = new DrawingVisual(); DrawingContext drawingContext = drawingVisual.RenderOpen(); //enables clicks to be registered all throughout the drawing (i.e. // no holes) but simultaneously remains transparent. drawingContext.DrawRectangle(Brushes.Transparent, null, ImgCoords); Pen p = new Pen(Brushes.Black,2); p.Freeze(); var busesToSource = Tracing.BusesOnRouteToTarget((Bus)SelectedElement, (Bus)Network.SourceBus); var busesFromSelection = Tracing.TraceWithoutCrossingBuses((Bus)SelectedElement, busesToSource); var buses = busesToSource.Union(busesFromSelection); Dictionary<Bus, double> lengths = new Dictionary<Bus, double>(); lengths[Network.SourceBus] = 0; Collection<Line> lines = new Collection<Line>(); Tracing.TraceFromWithCallback(Network.SourceBus, buses, (thisBus, line, nextBus) => { lengths[nextBus] = (lengths.ContainsKey(thisBus) ? lengths[thisBus] : 0) + line.Length; lines.Add(line); }); Limits lengthLimits = new Limits(); lengthLimits.ProcessData(lengths.Values); lengthLimits.LimitMax = ImgCoords.Right - Margin.Right; lengthLimits.LimitMin = ImgCoords.Left + Margin.Left; Limits voltLimits = new Limits(); voltLimits.ProcessData(buses.Select(b => -b.VoltagePU.Magnitude)); //choose grid for volts. MagicGridSpacer voltSpacer = new MagicGridSpacer(); voltSpacer.MinValue = voltLimits.AutoMin; voltSpacer.MaxValue = voltLimits.AutoMax; voltSpacer.MaxLines = 10; //TODO: change this based on pixels. min(pixelMax, 2) var voltSpacings = voltSpacer.GetGridSpacings(); voltLimits.ProcessData(voltSpacings.LowerLimit); voltLimits.ProcessData(voltSpacings.UpperLimit); voltLimits.LimitMin = ImgCoords.Top + Margin.Top; voltLimits.LimitMax = ImgCoords.Bottom - Margin.Bottom; MagicGridSpacer lengthSpacer = new MagicGridSpacer(); lengthSpacer.MinValue = lengthLimits.AutoMin; lengthSpacer.MaxValue = lengthLimits.AutoMax; lengthSpacer.MaxLines = 20; //TODO: change this based on pixels. var lengthSpacings = lengthSpacer.GetGridSpacings(); lengthLimits.ProcessData(lengthSpacings.LowerLimit); lengthLimits.ProcessData(lengthSpacings.UpperLimit); Dictionary<Bus, Point> BusPoints = new Dictionary<Bus, Point>(); foreach (Bus b in buses) { BusPoints[b] = new Point(lengthLimits.ValueScaledToLimits(lengths[b]), voltLimits.ValueScaledToLimits(-b.VoltagePU.Magnitude)); } Pen gridPen = new Pen(Brushes.LightGray, 1); gridPen.Freeze(); foreach (double yPos in voltSpacings.GetTicks()) { var y = voltLimits.ValueScaledToLimits(yPos); var leftPoint = new Point(ImgCoords.Left + Margin.Left, y); drawingContext.DrawLine(gridPen, leftPoint, new Point(ImgCoords.Right - Margin.Right, y)); var ft = new FormattedText((-yPos).ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(""), 12, Brushes.Black); drawingContext.DrawText(ft, leftPoint); } foreach (double xPos in lengthSpacings.GetTicks()) { var x = lengthLimits.ValueScaledToLimits(xPos); var bottomPoint = new Point(x, ImgCoords.Bottom - Margin.Bottom); drawingContext.DrawLine(gridPen, bottomPoint, new Point(x,ImgCoords.Bottom - Margin.Bottom - 10)); var ft = new FormattedText(xPos.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(""), 12, Brushes.Black); drawingContext.DrawText(ft, bottomPoint); } foreach (Line l in lines) { Bus b1, b2; b1 = l.ConnectedTo.OfType<Bus>().First(); b2 = l.ConnectedTo.OfType<Bus>().Last(); drawingContext.DrawLine(p, BusPoints[b1], BusPoints[b2]); } drawingContext.Close(); return drawingVisual; }
/// <summary> /// Draws all the network buses, using the specified value transforms. /// </summary> /// <param name="Network">The network from which to draw buses.</param> /// <param name="colorMap">A map of the colours to use from the specified gradient.</param> /// <param name="busSizeLimits">The limits of <see cref="BusSizeTransform"/>, /// used for scaling from that space to /// [<see cref="BusSizeMin"/>, <see cref="BusSizeMax"/>].</param> /// <param name="ringColorPen">A pen for drawing rings.</param> /// <param name="drawingContext">The target that we should draw to.</param> protected void DrawBuses(NetworkModel Network, AdaptiveGradientMap<Tuple<Brush, Pen>> colorMap, Limits busSizeLimits, Pen ringColorPen, DrawingContext drawingContext) { //Draw all the buses. foreach (var bus in Network.Buses.Values) { if (!(BusVisibleTransform(bus) && bus.Location.HasValue)) continue; var bSize = busSizeLimits.ValueScaledToLimits(BusSizeTransform(bus)); //value-dependant fill, no outline, centre is scaled, radius of 2 (small dots). drawingContext.DrawEllipse( colorMap.Map(BusColorTransform(bus)).Item1, null, ScaledLocation(bus.Location.Value), bSize, bSize); //Bus Ring if (RingEnabledTransform(bus)) { var ringRadius = RingDistanceFromCenter ? /*true*/ RingDistanceTransform(bus) : /*false*/ bSize + RingDistanceTransform(bus); drawingContext.DrawEllipse(null, ringColorPen, ScaledLocation(bus.Location.Value), ringRadius, ringRadius); } } }