#include "CProcess_Level_Ex.h"
#include "logic.h"
#include "cproductside.h"
#include "cmproduct.h"
#include "cprocess_level.h"
#include "cmproduct.h"
#include "cmworktabledriver.h"
#include "cworktableoffset.h"
#include "cworktableoffsetdriver.h"
CProcess_Level_Ex::CProcess_Level_Ex(const QString& name, int32_t id)
    :CProcess_Level(name, id)
{
}

CProcess_Level_Ex::~CProcess_Level_Ex()
{

}

void CProcess_Level_Ex::SetPtManual(int iSideID, int iCamID, int ptstyle, int iLineID, bool bManualSet)
{
    if(TYPE_PTBASE != ptstyle) {
        return CProcess_Level::SetPtManual(iSideID, iCamID, ptstyle, iLineID, bManualSet);
    }

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

    CImageContainer* pContainer = 0;
    int index = iSideID == SIDE_A ? 0 : 1;
    QString str;
    CMPointd wt;
    pWorktableDriver->CurAxisToWt(iCamID, wt, true);
    //X方向进行偏移
    double dOffset = wt.tX - m_AlignPtBase.Pt.tX;
    if(fabs(dOffset) > getCurSideStep(iSideID) / 2) {
        MQT_THROW_CODESTR(ALARM_MAIN_ALIGN_MANUALOFFSET_GreaterHalfIndex, QObject::trUtf8("Position set can not over half index"));
    }
    m_AlignPtBase.Pt = wt;
    m_AlignPtBase.bHasSet = true;
    calcuSideVector(iSideID, dOffset, iLineID, true);

    CProductSide* pSide = GET_CHDIRECT(iSideID, CProductSide);
    Q_ASSERT(pSide);
    pContainer = &(m_imageContainerBase[index]);
    str = QObject::trUtf8("Manual Set PtBase");

    AddProductData(QString("Manual Set PtBase  Offset:%1 Line:%2 at:%3").arg(dOffset).arg(iLineID + 1).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")));
    pSide->WriteRecoveredData();
    pSide->RecordLineData();

    CaptureImage(iCamID, pContainer, str, false);

    adjustPt(iSideID, ptstyle);
}

int32_t CProcess_Level_Ex::calcuPt(int32_t iSideID,
                                   double baseposX,
                                   double baseposY,
                                   double dStartTopPos,
                                   double dEndBottomPos)
{
    //调平缩进比例
    double dLevelParent = m_Variants.get_VData(Var_Process_Level_LevelParent)
        ->toDouble();

    //步长，使用另一面的步长
    double dStep = getOtherSideStep(iSideID);

    //某一侧找Mark最大允许找的范围
    double dLength = fabs(dEndBottomPos - dStartTopPos) * dLevelParent / 2;
    dLength = int(dLength / dStep) * dStep; //! 保证length范围内一定有整数个die

    //中点偏移die的个数
    int iMidStepOffset = m_Variants.get_VData(Var_Process_Level_MidStepOffset)
        ->toInt();

    CMPointd& LevelPt1 = m_AlignPt1.Pt;
    CMPointd& LevelPt2 = m_AlignPt2.Pt;
    CMPointd& LevelPtMid = m_AlignPtMid.Pt;
    CMPointd& LineBasePt = m_AlignPtBase.Pt;
    CMPointd& RotatePt = m_AlignPtRotate.Pt;

    //PT1 为上点 PT2为下点
    LevelPt1.tX = LevelPt2.tX = LevelPtMid.tX = LineBasePt.tX = baseposX;
    LineBasePt.tY = baseposY;
    LevelPt1.tY = baseposY + dLength;
    LevelPt2.tY = baseposY - dLength;
    LevelPtMid.tY = LevelPt1.tY - dStep * iMidStepOffset;
    RotatePt = LevelPt1;
    return MSG_FINISHED;
}

void CProcess_Level_Ex::CalcuPtByCell(int iSideID)
{
    //    CProductSide* pSide=GET_CHDIRECT(iSideID,CProductSide);
    //    Q_ASSERT(pSide);
    double dBasePosX = 0;
    double dBasePosY = 0;
    double dStart = 0;
    double dEnd = 0;
    double dLeft, dRight, dBottom, dTop;
    getCircleBoundary(iSideID, dLeft, dRight, dBottom, dTop);

    //dBasePosY = (dBottom + dTop) / 2;
    dBasePosX = (dLeft + dRight) / 2;
    //getX(iSideID, dBasePosY, dStart, dEnd);
    getY(iSideID, dBasePosX, dStart, dEnd);

    dBasePosX = (dStart + dEnd) / 2;
    calcuPt(iSideID, dBasePosX, dBasePosY, dStart, dEnd);
    m_iCurLineId = -1;
}

void CProcess_Level_Ex::CalcuPtByLine(int iSideID, int iLineID)
{
    //sideID A or B
    CProductSide* pSide = GET_CHDIRECT(iSideID, CProductSide);
    Q_ASSERT(pSide);
    double dBasePosX = 0;
    double dBasePosY = 0;
    double dStartTop = 0;
    double dEndBottom = 0;
    CUTLINE* pCutLine = pSide->GetCutLine(iLineID);
    Q_ASSERT(pCutLine);

    //切片的起点和终点
    dStartTop = pCutLine->m_WPPair.ptPostive.tY;
    dEndBottom = pCutLine->m_WPPair.ptNegative.tY;

    dBasePosX = pCutLine->m_BasePt.tX;
    dBasePosY = pCutLine->m_BasePt.tY;

    m_iCurLineId = iLineID;

    calcuPt(iSideID, dBasePosX, dBasePosY, dStartTop, dEndBottom);
}

void CProcess_Level_Ex::CalcuPtByPos(int iSideID, double baseposX, double baseposY, double dStartPos, double dEndPos)
{
    calcuPt(iSideID, baseposX, baseposY, dStartPos, dEndPos);
}

double CProcess_Level_Ex::SearchAlignPt(int iSideID, int iCamID, int ptstyle)
{
    AlignPoint* pALignPt = 0;
    CImageContainer* pContainer = 0;
    int index = iSideID == SIDE_A ? 0 : 1;
    switch(ptstyle) {
        case TYPE_PT1:
            pALignPt = &m_AlignPt1;
            pContainer = &(m_imageContainerAlign[index][0]);
            pContainer->addString(QObject::trUtf8("Align Pt1"));
            //CaptureImage(iCamID,pContainer,QObject::trUtf8("Align Pt1"));
            break;
        case TYPE_PTMID:
            pALignPt = &m_AlignPtMid;
            pContainer = &(m_imageContainerAlign[index][1]);
            pContainer->addString(QObject::trUtf8("Align PtMid"));
            //CaptureImage(iCamID,pContainer,QObject::trUtf8("Align PtMid"));
            break;
        case TYPE_PT2:
            pALignPt = &m_AlignPt2;
            pContainer = &(m_imageContainerAlign[index][1]);
            pContainer->addString(QObject::trUtf8("Align Pt2"));
            //CaptureImage(iCamID,pContainer,QObject::trUtf8("Align Pt2"));
            break;
        default:Q_ASSERT(0); break;
    }
    CMPointd pt;
    pALignPt->bHasMatch = search_pt(iSideID, pt, pALignPt->dAngle,
                                    iCamID, true, pContainer,
                                    true);
    double dOffset = 0;
    if(pALignPt->bHasMatch) {
        //TODO:处理X划线偏移
        //目标向上偏移为正
        dOffset = pt.tX - pALignPt->Pt.tX;

        QString str = QObject::trUtf8("offset:%1mm").arg(QString::number(dOffset, 'f', 4));
        CaptureImage(iCamID, pContainer, str, false);

        CCam* pCam = GET_CHDIRECT(iCamID, CCam);
        Q_ASSERT(pCam);
        CAMatch* pMatch = (CAMatch*)pCam->Find_Algorithm(m_gSystem.m_iMatchType);
        Q_ASSERT(pMatch);
        pMatch->showresult_shape(pContainer);

        pALignPt->Pt = pt;

        adjustPt(iSideID, ptstyle);
    }
    return dOffset;
}

void CProcess_Level_Ex::SearchBasePt(int iSideID, int iCamID, int iLineID)
{
    AlignPoint* pALignPt = 0;
    CImageContainer* pContainer = 0;
    pALignPt = &m_AlignPtBase;
    int index = iSideID == SIDE_A ? 0 : 1;
    pContainer = &(m_imageContainerBase[index]);
    //CaptureImage(iCamID,pContainer,QObject::trUtf8("Align PtBase"));
    CMPointd pt;
    pALignPt->bHasMatch = search_pt(iSideID, pt, pALignPt->dAngle,
                                    iCamID, true, pContainer, true);
    if(pALignPt->bHasMatch) {
        //TODO:处理偏移X
        double dOffset = pt.tX - pALignPt->Pt.tX;
        double dOffsetMax = m_Variants.get_VData(Var_Process_Level_BaseOffsetMax)->toDouble();
        double dOffsetMin = m_Variants.get_VData(Var_Process_Level_BaseOffsetMin)->toDouble();

        CProductSide* pSide = GET_CHDIRECT(iSideID, CProductSide);
        Q_ASSERT(pSide);
        int iLineSize = pSide->m_CutLineVector.size();
        if(fabs(dOffset) > dOffsetMax && iLineSize) {
            MQT_THROW_CODESTR(ALARM_MAIN_ALIGNPT_BaseLineOutrange, QObject::trUtf8("find base line err."
                                                                                   " offset(%1mm) out of range(%2mm).")
                              .arg(dOffset, 0, 'f', 4).arg(dOffsetMax));
        }

        if(fabs(dOffset) > dOffsetMin && !iLineSize) {
            if(fabs(dOffset) > 3 * dOffsetMin) {
                LOG_ERR(fmt::format("Align Base outrange:{}", dOffset));
                QString info = (QObject::tr("Align err.\n") + QObject::trUtf8("find base line "
                                                                              " offset(%1mm) out of range(%2mm).")
                                .arg(dOffset, 0, 'f', 4).arg(dOffsetMin))
                    + "\n" + QObject::tr("Please contact engineer");
                MQT_THROW_CODESTR(ALARM_MAIN_ALIGNPT_AlignBaseLineOutrange, info);
            } else {
                MQT_THROW_CODESTR(ALARM_MAIN_ALIGNPT_AlignBaseLineOutrange, (QObject::tr("Align err.\n") + QObject::trUtf8("find base line "
                                                                                                                           " offset(%1mm) out of range(%2mm).")
                                                                             .arg(dOffset, 0, 'f', 4).arg(dOffsetMin)));
            }
        }

        pALignPt->Pt = pt;
        //LOG(INFO)<<"Match Base Pt Move Pt to (" << pt.tX << "," << pt.tY << ")";
        pContainer->clearShape(-1);
        MovePt(iSideID, iCamID, TYPE_PTBASE, false, 0, 0);

        MSleep(50);
        CaptureImage(iCamID, pContainer,
                     QObject::trUtf8("Offset:%1mm").arg(dOffset, 0, 'f', 4), false);
        m_gSystem.SetCutStreet(pContainer, iSideID, iCamID);

        //int iLineSize=pSide->m_CutLineVector.size();
        if(fabs(dOffset) > 0.001 || !iLineSize) {
            //找到基准点后，就修正切割道
            calcuSideVector(iSideID, dOffset, iLineID);
        } else {
            //LOG(INFO) << "Base Align(Auto) " << iLineID+1 << " Not Modify Offset:" << dOffset;
            LOG_WARN(fmt::format("Ignore calcuSideVector offset:{} LineID:{}", dOffset, iLineID + 1));
            m_gSystem.LogInfo(QString("Base Align(Auto) ") + QString::number(iLineID + 1) + " Not Modify Offset:" + QString::number(dOffset));
            AddProductData(QString("Base Align(Auto) ") + QString::number(iLineID + 1) + " Not Modify Offset:" + QString::number(dOffset));
        }
    }
}

void CProcess_Level_Ex::calcuSideVector(int32_t iSideID,
                                        double dXOffset,
                                        int iLineID, bool bManualSet/*=false*/)
{
    CProductSide* pSide = GET_CHDIRECT(iSideID, CProductSide);
    Q_ASSERT(pSide);
    QMutexLocker l(&pSide->m_CutLineVector.mutex);
    int iLineSize = pSide->m_CutLineVector.size();
    if(iLineSize) {
        if(fabs(dXOffset) < 0.001) {
            LOG_WARN(fmt::format("Ignore calcuSideVector offset:{} LineID:{} Manual:{}", dXOffset, iLineID + 1, bManualSet));
            QString info = QString("Align Base Align(Auto) LINE(Ignored):")
                + QString::number(iLineID + 1) + " Offset"
                + QString::number(dXOffset) + (SIDE_A == iSideID ? " CH1" : " CH2");
            AddProductData(info);

            m_gSystem.EvtLog(QString::fromUtf8("POS"),
                             QObject::trUtf8("%3,LineID:%2,Offset:%1,Ignore").
                             arg(dXOffset).arg(iLineID + 1).arg(iSideID == SIDE_A ? "CH1" : "CH2"));
            return;
        }

        iLineID = max(0, iLineID);

        //HACK:只偏移一半
        dXOffset = dXOffset / 2;
        if(dXOffset > 0) {
            dXOffset -= 0.0003;
            if(dXOffset < 0) {
                dXOffset = 0;
            }
        }
        if(dXOffset < 0) {
            dXOffset += 0.0003;
            if(dXOffset > 0) {
                dXOffset = 0;
            }
        }
        //更新基准点
        int iFirstLine;
        int iStep;
        getCurSideAlignParam(iSideID, iFirstLine, iStep);
#if 1 //更新线偏移
        //如果是第一条，则往后更新
        if(iFirstLine == iLineID + 1) {
            iLineID = 0;
        }
        //直接向后更新,第一条
        for(int i = iLineID; i < iLineSize; i++) {
            pSide->m_CutLineVector[i].m_WPPair.ptPostive.tX += dXOffset;
            pSide->m_CutLineVector[i].m_WPPair.ptNegative.tX += dXOffset;
            pSide->m_CutLineVector[i].m_BasePt.tX += dXOffset;
        }

        l.unlock();
        if(bManualSet) {
            QString info = QString("Align Base Align(Manual) LINE:") + QString::number(iLineID + 1) + " Offset" + QString::number(dXOffset) + (SIDE_A == iSideID ? " CH1" : " CH2");
            AddProductData(info);
        } else {
            QString info = QString("Align Base Align(Auto) LINE:") + QString::number(iLineID + 1) + " Offset" + QString::number(dXOffset) + (SIDE_A == iSideID ? " CH1" : " CH2");
            AddProductData(info);
        }
#endif
        m_gSystem.EvtLog(QString::fromUtf8("POS"),
                         QObject::trUtf8("%3,LineID:%2,Offset:%1").
                         arg(dXOffset).arg(iLineID + 1).arg(iSideID == SIDE_A ? "CH1" : "CH2"));
    } else {
        //没有的时候，直接生成切割道
        //内部会进行平台误差的补偿
        l.unlock();
        calcuLineCircle(iSideID);

        AddProductData(QString("Generate Side:%1 Line  at:%2").arg(iSideID == SIDE_A ? "CH1" : "CH2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")));
        AddProductData(QString("Base Line Offset:%1").arg(dXOffset));
    }
}

