#include "cprocess_kerf.h"
#include "logic.h"
#include "cproductside.h"
#include "cmproduct.h"
#include "cprocess_level.h"
#include "cmproduct.h"
#include "cmworktabledriver.h"
#include "cakerfcheck_h.h"
#include "claserpathdriver.h"
CProcess_Kerf::CProcess_Kerf(const QString &name, int32_t id)
    :CMProcess(name,id)
{
    m_Variants.add_Variant(Var_Process_Kerf_BeforeSearchSleep_ID,
                           QObject::trUtf8("BeforeSearchSleep"),int(200),false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Kerf_AfterSearchSleep_ID,
                           QObject::trUtf8("AfterSearchSleep"),int(200),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(50),false,
                           Variant::TOXML);
    m_Variants.add_Variant(Var_Process_Kerf_AutoThresStep_ID,
                           QObject::trUtf8("AutoThresStep"),int(1),false,
                           Variant::TOXML);

    m_Variants.add_Variant(Var_Process_Kerf_EnableAutoCompensation,
                           QObject::trUtf8("EnableAutoCompensation"), bool(false), false,
                           Variant::TONONE);
    
    m_imageContainer[0].name=QObject::trUtf8("Kerf A Side");
    m_imageContainer[1].name=QObject::trUtf8("Kerf B Side");
    m_iKerfCamID=CAM6X;
	m_dKerfPower = 1.5;
	m_dKerfWidth = 2;
}
int CProcess_Kerf::CalcuKerfPos(int iSideID, int iLineID, int iLayerID)
{
    if (iSideID!=SIDE_A&&iSideID!=SIDE_B)
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Side"));
    }
    CProductSide* pSide=GET_CHDIRECT(iSideID,CProductSide);
    int iSize=pSide->m_vCutParam.size();
    if (OUTOFRANGE(iLayerID,0,iSize))
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Layer"));
    }
    int iSizeLine=pSide->m_CutLineVector.size();
    if (OUTOFRANGE(iLineID,0,iSizeLine))
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Line"));
    }
    const CUTLINE* pLine=pSide->GetCutLine(iLineID);

    KERFPARAM* pKerfParam=GetKerfParam(iSideID,iLayerID);
    const SINGLECUTPARAM& cutparam=pSide->m_vCutParam[iLayerID];
    double dPosOffset=cutparam.dKerfOffset;
    //mparams[PosOffset]->getDataDirect();
    if (pKerfParam->ikerfPos==SIDE_KERF)
    {
        //		CCam* pCam=GET_CHDIRECT(m_iKerfCamID,CCam);
        //		double  width,height;
        //		pCam->GetRealSize(width,height);

		//过切的起点，加偏移
        m_CheckPos.tX=pLine->m_WPPair.ptPostive.tX-
                pSide->m_vCutParam[iLayerID].dOvercut+dPosOffset;
        m_CheckPos.tY=pLine->m_BasePt.tY;
    }
    else if(pKerfParam->ikerfPos==CENTER_KERF)
    {
		//中心位置加偏移
        m_CheckPos.tX=pLine->m_BasePt.tX+dPosOffset;
        m_CheckPos.tY=pLine->m_BasePt.tY;
    }
    else if(pKerfParam->ikerfPos == SPEC_KERF)
    {
        //hack:特定位置如何计算来的
		//设定时=当前位置-中心点的偏移，可正可负
        double dKerflengX=pKerfParam->dSpecKerfPos;
        double dKerflengY=pLine->m_BasePt.tY-pSide->m_realCenter.tY;

        CMProduct* pProduct=GET_CHDIRECT(PRODUCT,CMProduct);
        double dDiameter=pProduct->m_Variants.get_VData(Var_Product_Diameter_ID)
                ->toDouble();
        if(sqrtf(pow(dKerflengX,2)+pow(dKerflengY,2))>dDiameter/2)
        {
            m_bHasSet=true;
            return 0;
        }
        m_CheckPos.tX=pKerfParam->dSpecKerfPos+pSide->m_realCenter.tX;
        m_CheckPos.tY=pLine->m_BasePt.tY;
    }
    m_bHasSet=false;
    return 0;
}

