using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Microsoft.Expression.Shapes;

namespace FLY.ControlLibrary
{
    /// <summary>
    /// UserControl1.xaml 的交互逻辑
    /// </summary>
    public partial class GraphScanCircular : UserControl, IGraphScanCircular, INotifyPropertyChanged
    {
        #region 私有成员变量
        /// <summary>
        /// 中心
        /// </summary>
        Point Center;
        /// <summary>
        /// 总半径
        /// </summary>
        double Radius;
        /// <summary>
        /// 分区环，宽度
        /// </summary>
        double BoltNoRingThickness;
        /// <summary>
        /// 最内环，宽度
        /// </summary>
        double InnerRingThickness;
        /// <summary>
        /// 图表，宽度
        /// </summary>
        double GraphThickness;

        double Avg;
        private string calstate_max = "null";
        public string CalState_Max
        {
            get { return calstate_max; }
            set
            {
                if (calstate_max != value)
                {
                    calstate_max = value;
                    NotifyPropertyChanged("CalState_Max");
                }
            }
        }
        private string calstate_min= "null";
        public string CalState_Min
        {
            get { return calstate_min; }
            set
            {
                if (calstate_min != value)
                {
                    calstate_min = value;
                    NotifyPropertyChanged("CalState_Min");
                }
            }
        }
        private string calstate_avg = "null";
        public string CalState_Avg
        {
            get { return calstate_avg; }
            set
            {
                if (calstate_avg != value)
                {
                    calstate_avg = value;
                    NotifyPropertyChanged("CalState_Avg");
                }
            }
        }
        private string calstate_2sigma = "null";
        public string CalState_2Sigma
        {
            get { return calstate_2sigma; }
            set
            {
                if (calstate_2sigma != value)
                {
                    calstate_2sigma = value;
                    NotifyPropertyChanged("CalState_2Sigma");
                }
            }
        }

        List<Arc> BoltArc = new List<Arc>();
        #endregion
        #region IGraphScanCircular
        public static readonly DependencyProperty BoltCntProperty =
DependencyProperty.Register("BoltCnt", typeof(int), typeof(GraphScanCircular), new PropertyMetadata(
88,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    (d as GraphScanCircular).NotifyPropertyChanged("BoltCnt");
})));
        public int BoltCnt
        {
            get
            {
                return (int)GetValue(BoltCntProperty);
            }
            set
            {
                SetValue(BoltCntProperty, value);
            }
        }


        public static readonly DependencyProperty ManualCntProperty =
DependencyProperty.Register("ManualCnt", typeof(int), typeof(GraphScanCircular), new PropertyMetadata(
8,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    (d as GraphScanCircular).NotifyPropertyChanged("ManualCnt");
})));
        public int ManualCnt
        {
            get
            {
                return (int)GetValue(ManualCntProperty);
            }
            set
            {
                SetValue(ManualCntProperty, value);
            }
        }
        public static readonly DependencyProperty MPIsRightProperty =