double CProcess_Level_Ex::get_XAdjust_step(int iSideID, int iCamID, bool bIndex)
{
    if(bIndex) {
        return -getOtherSideStep(iSideID);
    }

    CCam* pCam = GET_CHDIRECT(iCamID, CCam);
    double  width, height;
    pCam->GetRealSize(width, height);
    if(DEQUAL0(width)) {
        MQT_THROW_CODESTR(ALARM_MAIN_LOGIC_PARAM, QObject::trUtf8("level calcu err.X Adjust step equal 0"));
    }
    double dAdjustStep = width / 1.3;
    MqDebug() << "Get_XAdjust_step:" << dAdjustStep;
    return dAdjustStep;
}

double CProcess_Level_Ex::get_YAdjust_step(int iSideID, int iCamID, bool bIndex)
{
    if(bIndex) {
        return getCurSideStep(iSideID);
    }

    CCam* pCam = GET_CHDIRECT(iCamID, CCam);
    double  width, height;
    pCam->GetRealSize(width, height);
    if(DEQUAL0(height)) {
        MQT_THROW_CODESTR(ALARM_MAIN_LOGIC_PARAM, QObject::trUtf8("level calcu err.Y Adjust step equal 0"));
    }
    //HACK:1.1的参数根据实际调整或加到Recipe中
    double dAdjustStep = height / 1.2;

    MqDebug() << "Get_YAdjust_step:" << dAdjustStep;
    return dAdjustStep;
}