int CProcess_Kerf::CalcuKerfPos1( double dX, double dY,int iSideID, int iLayerID)
{
    if (iSideID!=SIDE_A&&iSideID!=SIDE_B)
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Side"));
    }
    CProductSide* pSide=GET_CHDIRECT(iSideID,CProductSide);
    int iSize=pSide->m_vCutParam.size();
    if (OUTOFRANGE(iLayerID,0,iSize))
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Layer"));
    }

    const SINGLECUTPARAM& cutparam=pSide->m_vCutParam[iLayerID];
    double dPosOffset=cutparam.dKerfOffset;
    //  =mparams[PosOffset]->getDataDirect();

    m_CheckPos.tX=dX-
            pSide->m_vCutParam[iLayerID].dKerfExpand+dPosOffset;
    m_CheckPos.tY=dY;
    m_bHasSet=false;
    return 0;
}

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

	//TODO:Z轴做一个偏移，以方便Kerf检查

    return 0;
}

int CProcess_Kerf::Kerf(int iSideID, int iLayerID )
{
	if(m_bHasSet){
		m_bHasSet = false;
		return 0;
	}

    m_KerfTime.StartTime();
    SetKerfLight(iSideID,iLayerID);
    MSleep(m_Variants.get_VData(Var_Process_Kerf_BeforeSearchSleep_ID)->toInt());

    QString str=QObject::trUtf8("Kerf Before");
    CaptureImage(iSideID,iLayerID,str);
    SetKerfParam(iSideID,iLayerID);
	CCam* pCam=GET_CHDIRECT(m_iKerfCamID,CCam);
    pCam->m_imageContainer.clearShape(-1);
    pCam->m_imageContainer.clearString(-1);

    SearchLine(iSideID, iLayerID,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_A?0:1;

	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;
}

int CProcess_Kerf::KerfWatch(int iSideID, int iLayerID)
{
	m_KerfTime.StartTime();
	SetKerfLight(iSideID,iLayerID);
	MSleep(m_Variants.get_VData(Var_Process_Kerf_BeforeSearchSleep_ID)->toInt());

	QString str=QObject::trUtf8("Kerf Watch");
	CaptureImage(iSideID,iLayerID,str);

	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);

	//TODO:显示线
	pCam->SetHairLineToImageContainer(0, true);

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

	m_KerfTime.StopTime();
	return 0;
}

