//时间：20200610
//作者：郝爽
//功能：测量线程

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Drawing;
using System.Xml;

using SmartSEMControl;
using MeasureData;
using FileManager;
using WebManager;

using OpenCvSharp;
using DBManager;
using Extender;
using CookComputing.XmlRpc;

namespace MeasureThread
{
    #region 信息定义
    public delegate void ThreadStatusHandler(object sender, ThreadStatusEventArgs e);  //声明委托
    public delegate void CutHolesStatusHandler(object sender, CutHolesStatusEventArgs e);

    //测量线程状态
    public class ThreadStatusEventArgs
    {
        //状态
        public Boolean State
        {
            get { return m_state; }
            set { m_state = value; }
        }
        private Boolean m_state;
        //时间
        public DateTime Time
        {
            get { return m_time; }
            set { m_time = value; }
        }
        private DateTime m_time;
        //步骤代码
        public String Step_Code
        {
            get { return step_Code; }
            set { step_Code = value; }
        }
        private String step_Code;
        //其他消息
        public String Message
        {
            get { return this.message; }
            set { this.message = value; }
        }
        private String message;

        //孔名
        public String HoleName
        {
            get { return this.holeName; }
            set { this.holeName = value; }
        }
        private String holeName;

        //图片信息
        public class PictureInformation
        {
            public String Picture_FullPath
            {
                get { return picture_FullPath; }
                set { picture_FullPath = value; }
            }
            private String picture_FullPath;

            public double Work_Voltage
            {
                get { return work_Voltage; }
                set { work_Voltage = value; }
            }
            private double work_Voltage;

            public double Magnification
            {
                get { return magnification; }
                set { magnification = value; }
            }
            private double magnification;

            public double Work_Distance
            {
                get { return work_Distance; }
                set { work_Distance = value; }
            }
            private double work_Distance;

            public String Work_Status
            {
                get { return work_Status; }
                set { work_Status = value; }
            }
            private String work_Status;
        }
        //图片信息实例类
        public PictureInformation Picture_Information
        {
            get { return picture_Information; }
            set { picture_Information = value; }
        }
        private PictureInformation picture_Information;

        //图像处理信息
        public class ImageInformation
        {
            public int Method_Name
            {
                get { return method_Name; }
                set { method_Name = value; }
            }
            private int method_Name;

            public Source_Img_Degree_Direction SIDD;
            public Cut_Position CP;
            public Cut_Success CS;
            public Trapezoid_Top_Center_Position TTCP;
            public Auto_Foucs AF;
            public Auto_Stigmatic AS;
            public Center_Position_OffsetAngle_Direction CPOD;
            public Measure_Size MS;

            public ImageInformation()
            {
                SIDD = new Source_Img_Degree_Direction();
                CP = new Cut_Position();
                CS = new Cut_Success();
                TTCP = new Trapezoid_Top_Center_Position();
                AF = new Auto_Foucs();
                AS = new Auto_Stigmatic();
                CPOD = new Center_Position_OffsetAngle_Direction();
                MS = new Measure_Size();
            }

            //1-计算原始图像偏移角度及方向
            public class Source_Img_Degree_Direction
            {
                public Boolean Is_Image = false;

                public double Degree
                {
                    get { return degree; }
                    set { degree = value; }
                }
                private double degree;

                public int Direction
                {
                    get { return direction; }
                    set { direction = value; }
                }
                private int direction;

                public int State
                {
                    get { return state; }
                    set { state = value; }
                }
                private int state;
            }

            //2-计算切割点位置
            public class Cut_Position
            {
                public Boolean Is_Image = false;

                public double Offsetx
                {
                    get { return offsetx; }
                    set { offsetx = value; }
                }
                private double offsetx;

                public double Offsety
                {
                    get { return offsety; }
                    set { offsety = value; }
                }
                private double offsety;

                public int State
                {
                    get { return state; }
                    set { state = value; }
                }
                private int state;
            }

            //3-是否切割成功
            public class Cut_Success
            {
                public Boolean Is_Image = false;

                public int State
                {
                    get { return state; }
                    set { state = value; }
                }
                private int state;

            }

            //4-计算切割后图像梯形区域上边中心点坐标
            public class Trapezoid_Top_Center_Position
            {
                public Boolean Is_Image = false;

                public double TopCenterX
                {
                    get { return topCenterX; }
                    set { topCenterX = value; }
                }
                private double topCenterX;

                public double TopCenterY
                {
                    get { return topCenterY; }
                    set { topCenterY = value; }
                }
                private double topCenterY;

                public int State
                {
                    get { return state; }
                    set { state = value; }
                }
                private int state;
            }

            //5-自动对焦
            public class Auto_Foucs
            {
                public Boolean Is_Image = true;

                public String Img_Path
                {
                    get { return img_Path; }
                    set { img_Path = value; }
                }
                private String img_Path;
            }

            //6-自动像闪
            public class Auto_Stigmatic
            {
                public Boolean Is_Image = true;

                public String Img_Path
                {
                    get { return img_Path; }
                    set { img_Path = value; }
                }
                private String img_Path;
            }

            //7-计算切割面区域中心坐标，以及偏移角度及方向
            public class Center_Position_OffsetAngle_Direction
            {
                public Boolean Is_Image = false;

                public double CenterX
                {
                    get { return centerX; }
                    set { centerX = value; }
                }
                private double centerX;

                public double CenterY
                {
                    get { return centerY; }
                    set { centerY = value; }
                }
                private double centerY;

                public double Degree
                {
                    get { return degree; }
                    set { degree = value; }
                }
                private double degree;

                public int Direction
                {
                    get { return direction; }
                    set { direction = value; }
                }
                private int direction;

                public int State
                {
                    get { return state; }
                    set { state = value; }
                }
                private int state;
            }

            //8-测量尺寸
            public class Measure_Size
            {
                public Boolean Is_Image = false;

                public int State
                {
                    get { return state; }
                    set { state = value; }
                }
                private int state;
            }
        }
        //图像处理信息实例类
        public ImageInformation Image_Information
        {
            get { return image_Information; }
            set { image_Information = value; }
        }
        private ImageInformation image_Information;

        public ThreadStatusEventArgs(string a_State)
        {
            picture_Information = new PictureInformation();
            image_Information = new ImageInformation();
        }
    }

    //切孔状态
    public class CutHolesStatusEventArgs
    {
        public string State
        {
            get { return m_state; }
            set { m_state = value; }
        }
        private string m_state;

        public string HoleName
        {
            get { return m_holeName; }
            set { m_holeName = value; }
        }
        private string m_holeName;

        public CutHolesStatusEventArgs(string a_state, string a_holeName)
        {
            this.m_state = a_state;
            this.m_holeName = a_holeName;
        }
    }
    #endregion

    public class Measure
    {
        NLog.Logger log;
        #region 变量定义
        //Web接口类
        public ImageProcess ImagePro = null;

        //SmartSEM远程路径
        public String RemoteELYPath = "";
        public String RemoteMLFPath = "";

        //扫描周期
        private float cycle_time = 0;

        //人工干预
        public int hand_intervene = 2;

        //样品台保护值
        public float X_Min = 0;
        public float X_Max = 0.13f;
        public float Y_Min = 0;
        public float Y_Max = 0.13f;
        public float Z_Min = 0;
        public float Z_Max = 0.05f;
        public float T_Min = -4;
        public float T_Max = 70;
        public float R_Min = -380;
        public float R_Max = 380;
        public float M_Min = 0;
        public float M_Max = 0.012f;

        public event ThreadStatusHandler SendThreadStatus;  // 声明事件
        public event CutHolesStatusHandler SendCutHolesStatus;  // 声明事件

        //定义一个全局的消息类
        ThreadStatusEventArgs arg = new ThreadStatusEventArgs("0-0");

        //全局只有一个fatorySEM
        static FactoryHardware factorySEM = FactoryHardware.Instance;
        ISEMControl iSEM = factorySEM.ISEM;

        //@的作用是不用转义字符\\只打一个就行
        const String ImageName0 = @"SEMStraighten.tif"; //传给客户，原始图像，为拉直操作
        const String ImageName1 = @"FIBStraighten.tif"; //传给客户，原始图像，为拉直操作
        //const String ImageName1 = @"SEMFindCutPostion.tif"; //传给客户，作水平校正
        const String ImageName2 = @"FIBCutPostion.tif";//传给客户，找到切割点
        const String ImageName31 = @"FIBBefore.tif";
        const String ImageName32 = @"FIBAfter.tif";
        const String ImageName4 = @"SEMTrapCP.tif";//传给客户，找到已经切割点
        const String ImageName5 = @"SEMDegreeTrap.tif";//传给客户，水平校正
        const String ImageName6 = @"SEMMagEnd.tif";//传给客户，测量层高
        const String ImageName7 = @"BeforeImage.tif";//计算感兴趣的区域
    