//查找时调整步进的次数
int CProcess_Level_Ex::get_XAdjust_count(int iSideID, int iCamID)
{
    //HACK:1.2这个参数根据实际调整
    int iCount = getOtherSideStep(iSideID) * 1.2 /
        get_XAdjust_step(iSideID, iCamID, false);
    iCount++;
    if(iCount <= 1) {
        iCount = 2;
    }
    MqDebug() << "Get_XAdjust_count:" << iCount;
    return iCount;
}

int CProcess_Level_Ex::get_YAdjust_count(int iSideID, int iCamID)
{
    int iCount = getCurSideStep(iSideID) * 1.2 /
        get_YAdjust_step(iSideID, iCamID, false);
    iCount++;
    if(iCount <= 1) {
        iCount = 2;
    }
    MqDebug() << "Get_YAdjust_count:" << iCount;
    return iCount;
}

bool CProcess_Level_Ex::getY(int iSideID, double dBaseX, double& dYTop, double& dYBottom)
{
    //上到下
    CProductSide* pSide = GET_CHDIRECT(iSideID, CProductSide);
    Q_ASSERT(pSide);
    CMProduct* pProduct = GET_CHDIRECT(PRODUCT, CMProduct);
    Q_ASSERT(pProduct);
    double dLeft = 0, dRight = 0, dBottom = 0, dTop = 0;
    getCircleBoundary(iSideID, dLeft, dRight, dBottom, dTop);
    if(dBaseX > dRight || dBaseX < dLeft) {
        dYTop = dYBottom = pSide->m_realCenter.tY;
        return false;
    }

    double dRadius = pProduct->m_Variants.get_VData(Var_Product_Diameter_ID)
        ->toDouble() / 2;

    //圆方程
    //圆心 (a,b)
    // 圆公式:(x－a)² + (y－b)² = r²
    //已知X求Y
    //y1 =  sqrt(r*r - (x-a)*(x-a)) + b
    //y2 = -sqrt(r*r - (x-a)*(x-a)) + b
    double A = pSide->m_realCenter.tX;
    double B = pSide->m_realCenter.tY;
    double X_A_Power = (dBaseX - A) * (dBaseX - A); //(x - a)*(x-a)
    double SqrtResult = sqrtf(dRadius * dRadius - X_A_Power);

    double Y_Positive = SqrtResult + B; //正向
    double Y_Negative = -SqrtResult + B; //负向

    if(Y_Positive > dTop) {
        Y_Positive = dTop;
    }
    if(Y_Negative < dBottom) {
        Y_Negative = dBottom;
    }

    dYTop = Y_Positive;
    dYBottom = Y_Negative;
    return true;
}

