
#include "cprocess_laserkerf.h"
#include <math.h>
#include "cproductside.h"
#include "cmproduct.h"
#include "logic_local_def.h"
#include "logic_eap.h"
#include "cmproduct.h"
#include "cmworktabledriver.h"
#include "cakerfcheck_h.h"
#include "claserpathdriver.h"
#include "cjig_driver.h"
#include "csystem_external.h"
#include "ccam.h"
#include "ccamdriver.h"
#include "claserpath.h"
#include "cmotordriver.h"
CProcess_LaserKerf::CProcess_LaserKerf(const QString& name, int32_t id)
    :CMProcess(name, id)
{
    m_Variants.add_Variant(Var_Process_Kerf_BeforeSearchSleep_ID,
                           QObject::trUtf8("BeforeSearchSleep"), int(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Kerf_AfterSearchSleep_ID,
                           QObject::trUtf8("AfterSearchSleep"), int(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Kerf_PosOffset_ID,
                           QObject::trUtf8("PosOffset"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Kerf_EnableAutoThres_ID,
                           QObject::trUtf8("EnableAutoThres"), false, false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Kerf_AutoThresRange_ID,
                           QObject::trUtf8("AutoThresRange"), int(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Kerf_AutoThresStep_ID,
                           QObject::trUtf8("AutoThresStep"), int(0), false,
                           Variant::TOXML);

    //功率,频率与速度控制
    m_Variants.add_Variant(Var_Process_LaserKerf_CheckPower,
                           QObject::trUtf8("Power"), double(0.5), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_LaserKerf_CheckFreq,
                           QObject::trUtf8("Freq"), int(50), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_LaserKerf_Speed,
                           QObject::trUtf8("Speed"), int(200), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_LaserKerf_CheckEpulse,
                           QObject::trUtf8("CheckEpulse"), double(100), false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_LaserKerf_CheckBeamWidth,
                           QObject::trUtf8("CheckBeamWidth"), double(0), false,
                           Variant::TOXML);
    
    //Kerf 参数
    m_Variants.add_Variant(Var_Process_KerfParm_LightDirect,
                           QObject::trUtf8("KerfParmLightCoaxial"), int(200), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_KerfParm_LightCircle,
                           QObject::trUtf8("KerfParmLightRing"), int(50), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_KerfParm_Exposure,
                           QObject::trUtf8("KerfParmLightExposure"), int(7000), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_KerfParm_Gain,
                           QObject::trUtf8("KerfParmLightGain"), int(0), false,
                           Variant::TOXML);

    //参数
    m_Variants.add_Variant(Var_Process_KerfParm_MaxRange,
                           QObject::trUtf8("LaserKerfMaxRange"), double(0.15), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_KerfParm_MinRange,
                           QObject::trUtf8("LaserKerfMinRange"), double(0), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_KerfParm_MaxWidth,
                           QObject::trUtf8("LaserKerfMaxWidth"), double(0.05), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_KerfParm_MinWidth,
                           QObject::trUtf8("LaserKerfMinWidth"), double(0.005), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_KerfParm_MinOffset,
                           QObject::trUtf8("LaserKerfMinOffset"), double(0.001), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_KerfParm_MaxOffset,
                           QObject::trUtf8("LaserKerfMaxOffset"), double(0.003), false,
                           Variant::TOXML);


    m_Variants.add_Variant(Var_Process_KerfParm_PixelThreshold,
                           QObject::trUtf8("LaserKerfMaxThreshold"), int(145), false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_KerfParm_BinThresold,
                           QObject::trUtf8("LaserKerfMaxBinThreshold"), double(185), false,
                           Variant::TOXML);

    //Wafer总长度 68mm 其中5mm是中间的不能用的地方
    //每个矩形是30mm*30mm 
    m_imageContainer[0] = nullptr;
    m_imageContainer[1] = nullptr;

    m_iKerfCamID = CAM6X;
    m_vKerfParam.resize(1);

    if (m_iID == PROCESS_LASERKERF_D_WIDE)
    {
        m_iLaserPathId = LASERPATH_D_WIDE;
    }
    else
    {
        m_iLaserPathId = LASERPATH_L_NARROW;
    }

    m_sTittleName = _SysExt_Instance.m_mapNameList[m_iLaserPathId] + QObject::trUtf8("Laser Cali");
}

int CProcess_LaserKerf::CalcuKerfPos(double& dStartPosX, double& dEndPosX, double& dPosY)
{

    CJigDriver* pJigDriver = GET_CARD(JigDriver, CJigDriver);

    QReadLocker l(&pJigDriver->m_Lock);
    if (pJigDriver->m_iCurPosIdx >= pJigDriver->m_MarkListTopLeft.size())
    {
        //没有区域可供划线了，请更换
        MQT_THROW_CODESTR(ALARM_MAIN_LASERCALI_ERROR, m_sTittleName + (QObject::trUtf8("Laser Cali") + QObject::trUtf8("No area available to cutline, please replace the check wafer")));
    }

    CMWorkTableDriver* pWorktableDriver = GET_CARD(WORKTABLE_DRIVER, CMWorkTableDriver);
    Q_ASSERT(pWorktableDriver);


    _Mark_Area markArea = pJigDriver->m_MarkListTopLeft[pJigDriver->m_iCurPosIdx];
    double dCenterX = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_AreaCenterX)->toDouble();
    double dCenterY = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_AreaCenterY)->toDouble();

    double posX = dCenterX + markArea.ptLeftTop.tX - markArea.dWidth / 2;
    double posY = dCenterY + markArea.ptLeftTop.tY + markArea.dStep * markArea.iLineIndex;
    pJigDriver->m_dFocusOffset = markArea.bFocused ? markArea.dFocusOffset : 0;


    //MqDebug() << "Calc Laser Cali Pos: CellIndex:" << markArea.iCellIndex << ",LineIndex;"<<markArea.iLineIndex;
    //MqDebug() << markArea.toString().c_str();

    //m_iCurPosIdx+=1;
    //if(m_iCurPosIdx>45)m_iCurPosIdx = 0;
    if (pJigDriver->m_iCurPosIdx >= pJigDriver->m_MarkListTopLeft.size())
    {
        pJigDriver->m_iCurPosIdx = 0;
    }

    l.unlock();

    double dKerfWidth = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_LineLength)->toDouble();
    //高倍相机看到时，坐标的位置
    double halfLineLength = dKerfWidth / 2;
    double posStart = posX + halfLineLength;

    CMPointd axisStart(posStart, posY);
    CMPointd wtStart;
    pWorktableDriver->AxisToWt(m_iKerfCamID, axisStart, wtStart);
    dStartPosX = wtStart.tX;
    dEndPosX = wtStart.tX + dKerfWidth;
    dPosY = wtStart.tY;

    m_CheckPos.tX = wtStart.tX + halfLineLength;
    m_CheckPos.tY = wtStart.tY;

    //m_bHasSet=false;
    return 0;
}

int CProcess_LaserKerf::MoveKerfPos()
{
    CJigDriver* pJigDriver = GET_CARD(JigDriver, CJigDriver);
    CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER, CMWorkTableDriver);
    Q_ASSERT(pWorkTableDriver);
    _SysExt_Instance.changeChannel(m_iKerfCamID, false);
    CMPointd Axis;
    pWorkTableDriver->WtToAxis(m_iKerfCamID, m_CheckPos, Axis);
    _SysExt_Instance.absmove_xy(Axis.tX, Axis.tY);

    //Z轴做一个偏移，相机偏移到焦点位置
    double dFocus = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_ZFocusThickness)->toDouble();
    dFocus += pJigDriver->m_dFocusOffset + 0.04;
    pWorkTableDriver->MoveToDeFoucsPos(m_iKerfCamID, dFocus);
    return RTN_SUCCESS1;
}