void CProcess_Kerf::AnalyseKerfResult(int iSideID, int iLayerID, CImageContainer* pContainer)
{
    KERFPARAM* pKerfParam=GetKerfParam(iSideID,iLayerID);
    int iSizeResult=VectorResult.size();
    if (iSizeResult!=pKerfParam->iLineCount*2)
    {
        MQT_THROW_CODESTR(ALARM_MAIN_KERF_ERROR, 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_KERF_ERROR, QObject::trUtf8("Kerf err. Offset: %1>Max Offset:%2")
                      .arg(dRealOffset,0,'f',4)
                      .arg(pKerfParam->dOffsetMax,0,'f',4));
    }
    if (iSizeResult==4)
    {
        if (dRealHeight>pKerfParam->dWidthMax)
        {
            MQT_THROW_STR(QObject::trUtf8("Kerf err. Left 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(QObject::trUtf8("Kerf err. Left Line "
                                          "Width: %1<Min Line Width:%2")
                          .arg(dRealHeight,0,'f',3)
                          .arg(pKerfParam->dWidthMin,0,'f',3));
        }
        if (dRealHeight1>pKerfParam->dWidthMax)
        {
            MQT_THROW_STR(QObject::trUtf8("Kerf err. Right Line "
                                          "Width: %1>Max Line Width:%2")
                          .arg(dRealHeight1,0,'f',3)
                          .arg(pKerfParam->dWidthMax,0,'f',3));
        }
        if (dRealHeight1<pKerfParam->dWidthMin)
        {
            MQT_THROW_STR(QObject::trUtf8("Kerf err. Right Line "
                                          "Width: %1<Min Line Width:%2")
                          .arg(dRealHeight1,0,'f',3)
                          .arg(pKerfParam->dWidthMin,0,'f',3));
        }
		//GAP为两条线的距离 Low-K时需要
        if (dRealGAP>pKerfParam->dGAPMax)
        {
            MQT_THROW_STR(QObject::trUtf8("Kerf err. GAP: %1>Max GAP:%2")
                          .arg(dRealGAP,0,'f',3)
                          .arg(pKerfParam->dGAPMax,0,'f',3));
        }
        if (dRealGAP<pKerfParam->dGAPMin)
        {
            MQT_THROW_STR(QObject::trUtf8("Kerf err. GAP: %1<Min GAP:%2")
                          .arg(dRealGAP,0,'f',3)
                          .arg(pKerfParam->dGAPMin,0,'f',3));
        }

    }
    else if (iSizeResult==2)
    {
        if (dRealHeight>pKerfParam->dWidthMax)
        {
            MQT_THROW_CODESTR(ALARM_MAIN_KERF_ERROR, QObject::trUtf8("Kerf 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_CODESTR(ALARM_MAIN_KERF_ERROR, QObject::trUtf8("Kerf 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,iLayerID,QString());
    ShowKerfResult( dRealOffset, dRealHeight , dRealHeight1 ,
                        dRealGAP,pContainer);

	int index=iSideID==SIDE_A?0:1;
	ShowKerfResult( dRealOffset, dRealHeight , dRealHeight1 ,
		dRealGAP,&m_imageContainer[index]);
    if(fabs(dRealOffset)>pKerfParam->dOffsetMin )
    {
		//如果偏移超过阈值，则自动校正刀痕
        CMPointd WPDP=m_CheckPos;
        WPDP.tY+=dRealOffset;
		bool bEnableOffset = true;
		if(m_gSystem.m_bDisableHairlineOffsetAutoCompensation)
			bEnableOffset = false;
        SetHairLineOffset(  iSideID,   iLayerID,  WPDP, bEnableOffset);
      }

    QString str=QObject::trUtf8("TM:%1,CH:%2,Offset:%3,Height:%4")
            .arg(m_KerfTime.FormatTime())
            .arg(iSideID==SIDE_A?1:2)
            .arg(dRealOffset)
            .arg(dRealHeight);
    m_gSystem.EvtLog(QString::fromUtf8("KERF"),str);
}

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

    double dOffset=SetHairLineOffset(  iSideID,   iLayerID,  WPDP, true, true);
    QString str=QObject::trUtf8("Manual Kerf Offset:%1mm").arg(dOffset,0,'f',3);
    CaptureImage(  iSideID,  iLayerID,str);
    m_bHasSet=true;
    return 0;
}

void CProcess_Kerf::CaptureImage(int iSideID,int iLayerID,QString& str)
{
    UNUSED(iSideID);
    UNUSED(iLayerID);
    CCamDriver* pCamDriver=GET_CARD(CAM_DRIVER,CCamDriver);
    Q_ASSERT(pCamDriver);
    int index=iSideID==SIDE_A?0:1;
    CImageContainer* pContainer=&m_imageContainer[index];
    pContainer->clearString(-1);
    pContainer->clearShape(-1);
	//{
	//	//TODO:这里不加锁，显示界面的时候图像内存错误
	//	QMutexLocker l(&pContainer->mutex);
	//	pCamDriver->grab_image(m_iKerfCamID,
 //                          &pContainer->m_Image);
	//}
	CMImage img;
	pCamDriver->grab_image(m_iKerfCamID, &img);
    pContainer->SetImage(img, false);
	
    if(!str.isEmpty())
    {pContainer->addString(str);}

    m_gSystem.SetCutStreet(pContainer,iSideID,m_iKerfCamID);

}

void CProcess_Kerf::TestKerf(int iSideID, int iLayerID)
{
    MoveKerfPos();
    SetKerfParam(iSideID,iLayerID);
    SearchLine(  iSideID,   iLayerID,false);
}

void CProcess_Kerf::ClearContainer()
{
    m_imageContainer[0].ClearImage();
    m_imageContainer[1].ClearImage();
}

void CProcess_Kerf::SetKerfParam(int iSideID,int iLayerID)
{
    CCam* pCam=GET_CHDIRECT(m_iKerfCamID,CCam);
    Q_ASSERT(pCam);
    CAKerfCheck_H* pAKerf=(CAKerfCheck_H*)pCam->Find_Algorithm(M_KERFCHECK);
    Q_ASSERT(pAKerf);
    KERFPARAM *pKerfParam=  GetKerfParam(  iSideID,   iLayerID);
    int iThreshold=pKerfParam->iPixelThres;
    double dResolutionY=pCam->m_CoordTrans.m_dresolution_Y;
    if(DEQUAL0(dResolutionY))
    {
        MQT_THROW_CODESTR(ALARM_MAIN_KERF_PARAM, QObject::trUtf8("Kerf process err. "
                                      "Cam resolution equal 0"));
    }
    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_Kerf::do_msg(int iID, QVariantList &vlInput, V_MsgOutput *pvlOutput)
{
    int32_t isize=vlInput.size();
    switch(iID)
    {
    case CALCUKERFPOS:
        if(isize>=3)
        {
            CalcuKerfPos(vlInput[0].toInt(),
                    vlInput[1].toInt(),vlInput[2].toInt());
        }
        break;
    case CALCUKERFPOS1:
        if(isize>=4)
        {
            CalcuKerfPos1(vlInput[0].toDouble(),vlInput[1].toDouble(),
                    vlInput[2].toInt(),vlInput[3].toInt());
        }
        break;
    case MOVEKERFPOS:
        if(isize>=0)
        {
            MoveKerfPos();
        }
        break;
    case KERF:
        if(isize>=2)
        {
            Kerf(vlInput[0].toInt(),
                    vlInput[1].toInt());
        }
        break;
	/*case KERF_CUT:
		if(isize>=2)
		{
			KerfCut(vlInput[0].toInt(),
				vlInput[1].toInt());
		}
		break;*/
	case KERF_WATCH:
		if(isize>=2)
		{
			KerfWatch(vlInput[0].toInt(),
				vlInput[1].toInt());
		}
		break;
    case SETKERFPOSMANUAL:
        if(isize>=2)
        {
            SetKerfPosManual(vlInput[0].toInt(),
                    vlInput[1].toInt());
        }
        break;
    case TESTKERF:
        if(isize>=2)
        {
            TestKerf(vlInput[0].toInt(),
                    vlInput[1].toInt());
        }
        break;
    /*case CALCCUTKERFPOSCUT:
        {
            CalcuKerfPosCut(vlInput[0].toInt(),vlInput[1].toInt(),vlInput[2].toInt());
        }
        break;
	case MOVEKKERFPOS_CUT:
		{
			MoveKerfPosCut();
		}
		break;
	case CALCANDCUTKERFLINE:
		if(isize>=3)
		{
			CalcAndCutKerfLine(vlInput[0].toInt(),
				vlInput[1].toInt(),vlInput[2].toInt());
		}
		break;*/
    }
    CMProcess::do_msg(iID, vlInput,pvlOutput);
}

void CProcess_Kerf::Serialize(QDataStream &stream, bool bwrite, int iVersion)
{
    int isize=0;
    if(bwrite)
    {
        QMutexLocker locker(&m_vKerfParam.mutex);
        isize=m_vKerfParam.size();
        stream<<isize;
        for(int i=0;i<isize;i++)
        {
            stream<<m_vKerfParam[i];
        }
    }
    else
    {
        stream>>isize;
        m_vKerfParam.resize(isize);
        QMutexLocker locker(&m_vKerfParam.mutex);
        for(int i=0;i<isize;i++)
        {
            stream>>m_vKerfParam[i];
        }

    }
}

void CProcess_Kerf::ReadRecipe(ConfigStreamReader& streamReader, int iVersion)
{
    CMProcess::ReadRecipe(streamReader, iVersion);
    streamReader.readNextStartElement();
    int iSize = streamReader.attributes().value("value").toInt();
    m_vKerfParam.resize(iSize);
    QMutexLocker locker(&m_vKerfParam.mutex);
    for (int i = 0; i < iSize; i++) {
        streamReader >> m_vKerfParam[i];
    }
    streamReader.skipCurrentElement();
}

void CProcess_Kerf::WriteRecipe(ConfigStreamWriter& streamWriter, int iVersion)
{
    CMProcess::WriteRecipe(streamWriter, iVersion);
    streamWriter.writeStartElement("kerf-count");
    int isize = m_vKerfParam.size();
    streamWriter.writeAttribute("value", QString::number(isize));
    for (int i = 0; i < isize; i++) {
        streamWriter << m_vKerfParam[i];
    }
    streamWriter.writeEndElement();
}

KERFPARAM *CProcess_Kerf::GetKerfParam(int iSideID, int iLayerID)
{
    CProductSide* pSide=GET_CHDIRECT(iSideID,CProductSide);
    Q_ASSERT(pSide);
    int iSize=pSide->m_vCutParam.size();
    if (OUTOFRANGE(iLayerID,0,iSize))
    {
		MQT_THROW_CODESTR(ALARM_MAIN_KERF_PARAM, QObject::trUtf8("Get kerf param err. In no Layer"));
    }
    int iKerfIndex=pSide->m_vCutParam[iLayerID].iKerfIndex;
    iSize=m_vKerfParam.size();
    if (OUTOFRANGE(iKerfIndex,0,iSize))
    {
        MQT_THROW_CODESTR(ALARM_MAIN_KERF_PARAM, QObject::trUtf8("Get kerf param err. In no Kerf param"));
    }
    return &m_vKerfParam[iKerfIndex];
}

//找线算法
void CProcess_Kerf::SearchLine(int iSideID, int iLayerID, bool_t bAutoThres)
{
    CCam* pCam=GET_CHDIRECT(m_iKerfCamID,CCam);
    Q_ASSERT(pCam);
    CAKerfCheck_H* pAKerf=(CAKerfCheck_H*)pCam->Find_Algorithm(M_KERFCHECK);
    Q_ASSERT(pAKerf);
    KERFPARAM *pKerfParam=  GetKerfParam(  iSideID,   iLayerID);
    int iThreshold=pKerfParam->iPixelThres;
    int iBinaryThres=pKerfParam->iBinaryThres;
    double dResolutionY=pCam->m_CoordTrans.m_dresolution_Y;
    if(DEQUAL0(dResolutionY))
    {
		MQT_THROW_CODESTR(ALARM_MAIN_KERF_PARAM, 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_Kerf::ShowKerfResult(CImageContainer* pContainer)
//{
//    CCam* pCam=GET_CHDIRECT(m_iKerfCamID,CCam);
//    Q_ASSERT(pCam);
//    CAKerfCheck_H* pAKerf=(CAKerfCheck_H*)pCam->Find_Algorithm(M_KERFCHECK);
//    Q_ASSERT(pAKerf);
//    pAKerf->showresult(pContainer);
//}

void CProcess_Kerf::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_CODESTR(ALARM_MAIN_KERF_PARAM, 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_Kerf::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',3));
        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',3));
        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_KERFCHECK);
    Q_ASSERT(pAKerf);
    pAKerf->showresult_shape(pContainer);
}


void CProcess_Kerf::SetKerfLight(int iSideID, int iLayerID)
{
    KERFPARAM *pkerf=GetKerfParam(iSideID,iLayerID);
    m_gSystem.SetCamLight(m_iKerfCamID,pkerf->iLight1,true,false);
    m_gSystem.SetCamLight(m_iKerfCamID,pkerf->iLight2,false,false);
    CCamDriver* pCamDriver=GET_CARD(CAM_DRIVER,CCamDriver);
    pCamDriver->set_cam_property(m_iKerfCamID,
                                 Var_Cam_Exposure_ID,
                                 pkerf->iExposure,
                                 false);

    pCamDriver->set_cam_property(m_iKerfCamID,
                                 Var_Cam_Gain_ID,
                                 pkerf->iGain,
                                 false);
}

double CProcess_Kerf::SetHairLineOffset(int iSideID, int iLayerID,
                                      const CMPointd &WPDP, bool bApplyOffset, bool bManualSet/*=false*/)
{
	//TODO:只检测，不做处理
	//设置BaseLine偏移
    CProductSide* pSide=GET_CHDIRECT(iSideID,CProductSide);
    Q_ASSERT(pSide);
    double dHairOffset=m_CheckPos.tY-WPDP.tY;
	if(fabs(dHairOffset) < 0.001)
	{
		dHairOffset = 0;
		return dHairOffset;
	}

    if (!bApplyOffset)
    {
        /*double dOffset = 0;

        dOffset = dHairOffset;*/
        //不做纠偏操作，只进行记录
        QString str_Offset=QObject::trUtf8("Offset:%1mm")
            .arg(dHairOffset,0,'f',4);
        m_gSystem.EvtLog(QString::fromUtf8("HA"),str_Offset);
        return dHairOffset;
    }

    double dCurHairOffset = dHairOffset;
	double dOldHairOffset = 0;
    m_CheckPos=WPDP;
    SINGLECUTPARAM& singleParam=pSide->m_vCutParam[iLayerID];
    CLaserPath* pLPath=GET_CHDIRECT(singleParam.laserpathID,CLaserPath);
    Q_ASSERT(pLPath);
    double dHairOffsetThres=pLPath->m_Variants.
            get_VData(Var_LaserPath_HairOffsetThres_ID)->toDouble();
    //if(!DEQUAL0(singleParam.dWidth)|| !DEQUAL0(singleParam.dDIndex))
    {
		pLPath->GetOffset(dOldHairOffset);
        dHairOffset+=dOldHairOffset;
        if (fabs(dHairOffset)>dHairOffsetThres)
        {
            MQT_THROW_CODESTR(ALARM_MAIN_KERF_ERROR, QObject::trUtf8("Kerf err. Hairline Offset: "
                                          "%1>Max Offset:%2")
                          .arg(dHairOffset,0,'f',3)
                          .arg(dHairOffsetThres,0,'f',3));
        }

		/*if(true == bApplyOffset)
			pLPath->SetOffset(dHairOffset);*/

    }
    
    pLPath->SetOffset(dHairOffset);
    QString str_Offset = QObject::trUtf8("Offset:%1mm,Form:%2mm,To:%3mm")
        .arg(dCurHairOffset, 0, 'f', 3)
        .arg(dOldHairOffset, 0, 'f', 3)
        .arg(dHairOffset, 0, 'f', 3);
    if (bManualSet)
    {
        str_Offset += QString::fromUtf8(",Manual");
    }
    
    m_gSystem.EvtLog(QString::fromUtf8("HA"), str_Offset);
    return dOldHairOffset;
}

#if 0
int CProcess_Kerf::CutKerf(int iSideID, int iLineID, int iLayerID,
                           double dStartPosX, double dEndPosX, double dPosY)
{
    CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER,
                                                   CMWorkTableDriver);
    Q_ASSERT(pWorkTableDriver);
    CProductSide* pProductSide = GET_CHDIRECT(iSideID, CProductSide);
    Q_ASSERT(pProductSide);
    if (iSideID != m_gSystem.m_iCurSideID)
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Cut Side :%1 not match cur side:%2")
                          .arg(m_gSystem.m_mapNameList[iSideID])
                          .arg(m_gSystem.m_mapNameList[m_gSystem.m_iCurSideID]));
    }
    try
    {
        int iSizeParam = pProductSide->m_vCutParam.size();
        if (OUTOFRANGE(iLayerID, 0, iSizeParam))return MSG_FINISHED;
        int iSizeLineVector = pProductSide->m_CutLineVector.size();
        if (OUTOFRANGE(iLineID, 0, iSizeLineVector)) return MSG_FINISHED;

        //划线的参数
        SINGLECUTPARAM Param = pProductSide->m_vCutParam[iLayerID];
        CUTLINE* pCutLine = pProductSide->GetCutLine(iLineID);
        Q_ASSERT(pCutLine);
        CMotorDriver* pMotorDriver = GET_CARD(MOTOR_DRIVER, CMotorDriver);
        Q_ASSERT(pMotorDriver);
        //检查是否开真空
        m_gSystem.AssertCheckWtVaccum();

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

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

        //TODO:参数是配置
        double dLaserPower = m_dKerfPower; //功率2W
        double dFreq = 50;
        pPathDriver->MovePathAngle(laserPathId, 0, 0, dFreq, dLaserPower);

        CMProduct* pProduct = GET_CHDIRECT(PRODUCT, CMProduct);
        //计算激光焦距并移动到焦距位置
        //切到膜上面
        double productThickness = pProduct->m_Variants.get_VData(Var_Product_Thick_ID)->toDouble();
        //设置切深为产品厚度
        double dDefoucs = pProduct->CutDepthToDefoucsDis(productThickness);
        double dZpos = pWorkTableDriver->DefoucsDisToZPos(laserPathId, dDefoucs);


        //生成起始和结束点
        //TODO:参数是配置
        //double lineLength = 2; //线长2mm
        //double targetOffset = 27+lineLength;
        //double dStartPosX=pCutLine->m_WPPair.second.tX+targetOffset; //结束位置的值要小一些，所以StartPosX > EndPosX
        //double dEndPosX= dStartPosX+lineLength;
        //double dPosY=pCutLine->m_WPPair.first.tY;

        //TODO:参数是配置
        double cutSpeed = 200;
        double dOffsetY = pCutLine->m_YOffset;
        int iDelayTime = 0;//Param.iSleepTime
        //重复多次切割,切割次数
        /*pMotorDriver->setio(IO_OUTPUT, OUT_BLUE, TRUE);
        pMotorDriver->setio(IO_OUTPUT, OUT_LENS_BLOW1, TRUE);
        pMotorDriver->setio(IO_OUTPUT, OUT_LENS_BLOW2, TRUE);
        pMotorDriver->setspeed(MOTORX,cutSpeed,0,0,0,0);*/

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

        //设置默认速度
        pMotorDriver->setdefaultspeed(MOTORX);
    }
    catch (QString& s)
    {
        throw(s);
    }
    return MSG_FINISHED;
}

int CProcess_Kerf::CalcuKerfPosCut(int iSideID, int iLineID, int iLayerID)
{
    if (iSideID != SIDE_A && iSideID != SIDE_B)
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Side"));
    }
    CProductSide* pSide = GET_CHDIRECT(iSideID, CProductSide);
    int iSize = pSide->m_vCutParam.size();
    if (OUTOFRANGE(iLayerID, 0, iSize))
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Layer"));
    }
    int iSizeLine = pSide->m_CutLineVector.size();
    if (OUTOFRANGE(iLineID, 0, iSizeLine))
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Line"));
    }
    const CUTLINE* pLine = pSide->GetCutLine(iLineID);

    KERFPARAM* pKerfParam = GetKerfParam(iSideID, iLayerID);
    const SINGLECUTPARAM& cutparam = pSide->m_vCutParam[iLayerID];
    //mparams[PosOffset]->getDataDirect();
    //移动到中心位置
    double lineLength = m_dKerfWidth; //线长2mm
    double targetOffset = cutparam.dKerfOffset + lineLength + 2;//HACK:默认添加5mm的偏移

    double dStartPosX = pLine->m_WPPair.ptNegative.tX + targetOffset; //结束位置的值要小一些，所以StartPosX > EndPosX
    double dEndPosX = dStartPosX + lineLength;
    double dPosY = pLine->m_BasePt.tY;

    m_CheckPos.tX = dStartPosX + lineLength / 2;
    m_CheckPos.tY = dPosY;

    //m_bHasSet=false;
    return 0;
}

