sivlerlight2D温度云图中的算法

siverlight中绘制温度云图,倒腾了好一段时间。

silverlight中的控件比较少,选择了OxyPlot控件中的heatmap曲线来画温度曲线

但是Oxyplot绘制的温度场不能满足要求。只能根据算法计算其中温度值。


1、初始化OxyPlot控件

2、根据传入的温度值计算温度无向图的最短路径

3、计算最短路径上的所有点的温度值。

4、计算温度值(以计算坐标周围8个点的值进行计算:大于等于3个点的坐标有温度值,求平均值作为计算坐标的温度值)

5、遍历二位数组,计算所有温度值。


结果:此算法不是完美算法。

1、无向图最短路径,存在点-点的超长跨度线。

2、插值算法不能完整计算所有点。

3、当插值算法遍历计算次数不同时,温度值会有明显的边界区分。





    public partial class UieHeatMap : UserControl, UieBase
    {
        //Color Palette Area
        protected static int PALETTE_STEP = 100;
        public int MAX_X = 1400;
        public int MAX_Y = 700;

        //无向温度图最短路径
        List<HeatMapPoint> ShortestPath = new List<HeatMapPoint>();

        //温度场页面所有温度点
        protected List<HeatMapPoint> heatMapPoints;

        protected PlotModel plotModel;
        protected LinearColorAxis linearColorAxis;
        protected HeatMapSeries heatMapSeries;

        /// <summary>
        /// 初始化函数
        /// </summary>
        /// <param name="x">heatMapSeries x pixel</param>
        /// <param name="y">heatMapSeries y pixel</param>
        public UieHeatMap()
        {
            InitializeComponent();
            plotModel = new PlotModel(); ;
            linearColorAxis = new LinearColorAxis();
            heatMapSeries = new HeatMapSeries();
            heatMapPoints = new List<HeatMapPoint>();
            plotModel.Axes.Clear();
        }

        public void InitData(List<HeatMapPoint> heatMapPoints)
        {
            heatMapSeries.X1 = MAX_X;
            heatMapSeries.Y1 = MAX_Y;
            foreach (var hmp in heatMapPoints)
            {
                // deal with edge
                hmp.X = hmp.X > MAX_X ? MAX_X : hmp.X;
                hmp.Y = hmp.Y > MAX_X ? MAX_Y : hmp.Y;
                hmp.Y = MAX_Y - hmp.Y;
                this.heatMapPoints.Add(hmp);
            }
            GetShortestPath(heatMapPoints);
            InitPlotModel();
        }

        private void GetShortestPath(List<HeatMapPoint> heatMapPoints)
        {
            HeatMapPoint startSearchKey = heatMapPoints[0].Copy();
            ShortestPath.Add(heatMapPoints[0].Copy());
            heatMapPoints.RemoveAt(0);

            List<int> hmpPath = new List<int>();
            while (heatMapPoints.Count > 1)
            {

                List<double> tempPath = new List<double>();
                for (int i = 0; i < heatMapPoints.Count; i++)
                {
                    double distance = Math.Sqrt((startSearchKey.X - heatMapPoints[i].X) * (startSearchKey.X - heatMapPoints[i].X) + (startSearchKey.Y - heatMapPoints[i].Y) * (startSearchKey.Y - heatMapPoints[i].Y));
                    tempPath.Add(distance);
                }
                var a = tempPath.Select((m, index) => new double[2] { index, m }).OrderBy(n => n[1]).Take(1).ToList();
                startSearchKey = heatMapPoints[(int)a[0][0]].Copy();
                ShortestPath.Add(heatMapPoints[(int)a[0][0]].Copy());
                heatMapPoints.RemoveAt((int)a[0][0]);
            }
        }


        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="rtds"></param>
        public void SetRtValue(List<RealTimeData> rtds)
        {
            RefreshData(rtds);
        }

        /// <summary>
        /// 是否显示标题
        /// </summary>
        /// <param name="isShow"></param>
        /// <param name="title"></param>
        /// <param name="fontSize"></param>
        public void SetIsShowTitle(bool isShow, string title, int fontSize)
        {
            //
        }


        /// <summary>
        /// 绑定别名
        /// </summary>
        public int BindRtdNo
        {
            get;
            set;
        }

        /// <summary>
        /// 设置控件大小
        /// </summary>
        /// <param name="isLockScale"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        public void SetUieSize(bool isLockScale, double width, double height)
        {
            heatmap.Width = width;
            if (!isLockScale)
            {
                heatmap.Height = height;
            }
        }

        /// <summary>
        /// 初始化图表
        /// </summary>
        public void InitPlotModel()
        {
            //调色板
            linearColorAxis.Position = AxisPosition.Right;
            linearColorAxis.Maximum = 60;
            linearColorAxis.Minimum = 5;
            linearColorAxis.Palette = new OxyPalette(InitPalette());
            plotModel.Axes.Add(linearColorAxis);

            //数据
            heatMapSeries.CoordinateDefinition = HeatMapCoordinateDefinition.Edge;
            heatMapSeries.Interpolate = false;
            heatMapSeries.Data = new Double[Convert.ToInt32(MAX_X), Convert.ToInt32(MAX_Y)];
            //AssignSeriesBaseData();

            TraversalData();
            plotModel.Series.Add(heatMapSeries);
            heatmap.Model = plotModel;
            plotModel.InvalidatePlot(true);
        }

        private void TraversalData()
        {
            for (int a = 0; a < MAX_X; a++)
            {
                for (int b = 0; b < MAX_Y; b++)
                {
                    heatMapSeries.Data[a, b] = 0;
                }
            }
            //初始化基本点温度值
            foreach (var htm in ShortestPath)
            {
                heatMapSeries.Data[(int)htm.X, (int)htm.Y] = htm.Temperature;
            }

            //初始化线性温度值
            for (int i = 0; i < ShortestPath.Count - 1; i++)
            {
                HeatMapPoint start = ShortestPath[i];
                HeatMapPoint end = ShortestPath[i + 1];

                if (start.X > end.X)
                {
                    start = ShortestPath[i + 1];
                    end = ShortestPath[i];
                }

                bool YisPlus = start.Y > end.Y ? true : false;

                try
                {
                    for (int j = 0; j < Math.Abs(start.X - end.X); j++)
                    {
                        int tempX = (int)(start.X + j);
                        int tempY = 0;
                        double xxxx = (start.Temperature - end.Temperature) * j / (start.X - end.X);
                        if (YisPlus)
                        {
                            tempY = (int)(start.Y - j / (start.X - end.X) * (start.Y + end.Y));
                            heatMapSeries.Data[(int)(start.X - j), (int)(start.Y - j / Math.Abs((start.X - end.X)) * (start.Y - end.Y))] = start.Temperature - (start.Temperature - end.Temperature) * j / (start.X - end.X);
                        }
                        else
                        {
                            tempY = (int)(start.Y + j / (start.X - end.X) * (start.Y + end.Y));
                            heatMapSeries.Data[(int)(start.X - j), (int)(start.Y - j / Math.Abs((start.X - end.X)) * (start.Y - end.Y))] = start.Temperature - (start.Temperature - end.Temperature) * j / (start.X - end.X);
                        }
                    }

                }
                catch (Exception)
                {
                    throw;
                }
            }

            int blankPointInt = 0;
            //以八个方向填充温度值
            for (int x = 1; x < MAX_X - 1; x++)
            {
                for (int y = 1; y < MAX_Y - 1; y++)
                {
                    if (heatMapSeries.Data[x, y] == 0)
                    {
                        List<double> aroudTemperature = new List<double>();
                        aroudTemperature.Add(heatMapSeries.Data[x, y - 1]);
                        aroudTemperature.Add(heatMapSeries.Data[x, y + 1]);

                        aroudTemperature.Add(heatMapSeries.Data[x - 1, y]);
                        aroudTemperature.Add(heatMapSeries.Data[x - 1, y + 1]);
                        aroudTemperature.Add(heatMapSeries.Data[x - 1, y - 1]);

                        aroudTemperature.Add(heatMapSeries.Data[x + 1, y]);
                        aroudTemperature.Add(heatMapSeries.Data[x + 1, y + 1]);
                        aroudTemperature.Add(heatMapSeries.Data[x + 1, y - 1]);
                        int existCount = aroudTemperature.Where(o => o > 0).ToList().Count;
                        if (existCount >= 3)
                        {
                            heatMapSeries.Data[x, y] = aroudTemperature.Sum(o => o) / existCount;
                        }
                        else
                        {
                            blankPointInt++;
                        }
                    }
                }
            }

            int CirlcleCount = 0;
            while (blankPointInt > 100 && CirlcleCount <1)
            {
                CirlcleCount++;
                blankPointInt = 0;
                //blankPoints.Clear();
                for (int x = 1; x < MAX_X - 1; x++)
                {
                    for (int y = 1; y < MAX_Y - 1; y++)
                    {
                        if (heatMapSeries.Data[x, y] == 0)
                        {
                            List<double> aroudTemperature = new List<double>();
                            aroudTemperature.Add(heatMapSeries.Data[x, y - 1]);
                            aroudTemperature.Add(heatMapSeries.Data[x, y + 1]);

                            aroudTemperature.Add(heatMapSeries.Data[x - 1, y]);
                            aroudTemperature.Add(heatMapSeries.Data[x - 1, y + 1]);
                            aroudTemperature.Add(heatMapSeries.Data[x - 1, y - 1]);

                            aroudTemperature.Add(heatMapSeries.Data[x + 1, y]);
                            aroudTemperature.Add(heatMapSeries.Data[x + 1, y + 1]);
                            aroudTemperature.Add(heatMapSeries.Data[x + 1, y - 1]);
                            int existCount = aroudTemperature.Where(o => o > 0).ToList().Count;
                            if (existCount >= 3)
                            {
                                heatMapSeries.Data[x, y] = aroudTemperature.Sum(o => o) / existCount;
                            }
                            else
                            {
                                //blankPoints.Add(new TempPoint { X = x, Y = y });
                                blankPointInt++;
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Init Palette
        /// </summary>
        /// <returns></returns>
        private List<OxyColor> InitPalette()
        {
            List<OxyColor> result = new List<OxyColor>();
            OxyColor temp = OxyColor.FromArgb((byte)0, (byte)1, (byte)1, (byte)1);
            result.Add(temp);
            result.AddRange(GetStepColors(Colors.Blue, Colors.Green));
            result.AddRange(GetStepColors(Colors.Green, Colors.Yellow));
            result.AddRange(GetStepColors(Colors.Yellow, Colors.Orange));
            result.AddRange(GetStepColors(Colors.Orange, Colors.Red));

            return result;
        }


        /// <summary>
        /// 获得从开始颜色到结束颜色的颜色表
        /// </summary>
        /// <param name="startColor"></param>
        /// <param name="endColor"></param>
        /// <returns></returns>
        private List<OxyColor> GetStepColors(Color startColor, Color endColor)
        {
            List<OxyColor> result = new List<OxyColor>();
            int r = 0;
            int g = 0;
            int b = 0;
            for (int i = 0; i < PALETTE_STEP; i++)
            {
                r = startColor.R + (endColor.R - startColor.R) * i / PALETTE_STEP;
                g = startColor.G + (endColor.G - startColor.G) * i / PALETTE_STEP;
                b = startColor.B + (endColor.B - startColor.B) * i / PALETTE_STEP;
                OxyColor temp = OxyColor.FromArgb((byte)255, (byte)r, (byte)g, (byte)b);
                result.Add(temp);
            }
            return result;
        }


        /// <summary>
        /// 将实时数据赋值给热点列表
        /// </summary>
        /// <param name="rtds">实时数据</param>
        private void ConvertRtdToHeatMapPoints(List<RealTimeData> rtds)
        {
            foreach (var rtd in rtds)
            {
                foreach (var hmp in ShortestPath)
                //foreach (var hmp in heatMapPoints)
                {
                    if (rtd.DevAlias == hmp.DevAlias && rtd.Name == "温度")
                    {
                        if (LJD.IMS.Ria.Utility.StringHelper.IsNumber(rtd.RtValue))
                            hmp.Temperature = double.Parse(rtd.RtValue);
                    }
                }
            }
        }

        /// <summary>
        /// 刷新数据
        /// </summary>
        /// <param name="rtds">传入实时数据</param>
        public void RefreshData(List<RealTimeData> rtds)
        {
            if (rtds.Count > 0)
            {
                ConvertRtdToHeatMapPoints(rtds);
                plotModel.Series.Clear();
                // AssignSeriesBaseData();
                TraversalData();
                //InitNewData();
                plotModel.Series.Add(heatMapSeries);
                plotModel.InvalidatePlot(true);
                heatmap.InvalidatePlot(true);
                heatmap.Model.InvalidatePlot(true);
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值