int CProcess_LaserKerf::Kerf(int iSideID, int iLayerID)
{
    m_KerfTime.StartTime();
    SetKerfLight();

    MSleep(m_Variants.get_VData(Var_Process_Kerf_BeforeSearchSleep_ID)->toInt());

    QString str = QObject::trUtf8("Laser Check Before");
    CaptureImage(iSideID, str);
    SetKerfParam();

    MSleep(m_Variants.get_VData(Var_Process_Kerf_AfterSearchSleep_ID)->toInt());

    CCam* pCam = GET_CHDIRECT(m_iKerfCamID, CCam);
    pCam->m_imageContainer.clearShape(-1);
    pCam->m_imageContainer.clearString(-1);

    SearchLine(m_Variants.get_VData(Var_Process_Kerf_EnableAutoThres_ID)->toBool());

    MSleep(m_Variants.get_VData(Var_Process_Kerf_AfterSearchSleep_ID)->toInt());

    int index = iSideID == SIDE_B ? 1 : 0;
    CAKerfCheck_H* pAKerf = (CAKerfCheck_H*)pCam->Find_Algorithm(M_KERFCHECK);
    Q_ASSERT(pAKerf);
    pAKerf->showresult(m_imageContainer[index]);
    //pAKerf->showragion_static(&m_imageContainer[index]);

    //AnalyseKerfResult(  iSideID,   iLayerID, &m_imageContainer[index]);
    AnalyseKerfResult(iSideID, iLayerID, &pCam->m_imageContainer);

    m_KerfTime.StopTime();
    return 0;
}

void CProcess_LaserKerf::AnalyseKerfResult(int iSideID, int iLayerID, CImageContainer* pContainer)
{
    KERFPARAM* pKerfParam = GetKerfParam();
    int iSizeResult = VectorResult.size();
    if (iSizeResult != pKerfParam->iLineCount * 2)
    {
        MQT_THROW_CODESTR(ALARM_MAIN_LASERCALI_ERROR, (m_sTittleName + QObject::trUtf8("Can not Locate Each Cut Line")));
    }

    double dRealOffset = 0, dRealHeight = 0, dRealHeight1 = 0, dRealGAP = 0;
    GetKerfResult(dRealOffset, dRealHeight, dRealHeight1, dRealGAP);

    if (fabs(dRealOffset) > pKerfParam->dOffsetMax)
    {
        MQT_THROW_CODESTR(ALARM_MAIN_LASERCALI_ERROR, (m_sTittleName + QObject::trUtf8("Laser Cail err. Offset: %1>Max Offset:%2")
                          .arg(dRealOffset, 0, 'f', 4)
                          .arg(pKerfParam->dOffsetMax, 0, 'f', 4)));
    }
    if (iSizeResult == 2)
    {
        if (dRealHeight > pKerfParam->dWidthMax)
        {
            MQT_THROW_STR(m_sTittleName + QObject::trUtf8("Laser Cali err. Line "
                          "Width: %1>Max Line Width:%2")
                          .arg(dRealHeight, 0, 'f', 3)
                          .arg(pKerfParam->dWidthMax, 0, 'f', 3));
        }
        if (dRealHeight < pKerfParam->dWidthMin)
        {
            MQT_THROW_STR(m_sTittleName + QObject::trUtf8("Laser Cali err.  Line "
                          "Width: %1<Min Line Width:%2")
                          .arg(dRealHeight, 0, 'f', 3)
                          .arg(pKerfParam->dWidthMin, 0, 'f', 3));
        }
    }
    else
    {
        Q_ASSERT(0);
    }
    CaptureImage(iSideID, m_sTittleName);
    ShowKerfResult(dRealOffset, dRealHeight, dRealHeight1,
                   dRealGAP, pContainer);

    int index = iSideID == SIDE_B ? 1 : 0;
    ShowKerfResult(dRealOffset, dRealHeight, dRealHeight1,
                   dRealGAP, m_imageContainer[index]);

    if (fabs(dRealOffset) > pKerfParam->dOffsetMin)
    {
        //如果偏移超过阈值，则自动校正刀痕
        CMPointd WPDP = m_CheckPos;
        WPDP.tY += dRealOffset;
        bool bEnableOffset = true;
        if (_SysExt_Instance.m_bDisableHairlineOffsetAutoCompensation)
             bEnableOffset = false;

        SetHairLineOffset(WPDP, bEnableOffset);
    }

    QString str = QObject::trUtf8("TM:%1,CH:%2,Laser Offset:%4,Height:%4")
        .arg(m_KerfTime.FormatTime())
        .arg(iLayerID)
        .arg(dRealOffset)
        .arg(dRealHeight);
    _SysExt_Instance.EvtLog(QString::fromUtf8("KERF(Cali)"), str);
}