void CProcess_Level_Ex::calcuLineCircle(int iSideID)
{
    //生成的切割线从右往左的顺序
    CProductSide* pSide = GET_CHDIRECT(iSideID, CProductSide);
    Q_ASSERT(pSide);
    double dStepX = getCurSideStep(iSideID);
    if(m_gSystem.IsSimulator()) {
        m_AlignPtBase.Pt.tX = 1;
        m_AlignPtBase.Pt.tY = 1;
        pSide->m_realCenter.tX = 1;
        pSide->m_realCenter.tY = 1;
    }

    CMPointd ptRight = m_AlignPtBase.Pt;
    pSide->m_dSolidBasePosX = m_AlignPtBase.Pt.tX;

    //生成外接矩形
    double dLeft, dRight, dBottom, dTop;
    getCircleBoundary(iSideID, dLeft, dRight, dBottom, dTop);
    //调整到最右边开始找
    while(ptRight.tX < dRight) {
        ptRight.tX += dStepX;
    }
    while(ptRight.tX > dRight) {
        ptRight.tX -= dStepX;
    }

    LOG_INFO(fmt::format("calcuLineCircle Side: {} Center X:{} Y: {} Base X:{} Base Y:{} Angle:{}",
                         iSideID == SIDE_A ? "CH1" : "CH2",
                         pSide->m_realCenter.tX, pSide->m_realCenter.tY,
                         m_AlignPtBase.Pt.tX, m_AlignPtBase.Pt.tY, pSide->m_dLevelAngle));

    //子切割道，默认没有子切割道
    int isize = pSide->m_vSubIndex.size();
    int ilineindex = 0;
    double dBaseRefPos = m_AlignPtBase.Pt.tX;
    QMutexLocker l(&pSide->m_CutLineVector.mutex);
    while(ptRight.tX > dLeft) {
        calculine(ptRight, dLeft, dRight, iSideID, FALSE, ilineindex, dBaseRefPos);
        //默认没子切割道,下面的代码不执行
        if(isize) {
            //TODO:子切割道的逻辑不正确
            for(int j = 0; j < isize; j++) {
                CMPointd subLinePt = ptRight;
                SUBINDEX subindex = pSide->m_vSubIndex[j];
                subLinePt.tX -= subindex.dLocationOffset;
                calculine(subLinePt, dLeft, dRight, iSideID, TRUE, j, dBaseRefPos);
                for(int i = 0; i < subindex.iCount; i++) {
                    subLinePt.tX -= subindex.dSolidOffset;
                    calculine(subLinePt, dLeft, dRight, iSideID, TRUE, j, dBaseRefPos);
                }
            }
        }
        ilineindex++;
        ptRight.tX -= dStepX;
    }
}

