コード例 #1
0
        internal void Draw()
        {
            if (!IsControlLaoded) return;

            //No cache for you gauge :( kill and redraw please
            foreach (var child in Canvas.Children
                .Where(x => !Equals(x, Stick) && !(x is AngularSection) && !(x is PieSlice)).ToArray())
                Canvas.Children.Remove(child);

            Wedge = Wedge > 360 ? 360 : (Wedge < 0 ? 0 : Wedge);

            var fromAlpha = (360-Wedge)*.5;
            var toAlpha = 360 - fromAlpha;

            var d = ActualWidth < ActualHeight ? ActualWidth : ActualHeight;

            Stick.Height = d*.5*.8;
            Stick.Width = Stick.Height*.2;

            Canvas.SetLeft(Stick, ActualWidth*.5 - Stick.Width*.5);
            Canvas.SetTop(Stick, ActualHeight*.5 - Stick.Height*.9);

            var ticksHi = d*.5;
            var ticksHj = d*.47;
            var labelsHj = d*.44;

            foreach (var section in Sections)
            {
                PieSlice slice;
                section.Owner = this;

                if (!Slices.TryGetValue(section, out slice))
                {
                    slice = new PieSlice();
                    Slices[section] = slice;
                }

                var p = (Canvas) section.Parent;
                p?.Children.Remove(section);
                Canvas.Children.Add(section);
                var ps = (Canvas) slice.Parent;
                ps?.Children.Remove(slice);
                Canvas.Children.Add(slice);
            }

            UpdateSections();

            for (var i = FromValue; i <= ToValue; i += TicksStep)
            {
                var alpha = LinearInterpolation(fromAlpha, toAlpha, FromValue, ToValue, i) + 90;

                var tick = new Line
                {
                    X1 = ActualWidth*.5 + ticksHi*Math.Cos(alpha*Math.PI/180),
                    X2 = ActualWidth*.5 + ticksHj*Math.Cos(alpha*Math.PI/180),
                    Y1 = ActualHeight*.5 + ticksHi*Math.Sin(alpha*Math.PI/180),
                    Y2 = ActualHeight*.5 + ticksHj*Math.Sin(alpha*Math.PI/180)
                };
                Canvas.Children.Add(tick);
                tick.SetBinding(Shape.StrokeProperty,
                    new Binding {Path = new PropertyPath("TicksForeground"), Source = this});
                tick.SetBinding(Shape.StrokeThicknessProperty,
                    new Binding { Path = new PropertyPath("TicksStrokeThickness"), Source = this });
            }

            for (var i = FromValue; i <= ToValue; i += LabelsStep)
            {
                var alpha = LinearInterpolation(fromAlpha, toAlpha, FromValue, ToValue, i) + 90;

                var tick = new Line
                {
                    X1 = ActualWidth*.5 + ticksHi*Math.Cos(alpha*Math.PI/180),
                    X2 = ActualWidth*.5 + labelsHj*Math.Cos(alpha*Math.PI/180),
                    Y1 = ActualHeight*.5 + ticksHi*Math.Sin(alpha*Math.PI/180),
                    Y2 = ActualHeight*.5 + labelsHj*Math.Sin(alpha*Math.PI/180)
                };

                Canvas.Children.Add(tick);
                var label = new TextBlock
                {
                    Text = LabelFormatter(i)
                };

                //label.SetBinding(EffectProperty,
                    //new Binding {Path = new PropertyPath("LabelsEffect"), Source = this});

                Canvas.Children.Add(label);
                label.UpdateLayout();
                Canvas.SetLeft(label, alpha < 270
                    ? tick.X2
                    : (Math.Abs(alpha - 270) < 4
                        ? tick.X2 - label.ActualWidth*.5
                        : tick.X2 - label.ActualWidth));
                Canvas.SetTop(label, tick.Y2);
                tick.SetBinding(Shape.StrokeProperty,
                    new Binding { Path = new PropertyPath("TicksForeground"), Source = this });
                tick.SetBinding(Shape.StrokeThicknessProperty,
                    new Binding { Path = new PropertyPath("TicksStrokeThickness"), Source = this });
            }
            MoveStick();
        }