int CProcess_LaserKerf::CalcuMeasurePos(double& dStartPosX, double& dEndPosX, double& dPosY, int iCellIndex/*=-1*/)
{
    CJigDriver* pJigDriver = GET_CARD(JigDriver, CJigDriver);
    QReadLocker l(&pJigDriver->m_Lock);
    if (iCellIndex <= 0)
        iCellIndex = pJigDriver->m_iCurPosIdx;

    if (iCellIndex >= pJigDriver->m_MarkListTopLeft.size())
    {
        //没有区域可供划线了，请更换
        MQT_THROW_CODESTR(ALARM_MAIN_LASERCALI_ERROR, (m_sTittleName + QObject::trUtf8("No area available to cutline, please replace the check wafer")));
    }

    CMWorkTableDriver* pWorktableDriver = GET_CARD(WORKTABLE_DRIVER, CMWorkTableDriver);
    Q_ASSERT(pWorktableDriver);

    _Mark_Area markArea = pJigDriver->m_MarkListTopLeft[iCellIndex];
    double dCenterX = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_AreaCenterX)->toDouble();
    double dCenterY = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_AreaCenterY)->toDouble();
    double posX = dCenterX + markArea.ptLeftTop.tX - markArea.dWidth / 2;
    double posY = dCenterY + markArea.ptLeftTop.tY + markArea.dStep * markArea.iReservedIndex;
    l.unlock();

    double dKerfWidth = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_LineLength)->toDouble();
    //高倍相机看到时，坐标的位置
    double halfLineLength = dKerfWidth / 2;
    double posStart = posX + halfLineLength;

    CMPointd axisStart(posStart, posY);
    CMPointd wtStart;
    pWorktableDriver->AxisToWt(m_iKerfCamID, axisStart, wtStart);
    dStartPosX = wtStart.tX;
    dEndPosX = wtStart.tX + dKerfWidth;
    dPosY = wtStart.tY;

    m_CheckPos.tX = wtStart.tX + halfLineLength;
    m_CheckPos.tY = wtStart.tY;

    //此时没有偏移
    pJigDriver->m_dFocusOffset = 0;

    return 0;
}



int CProcess_LaserKerf::SetKerfPosManual(int iSideID)
{
    CMPointd WPDP;
    CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER,
                                                   CMWorkTableDriver);
    Q_ASSERT(pWorkTableDriver);
    pWorkTableDriver->CurAxisToWt(m_iKerfCamID, WPDP, true);


    double dOffset = SetHairLineOffset(WPDP, true);
    QString str = m_sTittleName + QObject::trUtf8("Manual Laser Cali Offset:%1mm").arg(dOffset, 0, 'f', 3);
    _SysExt_Instance.EvtLog(QObject::tr("OP"), str);
    CaptureImage(iSideID, str);
    //m_bHasSet=true;
    return 0;
}

void CProcess_LaserKerf::CaptureImage(int iSideID, QString& str)
{
    UNUSED(iSideID);
    CCamDriver* pCamDriver = GET_CARD(CAM_DRIVER, CCamDriver);
    Q_ASSERT(pCamDriver);
    int index = iSideID == SIDE_B ? 1 : 0;
    CImageContainer* pContainer = m_imageContainer[index];
    pContainer->SetName(m_sTittleName);

    pContainer->clearString(-1);
    pContainer->clearShape(-1);

    CMImage img;
    pCamDriver->grab_image(m_iKerfCamID, &img);
    pContainer->SetImage(img, false);

    if (!str.isEmpty())
    {
        pContainer->addString(str);
    }

    _SysExt_Instance.SetCutStreet(pContainer, iSideID, m_iKerfCamID);

}

void CProcess_LaserKerf::TestKerf()
{
    MoveKerfPos();
    SetKerfParam();
    SearchLine(false);
}

void CProcess_LaserKerf::ClearContainer()
{
    m_imageContainer[0]->ClearImage();
    m_imageContainer[1]->ClearImage();
}