void CProcess_Level_Ex::calculine(CMPointd ptRef, double dStart, double dEnd,
                                  int iSideID, BOOL bsub, int index, double baseX)
{
    CProductSide* pSide = GET_CHDIRECT(iSideID, CProductSide);
    Q_ASSERT(pSide);
    CMProduct* pProduct = GET_CHDIRECT(PRODUCT, CMProduct);
    Q_ASSERT(pProduct);

    CMPointd CenterPt = pSide->m_realCenter;
    double dRadius = pProduct->m_Variants.get_VData(Var_Product_Diameter_ID)
        ->toDouble() / 2;

    
    double dLocationPos = ptRef.tX;    //! 当前定位点参考坐标
    double dCenterLocationPos = CenterPt.tX;    //! 中心定位点参考坐标
    double dCenterBasePos = CenterPt.tY;
    double dBaseCalcPos = m_AlignPtBase.Pt.tY;  //! 用于计算的基准点坐标
    double dStep = getOtherSideStep(iSideID);   //! 另一面的步长，用于计算基准点坐标
    double dBaseLocationPos = baseX;    //! 定位点的基准坐标，用于计算工作台偏移

    double dPositive = 0;
    double dNegative = 0;
	//计算定位位置时，以原点为基准边缘的数值
    calcCoordValue(dLocationPos, dCenterLocationPos, dCenterBasePos,  dRadius, dStart, dEnd, dPositive, dNegative);

    //计算平台补偿值
    double dWorktableOffset = calcWorktableOffset(dLocationPos, dBaseLocationPos);

    //偏差应该小于7um,否则是错误的数据
    if(fabs(dWorktableOffset) > 0.007)
        MQT_THROW_CODESTR(ALARM_MAIN_LEVEING_USESAVEPT, QString("Worktable offset max range 0.007"));

    //HACK:如果需要修改切割方向即在此处修改
    //X向为定位方向，Y向为切割方向
    CUTLINE Line;
    Line.m_BasePt.tX = dLocationPos - dWorktableOffset; //!note:从正向到负向是做减法，在逻辑层面减去了工作台的偏移
    Line.m_BasePt.tY = numDis((dNegative + dPositive) / 2 - dBaseCalcPos, dStep) + dBaseCalcPos;
    Line.m_WPPair.ptPostive = CMPointd(Line.m_BasePt.tX, dPositive);
    Line.m_WPPair.ptNegative = CMPointd(Line.m_BasePt.tX, dNegative);
    Line.m_bSUB = bsub;
    Line.m_index = index;
    pSide->m_CutLineVector.push_back(Line);

    QString info = QString("Calcline Line:%1 Offset:%2 Positive:%3 Negative:%4 Side:%5 Sub:%6 Index:%7")
        .arg(index + 1).arg(dWorktableOffset)
        .arg(dPositive).arg(dNegative).arg(iSideID == SIDE_A ? "CH1" : "CH2")
        .arg(bsub ? "Yes" : "No").arg(index);
    AddProductData(info);
}