        const String ImageNameTwo_1 = @"SEMRegion.tif";//第一个测量区域拍照
       

        const String MacoInsertPt = "GIS Insert.MLF"; //传入PT针
        const String MacoRetractPt = "GIS Retract.MLF"; //退出PT针
        const String MacoScanPic = "Scan picture.MLF";//一般质量抓图的宏
        const String MacoGoodPic = "Good picture.MLF";//高质量抓图的宏
        const String MacoExportTif = "Export TIFF.MLF";// 导出有标尺的图像，这个图像为使用工具SmartSEM工具的图像

        const String ElyDeposition = @"Deposition.ely"; //沉积
        const String ElyCrossSection = @"CrossSection.ely"; //切割

        const float fMin = (float)0.0000002; //单位是米
       
        private Locate m_locate;
        private Focus m_focuse;
        private Photo m_photo;
        private ArgSend mArgSend;
        public Boolean key_stop = false;
        FibWork m_FibWork;
        PTWork m_PTWork;


        //int m_nWorkHoleNo = -1;
        public ThreadStatusEventArgs GetArgs()
        {
            return arg;
        }

        //测量文件
        private MeasureFile m_measureFile;
        public MeasureFile MeasureFile
        {
            get { return this.m_measureFile; }
            set { this.m_measureFile = value; }
        }

        //测量的切割孔，这个切孔的状态要保存的测量文件中去
        private List<MeasureData.CutHole> m_cutHoles;
        public List<MeasureData.CutHole> cutHoles
        {
            get { return this.m_cutHoles; }
            set { this.m_cutHoles = value; }
        }
        public MeasureParam MParam//测量参数对象
        {
            get { return this.m_measureFile.MParam; }
            //set { this.m_measureParam = value; }
        }
        //工作文件夹
        private string m_WorkingFolder;
        public string mWorkingFolder
        {
            get { return this.m_WorkingFolder; }
            set { this.m_WorkingFolder = value; }
        }

        //程序当前路径
        private string m_ProgramFolder = Directory.GetCurrentDirectory();

        //线程状态
        private ThreadStatus m_ThreadStatus;
        public ThreadStatus TStatus
        {
            get { return this.m_ThreadStatus; }
            set { this.m_ThreadStatus = value; }
        }
        #endregion

        //构造函数
        public Measure(String webServerIP, String webServerPort, String webServerUrl)
        {
            log = NLog.LogManager.GetCurrentClassLogger();
            TStatus = new ThreadStatus();
            cutHoles = new List<MeasureData.CutHole>();
            //配置远程连接
            ImagePro = new ImageProcess(webServerIP, webServerPort, webServerUrl);
            m_locate = new Locate(iSEM);
            m_focuse = new Focus(iSEM);
            m_photo = new Photo(iSEM);
            mArgSend = new ArgSend(this, iSEM);
           
        }

