using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.IO;
using System.Drawing.Imaging;
using System.Text.RegularExpressions;
using System.Linq;
using WinControls;
using SMAT_CE.Properties;
namespace SMAT_CE
{
    /// <summary>
    /// 模型域里的一个网格
    /// </summary>
    public struct GridCell
    {
        /// <summary>
        /// 行,从1开始
        /// </summary>
        public int Row;
        /// <summary>
        /// 列,从1开始
        /// </summary>
        public int Col;
        /// <summary>
        /// 值
        /// </summary>
        public double Value;
    }

    public partial class PlotControl : UserControl
    {

        private PointF selectedPoint;
        public PointF SelectedPoint { get => selectedPoint; set => selectedPoint = value; }
        public string strSelectedPointLatLon;

        public bool isMarkSelectedPoint = false;

        #region 私有变量和属性
        /// <summary>
        /// 是否画监测点
        /// </summary>
        public bool IsDrawMonitors = false;

        /// <summary>
        /// 是否画污染源
        /// </summary>
        public bool IsDrawSSIASource = false;

        /// <summary>
        /// 监测点数值
        /// </summary>
        public Dictionary<string, double> dicMonitors = new Dictionary<string, double>();

        /// <summary>
        /// 污染源位置
        /// </summary>
        public PointF pointSource = new PointF();

        /// <summary>
        /// 投影参数
        /// </summary>
        public DotSpatial.Projections.ProjectionInfo projForMap = new DotSpatial.Projections.ProjectionInfo();

        private bool _useInterpolation = false;
        /// <summary>
        /// 是否使用插值
        /// </summary>
        public bool UseInterpolation
        {
            get { return _useInterpolation; }
            set
            {
                _useInterpolation = value;
                _needRedrawBmp = true;
                this.Invalidate();
            }
        }

        private bool _useContinuousColor = true;
        /// <summary>
        /// 使用连续的色彩
        /// </summary>
        public bool UseContinuousColor
        {
            get { return _useContinuousColor; }
            set
            {
                _useContinuousColor = value;
                _needRedrawBmp = true;
                this.Invalidate();
            }
        }

        /// <summary>
        /// 已选择的gridcell列表
        /// </summary>
        private List<GridCell> _selectedCells = null;
        /// <summary>
        /// 已选择的gridcell列表
        /// </summary>
        public List<GridCell> SelectedCells
        {
            get { return _selectedCells; }
            set { _selectedCells = value; }
        }

        /// <summary>
        /// 把世界坐标转换成页面坐标的系数
        /// </summary>
        private float _factor = 1;

        /// <summary>
        /// 坐标转换Matrix,默认为转换成Y向上为正
        /// </summary>
        /// <remarks>
        /// 1  0  1
        /// 0  -1 1
        /// dx dy 1
        /// </remarks>
        private Matrix _matrix = new Matrix(1f, 0f, 0f, -1f, 0f, 0f);

        private Color _shapeLineColor = Color.Gray;
        /// <summary>
        /// Shape的线颜色
        /// </summary>
        public Color ShapeLineColor
        {
            get { return _shapeLineColor; }
            set { _shapeLineColor = value; }
        }


        private ModelDef _modelDef;
        //private static RSMModelDef _modelDef;
        /// <summary>
        /// 用于此控件的RSMModelDef对象,通常要改变此控件对应的Policy时设置
        /// </summary>
        public ModelDef modelDef
        {
            get { return _modelDef; }
            set { _modelDef = value; }
        }



        List<List<PointF>> _segmentsList = null;
        /// <summary>
        /// 用于画Shape的线段List
        /// </summary>
        public List<List<PointF>> SegmentsList
        {
            get { return _segmentsList; }
            set { _segmentsList = value; }
        }

        private float[] _xCoords;
        /// <summary>
        /// 所有网格的X坐标,个数为LocationCount
        /// </summary>
        public float[] XCoords
        {
            get { return _xCoords; }
            set { _xCoords = value; }
        }

        private float[] _yCoords;
        /// <summary>
        /// 所有网格的Y坐标,个数为LocationCount
        /// </summary>
        public float[] YCoords
        {
            get { return _yCoords; }
            set { _yCoords = value; }
        }

        /// <summary>
        /// 所有网格在最小的值
        /// </summary>
        double _minValue = 0;
        /// <summary>
        /// 所有网格中最大的值
        /// </summary>
        double _maxValue = 0;
        private double[] _gridValues = new double[0];
        /// <summary>
        /// 所有网格的值,个数为locationCount
        /// </summary>
        public double[] GridValues
        {
            get { return _gridValues; }
            set
            {
                if (value == null || value.Length == 0) { return; }
                _gridValues = value;
                #region added by sclong
                double[] tmp = new double[_gridValues.Length];
                _gridValues.CopyTo(tmp, 0);
                Array.Sort(tmp);
                double minValue = tmp[_gridValues.Length - 1];
                double maxValue = _gridValues[0];
                #endregion
                //_minValue = 0;
                //_maxValue = _gridValues[0];
                for (int i = 1; i < _gridValues.Length; i++)
                {
                    if (_gridValues[i] != -9) //added by sclong 20130914
                    {
                        if (_gridValues[i] < _minValue) { _minValue = _gridValues[i]; }
                        else if (_gridValues[i] > _maxValue) { _maxValue = _gridValues[i]; }
                    }

                }
                if (_colorBlendControl != null)
                {
                    // isFirstLoad等于True,初始化社快分区
                    bool isFirstLoad = true;
                    _colorBlendControl.SetValueRange(_minValue, _maxValue, isFirstLoad);

                    // 设置网格的颜色
                    ResetAllGridsColor();
                }
                //_needRedrawBmp = true;// 移到ResetAllGridsColor()函数中
                //this.Invalidate();
            }
        }
        #region 网格值Dictionary<string, double> _NewGridValues
        // private Dictionary<string, double> _NewGridValues = new Dictionary<string, double>();
        //public Dictionary<string, double> NewGridValues
        //{
        //    get { return _NewGridValues; }
        //    set
        //    {
        //        if (value == null || value.Keys.Count == 0) { return; }
        //        _NewGridValues = value;
        //        double[] tmp = new double[value.Keys.Count];
        //        _minValue = CommonClass.minValue;
        //        _maxValue = 0;
        //        foreach (var key in _NewGridValues.Keys)
        //        {
        //            if (_NewGridValues[key] < _minValue) { _minValue = _NewGridValues[key]; }
        //            else if (_NewGridValues[key] > _maxValue) { _maxValue = _NewGridValues[key]; }
        //        }

        //        if (_colorBlendControl != null)
        //        {
        //            // isFirstLoad等于True,初始化社快分区
        //            bool isFirstLoad = true;
        //            _colorBlendControl.SetValueRange(_minValue, _maxValue, isFirstLoad);

        //            // 设置网格的颜色
        //            ResetNewAllGridsColor();
        //        }
        //    }
        //}
        #endregion

        #region added by Yangwenwei 20131218
        //use for recording the Map name in lstSpeciesTypeMap(Form SMAT_CE) 
        public string Mapname = "";
        //used for recoding the min&max value of each Maps
        private Dictionary<string, Dictionary<double, double>> dicMinMax = new Dictionary<string, Dictionary<double, double>>();
        //clean 
        public void MinMaxClean()
        {
            dicMinMax.Clear();
        }
        #endregion