void CProcess_Level_Ex::adjustPt(int iSideID, int ptstyle)
{
    double dMidStepOffset = m_Variants.get_VData(Var_Process_Level_MidStepOffset)
        ->toInt();
    double  dStepY = getOtherSideStep(iSideID);
    CMPointd refPt;
    switch(ptstyle) {
        case TYPE_PTROTATE:
            refPt = m_AlignPtRotate.Pt;
            //m_AlignPtBase.Pt=m_AlignPtRotate.Pt;
            //m_AlignPtBase.Pt.tX=numDis( m_AlignPtBase.Pt.tX-refPt.tX,dStepX)+refPt.tX;
            break;
        case TYPE_PTBASE:
            return;
        case TYPE_PT1:
            refPt = m_AlignPt1.Pt;
            break;
        case TYPE_PTMID:
            refPt = m_AlignPt1.Pt;
            return;
        case TYPE_PT2:
            refPt = m_AlignPt1.Pt;
            return;
    }

    CMPointd& LevelPt1 = m_AlignPt1.Pt;
    CMPointd& LevelPt2 = m_AlignPt2.Pt;
    CMPointd& LevelPtMid = m_AlignPtMid.Pt;
    CMPointd& LineBasePt = m_AlignPtBase.Pt;

    //在X的位置上调平，所以X方向应该是一样的
    LineBasePt.tX = LevelPt1.tX = LevelPt2.tX = LevelPtMid.tX = refPt.tX;

    //根据参考点的相对距离进行偏移
    LineBasePt.tY = numDis(LineBasePt.tY - refPt.tY, dStepY) + refPt.tY;
    LevelPt1.tY = numDis(LevelPt1.tY - refPt.tY, dStepY) + refPt.tY;
    LevelPt2.tY = numDis(LevelPt2.tY - refPt.tY, dStepY) + refPt.tY;
    LevelPtMid.tY = LevelPt1.tY - dMidStepOffset * dStepY;
}