int32_t CProcess_LaserKerf::init_Process()
{
    /*CProcess_Level* processKerf =  GET_PROCESS(PROCESS_LEVELING, SM_MAIN, CProcess_Level);

    m_imageContainer[0] = &processKerf->m_imageContainerAlign[0][1];
    m_imageContainer[1] = &processKerf->m_imageContainerAlign[1][1];*/
    CJigDriver* pJigDriver = GET_CARD(JigDriver, CJigDriver);
   /* CProcess_Level* processLevel = GET_PROCESS(PROCESS_LEVELING, SM_MAIN, CProcess_Level);

    m_imageContainer[0] = &processLevel->m_imageContainerBase[0];
    m_imageContainer[1] = &processLevel->m_imageContainerBase[1];*/


#ifdef __SIMULATOR__
    QWriteLocker l(&m_Lock);
    InitalPosVector(m_MarkListTopLeft, m_iCurPosIdx);
    l.unlock();

    LoadMarkData(false);
    SaveCutData(true);
#endif // __SIMULATOR__
    //加载配置参数
    pJigDriver->LoadMarkData(true);
    pJigDriver->SaveCutData(false);
    try
    {
        double dStartPosX = 0;
        double dEndPosX = 0;
        double dPosY = 0;
        CalcuKerfPos(dStartPosX, dEndPosX, dPosY);
    }
    catch (const QString& ex)
    {
        m_CheckPos.tX = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_AreaCenterX)->toDouble();
        m_CheckPos.tY = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_AreaCenterY)->toDouble();;
    }

    return CMProcess::init_Process();
}

void CProcess_LaserKerf::SetContainer(CImageContainer* pContainer1, CImageContainer* pContainer2)
{
    m_imageContainer[0] = pContainer1;
    m_imageContainer[1] = pContainer2;
}

void CProcess_LaserKerf::SetKerfParam()
{
    CCam* pCam = GET_CHDIRECT(m_iKerfCamID, CCam);
    Q_ASSERT(pCam);
    CAKerfCheck_H* pAKerf = (CAKerfCheck_H*)pCam->Find_Algorithm(M_KERF_LASER);
    Q_ASSERT(pAKerf);
    KERFPARAM* pKerfParam = &m_vKerfParam[0]; 
    int iThreshold = pKerfParam->iPixelThres;
    double dResolutionY = pCam->m_CoordTrans.m_dresolution_Y;
    if (DEQUAL0(dResolutionY))
    {
        MQT_THROW_CODESTR(ALARM_MAIN_LASERCALI_ERROR, (m_sTittleName + (QObject::trUtf8("Kerf process err. "
                          "Cam resolution equal 0"))));
    }

    m_Variants.get_VData(Var_Process_KerfParm_LightDirect)->setValue(pKerfParam->iLight1);
    m_Variants.get_VData(Var_Process_KerfParm_LightCircle)->setValue(pKerfParam->iLight2);
    m_Variants.get_VData(Var_Process_KerfParm_Exposure)->setValue(pKerfParam->iExposure);
    m_Variants.get_VData(Var_Process_KerfParm_Gain)->setValue(pKerfParam->iGain);

    m_Variants.get_VData(Var_Process_KerfParm_MinRange)->setValue(pKerfParam->dRangeMin);
    m_Variants.get_VData(Var_Process_KerfParm_MaxRange)->setValue(pKerfParam->dRange);
    m_Variants.get_VData(Var_Process_KerfParm_MinWidth)->setValue(pKerfParam->dWidthMin);
    m_Variants.get_VData(Var_Process_KerfParm_MaxWidth)->setValue(pKerfParam->dWidthMax);
    m_Variants.get_VData(Var_Process_KerfParm_MinOffset)->setValue(pKerfParam->dOffsetMin);
    m_Variants.get_VData(Var_Process_KerfParm_MaxOffset)->setValue(pKerfParam->dOffsetMax);

    m_Variants.get_VData(Var_Process_KerfParm_PixelThreshold)->setValue(pKerfParam->iPixelThres);
    m_Variants.get_VData(Var_Process_KerfParm_BinThresold)->setValue(pKerfParam->iBinaryThres);

    int iRange = pKerfParam->dRange / dResolutionY;
    int iRangeMin = pKerfParam->dRangeMin / dResolutionY;

    int iMinLength = pKerfParam->dWidthMin / dResolutionY;
    int iMaxLength = pKerfParam->dWidthMax / dResolutionY;
    pAKerf->m_Variants.get_VData(Var_KerfCheck_H_Rangemax)->setValue(iRange);
    pAKerf->m_Variants.get_VData(Var_KerfCheck_H_Rangemin)->setValue(iRangeMin);
    pAKerf->m_Variants.get_VData(Var_KerfCheck_H_Threshold)->setValue(iThreshold);
    pAKerf->m_Variants.get_VData(Var_KerfCheck_H_Minlength)->setValue(iMinLength);
    pAKerf->m_Variants.get_VData(Var_KerfCheck_H_Maxlength)->setValue(iMaxLength);
    pAKerf->m_Variants.get_VData(Var_KerfCheck_H_Direct_x)->setValue(true);

}