        //初始化测量业务, 读测量文件，判断是否有可测试的切孔
        public bool InitMeasure(MeasureFile a_measureFile)
        {
            log.Info("进入初始化函数");
            m_measureFile = a_measureFile;

  

            List<CutHole> listHoles = m_measureFile.ListCutHole;

            foreach (CutHole h in listHoles)
            {
                if (h.SWITCH == true)
                {
                    m_cutHoles.Add(h);
                }
            }

            if (m_cutHoles.Count == 0)  return false;
              

            if (MParam.EDS == true)
            {
                log.Info("要进行能谱分析，初始化Xray数据库", true);
                Init_MeasDB();
            }
            //设置工作文件夹
            mWorkingFolder = m_measureFile.FilePath;
            for(int i=0;i<m_cutHoles.Count;i++)
            {
               m_cutHoles[i].InitPath(i, mWorkingFolder);
            }
           
            //检查硬件连接是否正常
            if (!iSEM.ConnectStatus())
            {
                MessageBox.Show("连接电镜失败！", "重要错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.TStatus.ComputeTime(THREAD_TIME_TYPE.STOPPED);
                log.Error("测量线程报错：连接硬件硬件连接失败", false);
                return false;
            }



            //设置SmartSEM远程路径
            iSEM.SetRemoteELYPath(RemoteELYPath);
            iSEM.SetRemoteMLFPath(RemoteMLFPath);

            m_FibWork = new FibWork(iSEM, MParam.FIBTemp);
            m_PTWork = new PTWork(iSEM, MParam.PTTemp);

            iSEM.SetScanRotationOff();
            Thread.Sleep(200);

            //20.光束等复位
            iSEM.SetBeamShiftX(0);
            Thread.Sleep(200);
            iSEM.SetBeamShiftY(0);
            Thread.Sleep(200);

            return true;
        }

        //给前台UI发送消息步骤
        public void SendMsg(string step_code)
        {
            arg.Step_Code = step_code;
            arg.Time = DateTime.Now;
            SendThreadStatus(this, arg);
        }

        //给前台UI发送孔状态信息
        public void SendCutHoleMsg(string a_state, string a_holeName)
        {
            CutHolesStatusEventArgs arg = new CutHolesStatusEventArgs(a_state, a_holeName);
            arg.HoleName = a_holeName;
            arg.State = a_state;
            SendCutHolesStatus(this, arg);
        }

        //测量流程
        public void DoMeasure()
        {
            //创建线程的测量状态的更新
            this.TStatus.ComputeTime(THREAD_TIME_TYPE.START);


            //将停止键复位
            key_stop = false;

            //开始测量就将模式设置为SEM
            log.Info("测量线程：开始切换到SEM模式", true);
            if (!iSEM.CmdFIBModeSEM())
            {
                log.Error("测量线程报错：开始切换到SEM模式失败。", false);
                return;
            }
            arg.Picture_Information.Work_Status = "SEM";


            //开始做各个孔的测量
            for (int currHoleNo = 0; currHoleNo < m_cutHoles.Count; currHoleNo++)
            {
                var currHole = m_cutHoles[currHoleNo];
                //判断孔状态
                if (currHole.STATE != State.Ready)
                {
                    log.Warn("测试孔" + currHole.HoleName + "状态非就绪，不予测量。", true);
                    continue;
                }

                log.Warn("测量线程：第"+ currHoleNo.ToString() + "分析点，名称："  + currHole.HoleName + " 开始测量。", true);

                currHole.START = DateTime.Now;
                currHole.STATE = State.InProcess;
                SendCutHoleMsg(((int)currHole.STATE).ToString(), currHole.HoleName);
                //开始测量
                if (!HoleMeasure(currHole))
                {                   
                    currHole.STATE = State.Failed;
                    currHole.END = DateTime.Now;
                        
                    SendCutHoleMsg(((int)currHole.STATE).ToString(), currHole.HoleName);
                   Thread.Sleep(3000);
                   continue;
                }

                //保存文件，将测量状态更改
                currHole.STATE = State.Success;
                currHole.END = DateTime.Now;
          
                SendCutHoleMsg(((int)currHole.STATE).ToString(), currHole.HoleName);

                if (key_stop)
                {
                    log.Error("用户停止测量");                    
                    break;
                }

                //两个点之间更换，加延时以便完成显示
                Thread.Sleep(3000);
            }

            m_measureFile.Save();  //save all the measure info into Xml file.

        }

 


      

       

        /// <summary>
        ///13. 自动 定位功能,沉积
        /// </summary>
        /// <returns></returns>
        public bool GetFIBAndPTPoistion(CutHole currHole)
        {
          
            float px = 0;
            int state = 1;
            log.Info("测量线程：FIB自动定位放大倍数" + MParam.Location_Magnification.ToString(), true);
            Thread.Sleep(200);
  
         
            
            if (!m_focuse.SetMagnification(MParam.Location_Magnification))
            {

                log.Error("测量线程报错：13.自动定位、沉积-自动定位放大倍数" + MParam.Location_Magnification.ToString() + "控制失败", false);
                return false;
            }
            arg.State = true;
            arg.Message = "放大" + MParam.Location_Magnification.ToString("0.0") + "倍成功";
            SendMsg("2-0");
            //判断是否停止进程
            if (key_stop)
            {
                log.Info("停止键按下。", true);
                return false;
            }

            log.Info("测量线程：切换到FIB模式。", true);
            //6.设置FIB拍照参数——扫描时间、束流等
            //7.控制FIB自动亮度、对比度
            Thread.Sleep(200);
            if (!iSEM.CmdFIBModeFIB())
            {
                log.Error("测量线程报错：切换到FIB模式失败。", false);
                return false;
            }
            arg.State = true;
            arg.Picture_Information.Work_Status = "FIB";
            arg.Message = "FIB模式切换成功";
            SendMsg("2-1");
            Thread.Sleep(1000);
            //判断是否停止进程
            if (key_stop)
            {
                log.Info("停止键按下。", true);
                return false;
            }
            //刷亮度对比度
            iSEM.CmdFocusScanSpeed("CMD_SCANRATE4");//iSEM.CmdSaveRate();
            Thread.Sleep(200);
            iSEM.SetAutoBright(100);
            Thread.Sleep(200);
            iSEM.SetAutoContrast(100);
            iSEM.SetAutoVideoBrightnessAndContrast();
                           
                            
            Thread.Sleep(10000);

            iSEM.SetAutoVideoOff();



            //8.控制FIB拍照
            Thread.Sleep(200);
            String fileName2 = currHole.data_path + "\\" + currHole.HoleName + "_" + MParam.Location_Magnification.ToString("0") + "_" + ImageName2;
            m_photo.GetParam().Mag = MParam.Location_Magnification;
            m_photo.GetParam().savePath = fileName2;
            if (!m_photo.TakePhoto())
            {                    
                log.Error("测量线程报错：FIB拍照失败。", false);
                return false;
            }
                
            mArgSend.SendArgumentToScreen("2-3", "FIB拍照成功",fileName2);

            //判断是否停止进程
            if (key_stop)
            {
                log.Info("停止键按下。", true);
                return false;
            }

          
            float x1=0,y1=0, x2=0, y2=0;
            //10.将照片传给客户，返回梯形位置坐标，及样品类型参数（是否需要PT沉积，PT坐标位置，PT宽度、PT高度、梯形上、下边及深度、扫描时间、束流、样品放大倍数1、样品放大倍数2等切割参数）
            log.Info("测量线程：调用图像处理接口，准备移动样品台", true);
            log.Info("文件名=" + fileName2, true);
            log.Info("样品类型=" + MParam.SampleType, true);
            log.Info("供应商名称=" + MParam.Firm, true);
            ImagePro.Img_Cut_Position(fileName2, Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out x1, out y1, out x2, out y2, out state);
            log.Info("FIB梯形左上角和右上角位置信息= (" + x1.ToString() + ", " + y1.ToString() + "), (" + x2.ToString() + ", " + y2.ToString() + ")", true);
            log.Info("准备移动样品台返回状态=" + state.ToString(), true);
            if (state == 1)
            {
                m_FibWork.ModifyCutTemplate(x1, y1 ,x2, y2);

                //判断是否需要PT沉积，如果需要也要修改PT的ELY文件
                if (MParam.PT)
                {

                    m_PTWork.ModifyPTTemp(x1,y1,x2,y2);

                }

            }
            else
            {             

                log.Error("测量线程报错：自动定位图像接口返回0", false);
                return false;
            }

            iSEM.CmdFIBModeSEM();
            Thread.Sleep(200);

           
            if (key_stop)
            {
                log.Info("停止键按下", true);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 14. FIB切割
        /// </summary>
        /// <returns></returns>
        public bool FIBCross()
        {
            int state = 0;

            if (!iSEM.CmdFIBModeFIB())
            {

                log.Error("测量线程报错：切换到SEM模式失败", false);
                return false;
            }
            arg.Message = "切换到FIB模式成功。";
            arg.State = true;
            SendMsg("2-7");
            Thread.Sleep(1000);

            m_focuse.SetMagnification(MParam.Location_Magnification);
           

            //14.自动控制FIB切割
            //1.根据参数设置FIB草率时间（使图清晰），设置梯形上下边及深度、设置束流
            //2.控制FIB进行切割
            //以上1、2步全部用ELY文件代替
            if (!m_FibWork.DoFIBWork())
            { 
                log.Error("测量线程报错：" + arg.Message, false);
                return false;
            }
            arg.State = true;
            arg.Message = "FIB切割成功";
            SendMsg("2-8");
            Thread.Sleep(300);
            //判断是否停止进程
            if (key_stop)
            {
                log.Info("停止键按下", true);
                return false;
            }


            //做切割后SEM的拍照
            log.Info("测量线程：切割后SEM拍照", true);
            if (!iSEM.CmdFIBModeSEM())
            {
                
                log.Error("测量线程报错：切换到SEM模式失败", false);
                return false;
            }
            Thread.Sleep(1000);
            mArgSend.SendArgumentToScreen("3-0", "SEM模式切换成功");
            return true;
        }

        /// <summary>
        /// 16.自动调整SEM找到切割位置，这里不是简单的拉直旋转
        /// </summary>
        /// <returns></returns>
        public bool FindCross(CutHole currHole)
        {
            float x2 = 0, y2 = 0;
            int state = 0;
            //切换到SEM模式
            if (!iSEM.CmdFIBModeSEM())
            {

                log.Error("测量线程报错：" + arg.Message, false);
                return false;
            }
            Thread.Sleep(1000);


            if (key_stop)
            {
                log.Info("停止键按下", true);
                return false;
            }
            String fileName4 = currHole.data_path + "\\" + MParam.Firm + "-" + MParam.FindCrossMagnification.ToString("0") + "-" +currHole.HoleName + "-" + ImageName4;
            //add by zjx 2020-12-21 根据客户的需求修改图片的名称 end
            log.Info("fileName4=" + fileName4, true);
            float mag = MParam.FindCrossMagnification;
           
            m_photo.GetParam().Mag = mag;
         
            m_photo.GetParam().savePath = fileName4;
            m_photo.TakePhoto();
            //arg.Message = "SEM拍照成功";
            mArgSend.SendArgumentToScreen("3-2", "SEM拍照成功", fileName4);
            if (key_stop)
            {
                return false;
            }

            //4.将照片传给客户，获取偏移坐标，以及偏移角度
            //5.根据坐标控制SEM移动到切孔位置，居中
            log.Info("测量线程：图像处理接口，准备移动样品台", true);
            log.Info("文件名=" + fileName4, true);
            ImagePro.Img_Trapezoid_Top_Center_Position(fileName4, Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out x2, out y2, out state);

            log.Info("梯形中心点返回数据=" + x2.ToString() + ", " + y2.ToString(), true);
            log.Info("准备移动样品台返回状态=" + state.ToString(), true);
            if (state == 1)
            {
                //1. 根据客户PT沉积坐标控制FIB调整到中心位置？？？？？？？
                if (!m_locate.MoveToPixByMoveStage(x2, y2))
                {     
                    log.Error("测量线程报错：" + arg.Message, false);
                    return false;
                }
               
                
                arg.Message = "移动到新(" + x2.ToString() + "," + y2.ToString() + ")位置成功";
                mArgSend.SendArgumentToScreen("3-3",arg.Message);

                //add by zjx 2020-12-21 根据客户的需求修改图片的名称
               // String fileName10 = currHole.data_path + "\\" + MParam.Firm + "-" + MParam.Location_Magnification.ToString("0") + "-" + currHole.HoleName + "-" + ImageName10;
                //add by zjx 2020-12-21 根据客户的需求修改图片的名称 end 
                //log.Info("fileName10====================" + fileName10, true);
                //m_photo.GetParam().savePath = fileName10;
                

            }
            else
            {
               

                log.Error("测量线程报错：" + arg.Message, false);
                return false;
            }
            //判断是否停止进程
 

            return true;
        }

        /// <summary>
        /// 17.自动控制SEM拍截面照
        /// </summary>
        /// <returns></returns>
        public bool ShotSection(CutHole currHole,ref List<String> limg_path, ref List<float> lsize)
        {
            int state = 0;
            #region 对焦     
           
            Focusparam fprm = new Focusparam()
            {
                //voltage = MParam.Photograph_Voltage,
                mag = MParam.Photograph_Magnification,
                reduceWindowPos = new System.Drawing.Point(402, 128),
                reduceWinHeight = 600,
                reduceWinWidth = 600,
            
                IfAutoBrightnessAndContrast = true,
                brightness = 50.0f,
                contrast = 30.0f,
              
             
                tiltCorrAngle = MParam.Correction_Angle_Inside,
                workingDis = 5.0f,

            };

            //add by sun 2020-12-17 解决3大类样品FIB下亮度过白导致无法识别问题
            float m_TempBrightness=MParam.ShotSectionManualBrightness;
            float m_TempContrast = MParam.ShotSectionManualConstrast;

            fprm.brightness = m_TempBrightness;
            fprm.contrast = m_TempContrast;
            m_focuse.setFocusParam(fprm);
            m_focuse.DoFocusBySetMainParameter();


            Thread.Sleep(200);
            if (key_stop)
            {
                log.Info("停止键按下", true);
                return false;
            }




            //4、拍照，5、保存照片
          string  fileName6 =currHole.data_path + "\\" + MParam.Firm + "-" + MParam.Photograph_Magnification.ToString("0") + "-" + currHole.HoleName + "-" + ImageName6;
           log.Info("fileName6=" + fileName6, true);
         
            PhotoParam phop = new PhotoParam()
            {
                Mag = MParam.Photograph_Magnification,
                 savePath=fileName6,
            };
            m_photo.SetPhotoParam(phop);
            if (!m_photo.TakePhoto())
            {               
                log.Error("测量线程报错：" + arg.Message, false);
                return false;
            }

           
            mArgSend.SendArgumentToScreen("3-7", "SEM拍照成功", fileName6);
            //判断是否停止进程
            if (key_stop)
            {
                log.Info("停止键按下", true);
                return false;
            }
            #endregion

            if (MParam.Is_Photograph == false)
            {
              

              

                #region 获取两个位置上及放大倍数
                //计算两个测量区域坐标
                List<System.Drawing.Point> ct = new List<System.Drawing.Point>();
                List<float> mag = new List<float>();
                System.Drawing.Point ct0;
                float magMax;
               

                //log.Info("测量线程：图像处理接口，计算两个放大区域坐标，输入图像" + fileName6.ToString() + "控制失败", true);
                ImagePro.Img_Measure_Region_Position(fileName6, Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out ct, out mag, out ct0, out state);
                string s = "";
                        for (int i = 0; i < ct.Count; i++)
                        {
                            s += " 输出观测点" + i.ToString() + "为(" + ct[i].X.ToString() + "," + ct[i].Y.ToString() + ")"
                            + "放大倍数=" + mag[i];
                        }
                        log.Info("测量线程：图像处理接口返回值为" + state.ToString() +
                            "，计算放大区域坐标，输入图像" + fileName6.ToString() +
                            "输入样品 " + Convert.ToInt32(MParam.SampleTypeNo()) +
                            " 输入厂商" + MParam.Firm.ToString() +
                            s +
                          " 输出对焦点为(" + ct0.X.ToString() + "," + ct0.Y.ToString() + ")", true);
                #endregion
                if (state == 1 && ct.Count != 0 && mag.Count != 0)
                {
                   
                //    mArgSend.SendArgumentToScreen("3-10", "获取位置及放大倍数成功");

                    #region 记录初始设置的BeamShift的百分比和样品台XY位置
                   
                    m_locate.RecordCurrentBeamShiftAndStagePosition();
                    #endregion

                    //找到放大倍数最大值
                    magMax = mag[0];
                    for (int m = 1; m < mag.Count; m++)
                    {
                        if (mag[m] > magMax)
                        {
                            magMax = mag[m];
                        }
                    }

                    #region 移动到梯形左上角
                    //20201127将视野移动到梯形左上角位置
                  
                    m_locate.MoveToPix(ct0.X, ct0.Y,MParam.PixelSizeCor);

                    log.Info("测量线程：移动到对焦点（ " + ct0.X.ToString()
                        + "," + ct0.Y.ToString() + ")", true);

                    Thread.Sleep(200);
                   


                    //循环升级对焦，每次放大3000倍

                    int startmag=7000;
                    if (magMax < 7000)
                    {
                        startmag =(int) magMax;

                    }

                    for (int curmag= startmag; curmag < magMax+3000; curmag += 5000)
                    {
                        
                        fprm.IfAutoBrightnessAndContrast = true;                       

                        fprm.reduceWinHeight = 480;
                        fprm.reduceWinWidth = 450;
                        fprm.tiltCorrAngle = MParam.Correction_Angle_Inside;


                        fprm.mag = curmag;
                        m_focuse.setFocusParam(fprm);
                        m_focuse.DoFocusBySetMainParameter();


                    }

                    #endregion
                    m_photo.EnforceContrast() ;//enter inside,enforce the brightness.
                    #region 循环拍照
                    for (int n = 0; n < ct.Count; n++)
                    {
                        #region 恢复到拍照的状态
                        m_locate.RestoreLastBeamShiftAndStagePosition();
                       
                        #endregion

                        #region 移动到指定点位置
                        LocateParam lprm = new LocateParam()
                        {
                            PositionX = ct[n].X,
                            PositionY = ct[n].Y,
                            PixelSize_Y_cur = MParam.PixelSizeCor,
                        };
                        if (!m_locate.MoveToPix(lprm.PositionX,lprm.PositionY,lprm.PixelSize_Y_cur))
                        {
                            
                            //移动到第一个点失败
                            log.Error("测量线程报错：移动到点(" + ct[n].X.ToString() + "," + ct[n].Y.ToString() + ")失败", false);
                        }
                       
                        log.Info("测量线程：移动到第1个点（ " + ct[n].X.ToString()
                            + "," + ct[n].Y.ToString() + ")", true);
                        #endregion

                        log.Info("测量线程：移动到第一个点位置完成！", true);


                        #region 拍照

                        //add by zjx 2020-12-21 根据客户的需求修改图片的名称
                        String fileName7 = currHole.data_path + "\\" + MParam.Firm + "-" + mag[n].ToString() + "-" + currHole.HoleName + "-" + n.ToString() + "-" + ImageNameTwo_1;
                        //add by zjx 2020-12-21 根据客户的需求修改图片的名称 end 
                        log.Info("fileName7=" + fileName7, true);
                       
                        if (n == 0)//如果是第一个观测点就做角度修正
                        {
                            String fileName5 = currHole.data_path + "\\" + MParam.Firm + "-" + mag[n].ToString("0") + "-" + currHole.HoleName + "-" + ImageName5;
                            //add by zjx 2020-12-21 根据客户的需求修改图片的名称 end 
                            log.Info("纠正前 fileName5=" + fileName5, true);

                            m_photo.GetParam().savePath = fileName5;
                            m_photo.GetParam().Mag = mag[n];
                            m_photo.TakePhoto();

                            //8,计算切割面区域偏移角度及方向
                            float degree = 0;
                            int direction = 0;

                            ImagePro.Img_Center_Position_OffsetAngle_Direction(fileName5, Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out degree, out direction, out state);
                            log.Info("测量线程：拍照角度移动,输入图像" + fileName5 + "输出角度为" + degree.ToString() + "输出方向为" + direction.ToString() + "返回值为" + state.ToString(), true);
                            log.Info("样品" + currHole.HoleNo.ToString() + "计算切割面区域的角度=" + degree.ToString(), true);
                            //接口返回像素，*pixelsize,得到坐标点。判断移动方式
                            if (state == 1)
                            {
                                //梯形角度
                                iSEM.SetScanRotationOn();
                                Thread.Sleep(200);
                                //20201128陈工要求，谭博返回角度*0.7
                                iSEM.SetScanRotation(Convert.ToSingle(degree * MParam.ScanRotCor));
                                Thread.Sleep(200);


                                string Message = "图像接口返回角度为：" + degree.ToString();

                                mArgSend.SendArgumentToScreen("3-8", Message, fileName5);


                            }
                            else
                            {


                                log.Error("测量线程报错：" + arg.Message, false);
                            }
                            //纠正后再次拍照
                            log.Info("纠正后拍照！");
                            m_photo.GetParam().savePath = fileName7;
                            m_photo.GetParam().Mag = mag[n];

                            m_photo.TakePhoto();

                        }
                        else
                        {
                            m_photo.GetParam().savePath = fileName7;
                            m_photo.GetParam().Mag = mag[n];

                            m_photo.TakePhoto();


                        }
                       
                        iSEM.CmdFocusScanSpeed("CMD_SCANRATE4");//CmdFocusRate(4);
                        Thread.Sleep(200);
                        cycle_time = iSEM.GetCycleTime();
                        Thread.Sleep(Convert.ToInt32(cycle_time) + 100);
                        Thread.Sleep(200);

                        mArgSend.SendArgumentToScreen("3-11", "移动到第"+n+"个点位置拍照成功",fileName7);

                        // add by zjx 在测量图上显示放大倍数和像素大小等信息
                        
                        limg_path.Add(fileName7);
                        //获取像素大小
                        lsize.Add(iSEM.GetPixelSize());

                        float size = iSEM.GetPixelSize();
                        SaveMeasDataPic(fileName7, mag[n], size);
                        Thread.Sleep(1000);
                        #endregion
                    }

                    #endregion

                }
                else
                {
              
                    log.Error("测量线程报错：" + arg.Message, false);
                }
                //判断是否停止进程
                if (key_stop)
                {
                    log.Info("停止键按下", true);
                    return false;
                }

            }

          
            iSEM.SetTiltAngleOff();
            Thread.Sleep(200);
            iSEM.SetScanRotationOff();
            Thread.Sleep(200);
            iSEM.SetBeamShiftX(0);
            Thread.Sleep(200);
            iSEM.SetBeamShiftY(0);
            Thread.Sleep(200);
            //判断是否停止进程
            if (key_stop)
            {
                return false;
            }
            return true;
        }

       
        public bool HoleMeasure(CutHole currHole) 
        {
            // add by zjx 2020-12-18 为了测试只做能谱部分
            if (MParam.IsonlyEDSForDebug == true)
            {
                //第一步:位置恢复
                #region 第一步：坐标恢复
                log.Info("测量线程：恢复样品分析点位置(R,X,Y,Z) = (" + currHole.Position.R.ToString() + ","
                 + currHole.Position.X.ToString() + ","
                 + currHole.Position.Y.ToString() + ","
                 + currHole.Position.Z.ToString() + ")", true);
                Locate lo = new Locate(iSEM);
                lo.LocateCutHolePosition(currHole, MParam.Tilt);

                if (!m_focuse.SetMagnification(MParam.Location_Magnification))
                {

                    log.Error("测量线程报错：设置定位放大倍数" + MParam.Location_Magnification.ToString() + "控制失败", false);
                    return false;
                }
                if (key_stop)
                {

                    log.Info("停止键被按下", true);
                    return false;
                }
                arg.HoleName = currHole.HoleName;
                arg.State = true;
                arg.Message = "样品台移动到观测点：" + currHole.HoleName + "的位置成功。";
                SendMsg("0-0");


                #endregion
                //第二步：设置电流电压
                //add by sun 2020-12-17 不同样品电压、电流不一致，应设置灵活。123456类电压2000V电流200pA，7类5000V 500pA，能谱 7000V 500pA 
                log.Warn("测量线程：设置拍照电压 123456类电压2000V电流200pA，7类5000V 500pA，能谱 7000V 500pA  目前是第 " + MParam.SampleType + " 类！", true);
                if (!SetVoltageAndIPROBE())
                {
                    log.Error("测量线程：设置电压电流失败！目前是第 " + MParam.SampleType + " 类！", false);
                    return false;
                }               
              
               

                //第三步：自动化流程-每个点都需要补偿54度
                if (MParam.Is_Photograph == false)
                {
                    log.Info("测量线程：倾斜补偿角度为54度", true);
                    if (!m_focuse. TiltCorrection(MParam.Correction_Angle_OutSide))
                    {
                        log.Error("测量线程报错：倾斜补偿角度为54度失败", false);

                        return false;
                    }
                    arg.Message = "角度补偿54度成功！";
                    arg.State = true;
                    SendMsg("0-1");
                  
                    //判断是否停止进程
                    if (key_stop)
                    {
                        log.Info("停止键按下", true);
                        return false;
                    }
                }

                //第四步：拉直 （ 2是5/6类样品，不需要拉直）
                if (MParam.StraightenToRun)
                {

                    log.Warn("测量线程：拉直操作开始！", true);
                    if (!Straighten_Handle(currHole))
                    {
                        log.Info("测量线程报错：拉直操作失败。", true);
                        return false;
                    }
                    log.Info("测量线程：拉直操作结束！", true);
                    //判断是否停止进程
                    if (key_stop)
                    {
                        log.Info("停止键按下。", true);
                        return false;
                    }
                }
                else
                {
                    arg.Message = "拉直操作自动对焦成功！";
                    arg.State = true;
                    SendMsg("1-0");
                    Thread.Sleep(200);
                    arg.Message = "拉直拍照成功！";
                    arg.Picture_Information.Picture_FullPath = "";
                    arg.State = true;
                    SendMsg("1-1");
                    Thread.Sleep(200);
                    arg.Message = "拉直操作完成";
                    arg.State = true;
                    SendMsg("1-2");
                    Thread.Sleep(200);
                }

                //第五步： 定位功能 PT沉积                
                if (MParam.Is_Photograph==false)
                {
                    log.Warn("测量线程：PIB切割自动定位开始！", true);
                    if (!GetFIBAndPTPoistion(currHole))
                    {
                        log.Error("测量线程报错：自动定位失败，程序退出。", false);
                        return false;
                    }


                    //11.自动工具样品类型参数确定是否需要PT沉积
                    log.Info("是否PT：" + MParam.PT.ToString());
                    if (MParam.PT)
                    {
                   

                        arg.State = true;
                        arg.Message = "PT沉积";
                        SendMsg("2-4");
                        m_PTWork.DoWholePTWork();
                    }
                }
                arg.State = true;
                arg.Message = "";
                SendMsg("2-5");
                arg.State = true;
                arg.Message = "";
                SendMsg("2-6");


                log.Info("测量线程：自动定位结束！", true);
                //判断是否停止进程
                if (key_stop)
                {
                    log.Info("停止键按下。", true);
                    return false;
                }

                //14.自动控制FIB切割    del by sun 2020-12-15 temp            
                if (MParam.Is_Photograph == false)
                {
                    if (MParam.IsCutingForDebug)
                    {
                        log.Warn("测量线程：自动控制FIB切割开始！==" + MParam.IsCutingForDebug, true);
                        if (!FIBCross())
                        {
                            log.Error("测量线程报错：自动控制FIB切割失败。", false);
                            return false;
                        }
                        log.Info("测量线程：自动控制FIB切割结束！", true);
                    }
                }
                //del by sun 2020-12-15 temp end
                //判断是否停止进程
                if (key_stop)
                {
                    return false;
                }

                //16.找到切割位置
                if (MParam.Is_Photograph == false)
                {
                    log.Info("测量线程：找到切割位置开始！移动到视野中心", true);
                    if (!FindCross(currHole))
                    {
                        return false;
                    }
                    log.Info("测量线程：找到切割位置结束！", true);
                    //判断是否停止进程
                    if (key_stop)
                    {
                        return false;
                    }
                }
                log.Warn("测量线程：自动控制SEM拍截面照开始", true);
                //将过程17最后的拍照图片提出给18步进行调用
                List<String> limg_path = new List<string>();
                List<float> lsize = new List<float>();
                //17.自动控制SEM拍截面照
                if (!ShotSection(currHole,ref limg_path, ref lsize))
                {
                    log.Error("拍截面照失败！");
                    return false;
                }
                log.Info("测量线程：自动控制SEM拍截面照结束！", true);
                //判断是否停止进程
                if (key_stop)
                {
                    return false;
                }

             

                //18.自动层高分析
                if (MParam.Is_Photograph == false)
                {
                    log.Warn("测量线程：自动层高分析开始", true);
                    float size = iSEM.GetPixelSize();
                    int state = 1;
                    ImagePro.Img_Measure_Height(limg_path, lsize, currHole.data_path + "\\", Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out state);
                    if (state == 0)
                    {

                        log.Error("层高分析失败！");
                        return false;
                    }
                    arg.State = true;
                    arg.Message = "层高分析成功";
                    SendMsg("3-12");
                    log.Info("测量线程：自动层高分析结束！", true);
                }
            }
            //add by zjx 2020-12-18 为了测试只做能谱部分 end
            //19.能谱分析

            if (MParam.EDS)
            {
               
                if (currHole.HoleNo + 1 == m_cutHoles.Count)//最后样品分析点才跑能谱
                {
                    log.Warn("测量线程：能谱分析开始===" + MParam.EDS, true);
                    EDS_Analysis(currHole);
                    log.Info("测量线程：能谱分析结束===" + MParam.EDS, true);
                }
               
              
            }
            //20.复位
            log.Info("测量线程：复位开始", true);
            BeamShiftReset();
            return true;
        }

      

        //初始化拉直操作
        public bool Straighten_Handle(CutHole currHole)
        {

            //设置拉直的放大倍数
            log.Info("测量线程：设置拉直放大倍数，放大倍数为" + MParam.Straighten_Magnification.ToString(), true);

            if (!m_focuse.SetMagnification(MParam.Straighten_Magnification))
            {
                log.Error("测量线程报错：设置SEM放大倍数为拉直放大倍数失败，放大倍数为" + MParam.Straighten_Magnification.ToString(), false);

                return false;
            }
            arg.Message = "拉直放大倍数设置成功！";
            arg.State = true;
            SendMsg("0-2");
            //1、自动对焦
            log.Info("测量线程：拉直操作前自动对焦开始", true);

           
            var p = new Focusparam();

            p.IfAutoBrightnessAndContrast = true;
            p.mag = MParam.Straighten_Magnification;
            p.reduceWindowPos = new System.Drawing.Point(402, 128);
            p.reduceWinWidth = 400;
            p.reduceWinHeight = 400;
            p.brightness = MParam.StraightenManualBrightness;
            p.contrast = MParam.StraightenManualContrast;
            m_focuse.setFocusParam(p);
            if (!m_focuse.DoFocusByNewMagnification(MParam.Straighten_Magnification))
            {
                log.Error("测量线程报错：拉直操作自动对焦失败，程序退出。", false);
              
                return false;
            }
            Thread.Sleep(1000);


            arg.Message = "拉直操作自动对焦成功！";
            arg.State = true;
            SendMsg("1-0");
            //判断是否停止进程
            if (key_stop)
            {
                log.Info("停止键按下。", true);
                return false;
            }


            //2、拍张照片
            String fileName0 = currHole.data_path + "\\" + currHole.HoleName + "_" + MParam.Straighten_Magnification.ToString("0") + "_" + ImageName0;
            log.Info("测量线程：设置保存图像的是扫描速度保存图像" + fileName0, true);
            //拍照前改变速度,延时

            m_photo.GetParam().Mag = p.mag;
            m_photo.GetParam().savePath = fileName0;
            if (!m_photo.TakePhoto())
            {
                log.Error("测量线程报错：拉直拍照失败", false);
               
                return false;
            }
            arg.Message = "拉直拍照成功！";
            arg.Picture_Information.Picture_FullPath = fileName0;
            arg.State = true;
            SendMsg("1-1");


            //3、华为接口，获取旋转角度
            float degree = 0;
            int direction = 0;
            int state = 1;
            ImagePro.Img_OffsetAngle_Direction(fileName0, Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out degree, out direction, out state);
            log.Info("测量线程：使用图像处理接口：样品" + currHole.HoleNo.ToString() + "初始化拉直角度=" + degree.ToString(), true);
            log.Info("图像处理结果拉直角度=" + degree.ToString(), true);
            log.Info("图像处理结果拉直角度=" + degree.ToString(), true);
            if (state == 0)
            {
                log.Info("测量线程：图像处理接口参数state返回为零", false);        
   

                return false;
            }
            if (direction == 2)
            {
                degree = -degree;
            }

            if (degree != 0)
            {
                //4、拉直，旋转R轴
                log.Info("测量线程：图像拉直，旋转角度" + degree.ToString(), true);

                
                m_locate.RotateStageByDeltaR(degree);
              
                //判断是否停止进程
                if (key_stop)
                {
                    log.Info("停止键按下", true);
                    return false;
                }
             
            }
            arg.Message = "拉直操作完成";
            arg.State = true;
            SendMsg("1-2");

            return true;
        }

       

        #region 能谱所有参数
        //全局只有一个Extender
        static ExtenderInterface factoryExtender = ExtenderInterface.Instance;
        public IExtenderControl iExtender = null;
        const int ScanFieldSize = 1142;
        MeasureDB m_MeasDB = null;
        int m_nXrayId = 0;
        const String ImageNameEDS = @"EDSImage.tif"; //EDS能谱图片
        const String ImageNameEDS4 = @"SEMTrapCPEDS.tif";//传给客户，找到已经切割点
        const String ImageNameEDS5 = @"SEMDegreeTrapEDS.tif";//传给客户，水平校正
        const String ImageNameEDS6 = @"SEMMagEndEDS.tif";//传给客户，测量层高

        /// <summary>
        /// 做能谱分析
        /// </summary>
        /// <param name="a_CutHoleID">分析点视场ID，索引号</param>
        /// <param name="a_CutHoleName">分析点视场名称</param>
        /// <param name="a_FieldImagePositionID">分析点的视场位置ID，图像处理会返回多个Xray分析点，但我们这里只取第一个点所在的视场</param>
        /// <returns>成功或失败</returns>
        public bool DoEDS(CutHole currHole,  int a_FieldImagePositionID)
        {
            try
            {
              string CutHoleName = currHole.HoleName;
                //XrayID记录
                log.Info("程序进入EDS测量！", true);
                iExtender = factoryExtender.IExtender;
                Thread.Sleep(500);
                EDSParam param = MParam.EDSParam;
                double dDwellTime = param.DwellTime;
                int nImageType = param.ImageType;
                double dScanSizes = param.ScanSize;

                log.Info("dDwellTime=" + dDwellTime.ToString() + " nImageType=" + nImageType.ToString() + " dScanSizes=" + dScanSizes.ToString(), true);
                iExtender.SetImageAcquistionSetting(dDwellTime, nImageType, dScanSizes);

                string path = currHole.EDS_path;
                string edsfn = path + "\\" + a_FieldImagePositionID.ToString() + "_" + ImageNameEDS;
                log.Info("EDS_PATH=" + edsfn, true);



                iExtender.GrabImage(edsfn, 0, 0, 0, 0, 0);//get the field eds image where the anylysis point locate.
                arg.Picture_Information.Picture_FullPath = "";
                arg.State = true;
                SendMsg("4-5");//向界面发送指令：能谱拍照
                //arg.State = false;
                arg.Message = "";
                arg.Picture_Information.Picture_FullPath = edsfn;
                SendMsg("EDSPic");

                //送给客户，计算感兴趣的区域
                List<System.Drawing.Point> listPoints = new List<System.Drawing.Point>();
                List<System.Drawing.Point> LinesStartPoint = new List<System.Drawing.Point>();
                
                List<List<Segment>> Features = new List<List<Segment>>();
                List<int> lines_height = new List<int>();
                System.Drawing.Point area_pt = new System.Drawing.Point();
                int width = 1;
                int height = 1;
                int AreasNo = 0;
                long[] XrayData;
                Dictionary<string, double> listElement;
                int xrayCollectMode = param.XrayCollectMode;
                switch (xrayCollectMode)
                {
                    case 0://point mode
                           //点数据
                        int state = 0;
                        ImagePro.EDS_Param_Points(edsfn, a_FieldImagePositionID, Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out listPoints, out state);
                        if (state == 0)
                        {
                            log.Error("点采集失败", false);
                            return false;
                        }
                        log.Info("返回 listPoints=" + listPoints.Count.ToString(), true);
                        if (!m_MeasDB.InsertAnylysisField(currHole.HoleNo, CutHoleName, currHole.EDS_path, listPoints.Count, Features.Count, a_FieldImagePositionID))
                        {
                            log.Error("插入分析视场失败", false);
                        }


                        iExtender.BeginMultipleAquisition();
                        Thread.Sleep(100);
                        //点采集
                        m_nXrayId = 0;
                        foreach (System.Drawing.Point pt in listPoints)
                        {
                            XrayData = new long[2000];
                            listElement = new Dictionary<string, double>();
                          
                            if (iExtender.XrayPointCollecting(param.PointTime, pt.X, pt.Y , out XrayData, out listElement))
                            {
                                string ele = "";
                                foreach (var s in listElement)
                                {
                                    ele += s.ToString();
                                }
                                log.Info("采集点：（" + pt.X.ToString() + ":" + pt.Y.ToString() + ") 元素：" + ele);
                                //写入数据库
                                m_nXrayId++;
                                log.Info("点采集结束，写入数据库开始--" + m_nXrayId.ToString(), true);
                                Boolean ret = m_MeasDB.InsertAPointXray(currHole.HoleNo, m_nXrayId, pt.X, pt.Y, XrayData, listElement, a_FieldImagePositionID);
                                Thread.Sleep(1000);
                            }

                        }
                        iExtender.EndMultipleAquisition();
                        break;
                    case 1://line mode

                        log.Info("线扫描", true);
                        state = 0;
                        ImagePro.EDS_Param_Lines(edsfn, a_FieldImagePositionID, Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out LinesStartPoint, out lines_height, out state);
                        string sp = "";
                        foreach (System.Drawing.Point p in LinesStartPoint)
                        {
                            sp += "(" + p.X + "," + p.Y + ")";
                        }
                        log.Info("线返回数据,lines=" + LinesStartPoint.Count.ToString() + " " + sp, true);

                        if (state == 1)
                        {
                            //将线转换为segment数据
                            log.Info("将线转换为segment数据", true);
                           
                            for (int i = 0; i < LinesStartPoint.Count; i++)
                            {
                                int wholeHeight = lines_height[i];
                                int singleHeight = 5;//每5高度形成一个单元

                                for (int k = 0; k < wholeHeight; k += singleHeight)
                                {

                                    List<Segment> feature = new List<Segment>();
                                    for (int j = 0; j <= singleHeight; j++)
                                    {
                                        Segment segment = new Segment();
                                        segment.X = LinesStartPoint[i].X;
                                        segment.Y = LinesStartPoint[i].Y + j+ k;
                                        segment.Length = 2;
                                        feature.Add(segment);
                                    }
                                    Features.Add(feature);
                                }
                               
                            }

                        }
                        else
                        {
                            log.Error("线扫图片处理失败", false);
                            return false;
                        }
                        //线采集


                        iExtender.BeginMultipleAquisition();
                        Thread.Sleep(100);
                        for (int i = 0; i < Features.Count; i++)
                        {
                            List<Segment> listSeg = Features[i];
                            XrayData = new long[2000];
                            listElement = new Dictionary<string, double>();


                            if (iExtender.XrayAreaCollectiong(300, listSeg, out XrayData, out listElement))
                            {
                                string ele = "";
                                foreach (var s in listElement)
                                {
                                    ele += s.ToString();
                                }
                                log.Info("采集时间=300" , true);
                                log.Info("(" + listSeg[0].X + "," + listSeg[0].Y + ") height=5"  + " 元素：" + ele);
                                log.Info("线采集结束，写入数据库开始", true);
                                //写入数据库
                                m_nXrayId++;

                                AreasNo++;
                                m_MeasDB.InsertAAreaXay(currHole.HoleNo, m_nXrayId, AreasNo, listSeg, XrayData, listElement, a_FieldImagePositionID);



                            }
                            else
                            {
                                log.Error("线扫xray失败");
                            }


                        }
                        iExtender.EndMultipleAquisition();

                        break;
                    case 2: //area mode
                            //面数据
                        state = 0;
                        ImagePro.EDS_Param_Areas(edsfn, a_FieldImagePositionID, Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out area_pt, out width, out height, out state);
                        log.Info("面返回数据" + area_pt.X.ToString() + "," + area_pt.Y.ToString() + ",height=" + height.ToString() + ",width=" + width.ToString(), true);
                        if (state == 1)
                        {
                            //将面转换为segment数据,每5行形成一个面
                            int singleH = 5;
                            for (int k = 0; k < height; k += singleH)
                            {
                                List<Segment> segments = new List<Segment>();
                                for (int j = 0; j <= singleH; j++)
                                {
                                    Segment segment = new Segment();
                                    segment.X = area_pt.X;
                                    segment.Y = area_pt.Y + j+k;
                                    segment.Length = width;
                                    segments.Add(segment);
                                }
                                Features.Add(segments);

                            }
                            

                        }
                        else
                        {
                            log.Error("面扫图片处理失败", false);
                            return false;
                        }
                        //面采集
                        iExtender.BeginMultipleAquisition();
                        Thread.Sleep(100);
                        foreach (List<Segment> feature in Features)
                        {
                            XrayData = new long[2000];
                            listElement = new Dictionary<string, double>();

                            log.Info("AreaTime=500", true);
                            if (iExtender.XrayAreaCollectiong(500, feature, out XrayData, out listElement))
                            {
                                string ele = "";
                                foreach (var s in listElement)
                                {
                                    ele += s.ToString();
                                }
                                log.Info(" 元素：" + ele);
                                log.Info("面采集结束，写入数据库开始", true);
                                //写入数据库
                                m_nXrayId++;

                                AreasNo++;
                                m_MeasDB.InsertAAreaXay(currHole.HoleNo, m_nXrayId, AreasNo, feature, XrayData, listElement, a_FieldImagePositionID);
                            }
                            else
                            {
                                log.Error("面扫xray失败");
                            }
                        }
                        iExtender.EndMultipleAquisition();
                        break;

                }

                //存储数据
                //向分析点数据库更新


            }
            catch (Exception e)
            {
                iExtender.EndMultipleAquisition();
                log.Error(e.Message, false);
                return false;
            }
            return true;
        }

        /// <summary>
        /// 初始化数据库
        /// </summary>
        public void Init_MeasDB()
        {
            m_MeasDB = new MeasureDB(m_measureFile);
        }

        /// <summary>
        /// 161.自动调整SEM找到切割位置，这里不是简单的拉直旋转
        /// </summary>
        /// <returns></returns>
        public bool EDS_FindCross(CutHole currHole)
        {
            float x2 = 0, y2 = 0;
            int state = 0;
            float tmag = MParam.FindCrossMagnification;
 

            Focusparam focusPrm = new Focusparam()
            {
                IfAutoBrightnessAndContrast = true,
                mag = tmag,
                reduceWindowPos = new System.Drawing.Point(256, 192),
                reduceWinWidth = 400,
                reduceWinHeight = 400,
                workingDis = 10,//unit:mm
                brightness = 50,
                contrast = 29,
                tiltCorrAngle = MParam.Correction_Angle_OutSide,
                ifStig = false,

            };

            m_focuse.setFocusParam(focusPrm);
            m_focuse.DoFocusBySetMainParameter();

            float mag = tmag;
           
            String fileName4 = currHole.data_path + "\\EDS\\" + MParam.Firm + " - " + mag.ToString("0") + "-" + currHole.HoleName + "-" + ImageNameEDS4;
            PhotoParam prm = new PhotoParam()
            {
            
                Mag = mag,
                savePath = fileName4,
                              
                  
            };
            
            m_photo.SetPhotoParam(prm);
            m_photo.TakePhoto();
     
            arg.Picture_Information.Picture_FullPath = fileName4;
    
            mArgSend.SendArgumentToScreen("4-2", "", fileName4);
            
           

            if (key_stop)
            {
                return false;
            }

            //4.将照片传给客户，获取偏移坐标，以及偏移角度
            //5.根据坐标控制SEM移动到切孔位置，居中
            log.Info("测量线程：图像处理接口，准备移动样品台", true);
            log.Info("文件名=" + fileName4, true);
            ImagePro.Img_Trapezoid_Top_Center_Position(fileName4, Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out x2, out y2, out state);
           
            log.Info("梯形中心点返回数据=" + x2.ToString() + ", " + y2.ToString(), true);
            log.Info("准备移动样品台返回状态=" + state.ToString(), true);
            if (state == 1)
            {
                
                //1. 根据客户PT沉积坐标控制FIB调整到中心位置？？？？？？？
                if (!m_locate.MoveToPixByMoveStage(x2,y2))
                {

                    log.Error("测量线程报错：" + arg.Message, false);
                    return false;
                }
              

            }
            else
            {

                log.Error("测量线程报错：" + arg.Message, false);
                return false;
            }
            //判断是否停止进程
            if (key_stop)
            {
                log.Info("停止键按下", true);
                return false;
            }
            Thread.Sleep(2000);
            return true;
        }

        /// <summary>
        /// 171.能谱第17步找点采集数据
        /// </summary>
        /// <returns></returns>
        public bool EDS_ShotSection(CutHole currHole)
        {
            int state = 0;
          
      
       
        
            Focusparam fprm = new Focusparam()
            {
                mag = MParam.Photograph_Magnification,
                reduceWindowPos = new System.Drawing.Point(402, 128),
                reduceWinHeight = 600,
                reduceWinWidth = 600,
               
                IfAutoBrightnessAndContrast = true,
              
                workingDis = 10,//unit mm
                brightness = 50,
                contrast = 29,
                tiltCorrAngle = MParam.Correction_Angle_Inside,
                ifStig = false,
            };
          

            log.Info("自动对焦开始！", true);
            
            m_focuse.setFocusParam(fprm);
            m_focuse.DoFocusBySetMainParameter();
            SendMsg("4-4");
            fprm.ifStig = false;


            //add by zjx 2020-12-21 根据客户的需求修改图片的名称
            String fileName5 = currHole.data_path + "\\EDS\\" + MParam.Firm + "-" + MParam.Photograph_Magnification.ToString("0") + "-" + currHole.HoleName + "-" + ImageName5;
            //add by zjx 2020-12-21 根据客户的需求修改图片的名称 end 
            log.Info("fileName5=" + fileName5, true);
          
            log.Info("开始拍摄截面照！");
            PhotoParam phoPrm = new PhotoParam()
            {
                Mag = MParam.Photograph_Magnification,
                savePath = fileName5,
               

            };
            //Photo pho = new Photo(phoPrm, iSEM);
            m_photo.SetPhotoParam(phoPrm);
            m_photo.TakePhoto();

            //判断是否停止进程
            if (key_stop)
            {
                log.Info("停止键按下", true);
                return false;
            }
            #endregion

            if (MParam.Is_Photograph == false)//Is_Photograph 代表 是否是只拍照
            {

                #region 获取两个位置上及放大倍数
                //计算两个测量区域坐标
                List<System.Drawing.Point> ct = new List<System.Drawing.Point>();
                List<float> mag = new List<float>();
                System.Drawing.Point ct0;
                float  magMax;
                log.Info("图像处理接口，计算两个放大区域坐标，输入图像" + fileName5.ToString(), true);
                ImagePro.Img_Measure_Region_Position(fileName5, Convert.ToInt32(MParam.SampleTypeNo()), MParam.Firm, out ct, out mag, out ct0, out state);
                string s = "";
                for (int i = 0; i < ct.Count; i++)
                {
                    s += "输出观测点" + i.ToString() + "为(" + ct[i].X.ToString() + "," + ct[i].Y.ToString() + ")"
                    + "放大倍数=" + mag[i];
                }
                log.Info("测量线程：图像处理接口返回值为" + state.ToString() +
                    "，计算两个放大区域坐标，输入图像" + fileName5.ToString() +
                    "输入样品" + Convert.ToInt32(MParam.SampleTypeNo()) +
                    "输入厂商" + MParam.Firm.ToString() +
                    s +
                  "输出对焦点为(" + ct0.X.ToString() + "," + ct0.Y.ToString() + ")", true);
                #endregion
                if (state == 1 && ct.Count != 0 && mag.Count != 0)
                {
                    Locate recordPostion = new Locate(iSEM);
                    recordPostion.RecordCurrentBeamShiftAndStagePosition();
                    //找到第一个观测点放大倍数find the first anylysis point and the mag.
                    magMax = mag[0];
                  

                    #region 移动到梯形左上角
                    //20201127将视野移动到梯形左上角位置
                    log.Warn("开始对焦 移动到对焦点（ " + ct0.X.ToString()
                        + "," + ct0.Y.ToString() + ")", true);
                    
                 
                    m_locate.MoveToPix(ct0.X,ct0.Y,MParam.PixelSizeCor);

                    Thread.Sleep(200);
                    //add by sun 2020-12-15 拍截面图调用蔡司接口时，要保证扫描速度5以上，自动亮度对比度功能关闭
                    iSEM.CmdFocusScanSpeed("CMD_SCANRATE5");//CmdFocusRate(5);
                    //add by sun 2020-12-15 拍截面图调用蔡司接口时，要保证扫描速度5以上，自动亮度对比度功能关闭 end
                    
                    cycle_time = iSEM.GetCycleTime();
                    Thread.Sleep(100 + Convert.ToInt32(cycle_time));
                    Focusparam fprm1 = new Focusparam()
                    {
                        mag = magMax / 2,
                        reduceWindowPos = new System.Drawing.Point(402, 128),
                        reduceWinHeight = 600,
                        reduceWinWidth = 600,
                   
                        IfAutoBrightnessAndContrast = true,
                      
                        workingDis = 10,
                        brightness = 49.4f,
                        contrast = 30.1f,
                        tiltCorrAngle = MParam.Correction_Angle_Inside,
                        ifStig = false,
                    };
                                                                                          
                    log.Info("自动对焦1开始！", true);
                   
                    m_focuse.setFocusParam(fprm1);
                    m_focuse.DoFocusByNewMagnification(fprm1.mag);


                    log.Info("自动对焦2开始！", true);

                    m_focuse.DoFocusByNewMagnification(magMax);

                    #endregion


                    log.Warn("对焦完成，开始用能谱拍摄观测点照片！并分析图片以获得Xray点位置！");

                    recordPostion.RestoreLastBeamShiftAndStagePosition();

                    log.Warn("移动到指定观测点！并准备打Xray");

                    m_locate.MoveToPix(ct[0].X,ct[0].Y,MParam.PixelSizeCor);
                    SendMsg("4-4");//向界面发送指令：放大并对拍摄点对焦
                    Thread.Sleep(500);

                    #region 拍照
                    //log.Info("进入内部观察，不对焦！", true);

                   
                    
                    log.Info("开始EDS拍照，设置放大倍数" + mag[0]);
                 
                 m_focuse.SetMagnification(mag[0]);

                   // m_photo.EnforceContrast();

                log.Warn("EDS获取指定观测点图片,并打Xray");
                DoEDS(currHole, 1);

                log.Info("像素扫描：CmdPixelScan");
                iSEM.CmdPixelScan();

                Thread.Sleep(200);

                log.Info("改变刷新率 " + "CMD_SCANRATE4");
                iSEM.CmdFocusScanSpeed("CMD_SCANRATE4");//CmdFocusRate(4);
               
                cycle_time = iSEM.GetCycleTime();
                Thread.Sleep(Convert.ToInt32(cycle_time) + 100);

                SendMsg("4-6");//向界面发生指令：采集能谱信息
                }

                #endregion

            }

            iSEM.SetTiltAngleOff();
            Thread.Sleep(200);
            iSEM.SetScanRotationOff();
            Thread.Sleep(200);
            iSEM.SetBeamShiftX(0);
            Thread.Sleep(200);
            iSEM.SetBeamShiftY(0);
            Thread.Sleep(200);
            //判断是否停止进程

            return true;
        }

        /// <summary>
        /// 19.能谱分析
        /// </summary>
        /// <returns></returns>
        public bool EDS_Analysis(CutHole currHole)
        {
            //1.先降Z轴  37.241左右使工作距离从5mm 变为 10mm，这样方便能谱工作，麻烦是需要从新对焦。由于移动样品台会有误差，容易造成图像偏移，最好从新定位
            Locate lo = new Locate(iSEM);
            
            lo.MoveZAxisByAbs(MParam.EDSZ / 1000);          

            //判断是否停止进程
            if (key_stop)
            {
                log.Info("停止键按下", true);
                return false;
            }
            SendMsg("4-0");
           
            //2.角度补偿关闭
           // iSEM.SetScanRotationOff();
           //在层高分析时，角度补偿已经纠正，能谱分析不必再做

            Thread.Sleep(200);
            iSEM.SetSEMVoltage(MParam.EDSV);
            Thread.Sleep(200);
            iSEM.SetSEMIPROBE(MParam.EDSA  / 1000000000);
            Thread.Sleep(200);
           

            SendMsg("4-1");
            log.Warn("开始梯形移到视野中心！");
           
            if (!EDS_FindCross(currHole))
            {
                return false;
            }
            SendMsg("4-3");
            //7.调用171步过程

            log.Warn("开始打能谱图和打Xray！");


            if (!EDS_ShotSection(currHole))
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// 20.光束等复位
        /// </summary>
        public void BeamShiftReset()
        {
            iSEM.SetTiltAngleOff();
            Thread.Sleep(200);
            iSEM.SetScanRotationOff();
            Thread.Sleep(200);
            iSEM.SetBeamShiftX(0);
            Thread.Sleep(200);
            iSEM.SetBeamShiftY(0);
            Thread.Sleep(200);
        }


        //add by sun 2020-12-17 不同样品电压、电流不一致，应设置灵活。123456类电压2000V电流200pA，7类5000V 500pA，能谱 7000V 500pA
        #region 设置电压电流
        public bool SetVoltageAndIPROBE()
        {
            log.Info("测量线程：设置电压电流 123456类电压2000V电流200pA，7类5000V 500pA，能谱 7000V 500pA  目前是第 " + MParam.SampleType + " 类！", true);
          
            bool mRet_VoltageFlag = false;
            bool mRet_ElecFlag = false;
            float vot, iprobe;
            vot = MParam.Voltage;
            iprobe = MParam.Iprobe;
            
                mRet_VoltageFlag = iSEM.SetSEMVoltage(vot);
                Thread.Sleep(500);
                mRet_ElecFlag = iSEM.SetSEMIPROBE(iprobe / 1000000000);
                Thread.Sleep(500);
           
            if (!mRet_VoltageFlag) return false;
            if (!mRet_ElecFlag) return false;
            log.Info("测量线程：设置电压电流完成！", true);
            return true;
        }
        #endregion
        //add by sun 2020-12-17 不同样品电压、电流不一致，应设置灵活。123456类电压2000V电流200pA，7类5000V 500pA，能谱 7000V 500pA end

        //add by sun 2020-12-17 根据客户要求，3大类样品需要在5000倍下在拍摄一张图片，不需要分析
     
        //add by sun 2020-12-17 根据客户要求，3大类样品需要在5000倍下在拍摄一张图片，不需要分析 end
        //add by zjx 2020-12-21 在测量图上显示放大倍数和像素大小等信息
        public void SaveMeasDataPic(String picFullPath, float Mag, float pixelsize)
        {
            try
            {
                using (System.Drawing.Image img = Image.FromFile(picFullPath))
                {
                    Bitmap bmp = new Bitmap(img.Width, img.Height);
                    using (Graphics g = Graphics.FromImage(bmp))
                    {
                        g.DrawImage(img, 0, 0, img.Width, img.Height);
                        String str = "Mag:" + Mag.ToString("0") + "X\tPixelSize:" + (pixelsize * 1000000).ToString("0.00") + "um";
                        Font font = new Font("宋体", 16, FontStyle.Bold);
                        SolidBrush sbrush = new SolidBrush(Color.LimeGreen);
                        g.DrawString(str, font, sbrush, new PointF(40, img.Height - 30));
                    }
                    System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
                    Bitmap newBitmap = new Bitmap(img.Width, img.Height, bmpData.Stride, System.Drawing.Imaging.PixelFormat.Format8bppIndexed, bmpData.Scan0);

                    String path = Path.GetDirectoryName(picFullPath) +
                        Path.GetFileNameWithoutExtension(picFullPath) +
                        "_Data" + Path.GetExtension(picFullPath);

                    newBitmap.SetResolution(1, 1);
                    newBitmap.Save(path);
                }
            }
            catch
            {
                log.Error("在测量图上显示放大倍数和像素大小信息失败", false);
            }
        }
        //add by zjx 2020-12-21 在测量图上显示放大倍数和像素大小等信息 end

    }
}