int CProcess_Kerf::CalcAndCutKerfLine(int iSideID, int iLineID, int iLayerID)
{
    if (iSideID != SIDE_A && iSideID != SIDE_B)
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Side"));
    }
    CProductSide* pSide = GET_CHDIRECT(iSideID, CProductSide);
    int iSize = pSide->m_vCutParam.size();
    if (OUTOFRANGE(iLayerID, 0, iSize))
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Layer"));
    }
    int iSizeLine = pSide->m_CutLineVector.size();
    if (OUTOFRANGE(iLineID, 0, iSizeLine))
    {
        MQT_THROW_CODESTR(ALARM_MAIN_SAFE_PROTECT, QObject::trUtf8("Calcu kerf pos err. In no Line"));
    }
    const CUTLINE* pLine = pSide->GetCutLine(iLineID);

    KERFPARAM* pKerfParam = GetKerfParam(iSideID, iLayerID);
    const SINGLECUTPARAM& cutparam = pSide->m_vCutParam[iLayerID];
    //mparams[PosOffset]->getDataDirect();
    //移动到中心位置
    double lineLength = m_dKerfWidth; //线长2mm
    double targetOffset = cutparam.dKerfOffset + lineLength + 2;//HACK:默认添加5mm的偏移

    double dStartPosX = pLine->m_WPPair.ptNegative.tX + targetOffset; //结束位置的值要小一些，所以StartPosX > EndPosX
    double dEndPosX = dStartPosX + lineLength;
    double dPosY = pLine->m_BasePt.tY;

    m_CheckPos.tX = dStartPosX + lineLength / 2;
    m_CheckPos.tY = dPosY;

    CutKerf(iSideID, iLineID, iLayerID, dStartPosX, dEndPosX, dPosY);

    m_bHasSet = false;

    return 0;
}