void CProcess_LaserKerf::do_msg(int iID, QVariantList& vlInput, V_MsgOutput* pvlOutput)
{
    int32_t isize = vlInput.size();
    switch (iID)
    {
        case CALCUKERFPOS:
            if (isize >= 3)
            {
                double dStartPosX = 0;
                double dEndPosX = 0;
                double dPosY = 0;
                CalcuKerfPos(dStartPosX, dEndPosX, dPosY);
            }
            break;
        case MOVEKERFPOS:
            if (isize >= 0)
            {
                MoveKerfPos();
            }
            break;
        case KERF:
            if (isize >= 2)
            {
                Kerf(vlInput[0].toInt(),
                     vlInput[1].toInt());
            }
            break;
        case TESTKERF:
            if (isize >= 2)
            {
                TestKerf();
            }
            break;
        case SETKERFPOSMANUAL:
            if (isize >= 2)
            {
                SetKerfPosManual(vlInput[0].toInt());
            }
            break;
        case CUTKERFLINE:
            if (isize >= 1)
            {
                CutKerfLine(vlInput[0].toInt());
            }
            break;
        case MEASURE_THICKNESS:
            if (isize >= 2)
            {
                MeasureThickness(vlInput[0].toInt(), vlInput[1].toBool());
            }
            break;
        case REPLACE_MARKPANEL:
            ReplaceMarkPanel();
            break;
    }
    CMProcess::do_msg(iID, vlInput, pvlOutput);
}

void CProcess_LaserKerf::Serialize(QDataStream& stream, bool bwrite, int iVersion)
{

    if (false == bwrite)
    {
        int isize = 0;
        stream >> isize;
        m_vKerfParam.resize(isize);
        QMutexLocker locker(&m_vKerfParam.mutex);
        for (int i = 0; i < isize; i++)
        {
            stream >> m_vKerfParam[i];
        }

        KERFPARAM& param = m_vKerfParam[0];
        //更新参数
        m_vKerfParam[0].iLineCount = 1;

        m_vKerfParam[0].iLight1 = m_Variants.get_VData(Var_Process_KerfParm_LightDirect)->toInt();
        m_vKerfParam[0].iLight2 = m_Variants.get_VData(Var_Process_KerfParm_LightCircle)->toInt();
        m_vKerfParam[0].iExposure = m_Variants.get_VData(Var_Process_KerfParm_Exposure)->toInt();
        m_vKerfParam[0].iGain = m_Variants.get_VData(Var_Process_KerfParm_Gain)->toInt();

        m_vKerfParam[0].dRangeMin = m_Variants.get_VData(Var_Process_KerfParm_MinRange)->toDouble();
        m_vKerfParam[0].dRange = m_Variants.get_VData(Var_Process_KerfParm_MaxRange)->toDouble();
        m_vKerfParam[0].dWidthMin = m_Variants.get_VData(Var_Process_KerfParm_MinWidth)->toDouble();
        m_vKerfParam[0].dWidthMax = m_Variants.get_VData(Var_Process_KerfParm_MaxWidth)->toDouble();
        m_vKerfParam[0].dOffsetMin = m_Variants.get_VData(Var_Process_KerfParm_MinOffset)->toDouble();
        m_vKerfParam[0].dOffsetMax = m_Variants.get_VData(Var_Process_KerfParm_MaxOffset)->toDouble();

        m_vKerfParam[0].iPixelThres = m_Variants.get_VData(Var_Process_KerfParm_PixelThreshold)->toInt();
        m_vKerfParam[0].iBinaryThres = m_Variants.get_VData(Var_Process_KerfParm_BinThresold)->toInt();

        return;

    }
    else
    {
        QMutexLocker locker(&m_vKerfParam.mutex);
        int isize = m_vKerfParam.size();

        stream << isize;
        for (int i = 0; i < isize; i++)
        {
            stream << m_vKerfParam[i];
        }
    }
    return;
}
KERFPARAM* CProcess_LaserKerf::GetKerfParam()
{
    m_vKerfParam[0].iLineCount = 1;

    m_vKerfParam[0].iLight1 = m_Variants.get_VData(Var_Process_KerfParm_LightDirect)->toInt();
    m_vKerfParam[0].iLight2 = m_Variants.get_VData(Var_Process_KerfParm_LightCircle)->toInt();
    m_vKerfParam[0].iExposure = m_Variants.get_VData(Var_Process_KerfParm_Exposure)->toInt();
    m_vKerfParam[0].iGain = m_Variants.get_VData(Var_Process_KerfParm_Gain)->toInt();

    m_vKerfParam[0].dRangeMin = m_Variants.get_VData(Var_Process_KerfParm_MinRange)->toDouble();
    m_vKerfParam[0].dRange = m_Variants.get_VData(Var_Process_KerfParm_MaxRange)->toDouble();
    m_vKerfParam[0].dWidthMin = m_Variants.get_VData(Var_Process_KerfParm_MinWidth)->toDouble();
    m_vKerfParam[0].dWidthMax = m_Variants.get_VData(Var_Process_KerfParm_MaxWidth)->toDouble();
    m_vKerfParam[0].dOffsetMin = m_Variants.get_VData(Var_Process_KerfParm_MinOffset)->toDouble();
    m_vKerfParam[0].dOffsetMax = m_Variants.get_VData(Var_Process_KerfParm_MaxOffset)->toDouble();

    m_vKerfParam[0].iPixelThres = m_Variants.get_VData(Var_Process_KerfParm_PixelThreshold)->toInt();
    m_vKerfParam[0].iBinaryThres = m_Variants.get_VData(Var_Process_KerfParm_BinThresold)->toInt();

    return &m_vKerfParam[0];
}