DependencyProperty.Register("MPIsRight", typeof(bool), typeof(GraphScanCircular), new PropertyMetadata(
true,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    (d as GraphScanCircular).NotifyPropertyChanged("MPIsRight");
})));
        public bool MPIsRight
        {
            get
            {
                return (bool)GetValue(MPIsRightProperty);
            }
            set
            {
                SetValue(MPIsRightProperty, value);
            }
        }
        public static readonly DependencyProperty OrgBoltNoProperty =
    DependencyProperty.Register("OrgBoltNo", typeof(int), typeof(GraphScanCircular), new PropertyMetadata(
    1,
    new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        (d as GraphScanCircular).NotifyPropertyChanged("OrgBoltNo");
    })));
        public int OrgBoltNo
        {
            get
            {
                return (int)GetValue(OrgBoltNoProperty);
            }
            set
            {
                SetValue(OrgBoltNoProperty, value);
            }
        }
        public static readonly DependencyProperty BoltNoWithManual1stProperty =
            DependencyProperty.Register("BoltNoWithManual1st", typeof(int), typeof(GraphScanCircular), new PropertyMetadata(
            1,
            new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                (d as GraphScanCircular).NotifyPropertyChanged("BoltNoWithManual1st");
            })));
        public int BoltNoWithManual1st
        {
            get
            {
                return (int)GetValue(BoltNoWithManual1stProperty);
            }
            set
            {
                SetValue(BoltNoWithManual1stProperty, value);
            }
        }
        public static readonly DependencyProperty AlarmProperty =
    DependencyProperty.Register("Alarm", typeof(int), typeof(GraphScanCircular), new PropertyMetadata(
1000,
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    (d as GraphScanCircular).NotifyPropertyChanged("Alarm");
})));
        public int Alarm
        {
            get
            {
                return (int)GetValue(AlarmProperty);
            }
            set
            {
                SetValue(AlarmProperty, value);
            }
        }

        public static readonly DependencyProperty TargetProperty =
            DependencyProperty.Register("Target", typeof(int), typeof(GraphScanCircular), new PropertyMetadata(
        10000,
        new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as GraphScanCircular).NotifyPropertyChanged("Target");
        })));
        public int Target
        {
            get
            {
                return (int)GetValue(TargetProperty);
            }
            set
            {
                SetValue(TargetProperty, value);
            }
        }

        public static readonly DependencyProperty EmptyValueProperty =
            DependencyProperty.Register("EmptyValue", typeof(int), typeof(GraphScanCircular), new PropertyMetadata(
                99999998,
                new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
                {
                    (d as GraphScanCircular).NotifyPropertyChanged("EmptyValue");
                })));
        public int EmptyValue
        {
            get
            {
                return (int)GetValue(EmptyValueProperty);
            }
            set
            {
                SetValue(EmptyValueProperty, value);
            }
        }

        public static readonly DependencyProperty MultiProperty =
    DependencyProperty.Register("Multi", typeof(double), typeof(GraphScanCircular), new PropertyMetadata(
        100.0,
        new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as GraphScanCircular).NotifyPropertyChanged("Multi");
        })));
        public double Multi
        {
            get
            {
                return (double)GetValue(MultiProperty);
            }
            set
            {
                SetValue(MultiProperty, value);
            }
        }
        public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(GraphScanCircular), new PropertyMetadata(
"Title",
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    (d as GraphScanCircular).NotifyPropertyChanged("Title");
})));
        public string Title
        {
            get
            {
                return (string)GetValue(TitleProperty);
            }
            set
            {
                SetValue(TitleProperty, value);
            }
        }
        public static readonly DependencyProperty Title2Property =