コード例 #2
0
        /// <summary>
        /// Clears existing content then calculates new UI elements of the <see cref="Graph"/>
        /// for the current <see cref="BarometerTestUIModel.Graph"/>.
        /// </summary>
        private void DrawGraph()
        {
            // Initialize
            Graph.Children.Clear();

            // Calculate range and average
            var count = Model.Graph.Count;
            if (count == 0)
            {
                // Nothing to draw
                return;
            }
            var pressureMin = (double?)null;
            var pressureMax = (double?)null;
            var temperatureMin = (double?)null;
            var temperatureMax = (double?)null;
            var pressureTotal = (double?)null;
            var temperatureTotal = (double?)null;
            foreach (var point in Model.Graph)
            {
                var pressure = point.Pressure;
                if (!pressureMax.HasValue || pressure > pressureMax) pressureMax = pressure;
                if (!pressureMin.HasValue || pressure < pressureMin) pressureMin = pressure;
                pressureTotal = (pressureTotal ?? 0) + pressure;

                var temperature = point.Temperature;
                if (!temperatureMax.HasValue || temperature > temperatureMax) temperatureMax = temperature;
                if (!temperatureMin.HasValue || temperature < temperatureMin) temperatureMin = temperature;
                temperatureTotal = (temperatureTotal ?? 0) + temperature;
            }
            var pressureRange = (pressureMax ?? 0) - (pressureMin ?? 0);
            var pressureAverage = pressureTotal / count;
            var temperatureRange = (temperatureMax ?? 0) - (temperatureMin ?? 0);
            var temperatureAverage = temperatureTotal / count;

            // Calculate metrics
            Graph.UpdateLayout();
            var height = Graph.ActualHeight;
            var drawHeight = height - (GraphPadding * 2);
            var width = Graph.ActualWidth;
            var drawWidth = width - (GraphPadding * 2);
            var graphYMax = GraphPadding + drawHeight;
            Func<double, double, double, double> calculateGraphY = (double value, double minimum, double range) =>
            {
                if (range > 0)
                {
                    // Relative within range
                    return graphYMax - (drawHeight * ((value - minimum) / range));
                }
                else
                {
                    // Middle when flat line
                    return graphYMax - (drawHeight / 2);
                }
            };

            // Get resources
            var pressureBrush = (SolidColorBrush)Resources["GraphPressureBrush"];
            var temperatureBrush = (SolidColorBrush)Resources["GraphTemperatureBrush"];

            // Draw pressure average lines
            var pressureAverageY = calculateGraphY(pressureAverage.Value, pressureMin.Value, pressureRange);
            Graph.Children.Add(new Line
            {
                Stroke = pressureBrush,
                StrokeThickness = 1,
                X1 = GraphPadding,
                Y1 = pressureAverageY,
                X2 = GraphPadding + drawWidth,
                Y2 = pressureAverageY
            });

            // Draw temperature average line
            var temperatureAverageY = calculateGraphY(temperatureAverage.Value, temperatureMin.Value, temperatureRange);
            Graph.Children.Add(new Line
            {
                Stroke = temperatureBrush,
                StrokeThickness = 1,
                X1 = GraphPadding,
                Y1 = temperatureAverageY,
                X2 = GraphPadding + drawWidth,
                Y2 = temperatureAverageY
            });

            // Plot graph points
            var graphX = GraphPadding;
            var pressureLine = new Polyline
            {
                Stroke = pressureBrush,
                StrokeThickness = 1
            };
            var temperatureLine = new Polyline
            {
                Stroke = temperatureBrush,
                StrokeThickness = 1
            };
            for (var index = Model.Graph.Count - 1; index >= 0; index--)
            {
                // Iterate backwards so we start with latest measurement
                var point = Model.Graph[index];

                // Calculate relative pressure point
                var pressureY = calculateGraphY(point.Pressure, pressureMin.Value, pressureRange);
                var pressurePoint = new Point(graphX, pressureY);
                pressureLine.Points.Add(pressurePoint);

                // Calculate relative temperature point
                var temperatureY = calculateGraphY(point.Temperature, temperatureMin.Value, temperatureRange);
                var temperaturePoint = new Point(graphX, temperatureY);
                temperatureLine.Points.Add(temperaturePoint);

                // Move X for next point...
                graphX += GraphZoom;
                if (graphX > width)
                {
                    // Stop when outside view
                    break;
                }
            }
            Graph.Children.Add(pressureLine);
            Graph.Children.Add(temperatureLine);

            // Draw average text
            var pressureAverageString = string.Format(CultureInfo.CurrentCulture,
                "Pressure: {0}mbar", pressureAverage.Value);
            var pressureAverageText = new TextBlock
            {
                Foreground = pressureBrush,
                Text = pressureAverageString
            };
            Graph.Children.Add(pressureAverageText);
            var temperatureAverageString = string.Format(CultureInfo.CurrentCulture,
                "Temperature: {0}°c", temperatureAverage.Value);
            var temperatureAverageText = new TextBlock
            {
                Foreground = temperatureBrush,
                Text = temperatureAverageString
            };
            Graph.Children.Add(temperatureAverageText);

            // Position average text so that it does not overlap
            pressureAverageText.UpdateLayout();
            temperatureAverageText.UpdateLayout();
            Canvas.SetTop(pressureAverageText, pressureAverageY
                - pressureAverageText.ActualHeight);
            Canvas.SetLeft(pressureAverageText, width
                - pressureAverageText.ActualWidth - GraphPadding
                - temperatureAverageText.ActualWidth - GraphPadding);
            Canvas.SetTop(temperatureAverageText, temperatureAverageY
                - temperatureAverageText.ActualHeight);
            Canvas.SetLeft(temperatureAverageText, width
                - temperatureAverageText.ActualWidth - GraphPadding);
        }