aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/SideChains/RealTimeGraphEx/FastGraphs/RealTimeGraphExLineErase.cs
blob: f1902e6628943c14b0bae72f35fab15279c9a960 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
generated by cgit v1.3.1 (git 2.54.0) at 2026-07-20 19:45:33 +0000
 


a id='n229' href='#n229'>229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace RealTimeGraphEx.FastGraphs
{
    public class RealTimeGraphExLineErase : RealTimeGraphExLineScroll, INotifyPropertyChanged
    {
        #region Cross Thread Fields

        protected Color _markerColor;
        protected bool _showMarker;
        protected bool _endReached;
        protected int _currentReplaceIndex;
        protected bool _enableMarkerPosition;
        protected double lastVirtualValue;
        protected int lastMaxPoints;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the graph marker color.
        /// </summary>
        public Color MarkerColor
        {
            get { return (Color)GetValue(MarkerColorProperty); }
            set { SetValue(MarkerColorProperty, value); }
        }
        public static readonly DependencyProperty MarkerColorProperty =
            DependencyProperty.Register("MarkerBrush", typeof(Color), typeof(RealTimeGraphExLineErase), new PropertyMetadata(Colors.Red, new PropertyChangedCallback(CrossModelChanged)));

        /// <summary>
        /// Gets or sets whether to display the marker on the graph.
        /// </summary>
        public bool ShowMarker
        {
            get { return (bool)GetValue(ShowMarkerProperty); }
            set { SetValue(ShowMarkerProperty, value); }
        }
        public static readonly DependencyProperty ShowMarkerProperty =
            DependencyProperty.Register("ShowMarker", typeof(bool), typeof(RealTimeGraphExLineErase), new PropertyMetadata(true, new PropertyChangedCallback(CrossModelChanged)));

        /// <summary>
        /// Gets or sets a value indicating whether to enable the MarkerPosition property to be updated. (Affects performance).
        /// </summary>
        public bool EnableMarkerPosition
        {
            get { return (bool)GetValue(EnableMarkerPositionProperty); }
            set { SetValue(EnableMarkerPositionProperty, value); }
        }
        public static readonly DependencyProperty EnableMarkerPositionProperty =
            DependencyProperty.Register("EnableMarkerPosition", typeof(bool), typeof(RealTimeGraphExLineErase), new PropertyMetadata(false, new PropertyChangedCallback(CrossModelChanged)));

        /// <summary>
        /// Gets the current marker position on the graph.
        /// </summary>
        private Point markerPosition;
        public Point MarkerPosition
        {
            private get { return markerPosition; }
            set { markerPosition = value; RaisePropertyChanged("MarkerPosition"); }
        }

        #endregion

        #region Constructors

        public RealTimeGraphExLineErase()
            : base()
        {

        }

        #endregion

        #region Override Method

        protected override void OnSetCrossThreadFields()
        {
            base.OnSetCrossThreadFields();

            this.Dispatcher.Invoke(() =>
            {
                _markerColor = MarkerColor;
                _showMarker = ShowMarker;
                _enableMarkerPosition = EnableMarkerPosition;

                if (lastMaxPoints > _maxPoints && graphPolygon.Count > (lastMaxPoints - _maxPoints))
                {
                    graphPolygon.RemoveFromStart(lastMaxPoints - _maxPoints);
                }

                lastMaxPoints = _maxPoints;

            }, System.Windows.Threading.DispatcherPriority.Send);
        }

        protected internal override void OnRenderGraph()
        {
            if (_graphController != null && _graphController.dataSeries != null && _graphController.dataSeries.Points != null && _graphController.dataSeries.Points.Count > 0 && _width > 1 && _height > 1)
            {
                var points = _graphController.dataSeries.Points.GetAndClearAllPoints();

                if (!_isPaused)
                {

                    for (int i = 0; i < points.Count; i++) //Match
                    {
                        double value = points[i];
                        NormalizeValue(ref value);
                        lastVirtualValue = value;

                        if (graphPolygon.Count > _maxPoints)
                        {
                            graphPolygon.Replace(value, _currentReplaceIndex++);

                            for (int k = 0; k < _markers.Count; k++)
                            {
                                if (_markers[k] == _currentReplaceIndex)
                                {
                                    _markers.RemoveAt(k);
                                    k--;
                                }
                            }
                        }
                        else
                        {
                            graphPolygon.Add(value);
                        }

                        xValueCounter += _scaleFactor;

                        if (_currentReplaceIndex == graphPolygon.Count - 1)
                        {
                            xValueCounter = 0;
                            _currentReplaceIndex = 0;
                        }
                    }
                }

                updateCounter++;

                if (updateCounter >= 1)
                {
                    updateCounter = 0;

                    if (!_disableRendering)
                    {
                        WriteableBitmap bmp = BitmapFactory.New((int)_mainWidth, (int)_mainHeight);
                        bmp.Clear(Colors.Transparent);

                        OnDrawVisuals(bmp);

                        bmp.Freeze();

                        img.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            img.Source = bmp;
                        }), System.Windows.Threading.DispatcherPriority.Send);
                    }
                }
            }
        }

        protected override void OnDrawVisuals(WriteableBitmap bmp)
        {
            if (_graphController == null) return;

            Color stroke = _graphController.dataSeries.GetStrokeColor() != null ? _graphController.dataSeries.GetStrokeColor().Value : _stroke;
            Color fill = _graphController.dataSeries.GetFillColor() != null ? _graphController.dataSeries.GetFillColor().Value : _fill;
            double scale = GetPolygonScaleFactor();
            double currentWidth = _endReached ? _width : xValueCounter;


            if (_fillGraph) //Fill Graph
            {
                bmp.FillPolygon(graphPolygon.ToPolygonPointsFill(_offSetX, _offSetY, _mainWidth, _mainHeight, scale, ConvertYToImageYFliped), fill);
            }

            DrawPolyline(bmp, graphPolygon.ToPolygonPoints(_offSetX, _offSetY, scale, ConvertYToImageYFliped), stroke);


            //Draw marker
            if (_showMarker)
            {
                if (_currentReplaceIndex > 0)
                {
                    try
                    {

                        double x = (((_currentReplaceIndex - 1) * scale) + _offSetX);
                        bmp.DrawLine((int)x, 0, (int)x, (int)_mainHeight, _markerColor);
                    }
                    catch
                    {
                        Debug.WriteLine("[RealTimeGraphExLineErase] [OnDrawVisuals] Error on drawing marker!");
                    }
                }
            }

            for (int j = 0; j < _markers.Count; j++)
            {
                int x = (int)(((_markers[j] - 1) * scale) + _offSetX);
                bmp.DrawLine(x, 0, x, (int)_mainHeight, Colors.Silver);
            }

            if (_enableMarkerPosition)
            {
                MarkerPosition = new Point((_currentReplaceIndex * scale) + _offSetX, ConvertYToImageYFliped(lastVirtualValue) + _offSetY);
            }
        }

        protected override void OnClearGraph()
        {
            base.OnClearGraph();

            _currentReplaceIndex = 0;
            _endReached = false;
            MarkerPosition = new Point(0, 0);
        }

        protected override void OnPushMarker()
        {
            if (_currentReplaceIndex != 0)
            {
                _markers.Add(_currentReplaceIndex);
            }
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(String propName)
        {
            this.Dispatcher.Invoke(() =>
            {

                if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propName));

            });
        }

        #endregion
    }
}