//找线算法
void CProcess_LaserKerf::SearchLine(bool_t bAutoThres)
{
    CCam* pCam = GET_CHDIRECT(m_iKerfCamID, CCam);
    Q_ASSERT(pCam);
    CAKerfCheck_H* pAKerf = (CAKerfCheck_H*)pCam->Find_Algorithm(M_KERF_LASER);
    Q_ASSERT(pAKerf);
    KERFPARAM* pKerfParam = GetKerfParam();
    int iThreshold = pKerfParam->iPixelThres;
    int iBinaryThres = pKerfParam->iBinaryThres;
    double dResolutionY = pCam->m_CoordTrans.m_dresolution_Y;
    if (DEQUAL0(dResolutionY))
    {
        MQT_THROW_STR(m_sTittleName + QObject::trUtf8("Kerf process err. "
                      "Cam resolution equal 0"));
    }
    int iLineNum = pKerfParam->iLineCount;

    pAKerf->showragion(&pCam->m_imageContainer);

    QMutexLocker locker1(&pAKerf->m_lMorphology.mutex);
    int isizemorphology = pAKerf->m_lMorphology.size();
    if (isizemorphology)
    {
        CAMorphology* pMorphology = pAKerf->GetMorphology(CAMorphology::IMG_BINARY);
        if (pMorphology)
        {
            pMorphology->m_Variants.get_VData(Var_Morphology_Thres_ID)->setValue((double)iBinaryThres);

        }
    }
    locker1.unlock();

    CMImage Img;

    CCamDriver* pCamDriver = GET_CARD(CAM_DRIVER, CCamDriver);
    pCamDriver->grab_image(m_iKerfCamID, &Img);
    pAKerf->exe(&Img);
    pAKerf->showresult(&pCam->m_imageContainer);
    //pAKerf->showragion_static(&pCam->m_imageContainer);

    VectorResult.clear();
    int isize = pAKerf->lcenters.size();
    for (int i = 0; i < isize; i++)
    {
        VectorResult.push_back((int)pAKerf->lcenters[i].tY);
    }

    if (iLineNum == 1 && VectorResult.size() == 2)
    {
        return;
    }
    if (iLineNum == 2 && VectorResult.size() == 4)
    {
        return;
    }

    if (bAutoThres)
    {
        int iThresRange = abs(m_Variants.get_VData(Var_Process_Kerf_AutoThresRange_ID)->toInt());
        int iThresMax = min(iThreshold + iThresRange, 255);
        int iThresMin = max(iThreshold - iThresRange, 0);
        int iStep = max(abs(m_Variants.get_VData(Var_Process_Kerf_AutoThresStep_ID)->toInt()), 1);
        for (int i = iThresMax; i > iThresMin; i -= iStep)
        {
            pAKerf->m_Variants.get_VData(Var_KerfCheck_H_Threshold)->setValue(i);

            CCamDriver* pCamDriver = GET_CARD(CAM_DRIVER, CCamDriver);

            pCamDriver->grab_image(m_iKerfCamID, &Img);
            pAKerf->exe(&Img);
            pAKerf->showresult(&pCam->m_imageContainer);
            VectorResult.clear();
            int isize = pAKerf->lcenters.size();
            for (int i = 0; i < isize; i++)
            {
                VectorResult.push_back((int)pAKerf->lcenters[i].tY);
            }
            if (iLineNum == 1 && VectorResult.size() == 2)
            {
                break;
            }
            if (iLineNum == 2 && VectorResult.size() == 4)
            {
                break;
            }
        }
    }
}


void CProcess_LaserKerf::GetKerfResult(double& dRealOffset, double& dRealHeight,
                                       double& dRealHeight1, double& dRealGAP)
{
    CCam* pCam = GET_CHDIRECT(m_iKerfCamID, CCam);
    Q_ASSERT(pCam);
    int iwidth, iheight;
    pCam->GetPixelSize(iwidth, iheight);
    double dResolutionY = pCam->m_CoordTrans.m_dresolution_Y;
    if (DEQUAL0(dResolutionY))
    {
        MQT_THROW_STR(m_sTittleName + QObject::trUtf8("Kerf process err. "
                      "Cam resolution equal 0"));
    }
    double dPixelHeight = 0, dPixelGap = 0;
    CMPointd Real, Pixel;

    Pixel.tX = iwidth / 2.0;
    int iSizeResult = VectorResult.size();
    if (iSizeResult == 4)
    {
        Pixel.tY = (VectorResult[3] + VectorResult[2] + VectorResult[1] + VectorResult[0]) / 4.0;
        dPixelHeight = (VectorResult[1] - VectorResult[0]);
        dRealHeight = fabs(dPixelHeight * dResolutionY);

        dPixelHeight = (VectorResult[3] - VectorResult[2]);
        dRealHeight1 = fabs(dPixelHeight * dResolutionY);
        dPixelGap = (VectorResult[3] + VectorResult[2] - VectorResult[1] - VectorResult[0]) / 2.0;
        dRealGAP = fabs(dPixelGap * dResolutionY);
    }
    else if (iSizeResult == 2)
    {
        Pixel.tY = (VectorResult[1] + VectorResult[0]) / 2.0;
        dPixelHeight = (VectorResult[1] - VectorResult[0]);
        dRealHeight = fabs(dPixelHeight * dResolutionY);	//实际测量 切割道的高度
    }
    else
    {
        Q_ASSERT(0);

    }
    Real = pCam->DPTOLP(Pixel);
#if FILPCAM_XY
    CMPointd ptConveterd(Real.tY, Real.tX);
    ptConveterd.tY = -ptConveterd.tY;

    Real = ptConveterd;
#endif
    dRealOffset = Real.tY;
}