DependencyProperty.Register("Title2", typeof(string), typeof(GraphScanCircular), new PropertyMetadata(
"Title2",
new PropertyChangedCallback(delegate(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    (d as GraphScanCircular).NotifyPropertyChanged("Title2");
})));
        public string Title2
        {
            get
            {
                return (string)GetValue(Title2Property);
            }
            set
            {
                SetValue(Title2Property, value);
            }
        }
        ObservableCollection<int> dataSource;
        public ObservableCollection<int> DataSource
        {
            get
            {
                return dataSource;
            }
            set
            {
                if (dataSource != value)
                {
                    if(dataSource!=null)
                        dataSource.CollectionChanged-=_dataSource_CollectionChanged;

                    dataSource = value;

                    dataSource.CollectionChanged += _dataSource_CollectionChanged;
                    NotifyPropertyChanged("DataSource");
                }
            }
        }
        System.Collections.Specialized.NotifyCollectionChangedEventHandler _dataSource_CollectionChanged;

        public event EventHandler ShowSettingDialogEvent;
        #endregion
        public GraphScanCircular()
        {
            InitializeComponent();

            _dataSource_CollectionChanged = new System.Collections.Specialized.NotifyCollectionChangedEventHandler(dataSource_CollectionChanged);

            this.PropertyChanged += new PropertyChangedEventHandler(GraphScanCircular_PropertyChanged);

            this.run_title.DataContext = this;
            this.run_title2.DataContext = this;
            this.run_calstate.DataContext = this;
            Init();

            DataBindAll_Init();
        }

        void GraphScanCircular_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Target" || e.PropertyName == "Alarm") 
            {
                Draw();
            }
            else if (
                (new string[]{ "BoltCnt", "OrgBoltNo", "ManualCnt", "MPIsRight", "BoltNoWithManual1st" }).Contains(e.PropertyName)) 
            {
                Draw();
            }
        }
        void dataSource_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            double multi = Multi;
            int emptyvalue = EmptyValue;

            //根据修改， 操作mYVal， 与 IsEmpty
            switch (e.Action)
            {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                    {
                        DataBindAll();
                    } break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove://修改X. 永远不执行
                    {
                        DataBindAll();
                    } break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Replace://修改Y
                    {
                        DataBindAll();
                    } break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add://添加 X,Y
                    {
                        DataBindAll();
                    } break;
            }
        }

        void Init()
        {
            Center = new Point(LayoutRoot.Width / 2, LayoutRoot.Width / 2);
            Radius = LayoutRoot.Width / 2;
            BoltNoRingThickness = 20;
            InnerRingThickness = (Radius - BoltNoRingThickness) / 5;
            GraphThickness = (Radius - InnerRingThickness - BoltNoRingThickness);

        }

        void Draw()
        {
            Clear();
            UpdateCalState();
            
            Draw_Background();
            Draw_Manual();
            Draw_BoltNo();
            Draw_Datas();
            Draw_Alarm();
        }
        double TransformDegrees(double degrees)
        {
            if (MPIsRight)
                return -degrees + 90;
            else
                return -degrees - 90;
        }
        void Draw_BoltNo()
        {
            double startAngle;
            double endAngle;
            SolidColorBrush brush_line = new SolidColorBrush(Color.FromRgb(208, 208, 208));

            Arc arc_org = null;
            TextBlock t_org = null;

            for (int i = 0; i < BoltCnt; i++)
            {
                startAngle = TransformDegrees((i + 0 - (OrgBoltNo - 1) - 0.5) * 360 / BoltCnt);
                endAngle = TransformDegrees((i + 1 - (OrgBoltNo - 1) - 0.5) * 360 / BoltCnt);

                if (startAngle > endAngle)
                {
                    double tmp = endAngle;
                    endAngle = startAngle;
                    startAngle = tmp;
                }
                Arc arc = new Arc()
                {
                    ArcThickness = BoltNoRingThickness,
                    ArcThicknessUnit = Microsoft.Expression.Media.UnitType.Pixel,
                    StartAngle = startAngle,
                    EndAngle = endAngle,
                    Stretch = System.Windows.Media.Stretch.None,
                    Stroke = System.Windows.Media.Brushes.White,
                    Fill = System.Windows.Media.Brushes.Black,
                    Width = Radius * 2,
                    Height = Radius * 2

                };


                Point p = Polar.ToPoint(
                    new Polar() { Degrees = (endAngle + startAngle) / 2, Radius = Radius - BoltNoRingThickness / 2 },
                    Center);

                TextBlock t = new TextBlock()
                {
                    TextWrapping = System.Windows.TextWrapping.NoWrap,

                    TextAlignment = System.Windows.TextAlignment.Center,
                    Width = 20,
                    Height = 15,
                    Text = (i + 1).ToString(),
                    FontFamily = new System.Windows.Media.FontFamily("Trebuchet MS"),
                    FontWeight = System.Windows.FontWeights.Bold,
                    Foreground = System.Windows.Media.Brushes.White
                };

                t.SetValue(Canvas.LeftProperty, p.X - t.Width / 2);
                t.SetValue(Canvas.TopProperty, p.Y - t.Height / 2);

                if ((i + 1) == (int)OrgBoltNo)
                {
                    //凸显！！！！！！
                    arc_org = arc;
                    t_org = t;
                }
                else
                {
                    LayoutRoot.Children.Add(arc);
                    LayoutRoot.Children.Add(t);
                }
            }
            if (arc_org != null)
            {
                double w = arc_org.EndAngle - arc_org.StartAngle;
                arc_org.Fill = Brushes.White;// new SolidColorBrush(Color.FromRgb(0x57, 0x9a, 0xab));
                arc_org.Stroke = Brushes.Black;
                arc_org.Width += arc_org.ArcThickness;
                arc_org.ArcThickness *= 2;
                arc_org.Height = arc_org.Width;
                arc_org.Margin = new Thickness(Radius - arc_org.Width / 2);
                arc_org.StartAngle -= w / 2;
                arc_org.EndAngle += w / 2;

                LayoutRoot.Children.Add(arc_org);

                t_org.Foreground = Brushes.Black;
                LayoutRoot.Children.Add(t_org);
            }
        }
        void Draw_Manual()
        {
            double startAngle;
            double endAngle;


            for (int i = 0; i < ManualCnt; i++)
            {
                int start_boltindex = (i + 0) * BoltCnt / ManualCnt + BoltNoWithManual1st - 1;
                int end_boltindex = (i + 1) * BoltCnt / ManualCnt + BoltNoWithManual1st - 1;

                startAngle = TransformDegrees((start_boltindex + 0 - (OrgBoltNo - 1) - 0.5) * 360 / BoltCnt);
                endAngle = TransformDegrees((end_boltindex + 0 - (OrgBoltNo - 1) - 0.5) * 360 / BoltCnt);

                Point p1 = Polar.ToPoint(
                    new Polar() { Degrees = startAngle, Radius = InnerRingThickness + GraphThickness },
                    Center);

                Point p2 = Polar.ToPoint(
                    new Polar() { Degrees = startAngle, Radius = InnerRingThickness },
                    Center);

                Line l = new Line() { X1 = p1.X, Y1 = p1.Y, X2 = p2.X, Y2 = p2.Y, Stroke = new SolidColorBrush(Color.FromRgb(208, 208, 208)) };

                //Point p = Polar.ToPoint(
                //    new Polar() { Degrees = (endAngle + startAngle) / 2, Radius = InnerRingThickness + GraphThickness*3.5/4},
                //    Center);
                ////new System.Drawing.Font("Trebuchet MS", 8.25F, System.Drawing.FontStyle.Bold);
                ////FontFamily="Trebuchet MS" FontSize="12" FontWeight="Bold"
                //TextBlock t = new TextBlock()
                //{
                //    TextWrapping = System.Windows.TextWrapping.NoWrap,

                //    TextAlignment = System.Windows.TextAlignment.Center,
                //    Width = 20,
                //    Height = 15,
                //    Text = (i + 1).ToString(),
                //    FontFamily = new System.Windows.Media.FontFamily("Trebuchet MS"),
                //    FontWeight = System.Windows.FontWeights.Bold
                //};

                //t.SetValue(Canvas.LeftProperty, p.X - t.Width / 2);
                //t.SetValue(Canvas.TopProperty, p.Y - t.Height / 2);


                LayoutRoot.Children.Add(l);
                //LayoutRoot.Children.Add(t);
            }
        }
        void Draw_Background()
        {
            SolidColorBrush brush_line = new SolidColorBrush(Color.FromRgb(208, 208, 208));
            SolidColorBrush brush_alarm = new SolidColorBrush(Color.FromRgb(0xff,0xc1,0xc1));
            double r = InnerRingThickness;
            //最里面的圆
            Ellipse ellipse_inner = new Ellipse()
            {
                Width = r * 2,
                Height = r * 2,
                Stroke = Brushes.Black,
                Margin = new Thickness(Radius - r)
            };

            
            //-公差线
            r = InnerRingThickness + GraphThickness / 4;
            Ellipse ellipse_alarm1 = new Ellipse()
            {
                Width = r * 2,
                Height = r * 2,
                Stroke = brush_alarm,
                Margin = new Thickness(Radius - r),
                StrokeThickness=2
            };

            //目标线
            r = InnerRingThickness + GraphThickness * 2 / 4;
            Ellipse ellipse_target = new Ellipse()
            {
                Width = r * 2,
                Height = r * 2,
                Stroke = brush_line,
                Margin = new Thickness(Radius - r),
                
            };

            //-公差线
            r = InnerRingThickness + GraphThickness * 3 / 4;
            Ellipse ellipse_alarm2 = new Ellipse()
            {
                Width = r * 2,
                Height = r * 2,
                Stroke = brush_alarm,
                Margin = new Thickness(Radius - r),
                StrokeThickness = 2
            };

            LayoutRoot.Children.Add(ellipse_inner);
            LayoutRoot.Children.Add(ellipse_alarm1);
            LayoutRoot.Children.Add(ellipse_target);
            LayoutRoot.Children.Add(ellipse_alarm2);
        }
        void Draw_Datas()//初始化所有 BoltArc
        {
            double startAngle;
            double endAngle;

            if (BoltArc.Count > 0)
            {
                foreach (Arc arc in BoltArc)
                    LayoutRoot.Children.Remove(arc);
                BoltArc.Clear();
            }
            double percent = (double)Alarm / Target;
            if (percent < 0.01)
                percent = 0.01;
            for (int i = 0; i < BoltCnt ; i++)
            {
                startAngle = TransformDegrees((i + 0 - (OrgBoltNo - 1) - 0.5) * 360 / BoltCnt);
                endAngle = TransformDegrees((i + 1 - (OrgBoltNo - 1) - 0.5) * 360 / BoltCnt);

                if (startAngle > endAngle)
                {
                    double tmp = endAngle;
                    endAngle = startAngle;
                    startAngle = tmp;
                }

                double r;
                if (DataSource != null && i < DataSource.Count && DataSource[i] != EmptyValue)
                {
                    r = ((DataSource[i] - Avg) / Avg) / (4 * percent) * GraphThickness;
                }
                else 
                {
                    r = 0;
                }
                double target_r = InnerRingThickness + GraphThickness / 2;

                Arc arc = new Arc()
                {
                    ArcThicknessUnit = Microsoft.Expression.Media.UnitType.Pixel,
                    StartAngle = startAngle,
                    EndAngle = endAngle,
                    Stretch = System.Windows.Media.Stretch.None,
                    Fill = System.Windows.Media.Brushes.Green,
                    Stroke = System.Windows.Media.Brushes.Black,
                    StrokeThickness = 2
                };
                //--------------------------------------------------------------
                //限制
                if (r > GraphThickness / 2) 
                {
                    r = GraphThickness / 2;
                }
                else if (r < -GraphThickness / 2)
                {
                    r = -GraphThickness / 2;
                }

                //--------------------------------------------------------------
                //改变颜色
                if (r > GraphThickness / 4)
                {
                    arc.Fill = System.Windows.Media.Brushes.Orange;
                }
                else if (r < -GraphThickness / 4)
                {
                    arc.Fill = System.Windows.Media.Brushes.Red;
                }
                else 
                {
                    arc.Fill = System.Windows.Media.Brushes.Green;
                }



                if (r > 0)
                {
                    arc.Width = (target_r + r) * 2;
                }
                else
                {
                    arc.Width = target_r * 2;
                }
                arc.ArcThickness = Math.Abs(r);


                arc.Height = arc.Width;
                arc.Margin = new Thickness(Radius - arc.Width / 2);
                LayoutRoot.Children.Add(arc);
                BoltArc.Add(arc);
            }
        }
        
        void Draw_Alarm()
        {
            double startAngle = TransformDegrees(0);
            double percent = (double)Alarm / Target;
            if (percent < 0.01)
                percent = 0.01;
            //负公差
            Draw_Marker(new Polar() { Degrees = startAngle, Radius = InnerRingThickness + GraphThickness / 4 }, (-100 * percent).ToString() + "%");

            //正公差
            Draw_Marker(new Polar() { Degrees = startAngle, Radius = InnerRingThickness + GraphThickness * 3 / 4 }, (100 * percent).ToString() + "%");
        }
        void Draw_Marker(Polar polar, string s)
        {
            Point p1 = Polar.ToPoint(
                polar,
                Center);

            SolidColorBrush brush_alarm = new SolidColorBrush(Color.FromRgb(0xff, 0xc1, 0xc1));
            SolidColorBrush brush_line = new SolidColorBrush(Color.FromRgb(208, 208, 208));
            double r = 15;
            //底
            Ellipse ellipse_background = new Ellipse()
            {
                Width = r * 2,
                Height = r * 2,
                Fill = System.Windows.Media.Brushes.Red,
                Stroke = System.Windows.Media.Brushes.Black,
                StrokeThickness = 1
            };
            ellipse_background.SetValue(Canvas.LeftProperty, p1.X - ellipse_background.Width / 2);
            ellipse_background.SetValue(Canvas.TopProperty, p1.Y - ellipse_background.Width / 2);

            TextBlock t = new TextBlock()
            {
                TextWrapping = System.Windows.TextWrapping.NoWrap,

                TextAlignment = System.Windows.TextAlignment.Center,
                Width = 20,
                Height = 12,
                Text = s,
                FontFamily = new System.Windows.Media.FontFamily("Trebuchet MS"),
                FontWeight = System.Windows.FontWeights.Bold,
                Foreground = System.Windows.Media.Brushes.White,
                FontSize = 10
            };

            t.SetValue(Canvas.LeftProperty, p1.X - t.Width / 2);
            t.SetValue(Canvas.TopProperty, p1.Y - t.Height / 2);

            LayoutRoot.Children.Add(ellipse_background);
            LayoutRoot.Children.Add(t);
        }
        void Clear() 
        {
            LayoutRoot.Children.Clear();
            BoltArc.Clear();
        }
        /// <summary>
        /// 与 Multi,EmptyValue,DataFirst,DataLast 相关
        /// </summary>
        void UpdateCalState()
        {
            int emptyvalue = EmptyValue;
            double multi = Multi;

            if (DataSource == null)
            {
                goto _err;
            }
            List<int> datlist;
            if (BoltCnt >= DataSource.Count())
            {
                datlist = DataSource.ToList();
            }
            else 
            {
                datlist = DataSource.ToList().GetRange(0, BoltCnt);
            }


            var dats = from data in datlist where data != emptyvalue select data;
            if (dats.Count() == 0)
            {
                goto _err;
            }
            else
            {
                Avg = dats.Average();

                double avg = dats.Average() / multi;
                double max = dats.Max() / multi;
                double min = dats.Min() / multi;

                double sum = 0;
                foreach (int dat in dats)
                {
                    sum += Math.Pow(avg - (double)dat / multi, 2);
                }
                sum /= (dats.Count() - 1);
                double sigma = Math.Sqrt(sum);
                CalState_Max = "+"+(100.0 * (max - avg) / avg).ToString("N1") + "%";
                CalState_Min = (100.0 * (min- avg) / avg).ToString("N1") + "%";
                CalState_Avg = (avg).ToString("N1");
                CalState_2Sigma = (200* sigma / avg).ToString("N1") + "%";
            }
            return;

        _err:
            CalState_Max = "null";
            CalState_Min = "null";
            CalState_Avg = "null";
            CalState_2Sigma = "null";

        }
        void Update_OneData(int index)
        {
            if (index >= BoltArc.Count)
                return;
            double percent = (double)Alarm / Target;
            if (percent < 0.01)
                percent = 0.01;

            double r;
            if (DataSource != null && index < DataSource.Count && DataSource[index] != EmptyValue)
            {
                r = ((DataSource[index] - Avg) / Avg) / (4 * percent) * GraphThickness;
            }
            else
            {
                r = 0;
            }
            double target_r = InnerRingThickness + GraphThickness / 2;
            Arc arc = BoltArc[index];


            //--------------------------------------------------------------
            //限制
            if (r > GraphThickness / 2)
            {
                r = GraphThickness / 2;
            }
            else if (r < -GraphThickness / 2)
            {
                r = -GraphThickness / 2;
            }

            //--------------------------------------------------------------
            //改变颜色
            if (r > GraphThickness / 4)
            {
                arc.Fill = System.Windows.Media.Brushes.Orange;
            }
            else if (r < -GraphThickness / 4)
            {
                arc.Fill = System.Windows.Media.Brushes.Red;
            }
            else
            {
                arc.Fill = System.Windows.Media.Brushes.Green;
            }


            arc.ArcThickness = Math.Abs(r);
            if (r > 0)
            {
                arc.Width = (target_r + r) * 2;
            }
            else
            {
                arc.Width = target_r * 2;
            }
            arc.Height = arc.Width;
            arc.Margin = new Thickness(Radius - arc.Width / 2);
        }
        void Update_Datas() 
        {
            UpdateCalState();
            for (int i = 0; i < BoltCnt; i++)
                Update_OneData(i);
        }
        #region INotifyPropertyChanged 成员
        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            Draw();

        }
        public void Button_Click(object sender, RoutedEventArgs e)
        {
            if (ShowSettingDialogEvent != null)
                ShowSettingDialogEvent(this, new EventArgs());
        }


        bool batabindall_flag = false;
        System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
        void DataBindAll_Init()
        {
            timer = new System.Windows.Threading.DispatcherTimer();
            timer.Tick += new EventHandler(delegate(object sender, EventArgs e)
            {
                if (batabindall_flag)
                {
                    batabindall_flag = false;
                    Update_Datas();
                }
            });

            timer.Interval = TimeSpan.FromSeconds(0.2);
            timer.Start();
        }
        void DataBindAll()
        {
            batabindall_flag = true;
        }
    }
    public interface IGraphScanCircular
    {
        /// <summary>
        /// 分区数
        /// </summary>
        int BoltCnt { get; set; }

        /// <summary>
        /// 手动螺栓数
        /// </summary>
        int ManualCnt { get; set; }

        /// <summary>
        /// 测厚仪测量点位置方向：Left， Right （也就是三角形在左还是右）
        /// </summary>
        bool MPIsRight { get; set; }

        /// <summary>
        /// 复位分区号，也就是三角形对应的 分区号
        /// </summary>
        int OrgBoltNo { get; set; }

        /// <summary>
        ///  第1个手动螺栓 对应于 分区号
        /// </summary>
        int BoltNoWithManual1st { get; set; }

        /// <summary>
        /// 工艺值
        /// </summary>
        int Alarm { get; set; }

        /// <summary>
        /// 只能是自动目标值,  target 与 alarm 组合使用，工艺%
        /// </summary>
        int Target { get; set; }

        /// <summary>
        /// 空的数据，定义某个值为空，默认为 99999998
        /// </summary>
        int EmptyValue { get; set; }

        /// <summary>
        /// 放大倍数, 目标值= Target/放大倍数
        /// </summary>
        double Multi { get; set; }

        /// <summary>
        ///  标题
        /// </summary>
        string Title { get; set; }

        /// <summary>
        /// 副标题
        /// </summary>
        string Title2 { get; set; }

        /// <summary>
        /// 数据源
        /// </summary>
        ObservableCollection<int> DataSource { get; set; }

        /// <summary>
        /// 弹出设置界面
        /// </summary>
        event EventHandler ShowSettingDialogEvent;
    }

    /// <summary>
    /// Polar 12点方向=0°，3点方向=90°，6点方向=180°，9点方向=270°
    /// Point 左上角 x=0,y=0; 右上角 x=100, y=0; 左下角 x=0,y=100;
    /// </summary>
    class Polar
    {
        public double Degrees;//角度制！！！
        public double Radius;
        public static Point ToPoint(Polar polar, Point center)
        {
            Point p = new Point();
            Vector v = new Vector();
            v.Y = -polar.Radius * Math.Cos(DegreesToRadians(polar.Degrees));
            v.X = polar.Radius * Math.Sin(DegreesToRadians(polar.Degrees));
            p = center + v;
            return p;
        }
        public static double DegreesToRadians(double degrees)
        {
            double radians = Math.PI / 180 * degrees;
            return radians;
        }

    }
}