int CProcess_Kerf::MoveKerfPosCut()
{
    CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER, CMWorkTableDriver);
    Q_ASSERT(pWorkTableDriver);
    m_gSystem.changeChannel(m_iKerfCamID, false);
    CMPointd Axis;
    pWorkTableDriver->WtToAxis(m_iKerfCamID, m_CheckPos, Axis);
    m_gSystem.absmove_xy(Axis.tX, Axis.tY);

    //TODO:Z轴做一个偏移，焦点偏移到膜上
    CMProduct* pProduct = GET_CHDIRECT(PRODUCT, CMProduct);
    double dTapThickness = pProduct->m_Variants.get_VData(Var_MProduct_FilmThick_ID)->toDouble();
    pWorkTableDriver->MoveToDeFoucsPos(m_iKerfCamID, dTapThickness);

    return 0;
}

int CProcess_Kerf::KerfCut(int iSideID, int iLayerID)
{
    if (m_bHasSet)
    {
        m_bHasSet = false;
        return 0;
    }

    m_KerfTime.StartTime();
    SetKerfLight(iSideID, iLayerID);
    MSleep(m_Variants.get_VData(Var_Process_Kerf_BeforeSearchSleep_ID)->toInt());

    QString str = QObject::trUtf8("Kerf Before");
    CaptureImage(iSideID, iLayerID, str);

    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(iSideID, iLayerID, 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_A ? 0 : 1;

    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;
}
#endif
/*
QDataStream &operator<<(QDataStream &out, const KERFPARAM &param)
{
    out<<param.iLineCount;
    out<<param.iPixelThres;
    out<<param.iLight1;
    out<<param.iLight2;
    out<<param.dRange;
    out<<param.dWidthMax;
    out<<param.dWidthMin;
    out<<param.dGAPMax;
    out<<param.dGAPMin;
    out<<param.dOffsetMax;
    out<<param.dOffsetMin;
    out<<param.dRangeMin;
    out<<param.ikerfPos;
    out<<param.iExposure;
    out<<param.iGain;
    out<<param.dSpecKerfPos;
    out<<param.iBinaryThres;
    return out;
}

QDataStream &operator>>(QDataStream &in, KERFPARAM &param)
{

    in>>param.iLineCount;
    in>>param.iPixelThres;
    in>>param.iLight1;
    in>>param.iLight2;
    in>>param.dRange;
    in>>param.dWidthMax;
    in>>param.dWidthMin;
    in>>param.dGAPMax;
    in>>param.dGAPMin;
    in>>param.dOffsetMax;
    in>>param.dOffsetMin;
    in>>param.dRangeMin;
    in>>param.ikerfPos;
    in>>param.iExposure;
    in>>param.iGain;
    in>>param.dSpecKerfPos;
    in>>param.iBinaryThres;

    return in;
}

ConfigStreamWriter &operator<<(ConfigStreamWriter &out, const KERFPARAM &param)
{
    out.writeStartElement("param");
    out << param.iLineCount;
    out << param.iPixelThres;
    out << param.iLight1;
    out << param.iLight2;
    out << param.dRange;
    out << param.dWidthMax;
    out << param.dWidthMin;
    out << param.dGAPMax;
    out << param.dGAPMin;
    out << param.dOffsetMax;
    out << param.dOffsetMin;
    out << param.dRangeMin;
    out << param.ikerfPos;
    out << param.iExposure;
    out << param.iGain;
    out << param.dSpecKerfPos;
    out << param.iBinaryThres;
    out.writeEndElement();
    return out;
}

ConfigStreamReader &operator >> (ConfigStreamReader &in, KERFPARAM &param)
{
    in.readNextStartElement();
    in >> param.iLineCount;
    in >> param.iPixelThres;
    in >> param.iLight1;
    in >> param.iLight2;
    in >> param.dRange;
    in >> param.dWidthMax;
    in >> param.dWidthMin;
    in >> param.dGAPMax;
    in >> param.dGAPMin;
    in >> param.dOffsetMax;
    in >> param.dOffsetMin;
    in >> param.dRangeMin;
    in >> param.ikerfPos;
    in >> param.iExposure;
    in >> param.iGain;
    in >> param.dSpecKerfPos;
    in >> param.iBinaryThres;
    in.skipCurrentElement();
    return in;
}

*/