void CProcess_LaserKerf::ShowKerfResult(double dRealOffset, double dRealHeight,
                                        double dRealHeight1, double dRealGAP,
                                        CImageContainer* pContainer)
{
    CCam* pCam = GET_CHDIRECT(m_iKerfCamID, CCam);
    Q_ASSERT(pCam);
    int iSizeResult = VectorResult.size();
    double dPixelHeight = 0;
    double dResolutionY = pCam->m_CoordTrans.m_dresolution_Y;
    if (iSizeResult == 4)
    {
        pContainer->addString(QObject::trUtf8("Offset:%1mm")
                              .arg(dRealOffset, 0, 'f', 4));
        pContainer->addString(QObject::trUtf8("Bottom Height:%1mm")
                              .arg(dRealHeight, 0, 'f', 3));
        pContainer->addString(QObject::trUtf8("Top Height:%1mm")
                              .arg(dRealHeight1, 0, 'f', 3));
        pContainer->addString(QObject::trUtf8("Gap:%1")
                              .arg(dRealGAP, 0, 'f', 3));

        dPixelHeight = fabs(dRealGAP / dResolutionY);
    }
    else if (iSizeResult == 2)
    {
        pContainer->addString(QObject::trUtf8("Offset:%1mm")
                              .arg(dRealOffset, 0, 'f', 4));
        pContainer->addString(QObject::trUtf8("Height:%1mm")
                              .arg(dRealHeight, 0, 'f', 3));
        dPixelHeight = fabs(dRealHeight / dResolutionY);
    }
    else
    {
        Q_ASSERT(0);
    }

    CAKerfCheck_H* pAKerf = (CAKerfCheck_H*)pCam->Find_Algorithm(M_KERF_LASER);
    Q_ASSERT(pAKerf);
    pAKerf->showresult_shape(pContainer);
}


void CProcess_LaserKerf::SetKerfLight()
{
    KERFPARAM* pkerf = GetKerfParam();
    _SysExt_Instance.SetCamLight(m_iKerfCamID, pkerf->iLight1, true, false);
    _SysExt_Instance.SetCamLight(m_iKerfCamID, pkerf->iLight2, false, false);
    CCamDriver* pCamDriver = GET_CARD(CAM_DRIVER, CCamDriver);
    _SysExt_Instance.SetCamParam(m_iKerfCamID, pkerf->iExposure, pkerf->iGain);
}

double CProcess_LaserKerf::SetHairLineOffset(const CMPointd& WPDP, bool bApplyOffset)
{
    double dHairOffset = m_CheckPos.tY - WPDP.tY;

    //小于最小偏差，则不处理
    double dThreadMinOffset = m_Variants.get_VData(Var_Process_KerfParm_MinOffset)->toDouble();
    if (fabs(dHairOffset) < dThreadMinOffset)
    {
        dHairOffset = 0;
        return dHairOffset;
    }

    //允许dThreadMinOffset的偏差，如果大于dThreadMinOffset则减掉偏差值
    if (dHairOffset > 0)
    {
        dHairOffset -= dThreadMinOffset;
    }
    else
    {
        dHairOffset += dThreadMinOffset;
    }

    double dOffset = 0;
    CLaserPath* pLPath = GET_CHDIRECT(LASERPATH_L_NARROW, CLaserPath);
    Q_ASSERT(pLPath);
    double dHairOffsetThres = pLPath->m_Variants.get_VData(Var_LaserPath_HairOffsetThres_ID)->toDouble();
    double dNewOffset = 0;
    {
        pLPath->GetOffset(dOffset);
        dNewOffset = dHairOffset + dOffset;
        if (fabs(dHairOffset) > dHairOffsetThres)
        {
            MQT_THROW_STR(m_sTittleName + QObject::trUtf8("Laser Cali err. Hairline Offset: "
                          "%1>Max Offset:%2")
                          .arg(dHairOffset, 0, 'f', 3)
                          .arg(dHairOffsetThres, 0, 'f', 3));
        }
        if (true == bApplyOffset)
            pLPath->SetOffset(dNewOffset);
    }

    if (true == bApplyOffset)
    {
        m_CheckPos = WPDP;
        QString str_Offset = QObject::trUtf8("Offset:%1mm HairfOffset:%2mm to %3mm")
            .arg(dHairOffset, 0, 'f', 4).arg(dOffset, 0, 'f', 4).arg(dNewOffset, 0, 'f', 4);
        _SysExt_Instance.EvtLog(QString::fromUtf8("HA(Cali)"), str_Offset);
    }
    return dOffset;
}