        private Dictionary<string, double> _NewGridValues = new Dictionary<string, double>();
        public Dictionary<string, double> NewGridValues
        {
            get { return _NewGridValues; }
            set
            {
                if (value == null || value.Keys.Count == 0) { return; }
                _NewGridValues = value;
                double[] tmp = new double[value.Keys.Count];

                //_minValue = CommonClass.minValue;
                _minValue = _NewGridValues.Values.Max();
                _maxValue = 0;
                foreach (var key in _NewGridValues.Keys)
                {
                    if (_NewGridValues[key] == -9 || _NewGridValues[key] == -7)
                        continue;
                    if (_NewGridValues[key] < _minValue) { _minValue = _NewGridValues[key]; }
                    else if (_NewGridValues[key] > _maxValue) { _maxValue = _NewGridValues[key]; }
                }

                _colorBlendControl._minPlotValue = _minValue;
                _colorBlendControl._maxPlotValue = _maxValue;

                ////Get min&max value from Dictionary 'MinMax'  added and modified by Yangwenwei 20131218
                //if (!(_minValue == 0 && _maxValue == 0) && Mapname != "" && dicMinMax.Keys.Contains(Mapname))
                //{
                //    Dictionary<double, double> dic = new Dictionary<double, double>();
                //    dicMinMax.TryGetValue(Mapname, out dic);
                //    _minValue = dic.Keys.First();
                //    _maxValue = dic.Values.Last();
                //}


                if (_colorBlendControl != null)
                {
                    //added by Yangwenwei 2014.3.24
                    if (CommonClass.dicBlend.Keys.Contains("Map") && CommonClass.dicBlend["Map"].Keys.Contains(Mapname))
                    {
                        SetValueRange frm = new SetValueRange();
                        frm.ColorArray = CommonClass.dicBlend["Map"][Mapname].colorarray;
                        frm.ValueArray = CommonClass.dicBlend["Map"][Mapname].value;
                        frm.MinValue = CommonClass.dicBlend["Map"][Mapname].min;
                        frm.MaxValue = CommonClass.dicBlend["Map"][Mapname].max;
                        _colorBlendControl.SetValueRangeAndBundaryColor(frm, false);
                    }
                    else
                    {
                        // isFirstLoad等于True,初始化色块分区
                        bool isFirstLoad = true;
                        _colorBlendControl.SetValueRange(_minValue, _maxValue, isFirstLoad);

                    }
                    // 设置网格的颜色
                    ResetNewAllGridsColor();
                }

            }
        }
        /// <summary>
        /// 重新设置所有网格的颜色,并重画所有网格
        /// </summary>
        public void ResetNewAllGridsColor()
        {
            try
            {
                _gridColors = new Color[_NewGridValues.Keys.Count];
                int j = 0;
                foreach (var key in _NewGridValues.Keys)
                {
                    _gridColors[j] = _colorBlendControl.GetValueColor(_NewGridValues[key]);
                    j++;
                }

                _needRedrawBmp = true;
                this.Invalidate();

                ////...Save min&max value to Dictionary MinMax added by Yangwenwei 201301218
                //Dictionary<double, double> dic = new Dictionary<double, double>();
                //dic.Add(_colorBlendControl.MinValue, _colorBlendControl.MaxValue);
                //if (dicMinMax.Keys.Contains(Mapname))
                //    dicMinMax[Mapname] = dic;
                //else
                //    dicMinMax.Add(Mapname, dic);

                //added by Yangwenwei 2014.3.24
                CommonClass.SaveBlend saveblend = new CommonClass.SaveBlend(_colorBlendControl.ColorArray, _colorBlendControl.ValueArray);
                saveblend.max = _colorBlendControl.MaxValue;
                saveblend.min = _colorBlendControl.MinValue;
                _colorBlendControl.SetValueRange(saveblend.min, saveblend.max, false);//让txtmax是红色的最小值
                if (!CommonClass.dicBlend.Keys.Contains("Map"))
                {
                    Dictionary<string, CommonClass.SaveBlend> dic = new Dictionary<string, CommonClass.SaveBlend>();
                    dic.Add(Mapname, saveblend);
                    CommonClass.dicBlend.Add("Map", dic);
                }
                else if (CommonClass.dicBlend["Map"].Keys.Contains(Mapname))
                    CommonClass.dicBlend["Map"][Mapname] = saveblend;
                else
                    CommonClass.dicBlend["Map"].Add(Mapname, saveblend);
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }
        /// <summary>
        /// 重新设置所有网格的颜色,并重画所有网格
        /// </summary>
        public void ResetAllGridsColor()
        {
            try
            {
                _gridColors = new Color[_gridValues.Length];
                for (int j = 0; j < _gridValues.Length; j++)
                {
                    if (_gridValues[j] != -9) //added by sclong 20130914
                    {
                        _gridColors[j] = _colorBlendControl.GetValueColor(_gridValues[j]);
                    }

                }
                _needRedrawBmp = true;
                this.Invalidate();
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        /// <summary>
        /// 所有网格的颜色,在设置_gridValues时设置
        /// </summary>
        private Color[] _gridColors = new Color[0];

        private ColorBlendControl _colorBlendControl;
        /// <summary>
        /// 颜色图例
        /// </summary>
        public ColorBlendControl ColorBlendControl
        {
            get { return _colorBlendControl; }
            set { _colorBlendControl = value; }
        }


        /// <summary>
        /// 网格颜色向周边过度的混合,在构造函数中初始化
        /// </summary>
        Blend _blend = new Blend();


        /// <summary>
        /// 模型域在窗体上画出时，被缩小的边，以窗体坐标为单位的宽度或高度的大小
        /// </summary>
        private float _modelWidthOrHeightInForm = 0f;


        /// <summary>
        /// 标识模型值发生变化的坐标轴
        /// </summary>
        private string _axisChanged = "x";
        #endregion

        /// <summary>
        /// plotting monitors on Map
        /// </summary>
        /// <param name="dicMonitors">dictionary of monitors; key->x,y; value->concentration</param>
        /// <param name="bmpGraphics"></param>
        /// <returns>T or F</returns>
        private bool drawMonitor(Dictionary<string, double> dicMonitors, Graphics bmpGraphics)
        {

            string errorMsg = "";
            SolidBrush brush = new SolidBrush(Color.Blue);
            if (dicMonitors.Keys.Count <= 0) { errorMsg = "No monitors!"; goto Exit; }
            try
            {
                // TODO: 确定网格坐标是在cell的左下角,还是cell的中点
                float d = 8 / _factor;
                SizeF size = new SizeF(d, d);
                int i = 0;
                foreach (var key in dicMonitors.Keys)
                {
                    Color cellColor = _colorBlendControl.GetValueColor(dicMonitors[key]);

                    brush = new SolidBrush(cellColor);

                    string[] vars = key.Split(',');
                    float x = 0;
                    float y = 0;
                    x = float.Parse(vars[0]);
                    y = float.Parse(vars[1]);
                    //bmpGraphics.FillRectangle(brush, new RectangleF(new PointF(x, y), size));
                    bmpGraphics.FillEllipse(brush, new RectangleF(new PointF(x, y), size));

                    Pen p = new Pen(Color.Black, 2.0f);
                    bmpGraphics.DrawEllipse(p, new RectangleF(new PointF(x, y), size));

                    i++;
                }




            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        Exit:
            {
                //MessageBox.Show(errorMsg);
                return false;
            }
        }

        /// <summary>
        /// plotting monitors on Map
        /// </summary>
        /// <param name="dicMonitors">dictionary of monitors; key->x,y; value->concentration</param>
        /// <param name="bmpGraphics"></param>
        /// <returns>T or F</returns>
        private bool MarkSelectMonitor(PointF m, Graphics bmpGraphics)
        {            
            SolidBrush brush = new SolidBrush(Color.Blue);
            try
            {
                // TODO: 确定网格坐标是在cell的左下角,还是cell的中点
                float d = 8 / _factor;
                SizeF size = new SizeF(d, d);
                int i = 0;
                //foreach (var key in dicMonitors.Keys)
                //{
                //    //Color cellColor = _colorBlendControl.GetValueColor(dicMonitors[key]);
                //    //brush = new SolidBrush(cellColor);

                //    string[] vars = key.Split(',');
                //    float x = 0;
                //    float y = 0;
                //    x = float.Parse(vars[0]);
                //    y = float.Parse(vars[1]);
                    //bmpGraphics.FillRectangle(brush, new RectangleF(new PointF(x, y), size));
                    //bmpGraphics.FillEllipse(brush, new RectangleF(new PointF(x, y), size));

                    Pen p = new Pen(Color.Red, 2.0f/_factor);
                    bmpGraphics.DrawEllipse(p, new RectangleF(m, size));
                    i++;
                //}
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        Exit:
            {
                //MessageBox.Show(errorMsg);
                return false;
            }
        }

        /// <summary>
        /// plotting SSIA Source on Map
        /// </summary>
        /// <param name="dicMonitors">dictionary of monitors; key->x,y; value->concentration</param>
        /// <param name="bmpGraphics"></param>
        /// <returns>T or F</returns>
        public bool drawSSIASource(PointF p, Graphics bmpGraphics)
        {

            //string errorMsg = "";
            //SolidBrush brush = new SolidBrush(Color.Blue);
            //if (dicMonitors.Keys.Count <= 0) { errorMsg = "No monitors!"; goto Exit; }
            try
            {
                double[] arrayPoint = new double[] { (double)p.X, (double)p.Y };
                DotSpatial.Projections.Reproject.ReprojectPoints(arrayPoint, null,
                    DotSpatial.Projections.KnownCoordinateSystems.Geographic.World.WGS1984,
                    projForMap, 0, 1);

                //point = new PointF((float)arrayPoint[0], (float)arrayPoint[1]);


                // TODO: 确定网格坐标是在cell的左下角,还是cell的中点
                float d = 12 / _factor;
                SizeF size = new SizeF(d, d);
                //int i = 0;
                //foreach (var key in dicMonitors.Keys)
                //{
                //   Color cellColor = _colorBlendControl.GetValueColor(dicMonitors[key]);

                // brush = new SolidBrush(cellColor);

                //string[] vars = key.Split(',');
                //float x = 0;
                //float y = 0;
                //x = float.Parse(vars[0]);
                //y = float.Parse(vars[1]);
                //bmpGraphics.FillRectangle(brush, new RectangleF(new PointF(x, y), size));
                // bmpGraphics.FillEllipse(brush, new RectangleF(new PointF(x, y), size));

                bmpGraphics.DrawImage(Resources.sourceX,
                    (float)arrayPoint[0] - size.Width / 2,
                    (float)arrayPoint[1] - size.Height / 2,
                    size.Width, size.Height);

                //Pen p = new Pen(Color.Black, 2.0f);
                //bmpGraphics.DrawEllipse(p, new RectangleF(new PointF(x, y), size));

                //i++;
                //}




            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        Exit:
            {
                //MessageBox.Show(errorMsg);
                return false;
            }
        }

        public PlotControl()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);//设置双缓冲，防止图像抖动,必须和AllPaintingInWmPaint一起设置。设置为true会自动使用双缓冲，没必再要手工用bmp
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);//   忽略系统消息，防止图像闪烁  
            //this.SetStyle(ControlStyles.UserMouse, true);//控制鼠标完成事件   

            _blend.Factors = new float[] { 0f, 0.5f, 1f };//{ 0.0f, 0.3f, 0.5f, 1.0f };
            _blend.Positions = new float[] { 0f, 0.5f, 1f };// { 0.0f, 0.2f, 0.6f, 1.0f };
        }


        /// <summary>
        /// 用于缓冲的bitmap对象,当控件尺寸或者网格值未变化时,在OnPaint中把该对象画到界面上,不再重画1万多个网格
        /// </summary>
        Bitmap _bmp = null;
        /// <summary>
        /// 是否需要重新生成bitmap对象,当网格值改变,控件尺寸变化,或者放大,缩小,平移后,都要设为true,重新生成bitmap后设为false
        /// </summary>
        bool _needRedrawBmp = false;
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            try
            {
                if (_needRedrawBmp)
                {

                    DrawImage();
                }

                if (_bmp != null)
                {
                    e.Graphics.DrawImage(_bmp, 0f, 0f);// 坐标变换在bmp中进行,窗体的坐标系统没有变化,依然是左上角为原点

                }

            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        /// <summary>
        /// 把图形画到一个Bitmap上返回.该Bitmap在保存时会用到,但在当前窗体由OnPaint方法调用时,使用的是_bmp,不直接使用返回值
        /// </summary>
        /// <returns></returns>
        private Bitmap DrawImage()
        {
            try
            {
                // 手工双缓冲技术,先把所有内容画到内存(一个Bitmap中)
                _bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height);
                CalFactorAndMatrix();
                using (Graphics bmpGraphics = Graphics.FromImage(_bmp))
                {
                    // 坐标变换在bmp中进行,窗体的坐标系统没有变化,依然是左上角为原点
                    bmpGraphics.Transform = _matrix;
                   
                    // 画网格
                    if (_useInterpolation)
                    {
                        DrawGridWithInterpolate();
                    }
                    else
                    {
                        DrawGrid(bmpGraphics);
                    }

                    // 画选择的网格
                    DrawSelectedCells(bmpGraphics);

                    //画监测点
                    if (IsDrawMonitors)
                    {
                        drawMonitor(dicMonitors, bmpGraphics);
                        if (isMarkSelectedPoint)
                        { MarkSelectMonitor(SelectedPoint, bmpGraphics); }
                    }

                    //画污染源
                    if (IsDrawSSIASource)
                    {
                        drawSSIASource(pointSource, bmpGraphics);
                    }


                    // 画地图
                    DrawShape(bmpGraphics);


                }
                #region draw the variables,by sclong,2017-03-09
           
                Graphics g = Graphics.FromImage(_bmp);
                Font titleFont = new Font("Calibri", 14f, FontStyle.Bold);
                Color titleColor = Color.Black;
                string title = this.Mapname;
                float locationWidth = _bmp.Width / 2;
              
                if (title == "Δ(o3_used)")
                {
                    title = "deltaO3 = b_o3_used - f_o3_used";
                }
                SizeF string_size = g.MeasureString(title, titleFont);
                locationWidth = locationWidth - string_size.Width / 2;
                g.DrawString(title, titleFont, new SolidBrush(titleColor), new PointF(locationWidth, 5));
                g.Dispose();
                GC.Collect();
                #endregion draw the variables,by sclong,2017-03-09
                //e.Graphics.DrawImage(_bmp, 0f, 0f);// 坐标变换在bmp中进行,窗体的坐标系统没有变化,依然是左上角为原点
                _needRedrawBmp = false;
                return _bmp;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return null;
            }
        }



        /// <summary>
        /// 用于由SavePictures调用保存成emf文件,暂时有问题
        /// </summary>
        /// <param name="g"></param>
        public void DrawImageToGraphics(Graphics g)
        {
            try
            {
                CalFactorAndMatrix();
                // 坐标变换在bmp中进行,窗体的坐标系统没有变化,依然是左上角为原点
                g.Transform = _matrix;
                // 画网格
                DrawGrid(g);
                //DrawGradientGrid(bmpGraphics);
                // 画选择的网格
                DrawSelectedCells(g);

                // 画地图
                DrawShape(g);
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        protected new void Dispose()
        {
            if (_bmp != null) { _bmp.Dispose(); }
            base.Dispose();
        }

        /// <summary>
        /// 真正画模型结果图的大小
        /// </summary>
        private Size _drawSize = new Size(1, 1);

        /// <summary>
        /// 计算用于坐标转换的成员变量.
        /// 在每次Draw之前都要调用
        /// </summary>
        private void CalFactorAndMatrix()
        {
            try
            {
                _drawSize = this.ClientSize;
                // 一个地图单位相当于多少个屏幕单位,以小的为主
                float factorX = (float)this.ClientSize.Width / (_modelDef.MaxX - _modelDef.MinX + _modelDef.CellWidth);
                float factorY = (float)this.ClientSize.Height / (_modelDef.MaxY - _modelDef.MinY + _modelDef.CellHeight);
                if (factorX < factorY)
                {
                    _factor = factorX;
                    // 实际模型域转到窗体坐标系的宽度
                    _modelWidthOrHeightInForm = (_modelDef.MaxY - _modelDef.MinY + _modelDef.CellHeight) * factorX;
                    _axisChanged = "y";
                    _drawSize.Height = (int)_modelWidthOrHeightInForm;
                }
                else
                {
                    _factor = factorY;
                    // 实际模型域转到窗体坐标系的高度
                    _modelWidthOrHeightInForm = (_modelDef.MaxX - _modelDef.MinX + _modelDef.CellWidth) * factorY;
                    _axisChanged = "x";
                    _drawSize.Width = (int)_modelWidthOrHeightInForm;

                }
                //Console.WriteLine("factor={0}", factor);
                //把y方向值*-1,相当于向上为正.同时把y值+this.Height,相当于把窗体坐标原点往下移this.Height个单位
                //float dx = -_cmaqModeDef.MinX * _factor + (this.ClientSize.Width - (_cmaqModeDef.MaxX - _cmaqModeDef.MinX+_modelDef.CellWidth) * _factor) / 2f;// 以窗体宽度大于模型域宽度推算.小于也正确
                // 上面公式的合并
                float dx = (this.ClientSize.Width - (_modelDef.MaxX + _modelDef.MinX + _modelDef.CellWidth) * _factor) / 2f;
                //float dy = this.ClientSize.Height + _cmaqModeDef.MinY * _factor- (this.ClientSize.Height - (_cmaqModeDef.MaxY - _cmaqModeDef.MinY+_modelDef.CellHeight) * _factor) / 2f;// 以窗体高度大于模型域宽度推算.小于也正确
                // 上面公式的合并
                float dy = (this.ClientSize.Height + (_modelDef.MaxY + _modelDef.MinY + _modelDef.CellHeight) * _factor) / 2f;
                _matrix = new Matrix(_factor, 0f, 0f, -_factor, dx, dy);
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }



        /// <summary>
        /// 画网格,无插值
        /// </summary>
        /// <param name="bmpGraphics">用于画图的Bitmap对象的Graphics</param>
        private void DrawGrid(Graphics bmpGraphics)
        {
            #region
            //SolidBrush brush = new SolidBrush(Color.Blue);
            //if (_gridValues.Length <= 0) { return; }
            //try
            //{
            //    // TODO: 确定网格坐标是在cell的左下角,还是cell的中点
            //    SizeF size = new SizeF(_modelDef.CellWidth, _modelDef.CellHeight);
            //    for (int i = 0; i < _modelDef.LocationCount; i++)
            //    {
            //        Color cellColor = _gridColors[i];
            //        if (!_useContinuousColor)
            //        {
            //            cellColor = _colorBlendControl.GetValueRangeColor(_gridValues[i]);
            //        }
            //        brush = new SolidBrush(cellColor);// new SolidBrush(cellColor);
            //        bmpGraphics.FillRectangle(brush, new RectangleF(new PointF(_xCoords[i], _yCoords[i]), size));
            //        //Console.WriteLine("Row {0}", i);
            //    }
            //}
            #endregion
            SolidBrush brush = new SolidBrush(Color.Blue);
            if (_NewGridValues.Keys.Count <= 0) { return; }
            try
            {
                // TODO: 确定网格坐标是在cell的左下角,还是cell的中点
                SizeF size = new SizeF(_modelDef.CellWidth, _modelDef.CellHeight);
                int i = 0;
                foreach (var key in _NewGridValues.Keys)
                {
                    Color cellColor = _gridColors[i];

                    if (!_useContinuousColor)
                    {
                        cellColor = _colorBlendControl.GetValueRangeColor(_NewGridValues[key]);
                    }
                    brush = new SolidBrush(cellColor);// new SolidBrush(cellColor);
                    #region string类型
                    //Regex _regex = new Regex(",");
                    //string[] vars;
                    //vars = _regex.Split(key);
                    //bmpGraphics.FillRectangle(brush, new RectangleF(new PointF(float.Parse(vars[0]), float.Parse(vars[1])), size));
                    #endregion
                    string[] vars = key.Split(',');
                    float x = 0;
                    float y = 0;
                    if (vars.Count() == 3)//"d,lat,long"---ssia dispersion
                    {
                        x = float.Parse(vars[1]);
                        y = float.Parse(vars[2]);
                        bmpGraphics.FillRectangle(brush, new RectangleF(new PointF(x, y), new SizeF(100, 100)));
                        //bmpGraphics.FillEllipse(brush, new RectangleF(new PointF(x, y), new SizeF(200, 200)));
                    }
                    else
                    {
                        x = float.Parse(vars[0]);
                        y = float.Parse(vars[1]);
                        bmpGraphics.FillRectangle(brush, new RectangleF(new PointF(x, y), size));
                    }
                    i++;
                }

            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
            finally
            {
                brush.Dispose();
            }
        }

        #region 插值,v2.0
        /// <summary>
        /// 画网格,有插值
        /// </summary>
        /// <param name="bmpGraphics">用于画图的Bitmap对象的Graphics</param>
        private void DrawGridWithInterpolate()
        {
            if (_gridValues.Length <= 0 || _bmp == null) { return; }
            try
            {
                int xOffset = (_bmp.Width - _drawSize.Width) / 2;
                int yOffset = (_bmp.Height - _drawSize.Height) / 2;
                double pixelsPerGridX = (double)_drawSize.Width / _modelDef.ColCount;
                double pixelsPerGridY = (double)_drawSize.Height / _modelDef.RowCount;
                int lastRow = -1, lastCol = -1;
                double cellValue = 0, v1 = 0, v2 = 0, v3 = 0, v4 = 0, val = 0;
                double v12 = 0, v13 = 0, v24 = 0, v34 = 0;
                double v10 = 0, v20 = 0, v30 = 0, v40 = 0;
                //int cnt = 0;
                for (int y = 0; y < _drawSize.Height; y++)
                {
                    double tmp = (_drawSize.Height - y) / pixelsPerGridY;
                    int row = (int)Math.Floor(tmp);
                    if (row == _modelDef.RowCount) { row = _modelDef.RowCount - 1; }
                    double gridYPercent = tmp - row;
                    bool isYGreaterHalf = false;
                    if (gridYPercent > 0.5)
                    {
                        isYGreaterHalf = true;
                        gridYPercent = (gridYPercent - 0.5) * 2;    // 必须在这里设置值
                    }
                    else
                    {
                        gridYPercent = gridYPercent * 2;
                    }
                    for (int x = 0; x < _drawSize.Width; x++)
                    {
                        tmp = x / pixelsPerGridX;
                        int col = (int)Math.Floor(tmp);
                        if (col == _modelDef.ColCount) { col = _modelDef.ColCount - 1; }
                        double gridXPercent = tmp - col;
                        if (row != lastRow || col != lastCol)
                        {
                            // VPI的网格索引1位于左下角起第二行,第一列.CMAQ的网格索引1位于左下角起第一行,第二列
                            CalcVertex(ref v1, ref v2, ref v3, ref v4, ref v12, ref v13, ref v24, ref v34, ref cellValue, row, col);
                            lastRow = row;
                            lastCol = col;
                        }

                        if (gridXPercent > 0.5)
                        {
                            gridXPercent = (gridXPercent - 0.5) * 2;
                            if (isYGreaterHalf)
                            {
                                v10 = v12;
                                v20 = v2;
                                v30 = cellValue;
                                v40 = v24;
                            }
                            else
                            {
                                v10 = cellValue;
                                v20 = v24;
                                v30 = v34;
                                v40 = v4;
                            }
                        }
                        else
                        {
                            gridXPercent = gridXPercent * 2;
                            if (isYGreaterHalf)
                            {
                                v10 = v1;
                                v20 = v12;
                                v30 = v13;
                                v40 = cellValue;
                            }
                            else
                            {
                                v10 = v13;
                                v20 = cellValue;
                                v30 = v3;
                                v40 = v34;
                            }
                        }
                        //v10 = v1; v20 = v2; v30 = v3; v40 = v4;
                        val = v30 + (v40 - v30) * gridXPercent + (v10 - v30) * gridYPercent + (v20 - v10 + v30 - v40) * gridXPercent * gridYPercent;
                        //val = v3 + (v4 - v3) * gridXPercent + (v1 - v3) * gridYPercent + (v2 - v1 + v3 - v4) * gridXPercent * gridYPercent;
                        Color color;
                        if (_useContinuousColor)
                        {
                            color = _colorBlendControl.GetValueColor(val);
                            //color = _colorBlendControl.GetValueColor2(val);
                        }
                        else
                        {
                            color = _colorBlendControl.GetValueRangeColor(val);
                        }
                        _bmp.SetPixel(x + xOffset, y + yOffset, color);
                    }
                }
                //Console.WriteLine("cnt={0}", cnt);
                /*   插值示意图
                 * 
                 *   v1----a----v2
                 *   |          |
                 *   |---x0---v |
                 *   a        | | 
                 *   |        y0|
                 *   v3-------|-v4
                 *   
                 *   v=v3+(v4-v3)*x0/a+(v1-v3)*y0/a+(v2-v1+v3-v4)*x0*y0/a/a
                 *   其中:
                 *   v1,v2,v3,v4为网格四个顶点的值.每个值都由该顶点周边四个网格值平均得到
                 *   a为网格宽度
                 *   x0为要求值的点离网格左边框的距离
                 *   x0/a=gridXPercent
                 */

            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        /// <summary>
        /// 计算所有网格周边顶点,中点值
        /// </summary>
        /// <param name="cellValue">保存求得的当前网格值</param>
        /// <param name="v12">V1,V2的中点值</param>
        /// <param name="row">当前网格行,用于计算cellValue</param>
        /// <param name="col">当前网格列,用于计算cellValue</param>
        private void CalcVertex(ref double v1, ref double v2, ref double v3, ref double v4
            , ref double v12, ref double v13, ref double v24, ref double v34, ref double cellValue, int row, int col)
        {
            try
            {
                // 确定周边行列
                int row1 = row - 1;
                if (row1 < 0) { row1 = 0; }
                int row2 = row + 1;
                if (row2 >= _modelDef.RowCount) { row2 = _modelDef.RowCount - 1; }
                int col1 = col - 1;
                if (col1 < 0) { col1 = 0; }
                int col2 = col + 1;
                if (col2 >= _modelDef.ColCount) { col2 = _modelDef.ColCount - 1; }
                // 计算当前网格及周边网格植
                double c0 = _gridValues[GetLocationBaseRow0(row, col)];
                double c1 = _gridValues[GetLocationBaseRow0(row2, col1)];
                double c2 = _gridValues[GetLocationBaseRow0(row2, col)];
                double c3 = _gridValues[GetLocationBaseRow0(row2, col2)];
                double c4 = _gridValues[GetLocationBaseRow0(row, col1)];
                double c5 = _gridValues[GetLocationBaseRow0(row, col2)];
                double c6 = _gridValues[GetLocationBaseRow0(row1, col1)];
                double c7 = _gridValues[GetLocationBaseRow0(row1, col)];
                double c8 = _gridValues[GetLocationBaseRow0(row1, col2)];
                // 计算当前网格及周边网格植
                // c0: row,col所在网格的值
                // c1-c8,当前网格周边8个网格值,按以下顺序排列
                //  c1 c2 c3
                //  c4 c0 c5
                //  c6 c7 c8
                v1 = (c1 + c2 + c4 + c0) / 4;
                v2 = (c2 + c3 + c0 + c5) / 4;
                v3 = (c4 + c0 + c6 + c7) / 4;
                v4 = (c0 + c5 + c7 + c8) / 4;
                v12 = (c2 + c0) / 2;
                v13 = (c4 + c0) / 2;
                v24 = (c0 + c5) / 2;
                v34 = (c0 + c7) / 2;
                cellValue = c0;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        #endregion


        /// <summary>
        /// 绘制选择的网格
        /// </summary>
        /// <param name="bmpGraphics">用于画图的Graphics对象</param>
        private void DrawSelectedCells(Graphics bmpGraphics)
        {
            if (_selectedCells == null) { return; }
            if (_gridValues.Length <= 0) { return; }
            try
            {
                // TODO: 确定网格坐标是在cell的左下角,还是cell的中点
                //SizeF size = new SizeF(_modelDef.CellWidth, _modelDef.CellHeight);
                //bmpGraphics.Transform = _matrix;
                using (Pen pen = new Pen(Color.Gray))
                {
                    pen.DashStyle = DashStyle.Solid;
                    foreach (GridCell cell in _selectedCells)
                    {
                        int idx = GetLocation(cell.Row, cell.Col);
                        //this.Invalidate(); // 这样做会把下面画出的框也消除掉
                        bmpGraphics.DrawRectangle(pen, _xCoords[idx], _yCoords[idx], _modelDef.CellWidth, _modelDef.CellHeight);
                    }
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }


        /// <summary>
        /// 画Shape
        /// </summary>
        /// <param name="bmpGraphics">用于画图的Bitmap对象的Graphics</param>
        private void DrawShape(Graphics g)
        {
            try
            {
                if (_segmentsList == null || _segmentsList.Count == 0) { return; }
                //g.Transform = _matrix;
                using (Pen pen = new Pen(_shapeLineColor, 1f / _factor))
                {
                    foreach (List<PointF> pts in _segmentsList)
                    {
                        PointF[] points = new PointF[pts.Count];
                        pts.CopyTo(points);
                        g.DrawLines(pen, points);// 生硬
                        //g.DrawPolygon(pen, points);// 多出一条从终点到起点的线
                        //g.DrawBeziers(pen, points);// 参数无效
                        //g.DrawCurve(pen, points);// 效果最好
                    }
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        private void RSMPlotControl_SizeChanged(object sender, EventArgs e)
        {

            // 每次改变大小都刷新整个控件
            _needRedrawBmp = true;
            this.Invalidate();
        }

        /// <summary>
        /// 把传入的屏幕坐标点(通常从MouseClick事件中直接取得),转换成模型的GridCell对象
        /// </summary>
        /// <param name="pt">屏幕坐标点(通常从MouseClick事件中直接取得)</param>
        /// <returns>对应的模型的GridCell对象.如果转换失败,则GridCell.Row=-1</returns>
        public string TransformToGridCell(Point pt)
        {
            try
            {
                // 把屏幕坐标变换成模型坐标
                Matrix matrix = _matrix.Clone();
                matrix.Invert();
                PointF[] pts = new PointF[] { pt };
                matrix.TransformPoints(pts);
                //Console.WriteLine("X={0},\tY={1}", pts[0].X, pts[0].Y);
                int cellwidth = CommonClass.modelDefinition.ActiveGridType == "12km" ? cellwidth = 12100 / 2 : cellwidth = 36000 / 2;
                int cellheight = cellwidth;
                if (CommonClass.modelDefinition.CellWidthHeight != null && CommonClass.modelDefinition.CellWidthHeight[0] > 0 && CommonClass.modelDefinition.CellWidthHeight[1] > 0)
                {
                    cellwidth = (int)CommonClass.modelDefinition.CellWidthHeight[0];
                    cellheight = (int)CommonClass.modelDefinition.CellWidthHeight[1];
                }

                foreach (var key in _NewGridValues.Keys)
                {
                    string skey = key;
                    Regex _regex = new Regex(",");
                    string[] vars;
                    if (skey.Contains("d"))
                        skey = skey.Substring(2);
                    vars = _regex.Split(skey);
                    float x = 0;
                    float y = 0;
                    x = float.Parse(vars[0]);
                    y = float.Parse(vars[1]);
                    if (Math.Abs(x - pts[0].X) <= cellwidth & Math.Abs(y - pts[0].Y) <= cellheight)
                    {
                        //cell.Value = _NewGridValues[key];
                        #region MyRegion
                        //var keys = CommonClass.modelDefinition.ColRowgridValues.FirstOrDefault(q => q.Value ==cell.Value).Key;
                        //Regex _regex = new Regex(",");
                        //string[] vars;
                        //vars = _regex.Split(keys);
                        //cell.Row = int.Parse(vars[0]);
                        //cell.Col = int.Parse(vars[1]);
                        #endregion
                        return skey;
                    }
                }
                #region 注释 by sclong

                //// 取得点对应的网格行,行从1开始计数
                //int row = (int)Math.Truncate((pts[0].Y - _modelDef.MinY) / _modelDef.CellHeight) + 1;
                //if (row < 1 || row > _modelDef.RowCount) { return cell; }
                //// 取得点对应的网格列
                //int col = (int)Math.Truncate((pts[0].X - _modelDef.MinX) / _modelDef.CellWidth) + 1;
                //if (col < 1 || col > _modelDef.ColCount) { return cell; }
                //cell.Row = row;
                //cell.Col = col;
                //// 取得网格的值
                //cell.Value = _gridValues[GetLocation(row, col)];

                #endregion
                //AddCell2SelectedList(cell, true);
                return "";
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return "";
            }
        }
        #region 把网格加入到已选择列表中 未改动
        /// <summary>
        /// 把网格加入到已选择列表中
        /// </summary>
        /// <param name="cell">要加入选择列表的网格</param>
        /// <param name="clearOthers">是否先清空已选择列表</param>
        //public void AddCell2SelectedList(GridCell cell, bool clearOthers)
        //{
        //    Graphics g = this.CreateGraphics();
        //    g.Transform = _matrix;
        //    //SolidBrush brush = new SolidBrush(Color.Red);
        //    Pen pen = new Pen(Color.Red);
        //    int location;
        //    pen.DashStyle = DashStyle.Solid;

        //    try
        //    {
        //        if (_selectedCells == null)
        //        {
        //            _selectedCells = new List<GridCell>();
        //        }
        //        else
        //        {
        //            // 还原所有网格到原始状态                    
        //            SizeF size = new SizeF(_modelDef.CellWidth, _modelDef.CellHeight);
        //            foreach (GridCell cell1 in _selectedCells)
        //            {
        //                location = GetLocation(cell1.Row, cell1.Col);
        //                //brush = new SolidBrush(_gridColors[location]);
        //                //g.FillRectangle(brush, new RectangleF(new PointF(_xCoords[location], _yCoords[location]), size));
        //                Color clr = _gridColors[location];
        //                if (clr == Color.Transparent) { clr = this.BackColor; }
        //                pen = new Pen(clr);

        //                g.DrawRectangle(pen, _xCoords[location], _yCoords[location], _modelDef.CellWidth, _modelDef.CellHeight);
        //            }
        //            DrawShape(g);
        //        }
        //        if (clearOthers)
        //        {
        //            _selectedCells.Clear();
        //        }
        //        _selectedCells.Add(cell);
        //        // 绘制选择的网格边框

        //        pen = new Pen(Color.Gray);
        //        foreach (GridCell cell2 in _selectedCells)
        //        {
        //            location = GetLocation(cell2.Row, cell2.Col);
        //            //this.Invalidate(); // 这样做会把下面画出的框也消除掉


        //            g.DrawRectangle(pen, _xCoords[location], _yCoords[location], _modelDef.CellWidth, _modelDef.CellHeight);
        //        }

        //        _needRedrawBmp = true;// 确保重新生成缓冲bmp
        //        //this.Invalidate();
        //    }
        //    catch (Exception ex)
        //    {
        //        CommonClass.LogError(ex);
        //    }
        //    finally
        //    {
        //        g.Dispose();
        //        //brush.Dispose();
        //        pen.Dispose();
        //    }
        //}
        #endregion
        /// <summary>
        /// 把网格加入到已选择列表中
        /// </summary>
        /// <param name="cell">要加入选择列表的网格</param>
        /// <param name="clearOthers">是否先清空已选择列表</param>
        public void AddCell2SelectedList(GridCell cell, bool clearOthers)
        {
            Graphics g = this.CreateGraphics();
            g.Transform = _matrix;
            //SolidBrush brush = new SolidBrush(Color.Red);
            Pen pen = new Pen(Color.Red);
            int location;
            pen.DashStyle = DashStyle.Solid;
            var keys = _NewGridValues.FirstOrDefault(q => q.Value == cell.Value).Key;
            try
            {
                if (_selectedCells == null)
                {
                    _selectedCells = new List<GridCell>();
                }
                else
                {
                    // 还原所有网格到原始状态                    
                    SizeF size = new SizeF(_modelDef.CellWidth, _modelDef.CellHeight);
                    foreach (GridCell cell1 in _selectedCells)
                    {
                        //location = GetLocation(cell1.Row, cell1.Col);
                        //brush = new SolidBrush(_gridColors[location]);
                        //g.FillRectangle(brush, new RectangleF(new PointF(_xCoords[location], _yCoords[location]), size));
                        Color clr = _gridColors[0];
                        if (clr == Color.Transparent) { clr = this.BackColor; }
                        pen = new Pen(clr);
                        Regex _regex = new Regex(",");
                        string[] vars;
                        vars = _regex.Split(keys);
                        float x = 0;
                        float y = 0;
                        x = float.Parse(vars[0]);
                        y = float.Parse(vars[1]);
                        g.DrawRectangle(pen, x, y, _modelDef.CellWidth, _modelDef.CellHeight);
                        //g.DrawRectangle(pen, _xCoords[location], _yCoords[location], _modelDef.CellWidth, _modelDef.CellHeight);
                    }
                    DrawShape(g);
                }
                if (clearOthers)
                {
                    _selectedCells.Clear();
                }
                _selectedCells.Add(cell);
                // 绘制选择的网格边框

                pen = new Pen(Color.Gray);
                foreach (GridCell cell2 in _selectedCells)
                {
                    location = GetLocation(cell2.Row, cell2.Col);
                    //this.Invalidate(); // 这样做会把下面画出的框也消除掉
                    Regex _regex = new Regex(",");
                    string[] vars;
                    vars = _regex.Split(keys);
                    float x = 0;
                    float y = 0;
                    x = float.Parse(vars[0]);
                    y = float.Parse(vars[1]);
                    g.DrawRectangle(pen, x, y, _modelDef.CellWidth, _modelDef.CellHeight);
                    //g.DrawRectangle(pen, _xCoords[location], _yCoords[location], _modelDef.CellWidth, _modelDef.CellHeight);
                }

                _needRedrawBmp = true;// 确保重新生成缓冲bmp
                //this.Invalidate();
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
            finally
            {
                g.Dispose();
                //brush.Dispose();
                pen.Dispose();
            }
        }

        /// <summary>
        /// 根据行(从1开始),列(从1开始)计算Location索引.
        /// VPI的网格索引1位于左下角起第二行,第一列.CMAQ的网格索引1位于左下角起第一行,第二列
        /// </summary>
        /// <param name="row">行(从1开始)</param>
        /// <param name="col">列(从1开始)</param>
        /// <returns>Location索引</returns>
        private int GetLocation(int row, int col)
        {
            return _modelDef.RowCount * (col - 1) + row - 1;
        }

        /// <summary>
        /// 根据行(从0开始),列(从0开始)计算Location索引
        /// VPI的网格索引1位于左下角起第二行,第一列.CMAQ的网格索引1位于左下角起第一行,第二列
        /// </summary>
        /// <param name="row">行(从0开始)</param>
        /// <param name="col">列(从0开始)</param>
        /// <returns>Location索引</returns>
        private int GetLocationBaseRow0(int row, int col)
        {
            return _modelDef.RowCount * (col) + row;
        }

        /// <summary>
        /// 根据行,列取得网格的值.如果行或列超出范围,则返回double.NaN
        /// </summary>
        /// <param name="row">行,从1开始索引</param>
        /// <param name="col">列,从1开始索引</param>
        /// <returns></returns>
        public double GetCellValue(int row, int col)
        {
            if (row < 1 || row > _modelDef.RowCount || col < 1 || col > _modelDef.ColCount) { return double.NaN; }
            return _gridValues[GetLocation(row, col)];
        }

        // 右键上下文菜单
        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                //SavePicture save = new SavePicture(this.ColorBlendControl);
                //save.SaveAs();
                SaveRsmAndBlend(false); //false represents for saving without blend. added and modified by Yangwenwei 20131219
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        // 右键上下文菜单保存数据为BenMAPFile
        private void saveDataAsBenMAPFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string msg = "";
            try
            {
                msg = SaveDataToFile();
                if (msg != "")
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
            finally
            {
                if (msg != "")
                {
                    MessageBox.Show(msg, "Tip", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
        }

        // 将数据保存到文件,返回空值说明保存成功，否则保存失败
        private string SaveDataToFile()
        {

            string strPath = "";
            string msg = "";
            try
            {
                SaveFileDialog SFD = new SaveFileDialog();
                SFD.DefaultExt = "CSV";
                SFD.Filter = "CSV文件(*.csv)|*.csv";

                if (SFD.ShowDialog() == DialogResult.OK)
                {
                    strPath = SFD.FileName;

                    // 保存BenMAPFile
                    msg = SaveToBenMAPFile(strPath);
                }
                return msg;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return msg + ex.Message;
            }

        }

        /// <summary>
        /// 将数据保存为BenMAPFile
        /// </summary>
        /// <param name="strPath">本次文件的文件名</param>
        /// <returns>返回空值：保存成功，否则保存失败。</returns>
        private string SaveToBenMAPFile(string strPath)
        {
            string msg = "";
            StreamWriter Writer = new StreamWriter(strPath, false, Encoding.Default);
            double tmp = 0.0d;
            try
            {
                // 每个BenMAP文件的第一行都要写lines
                string lines = "Row,Column,Metric,Seasonal Metric,Statistic,Values";
                // 定义数组的长度
                int count = _modelDef.RowCount * _modelDef.ColCount + 1;
                string[] DataLines = new string[count];
                DataLines[0] = lines;
                // Console.WriteLine(count);
                // 数组的元素从1开始一直到最后
                count = 1;
                // 将每个网格的值赋给数组，每个网格一个作为一个元组。
                for (int j = 1; j < (_modelDef.RowCount + 1); j++)
                {
                    for (int k = 1; k < (_modelDef.ColCount + 1); k++)
                    {
                        tmp = _gridValues[GetLocation(j, k)];
                        tmp = Math.Round(tmp, 5);
                        DataLines[count] = string.Format("{0},{1},D24HourMean,QuarterlyMean,Mean,{2}", j, k, tmp);
                        //Console.WriteLine(DataLines[count]);
                        count++;
                    }
                }

                // XCoords x的坐标；YCoords的坐标；
                // 将数组写到文件中
                foreach (string line in DataLines)
                {
                    //File.AppendAllText(strFilePath, line+"\r\n", Encoding.Default);
                    Writer.Write(line + "\n", Encoding.Default);
                }

                Writer.Flush();//将缓冲区的数据写入流
                // 写入成功
                msg = "Save to BenMAP file succeeded!";
                return msg;
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return msg + ex.Message;
            }
            finally
            {
                Writer.Close();
            }
        }// msg = "Fale to save data to BenMAP file !";

        private void saveDataAsCMAQToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //string msg = "";
            try
            {
                SaveCMAQToFile();
            }
            catch (Exception ex)
            {

                CommonClass.LogError(ex);
            }

        }

        private void SaveCMAQToFile()
        {
            string msg = "";
            bool ok = false;
            string strPath = "";
            try
            {
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.DefaultExt = "";
                sfd.Filter = "CMAQ Data File|";
                if (sfd.ShowDialog() == DialogResult.OK && sfd.FileName != "")
                {
                    strPath = sfd.FileName;
                    // 保存BenMAPFile
                    //ok = SaveCMAQDataToFile(strPath);
                    if (!ok)
                    {
                        msg = string.Format("Fail to save " + strPath + " as CMAQ File!");
                        return;
                    }
                    msg = "The CMAQ Data file has been saved successfully !";
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                msg = "An exception has happened when save file as CMAQ data file!";
            }
            finally
            {
                if (msg != "")
                {
                    MessageBox.Show(msg, "Tip", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
            }
        }

        //private bool SaveCMAQDataToFile(string strPath)
        //{
        //    //string msg = "";
        //    bool ok = false;
        //    double[] gridValues = new double[_gridValues.Length];
        //    int count = 0;
        //    try
        //    {
        //        // get _gridValues for row->col
        //        for (int i = 1; i < _modelDef.RowCount + 1; i++)
        //        {
        //            for (int j = 1; j < _modelDef.ColCount + 1; j++)
        //            {
        //                gridValues[count] = _gridValues[GetLocation(i, j)];
        //                #region Console.Write
        //                //if (count <= _gridValues.Length)
        //                //{
        //                //    if (count % 7 == 0)
        //                //    {
        //                //        Console.Write("\n" + gridValues[count] + ",");
        //                //    }
        //                //    else
        //                //    {
        //                //        if (count % 147 == 0) { Console.Write(gridValues[count] + "\n"); }
        //                //        else
        //                //        { Console.Write(gridValues[count] + ","); }
        //                //    }
        //                //} 
        //                #endregion
        //                count++;
        //            }
        //        }

        //        // CommonClass.saveCMAQDataFile.CreateDataFile(strPath);
        //        NetCDFDataParer saveNetCDFData = new NetCDFDataParer();

        //        string pollutant = CommonClass.rsmPolicy.modelDef.Pollutant;
        //        string valueUnit = CommonClass.rsmPolicy.modelDef.ValueUnit;

        //        //-----------------modied by longsc 20120812------
        //        List<string[]> GlobalAttributeslst = new List<string[]>();
        //        GlobalAttributeslst = CommonClass.rsmPolicy.modelDef.GlobalAttributeslst;
        //        ok = saveNetCDFData.CreateDataFile(strPath, _modelDef.RowCount, _modelDef.ColCount, pollutant, valueUnit,GlobalAttributeslst, gridValues);
        //        return ok;
        //    }
        //    catch (Exception ex)
        //    {
        //        CommonClass.LogError(ex);
        //        return false;
        //    }
        //}

        private void tsmnuSaveRsmAndBlend_Click(object sender, EventArgs e)
        {
            try
            {
                SaveRsmAndBlend(true); //true represents for saving with blend  added and modified by Yangwenwei
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        /// <summary>
        /// 把Map图片保存在剪贴板里随意粘贴
        /// 默认保存为png
        /// </summary>
        /// <remarks>
        /// add by ty 2016-07-09
        /// </remarks>
        private void saveImageLegendToClipboardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                Bitmap img = GetFixedPlot(true);
                if (img != null)
                {
                    Clipboard.Clear();
                    Clipboard.SetImage(img);
                }
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }


        /// <summary>
        /// 保存Map
        /// </summary>
        /// <param name="ContainsBlend">包含图例则true</param>
        public void SaveRsmAndBlend(bool ContainsBlend)
        {
            try
            {
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.Filter =
                    //"Emf Format (*.emf)|*.emf|" +
                "Gif Format (*.gif)|*.gif|" +
                "Jpeg Format (*.jpg)|*.jpg|" +
                "PNG Format (*.png)|*.png|" +
                "Tiff Format (*.tif)|*.tif|" +
                "Bmp Format (*.bmp)|*.bmp";
                saveFileDialog.InitialDirectory = CommonClass.ResultFilePath + @"\Result\Picture";
                String DefaultFileName = null;
                if (DefaultFileName != null && DefaultFileName.Length > 0)
                {
                    //  获得扩展名
                    String ext = System.IO.Path.GetExtension(DefaultFileName).ToLower();
                    switch (ext)
                    {
                        //case ".emf": _saveFileDialog.FilterIndex = 1; break;
                        case ".png": saveFileDialog.FilterIndex = 2; break;
                        case ".gif": saveFileDialog.FilterIndex = 3; break;
                        case ".jpeg": saveFileDialog.FilterIndex = 1; break;
                        case ".jpg": saveFileDialog.FilterIndex = 1; break;
                        case ".tiff": saveFileDialog.FilterIndex = 4; break;
                        case ".tif": saveFileDialog.FilterIndex = 4; break;
                        case ".bmp": saveFileDialog.FilterIndex = 5; break;
                    }
                    //If we were passed a file name, not just an extension, use it
                    if (DefaultFileName.Length > ext.Length)
                    {
                        saveFileDialog.FileName = DefaultFileName;
                    }
                }
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    Stream myStream = saveFileDialog.OpenFile();
                    //// 20090902 @陈志润
                    //MemoryStream myStream = _saveFileDialog.OpenFile();
                    if (myStream != null)
                    {
                        ImageFormat format = ImageFormat.Png;
                        switch (saveFileDialog.FilterIndex)
                        {
                            case 1: format = ImageFormat.Gif; break;
                            case 2: format = ImageFormat.Png; break;
                            case 3: format = ImageFormat.Jpeg; break;
                            case 4: format = ImageFormat.Tiff; break;
                            case 5: format = ImageFormat.Bmp; break;
                        }
                        //Bitmap bmpBlend = _colorBlendControl.DrawImage();

                        Image bmpRsm = GetFixedPlot(ContainsBlend);
                        //Image srcImage = new Bitmap(bmpBlend, 100, 20);
                        //Graphics gSrc = _colorBlendControl.CreateGraphics();// 必须用这个方法，用Graphics.FromImage(bmpBlend);无效，原因未明
                        Image destImage = bmpRsm;// new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);// new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, gSrc);
                        Graphics gDest = Graphics.FromImage(bmpRsm);// this.CreateGraphics();
                        //gDest.FillRectangle(Brushes.White, 0, bmpRsm.Height - bmpBlend.Height, bmpRsm.Width, bmpRsm.Height);//add White Rectangle under the Map added by Yangwenwei
                        //IntPtr srcDC = gSrc.GetHdc();
                        //IntPtr destDC = gDest.GetHdc();
                        //WinBmpAPI.BitBlt(destDC, (bmpRsm.Width - bmpBlend.Width) / 2, bmpRsm.Height - bmpBlend.Height, bmpBlend.Width, bmpBlend.Height, srcDC, 0, 0, 0xCC0020); //13369376);//modified by Yangwenwei
                        //gSrc.ReleaseHdc(srcDC);
                        //gDest.ReleaseHdc(destDC);
                        //gSrc.Dispose();
                        gDest.Dispose();
                        destImage.Save(myStream, format);
                        myStream.Close();
                    }
                    MessageBox.Show(LanguageOld.Translate("Save map image successfully!"));
                }
                //WinAPIuse.BitBlt();
            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
            }
        }

        /// <summary>
        ///  把图形画到一个Bitmap上返回.该Bitmap在保存时会用到
        /// </summary>
        /// <returns>返回图片</returns>
        public Bitmap GetFixedPlot(bool ContainBlend)
        {
            try
            {
                Bitmap bmpRsm = this.DrawImage();
                int width = this.ClientSize.Width;
                int height = this.ClientSize.Height;
                int originX = 0;
                int originY = 0;
                Bitmap destImage = null;
                if (_axisChanged.ToLower() == "x")
                {
                    width = (int)_modelWidthOrHeightInForm;
                    originX = (this.ClientSize.Width - width) / 2;
                }
                else
                {
                    height = (int)_modelWidthOrHeightInForm;
                    originY = (this.ClientSize.Height - height) / 2;
                }

                if (ContainBlend)
                {
                    int upperHeight = 0;
                    int[] filenameWidthHeight = new int[2];
                    int filenameparts = 1;
                    int[] pollutantNameWidthHeight = new int[2];
                    int leftWidth = 0;//the width of color blend, including the space
                    int valueHeight = 0;//the height of number
                    int[] colorsquareWidthHeight = new int[3];
                    colorsquareWidthHeight[0] = 10;//width
                    colorsquareWidthHeight[1] = 40;//height
                    colorsquareWidthHeight[2] = 5;//the left space
                    Font[] font = new Font[5];
                    font[0] = new Font("Calibri", 20, FontStyle.Bold);//pollutant name
                    font[1] = new Font("Calibri", 12, FontStyle.Bold);//file name
                    font[2] = new Font("Calibri", 10, FontStyle.Bold);//color value
                    font[3] = new Font("Calibri", 10, FontStyle.Bold);//col row
                    font[4] = new Font("Calibri", 12, FontStyle.Bold);//min max value
                    int[] colrowWidthHeight = new int[2];
                    string[] strMapInfo = (this.ParentForm as SMAT_CE).strMapNameColRow;
                    string minmaxValue = "";
                    if (!string.IsNullOrEmpty(CommonClass.modelDefinition.MinmaxValueGrid))
                    {
                        string[] minmaxGridValue = CommonClass.modelDefinition.MinmaxValueGrid.Split(',');
                        if (minmaxGridValue.Count() == 6)
                            minmaxValue = "Min = " + Convert.ToDouble(minmaxGridValue[2]).ToString("F3") + " at (" + Math.Round(Convert.ToDouble(minmaxGridValue[0]), 2) + "," + Math.Round(Convert.ToDouble(minmaxGridValue[1]), 2) + "), Max = " + Convert.ToDouble(minmaxGridValue[5]).ToString("F3") + " at (" + Math.Round(Convert.ToDouble(minmaxGridValue[3]), 2) + "," + Math.Round(Convert.ToDouble(minmaxGridValue[4]), 2) + ")";
                        else
                            minmaxValue = "Min = " + Convert.ToDouble(minmaxGridValue[1]).ToString("F3") + " at (" + Convert.ToInt32(minmaxGridValue[0]) / 1000 + "," + Convert.ToInt32(minmaxGridValue[0]) % 1000 + "), Max = " + Convert.ToDouble(minmaxGridValue[3]).ToString("F3") + " at (" + Convert.ToInt32(minmaxGridValue[2]) / 1000 + "," + Convert.ToInt32(minmaxGridValue[2]) % 1000 + ")";
                    }
                    int[] minmaxValueWidthHeight = new int[2];
                    string[] colorValue = new string[7];
                    //for (int i = 0; i < 5; i++)
                    //{
                    //    if ((0.00001 < _colorBlendControl.ValueArray[i]) && (_colorBlendControl.ValueArray[i] < 100000))
                    //    { colorValue[i] = string.Format("{0}", Math.Round(_colorBlendControl.ValueArray[i], 3)); }
                    //    else
                    //    { colorValue[i] = string.Format("{0}", Math.Round(_colorBlendControl.ValueArray[i], 3).ToString("G3")); }
                    //}
                    //if ((0.00001 < _colorBlendControl.MaxValue) && (_colorBlendControl.MaxValue < 100000))
                    //{ colorValue[5] = string.Format("{0}", Math.Round(_colorBlendControl.MaxValue, 3)); }
                    //else
                    //{ colorValue[5] = string.Format("{0}", Math.Round(_colorBlendControl.MaxValue, 3).ToString("G3")); }
                    int d = (_colorBlendControl.MaxValue - _colorBlendControl.MinValue) > 1 ? 1 : 3;
                    for (int i = 0; i < 7; i++)
                    {
                        colorValue[i] = Math.Round(_colorBlendControl.ValueArray[i], d).ToString(string.Format("F{0}", d));
                    }
                    //colorValue[6] = Math.Round(_colorBlendControl.MaxValue, d).ToString(string.Format("F{0}", d));

                    using (Graphics g0 = this.CreateGraphics())
                    {
                        SizeF string_size = g0.MeasureString(strMapInfo[0], font[1]);
                        filenameWidthHeight[0] = (int)string_size.Width;
                        filenameWidthHeight[1] = (int)string_size.Height;
                        if (filenameWidthHeight[0] <= width + 10)
                            upperHeight = filenameWidthHeight[1] + 2;
                        else
                        {
                            do
                            {
                                filenameparts++;
                            } while (filenameWidthHeight[0] > filenameparts * width);
                            upperHeight = filenameparts * filenameWidthHeight[1] + 2;
                        }

                        string_size = g0.MeasureString(strMapInfo[1], font[0]);
                        pollutantNameWidthHeight[0] = (int)string_size.Width;
                        pollutantNameWidthHeight[1] = (int)string_size.Height;
                        upperHeight = upperHeight + pollutantNameWidthHeight[1] + 20;

                        string_size = g0.MeasureString(colorValue[5], font[2]);
                        leftWidth = (int)string_size.Width;
                        valueHeight = (int)string_size.Height;
                        for (int i = 0; i < 5; i++)
                        {
                            string_size = g0.MeasureString(colorValue[i], font[3]);
                            leftWidth = Math.Max((int)string_size.Width, leftWidth);
                        }

                        string_size = g0.MeasureString("999", font[3]);
                        colrowWidthHeight[0] = (int)string_size.Width;
                        colrowWidthHeight[1] = (int)string_size.Height;
                        leftWidth = leftWidth + colorsquareWidthHeight[0] + colorsquareWidthHeight[2] + colrowWidthHeight[0] + 6;//add the space of Row
                        upperHeight = upperHeight + colrowWidthHeight[1] / 2;//add the space of Col

                        string_size = g0.MeasureString(minmaxValue, font[4]);
                        minmaxValueWidthHeight[0] = (int)string_size.Width;
                        minmaxValueWidthHeight[1] = (int)string_size.Height;
                    }

                    destImage = new Bitmap(width + leftWidth + colrowWidthHeight[0] / 2 + 5, height + upperHeight + colrowWidthHeight[1] + minmaxValueWidthHeight[1] + 17);
                    Graphics g = Graphics.FromImage(destImage);
                    g.Clear(Color.White);

                    //draw pollutant name
                    g.DrawString(strMapInfo[1], font[0], new SolidBrush(Color.Black), new PointF(leftWidth + 2 + (width - pollutantNameWidthHeight[0]) / 2, 10));

                    //draw file name
                    //if file name is too long
                    if (filenameWidthHeight[0] < width + 10)
                    {
                        g.DrawString(strMapInfo[0], font[1], new SolidBrush(Color.Black), new PointF(leftWidth + 2 + (width - filenameWidthHeight[0]) / 2, 20 + pollutantNameWidthHeight[1]));
                    }
                    else
                    {
                        int iCountIn1Row = strMapInfo[0].Length / filenameparts;
                        int y = 20 + pollutantNameWidthHeight[1];
                        List<string> lstStr = GetStringRows(g, font[1], strMapInfo[0], width);
                        for (int i = 0; i < filenameparts; i++)
                        {
                            g.DrawString(lstStr[i], font[1], new SolidBrush(Color.Black), new PointF(leftWidth, y));
                            y += filenameWidthHeight[1];
                        }
                    }

                    //draw color blend
                    int location = upperHeight;
                    for (int i = 6; i >= 0; i--)
                    {
                        g.FillRectangle(new SolidBrush(_colorBlendControl.ColorArray[i]), colorsquareWidthHeight[2], location, colorsquareWidthHeight[0], colorsquareWidthHeight[1]);
                        location += colorsquareWidthHeight[1];
                    }
                    g.DrawRectangle(new Pen(Color.Black, 1), colorsquareWidthHeight[2], upperHeight, colorsquareWidthHeight[0], colorsquareWidthHeight[1] * 7);//add the border of color blend
                    g.DrawString(_colorBlendControl.ValueUnit, font[2], new SolidBrush(Color.Black), new PointF(colorsquareWidthHeight[2], location + colrowWidthHeight[1] / 2 + 2));

                    //draw color range value
                    location -= valueHeight / 2;
                    //for (int i = 0; i < 6; i++)
                    //{
                    //    g.DrawString(colorValue[i], font[2], new SolidBrush(Color.Black), new PointF(colorsquareWidthHeight[0] + colorsquareWidthHeight[2] + 3, location));
                    //    location -= colorsquareWidthHeight[1];
                    //}
                    //不画最小最大值
                    location -= colorsquareWidthHeight[1];
                    g.DrawString("<" + colorValue[1], font[2], new SolidBrush(Color.Black), new PointF(colorsquareWidthHeight[0] + colorsquareWidthHeight[2] + 3, location));
                    for (int i = 2; i < 6; i++)
                    {
                        location -= colorsquareWidthHeight[1];
                        g.DrawString(colorValue[i], font[2], new SolidBrush(Color.Black), new PointF(colorsquareWidthHeight[0] + colorsquareWidthHeight[2] + 3, location));
                    }
                    location -= colorsquareWidthHeight[1];
                    g.DrawString(">" + colorValue[6], font[2], new SolidBrush(Color.Black), new PointF(colorsquareWidthHeight[0] + colorsquareWidthHeight[2] + 3, location));

                    //g.DrawString(_colorBlendControl.MaxValue.ToString(), font[2], new SolidBrush(Color.Black), new PointF(colorsquareWidthHeight[0] + colorsquareWidthHeight[2] + 3, location));

                    //draw colrow
                    g.DrawString(strMapInfo[2], font[3], new SolidBrush(Color.Black), new PointF(leftWidth - colrowWidthHeight[0] / 2 + (3 - strMapInfo[2].Length) * colrowWidthHeight[0] / 3, height + upperHeight + 2));//col.min
                    g.DrawString(strMapInfo[3], font[3], new SolidBrush(Color.Black), new PointF(leftWidth + width - colrowWidthHeight[0] / 2 + (3 - strMapInfo[3].Length) * colrowWidthHeight[0] / 3, height + upperHeight + 2));//col.max
                    g.DrawString(strMapInfo[4], font[3], new SolidBrush(Color.Black), new PointF(leftWidth - colrowWidthHeight[0] + (3 - strMapInfo[4].Length) * colrowWidthHeight[0] / 3, height + upperHeight - colrowWidthHeight[1] / 2));//row.min
                    g.DrawString(strMapInfo[5], font[3], new SolidBrush(Color.Black), new PointF(leftWidth - colrowWidthHeight[0] + (3 - strMapInfo[5].Length) * colrowWidthHeight[0] / 3, upperHeight - colrowWidthHeight[1] / 2));//row.max

                    //draw map
                    //g.DrawImage(bmpRsm, new Rectangle(new Point(leftWidth + 2, upperHeight), destImage.Size), new Rectangle(new Point(originX, originY), destImage.Size), GraphicsUnit.Pixel);
                    g.DrawImage(bmpRsm, new Rectangle(new Point(leftWidth + 2, upperHeight), new Size(width, height)), new Rectangle(new Point(originX, originY), new Size(width, height)), GraphicsUnit.Pixel);
                    g.DrawRectangle(new Pen(Color.Black, 1), leftWidth + 2, upperHeight, width, height);//add the border of map

                    //draw min max value
                    g.DrawString(minmaxValue, font[4], new SolidBrush(Color.Black), new PointF(leftWidth + 2 + (width - minmaxValueWidthHeight[0]) / 2, upperHeight + height + colrowWidthHeight[1] + 7));
                    g.Dispose();
                }
                else
                {
                    destImage = new Bitmap(width, height);
                    Graphics g = Graphics.FromImage(destImage);
                    g.Clear(Color.White);
                    g.DrawImage(bmpRsm, new Rectangle(new Point(0, 0), destImage.Size), new Rectangle(new Point(originX, originY), destImage.Size), GraphicsUnit.Pixel);
                    g.Dispose();
                }

                #region 调用Windows API 合成图片
                //Graphics gSrc = this.CreateGraphics();
                ////Graphics gDest = Graphics.FromImage(destImage);
                ////IntPtr srcDC = gSrc.GetHdc();
                ////IntPtr destDC = gDest.GetHdc();
                ////WinAPIuse.BitBlt(destDC, 0, 0,destImage.Width , destImage.Height, srcDC, originX, originY, 0xCC0020); //13369376);

                ////gSrc.ReleaseHdc(srcDC);
                ////gDest.ReleaseHdc(destDC);
                ////// destImage.Save(myStream, format);
                ////gSrc.Dispose();
                ////// gDest = Graphics.FromImage(this.DrawImage());
                ////gDest.Dispose();
                //destImage.Save(@"c:\ttt.bmp", ImageFormat.Bmp); 
                #endregion
                GC.Collect();
                return destImage;

            }
            catch (Exception ex)
            {
                CommonClass.LogError(ex);
                return null;
            }
        }

        private List<string> GetStringRows(Graphics graphic, Font font, string text, int width)
        {
            int RowBeginIndex = 0;
            int rowEndIndex = 0;
            int textLength = text.Length;
            List<string> textRows = new List<string>();
            for (int index = 0; index < textLength; index++)
            {
                rowEndIndex = index;
                if (index == textLength - 1)
                {
                    textRows.Add(text.Substring(RowBeginIndex));
                }
                else if (rowEndIndex + 1 < text.Length && text.Substring(rowEndIndex, 2) == "\r\n")
                {
                    textRows.Add(text.Substring(RowBeginIndex, rowEndIndex - RowBeginIndex));
                    rowEndIndex = index += 2;
                    RowBeginIndex = rowEndIndex;
                }
                else if (graphic.MeasureString(text.Substring(RowBeginIndex, rowEndIndex - RowBeginIndex + 1), font).Width > width)
                {
                    textRows.Add(text.Substring(RowBeginIndex, rowEndIndex - RowBeginIndex));
                    RowBeginIndex = rowEndIndex;
                }
            }
            return textRows;
        }

        private void PlotControl_Click(object sender, EventArgs e)
        {
            
        }

        private void PlotControl_MouseClick(object sender, MouseEventArgs e)
        {
            if(dicMonitors == null ||dicMonitors.Keys.Count==0)
            { return; }
            var m_Point = e.Location;
            //Console.WriteLine(m_Point.X.ToString() + ", " + m_Point.Y.ToString());

            //// 把屏幕坐标变换成模型坐标
            //Matrix matrix = _matrix.Clone();
            //matrix.Invert();
            //PointF[] pts = new PointF[] { m_Point };
            //matrix.TransformPoints(pts);


            List<PointF> lstM = new List<PointF>();            
            foreach (var k in dicMonitors.Keys)
            {
                var s = k.Split(',');
                lstM.Add(new PointF(float.Parse(s[0]), float.Parse(s[1])));
            }
            var arrayM = lstM.ToArray();
            _matrix.TransformPoints(arrayM);

            List<PointF> lstOpt = new List<PointF>();
            List<int> lstIndex = new List<int>();
            double mind = 100; int minID = -1;
            for (int i = 0; i < arrayM.Length; i++)
            {
                double d = Math.Pow((arrayM[i].X - e.Location.X), 2) + Math.Pow(arrayM[i].Y - e.Location.Y, 2);                
                if(mind>d)
                {
                    minID = i;
                    mind = d;
                    //Console.WriteLine(d);
                }
            }
            if (minID != -1)
            {
                SelectedPoint = lstM[minID];
                strSelectedPointLatLon = dicMonitors.Keys.ToArray()[minID];
                isMarkSelectedPoint = true;
                _needRedrawBmp = true;
                this.Invalidate();
            }
            else
            {
                isMarkSelectedPoint = false;
                _needRedrawBmp = true;
                this.Invalidate();
            }
            //MarkSelectMonitor(lstM[lstIndex.First()], null);
        }

        private void PlotControl_Leave(object sender, EventArgs e)
        {
            isMarkSelectedPoint = false;
        }
    }//class



}//namespace