double CProcess_Level_Ex::calcuAngle(CMPointd Pt1, CMPointd Pt2)
{
    double dAngle = 0;
    CMPointd tmpTop, tmpBottom;
    if(fabs(Pt1.tY - Pt2.tY) < 0.1) {
        MQT_THROW_CODESTR(ALARM_MAIN_LEVEING_USESAVEPT, QObject::trUtf8("Calcu level Angle err.Some Point"));
    }
    //在右边的点为点1
    //在左边的点为点2
    //则Pt2右偏angle为负，Pt2在左边则angle为正
    tmpTop = Pt1.tY > Pt2.tY ? Pt1 : Pt2;
    tmpBottom = Pt1.tY < Pt2.tY ? Pt1 : Pt2;

    CMPointd dStart = tmpBottom;
    CMPointd dEnd = tmpTop;

    double dDisX = dStart.tX - dEnd.tX;
    double dDisY = dStart.tY - dEnd.tY;

    //三角函数求顺时针为正的角度
    double temp = sqrtf(dDisY * dDisY + dDisX * dDisX);
    dAngle = DEG(asin(dDisX / temp));

    return dAngle;
}
void CProcess_Level_Ex::calcCoordValue(double dCoordValue, double dCenterValue, double dCenterBaseOffset, double dRadius,
                                       double dStart, double dEnd, double& dPositive, double& dNegative)
{
    Q_ASSERT(dRadius > 0 && "dRadius must > 0");
    double dMin = min(dStart, dEnd);
    double dMax = max(dStart, dEnd);
    double dRefOffset = fabs(dCoordValue - dCenterValue);
    if(dRefOffset > dRadius) {
        Q_ASSERT(0 && "Ref pt distance > Radius");
    }

    double dLength = sqrtf(dRadius * dRadius - dRefOffset * dRefOffset);

    dPositive = dLength + dCenterBaseOffset;
    dNegative = -dLength + dCenterBaseOffset;
    if(dPositive > dMax) {
        dPositive = dMax;
    }
    if(dNegative < dMin) {
        dNegative = dMin;
    }
}

double CProcess_Level_Ex::calcWorktableOffset(double dCoordValue, double dRefValue)
{
    CWorktableOffset* pOffset = GET_CHDIRECT(WTOFFSET, CWorktableOffset);
    int bEnable = pOffset->m_Variants.get_VData(Var_WorkTable_Offset_EnableOffset)
        ->toBool();
    if(!bEnable) {
        return 0;
    }
    //平台位置补偿,默认禁用
    CWorktableOffsetDriver* pOffsetDriver = GET_CARD(WTOFFSET_DRIVER, CWorktableOffsetDriver);
    //当前位置的补偿值
    double dWorktableOffsetX = pOffsetDriver->GetOffset(WTOFFSET, dCoordValue);
    //基准线的补偿值
    double dBaseXOffset = pOffsetDriver->GetOffset(WTOFFSET, dRefValue);
    //先以基准位置的偏移较正回去，较正是以图像为准的
    dWorktableOffsetX -= dBaseXOffset;

    //非基准点进行较正，基准点附近则不应用
    if(dCoordValue > dRefValue - 0.01 && dCoordValue < dRefValue + 0.01) {
        dWorktableOffsetX = 0;
    }

    return dWorktableOffsetX;
}