//切割Kerf位置,不能单独切割，切割前要重新计算一下
int CProcess_LaserKerf::CutKerf(int iLaserPath, double dStartPosX, double dEndPosX, double dPosY, bool bMeasure/*=false*/, int iCellIndex/*=-1*/)
{
    CJigDriver* pJigDriver = GET_CARD(JigDriver, CJigDriver);
    CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER,
                                                   CMWorkTableDriver);
    Q_ASSERT(pWorkTableDriver);
    if (iCellIndex == -1)
        iCellIndex = pJigDriver->m_iCurPosIdx;
    try
    {
        CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        Q_ASSERT(pMotorDriver);

        //光路移动到设定的功率
        int laserPathId = m_iLaserPathId;
        CLaserPath* pLPath = GET_CHDIRECT(laserPathId, CLaserPath);
        Q_ASSERT(pLPath);

        CLaserPathDriver* pPathDriver = GET_CARD(LASERPATH_DRIVER, CLaserPathDriver);
        Q_ASSERT(pPathDriver);

        //TODO:参数是配置
        double dLaserPower = m_Variants.get_VData(Var_Process_LaserKerf_CheckPower)->toDouble(); //功率2W
        uint dFreq = m_Variants.get_VData(Var_Process_LaserKerf_CheckFreq)->toUInt();
        int iEpulse = m_Variants.get_VData(Var_Process_LaserKerf_CheckEpulse)->toInt();
        double dBeamWidth = m_Variants.get_VData(Var_Process_LaserKerf_CheckBeamWidth)->toDouble();
        pPathDriver->MovePathAngle(laserPathId, iEpulse, dBeamWidth, dFreq, dLaserPower);

        CMProduct* pProduct = GET_CHDIRECT(PRODUCT, CMProduct);

        double dFocus = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_ZFocusThickness)->toDouble();
        dFocus += pJigDriver->m_dFocusOffset;
        //计算激光焦距并移动到焦距位置
        double dZpos = pWorkTableDriver->DefoucsDisToZPos(laserPathId, dFocus);

        //生成起始和结束点
        double cutSpeed = m_Variants.get_VData(Var_Process_LaserKerf_Speed)->toDouble();
        double dOffsetY = pJigDriver->m_Variants.get_VData(Var_Process_LaserKerf_WorkTableYOffset)->toDouble();
        int iDelayTime = 0; //Param.iSleepTime

        try
        {
            //X轴进行切割,移动到位并且使用PEG功能划线
            //dOffsetY 为光路关联的偏移补偿
            _SysExt_Instance.CutPosX(dStartPosX, dEndPosX, dPosY, dZpos, iDelayTime,
                              laserPathId, dOffsetY, cutSpeed,
                              SIDE_A, -1, true,
                              0, true, true, true);

            if (!bMeasure)
            {
                //切割过了
                pJigDriver->PosIndexIncrease();
            }
            else
            {
                //更新测量标志
                if (false == _SysExt_Instance.m_bDisableCutlineLaser)
                {
                    pJigDriver->SetMeasureCuttedMark(iCellIndex, true);
                }
            }


            //设置默认速度
            pMotorDriver->setdefaultspeed(MOTORX);

        }
        catch (const QString& s)
        {

            //切割过了
            if (!bMeasure)
            {
                //切割过了
                pJigDriver->PosIndexIncrease();
            }

            //设置默认速度
            pMotorDriver->setdefaultspeed(MOTORX);

            throw;
        }


    }
    catch (QString& s)
    {
        throw(s);
    }
    return MSG_FINISHED;
}

int CProcess_LaserKerf::CutKerfLine(int iLaserPath)
{
    CJigDriver* pJigDriver = GET_CARD(JigDriver, CJigDriver);
    double dStartPosX = 0;
    double dEndPosX = 0;
    double dPosY = 0;
    CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER, CMWorkTableDriver);
    Q_ASSERT(pWorkTableDriver);
    _SysExt_Instance.changeChannel(m_iKerfCamID, false);
    //测量
    if (pJigDriver->IsNeedMeasureCut())
    {
        CalcuMeasurePos(dStartPosX, dEndPosX, dPosY);
        CutKerf(iLaserPath, dStartPosX, dEndPosX, dPosY, true);

        MoveKerfPos();
        pJigDriver->MeasTargetThick(pJigDriver->m_iCurPosIdx);
    }
    //重新进行测量
    if (pJigDriver->IsNeedMeasure())
    {
        CalcuMeasurePos(dStartPosX, dEndPosX, dPosY);
        MoveKerfPos();
        pJigDriver->MeasTargetThick(pJigDriver->m_iCurPosIdx);
    }


    CalcuKerfPos(dStartPosX, dEndPosX, dPosY);
    CutKerf(iLaserPath, dStartPosX, dEndPosX, dPosY);

    return 0;
}

int CProcess_LaserKerf::MeasureThickness(int iCellIndex/*=-1*/, bool bOnlyMeasure/*=false*/)
{
    CJigDriver* pJigDriver = GET_CARD(JigDriver, CJigDriver);
    double dStartPosX = 0;
    double dEndPosX = 0;
    double dPosY = 0;

    CalcuMeasurePos(dStartPosX, dEndPosX, dPosY, iCellIndex);
    if (!bOnlyMeasure && pJigDriver->IsNeedMeasureCut(iCellIndex))
    {
        CutKerf(m_iLaserPathId, dStartPosX, dEndPosX, dPosY, true, iCellIndex);
    }

    MoveKerfPos();
    pJigDriver->MeasTargetThick(iCellIndex);
    return 0;
}

int CProcess_LaserKerf::ReplaceMarkPanel()
{
    std::vector<_Mark_Area> tempVec;
    int iCurIndex = 0;
    int iTempIndex = 0;

    CJigDriver* pJigDriver = GET_CARD(JigDriver, CJigDriver);
    {
        QWriteLocker l(&pJigDriver->m_Lock);
        tempVec.swap(pJigDriver->m_MarkListTopLeft);
        iCurIndex = pJigDriver->m_iCurPosIdx;
        l.unlock();
    }


    try
    {
        pJigDriver->InitalPosVector(pJigDriver->m_MarkListTopLeft, iCurIndex);

        int size = pJigDriver->m_MarkListTopLeft.size();
        int iStep = size / 4;
        int iIndex = iStep / 2;
        for (int i = 0; i < 4; i++)
        {
            MeasureThickness(iIndex, false);
            iIndex += iStep;
        }

    }
    catch (const QString& ex)
    {
        //恢复
        QWriteLocker l(&pJigDriver->m_Lock);
        pJigDriver->m_MarkListTopLeft.clear();
        pJigDriver->m_MarkListTopLeft.swap(tempVec);
        MQT_THROW_STR(ex);
        return -1;
    }

    {
        QWriteLocker l(&pJigDriver->m_Lock);
        pJigDriver->m_iCurPosIdx = iCurIndex;
        l.unlock();
    }

    pJigDriver->SaveCutData(true);
    pJigDriver->LoadMarkData(false);
    return 0;
}
