/// <summary>
        /// Draws all the network lines.
        /// </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="drawingContext">The target that we should draw to.</param>
        protected void DrawLines(NetworkModel Network, AdaptiveGradientMap <Tuple <Brush, Pen> > colorMap, DrawingContext drawingContext)
        {
            //Draw all the lines.
            foreach (Line line in Network.Lines)
            {
                if (line.ConnectedTo.Count() != 2)
                {
                    continue;
                }
                Bus bus1 = (Bus)line.ConnectedTo.ElementAt(0);
                Bus bus2 = (Bus)line.ConnectedTo.ElementAt(1);

                if (!(bus1.Location.HasValue && bus2.Location.HasValue))
                {
                    continue;
                }

                //color based on average value.
                var bCol1 = BusVisibleTransform(bus1) ? BusColorTransform(bus1) : 0;
                var bCol2 = BusVisibleTransform(bus2) ? BusColorTransform(bus2) : 0;

                double v_avg = (bCol1 + bCol2) / 2;
                drawingContext.DrawLine(
                    colorMap.Map(v_avg).Item2,           //choose the right color for the value
                    ScaledLocation(bus1.Location.Value), //scale the locations to image coordinates.
                    ScaledLocation(bus2.Location.Value)
                    );
            }
        }
        /// <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);
                }
            }
        }
        /// <summary>
        /// Builds a gradient map based upon <see cref="BusColorGradient"/> and
        /// <see cref="BusColorTransform"/> for the data in this network.
        /// </summary>
        /// <param name="Network">The network that data should be taken from.</param>
        /// <returns>A map of gradients.</returns>
        protected AdaptiveGradientMap <Tuple <Brush, Pen> > BuildGradientMap(NetworkModel Network)
        {
            //1. Setup adaptive gradient.
            BusColorGradient.ResetAutoData();
            foreach (var b in Network.Buses.Values)
            {
                BusColorGradient.ProcessData(BusColorTransform(b));
            }

            AdaptiveGradientMapBuilder mapBuilder = new AdaptiveGradientMapBuilder(BusColorGradient);

            AdaptiveGradientMap <Tuple <Brush, Pen> > colorMap = mapBuilder.BuildGradientMap(c =>
            {
                Brush b = new SolidColorBrush(c);
                b.Freeze();
                Pen p = new Pen(b, LineThickness);
                p.Freeze();
                return(new Tuple <Brush, Pen>(b, p));
            });

            return(colorMap);
        }
        /// <inheritdoc />
        public override Visual Draw()
        {
            if (Network == null)
            {
                throw new Exception("Network is Null");
            }

            if (PresentationMode && ColorConveysMostInformation())
            {
                ValueTransformableTreeGraph newGraph = GetAccessibleGraph();
                return(newGraph.Draw());
            }

            ProtectInitialise();
            Limits busSizeLimits = GetBusSizeLimits();

            AdaptiveGradientMap <Tuple <Brush, Pen> > colorMap = BuildGradientMap(Network);

            Pen ringColorPen = GetRingPen();

            //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);

            DrawLines(Network, colorMap, drawingContext);

            DrawBuses(Network, colorMap, busSizeLimits, ringColorPen, drawingContext);

            //free up resources
            drawingContext.Close();
            return(drawingVisual);
        }
        /// <summary>
        /// Draws all the network lines.
        /// </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="drawingContext">The target that we should draw to.</param>
        protected void DrawLines(NetworkModel Network, AdaptiveGradientMap<Tuple<Brush, Pen>> colorMap, DrawingContext drawingContext)
        {
            //Draw all the lines.
            foreach (Line line in Network.Lines)
            {
                if (line.ConnectedTo.Count() != 2)
                    continue;
                Bus bus1 = (Bus)line.ConnectedTo.ElementAt(0);
                Bus bus2 = (Bus)line.ConnectedTo.ElementAt(1);

                if (!(bus1.Location.HasValue && bus2.Location.HasValue))
                    continue;

                //color based on average value.
                var bCol1 = BusVisibleTransform(bus1) ? BusColorTransform(bus1) : 0;
                var bCol2 = BusVisibleTransform(bus2) ? BusColorTransform(bus2) : 0;

                double v_avg = (bCol1 + bCol2) / 2;
                drawingContext.DrawLine(
                    colorMap.Map(v_avg).Item2, //choose the right color for the value
                    ScaledLocation(bus1.Location.Value), //scale the locations to image coordinates.
                    ScaledLocation(bus2.Location.Value)
                    );
            }
        }
        /// <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);
                }
            }
        }