mrDarker
2025-08-11 bd9942d185fb25b35b0c6e089e5763d45e5c83ce
1. 侧面检校验报警
2. 输入配方参数执行
已修改5个文件
481 ■■■■■ 文件已修改
EdgeInspector_App/Data/DefectStorage.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Defect.h 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Process/InspectCamera.cpp 453 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Process/InspectCamera.h 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Recipe/GlassRecipe.cpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
EdgeInspector_App/Data/DefectStorage.cpp
@@ -433,8 +433,8 @@
    pDefect->Reset();
    pDefect->m_bJudge_NG = TRUE;            // RIP 厚度异常即 NG
    pDefect->m_dSizeX_um = dMeasured_um;    // 记录测得厚度
    pDefect->m_dSizeY_um = dSpecDiff_um;    // 记录与规格差值
    pDefect->m_nJudge_X_um = dMeasured_um;  // 记录测得厚度
    pDefect->m_nJudge_Y_um = dSpecDiff_um;  // 记录与规格差值
    pDefect->m_DefectInfo = defectInfo;
    int nXStart = defectInfo.m_ptDefectPos_pxl.x - (DEFECTIMAGE_WIDTH / 2);
EdgeInspector_App/Defect.h
@@ -37,7 +37,9 @@
    DefectLoc_License,
    DefectLoc_Rip_Thickness,
    DefectLoc_Rip_Thickness_Glass,
    DefectLoc_Rip_Thickness_Left,
    DefectLoc_Rip_Thickness_Right,
    DefectLoc_Unknown,
    
@@ -79,7 +81,9 @@
    _T("License"),
    _T("Rip_Thickness"),
    _T("Rip_GlassThickness"),
    _T("Rip_LeftGap"),
    _T("Rip_RightGap"),
    _T("Unknown")
};
EdgeInspector_App/Process/InspectCamera.cpp
@@ -424,6 +424,458 @@
        }
    }
#endif // HALCON_VISION_KEY
    MeasureSideEdge_EI(eDim);
}
BOOL CInspectCamera::MeasureSideEdge_EI(DimensionDir eDim) {
    /* code */
    bool bExec = (DIMENSION_A_RIP == eDim) || (DIMENSION_B_RIP == eDim) || (DIMENSION_C_RIP == eDim) || (DIMENSION_D_RIP == eDim);
    if (!bExec) return FALSE;
    CSide_Data* pSideData = m_pGlassData->GetSideData(eDim);
    //查找边界
    CFrameBufferController* pFrameBufferController = m_pGrabber->GetFrameBuffer();
    int imgWidth = pFrameBufferController->GetFrameWidth();
    //获取上边界和下边
    int nTopEdge = pSideData->m_nGlassStartLine;
    int nBottomEdge = pSideData->m_nGlassEndLine;
    g_pLog->DisplayMessage(_T("[APP]Measure Side Edge Start, StartEdge = %d, EndEdge = %d, Width = %d"), nTopEdge, nBottomEdge, imgWidth);
    stFrameIndex stFrame = m_pGrabber->GetGrabFrame();
    CRIP_THICKNESS_PARM& rip = m_pRecipe->m_SideParam[eDim].m_RipThk;
    if (rip.m_bUseInspect != TRUE) {
        return TRUE;
    }
    int inspectNum = 36;
    //输入参数
    int topOffset = rip.m_nTopOffset;        //T Offset
    int botOffset = rip.m_nBottomOffset;    //B Offset
    int leftEdge = rip.m_nRectLeft;            //Rect L
    int rightEdge = rip.m_nRectRight;        //Rect R
    int leftThres = rip.m_nLeftThres;       //Left Thres
    int rightThres = rip.m_nRightThres;     //Right Thres
    int gassThres = rip.m_nGlassThres;      //Gas Thres
    double dist_array[36];                     //输出结果
    double left_dist_Gass_array[36];           //输出结果
    double right_dist_Gass_array[36];          //输出结果
    double xMinEdge_array_px[36];              //输出结果
    double yMinEdge_array_px[36];              //输出结果
    double xMaxEdge_array_px[36];              //输出结果
    double yMaxEdge_array_px[36];              //输出结果
    double xMinGas_array_px[36];               //输出结果
    double yMinGas_array_px[36];               //输出结果
    double xMaxGas_array_px[36];               //输出结果
    double yMaxGas_array_px[36];               //输出结果
    int startY = nTopEdge + topOffset;
    int endY = nBottomEdge - botOffset;
    int step = (int)((endY - startY) / inspectNum);
    g_pLog->DisplayMessage(_T("[APP]Measure Side Edge, (startY, endY, step) = (%d, %d, %d)"), startY, endY, step);
    for (int i = 0; i < inspectNum; i++) {
        int x1 = leftEdge;
        int y1 = startY + i * step;
        int x2 = rightEdge;
        int y2 = startY + (i + 1) * step;
        double szDist, leftGassDist, rightGassDist;
        MeasureSideEdge_POS(eDim,
            x1, y1, x2, y2,
            leftThres, rightThres, gassThres,
            xMinEdge_array_px[i], yMinEdge_array_px[i], xMaxEdge_array_px[i], yMaxEdge_array_px[i],
            xMinGas_array_px[i], yMinGas_array_px[i], xMaxGas_array_px[i], yMaxGas_array_px[i],
            szDist, leftGassDist, rightGassDist);
        dist_array[i] = m_dPixelSizeX * szDist;
        left_dist_Gass_array[i] = m_dPixelSizeX * leftGassDist;
        right_dist_Gass_array[i] = m_dPixelSizeX * rightGassDist;
        g_pLog->DisplayMessage(_T("[APP]Measure Result %d: LeftEdge = (%.1f, %.1f), LeftGas = (%.1f, %.1f), rightGas = (%.1f, %.1f), RightEdge = (%.1f, %.1f), (Dist, LeftGass, RightGass) = (%.1f, %.1f, %.1f)"),
            i + 1,
            xMinEdge_array_px[i], yMinEdge_array_px[i],
            xMinGas_array_px[i], yMinGas_array_px[i],
            xMaxGas_array_px[i], yMaxGas_array_px[i],
            xMaxEdge_array_px[i], yMaxEdge_array_px[i],
            dist_array[i], left_dist_Gass_array[i], right_dist_Gass_array[i]);
        // 添加缺陷
        int nStep = max(1, (endY - startY) / inspectNum); // 防 0
        auto SpecDiff = [](double v, double vMin, double vMax)->double {
            if (v <= 0) return 0.0;            // 无效值
            if (v < vMin) return v - vMin;     // 负:低于下限
            if (v > vMax) return v - vMax;     // 正:高于上限
            return 0.0;                        // 在规格内
        };
        auto MakeBaseInfo = [&](CPoint pt, CRect rt, DefectLocation loc)->CDefect_Info {
            CDefect_Info info;
            info.m_iFrameIdx = stFrame.nFrameIdx;
            info.m_nCamID = m_iCamera;
            info.m_nScanIdx = stFrame.nScanIdx;
            info.m_nGlassStartLine = pSideData->m_nGlassStartLine;
            info.m_nSideIdx = (int)eDim;
            info.m_ptDefectPos_pxl = pt;
            info.m_rtDefectPos_pxl = rt;
            info.m_DefectLoc = loc;
            return info;
        };
        bool ngGlass = (dist_array[i] > 0) && (dist_array[i] < rip.m_nGlassSizeMin_um || dist_array[i] > rip.m_nGlassSizeMax_um);
        bool ngLeft = (left_dist_Gass_array[i] > 0) && (left_dist_Gass_array[i] < rip.m_nLeftRipSizeMin_um || left_dist_Gass_array[i] > rip.m_nLeftRipSizeMax_um);
        bool ngRight = (right_dist_Gass_array[i] > 0) && (right_dist_Gass_array[i] < rip.m_nRightRipSizeMin_um || right_dist_Gass_array[i] > rip.m_nRightRipSizeMax_um);
        // Glass 厚度 NG
        if (ngGlass) {
            CRect rt(
                (int)min(min(xMinEdge_array_px[i], xMinGas_array_px[i]), min(xMaxEdge_array_px[i], xMaxGas_array_px[i])),
                (int)min(min(yMinEdge_array_px[i], yMinGas_array_px[i]), min(yMaxEdge_array_px[i], yMaxGas_array_px[i])),
                (int)max(max(xMinEdge_array_px[i], xMinGas_array_px[i]), max(xMaxEdge_array_px[i], xMaxGas_array_px[i])),
                (int)max(max(yMinEdge_array_px[i], yMinGas_array_px[i]), max(yMaxEdge_array_px[i], yMaxGas_array_px[i]))
            );
            CPoint pt((rt.left + rt.right) / 2, (rt.top + rt.bottom) / 2);
            CDefect_Info defect = MakeBaseInfo(pt, rt, DefectLoc_Rip_Thickness_Glass);
            double dDiff = SpecDiff(dist_array[i], rip.m_nGlassSizeMin_um, rip.m_nGlassSizeMax_um);
            m_pDefectControl->ExtractDefect_RipThickness(eDim, m_iCamera, stFrame.nScanIdx, defect, dist_array[i], dDiff);
        }
        // 左侧气隙 NG
        if (ngLeft) {
            CRect rt(
                (int)min(xMinEdge_array_px[i], xMinGas_array_px[i]),
                (int)min(yMinEdge_array_px[i], yMinGas_array_px[i]),
                (int)max(xMinEdge_array_px[i], xMinGas_array_px[i]),
                (int)max(yMinEdge_array_px[i], yMinGas_array_px[i])
            );
            CPoint pt((rt.left + rt.right) / 2, (rt.top + rt.bottom) / 2);
            CDefect_Info defect = MakeBaseInfo(pt, rt, DefectLoc_Rip_Thickness_Left);
            double dDiff = SpecDiff(left_dist_Gass_array[i], rip.m_nLeftRipSizeMin_um, rip.m_nLeftRipSizeMax_um);
            m_pDefectControl->ExtractDefect_RipThickness(eDim, m_iCamera, stFrame.nScanIdx, defect, left_dist_Gass_array[i], dDiff);
        }
        // 右侧气隙 NG
        if (ngRight) {
            CRect rt(
                (int)min(xMaxEdge_array_px[i], xMaxGas_array_px[i]),
                (int)min(yMaxEdge_array_px[i], yMaxGas_array_px[i]),
                (int)max(xMaxEdge_array_px[i], xMaxGas_array_px[i]),
                (int)max(yMaxEdge_array_px[i], yMaxGas_array_px[i])
            );
            CPoint pt((rt.left + rt.right) / 2, (rt.top + rt.bottom) / 2);
            CDefect_Info defect = MakeBaseInfo(pt, rt, DefectLoc_Rip_Thickness_Right);
            double dDiff = SpecDiff(right_dist_Gass_array[i], rip.m_nRightRipSizeMin_um, rip.m_nRightRipSizeMax_um);
            m_pDefectControl->ExtractDefect_RipThickness(eDim, m_iCamera, stFrame.nScanIdx, defect, right_dist_Gass_array[i], dDiff);
        }
    }
    return TRUE;
}
void CInspectCamera::MeasureSideEdge_POS(DimensionDir eDim,
    int x1, int y1, int x2, int y2,
    int leftThres, int rightThres, int gassThres,
    double& minEdgeX, double& minEdgeY, double& maxEdgeX, double& maxEdgeY,
    double& minGasX, double& minGasY, double& maxGasX, double& maxGasY,
    double& szDist, double& leftGassDist, double& rightGassDist) {
    /* code */
    szDist = 0.0f;
    leftGassDist = 0.0f;
    rightGassDist = 0.0f;
    int width = x2 - x1 + 1;
    int height = y2 - y1 + 1;
    uchar* imgData = new uchar[width * height];
    try {
        CutImageROI(imgData, eDim, x1, y1, x2, y2);
        MeasurePoint dotResult1[100];
        MeasurePoint dotResult2[100];
        MeasurePoint dotResult3[100];
        MeasurePoint dotResult4[100];
        MeasurePoint dotResult5[100];
        MeasurePoint dotResult6[100];
        MeasurePoint dotResult7[100];
        int dotNum1 = 0;
        int dotNum2 = 0;
        int dotNum3 = 0;
        int dotNum4 = 0;
        int dotNum5 = 0;
        int dotNum6 = 0;
        int dotNum7 = 0;
        CVisionMeasureClass doExec;
        double sigma = 2.5f;   //输入参数, 增加参数
        doExec.doMeasurePosA(imgData, width, height, sigma,
            dotResult1, dotNum1,
            dotResult2, dotNum2,
            dotResult3, dotNum3,
            dotResult4, dotNum4,
            dotResult5, dotNum5,
            dotResult6, dotNum6,
            dotResult7, dotNum7);
        for (int i = 0; i < dotNum1; i++) {
            dotResult1[i].x += x1;
            dotResult1[i].y += y1;
        }
        for (int i = 0; i < dotNum2; i++) {
            dotResult2[i].x += x1;
            dotResult2[i].y += y1;
        }
        for (int i = 0; i < dotNum3; i++) {
            dotResult3[i].x += x1;
            dotResult3[i].y += y1;
        }
        for (int i = 0; i < dotNum4; i++) {
            dotResult4[i].x += x1;
            dotResult4[i].y += y1;
        }
        for (int i = 0; i < dotNum5; i++) {
            dotResult5[i].x += x1;
            dotResult5[i].y += y1;
        }
        for (int i = 0; i < dotNum6; i++) {
            dotResult6[i].x += x1;
            dotResult6[i].y += y1;
        }
        for (int i = 0; i < dotNum7; i++) {
            dotResult7[i].x += x1;
            dotResult7[i].y += y1;
        }
        int fzDist = 4.5;                 //输入参数, 增加参数
        double xMinResult[7] = { -1 };
        double yMinResult[7] = { -1 };
        double xMaxResult[7] = { -1 };
        double yMaxResult[7] = { -1 };
        double xMinGassResult[7] = { -1 };
        double yMinGassResult[7] = { -1 };
        double xMaxGassResult[7] = { -1 };
        double yMaxGassResult[7] = { -1 };
        MeasureResultProc(dotResult1, dotNum1, leftThres, rightThres, gassThres, fzDist,
            xMinResult[0], yMinResult[0], xMaxResult[0], yMaxResult[0],
            xMinGassResult[0], yMinGassResult[0], xMaxGassResult[0], yMaxGassResult[0]);
        MeasureResultProc(dotResult2, dotNum2, leftThres, rightThres, gassThres, fzDist,
            xMinResult[1], yMinResult[1], xMaxResult[1], yMaxResult[1],
            xMinGassResult[1], yMinGassResult[1], xMaxGassResult[1], yMaxGassResult[1]);
        MeasureResultProc(dotResult3, dotNum3, leftThres, rightThres, gassThres, fzDist,
            xMinResult[2], yMinResult[2], xMaxResult[2], yMaxResult[2],
            xMinGassResult[2], yMinGassResult[2], xMaxGassResult[2], yMaxGassResult[2]);
        MeasureResultProc(dotResult4, dotNum4, leftThres, rightThres, gassThres, fzDist,
            xMinResult[3], yMinResult[3], xMaxResult[3], yMaxResult[3],
            xMinGassResult[3], yMinGassResult[3], xMaxGassResult[3], yMaxGassResult[3]);
        MeasureResultProc(dotResult5, dotNum5, leftThres, rightThres, gassThres, fzDist,
            xMinResult[4], yMinResult[4], xMaxResult[4], yMaxResult[4],
            xMinGassResult[4], yMinGassResult[4], xMaxGassResult[4], yMaxGassResult[4]);
        MeasureResultProc(dotResult6, dotNum6, leftThres, rightThres, gassThres, fzDist,
            xMinResult[5], yMinResult[5], xMaxResult[5], yMaxResult[5],
            xMinGassResult[5], yMinGassResult[5], xMaxGassResult[5], yMaxGassResult[5]);
        MeasureResultProc(dotResult7, dotNum7, leftThres, rightThres, gassThres, fzDist,
            xMinResult[6], yMinResult[6], xMaxResult[6], yMaxResult[6],
            xMinGassResult[6], yMinGassResult[6], xMaxGassResult[6], yMaxGassResult[6]);
        std::vector<double> vDist, vLeftGass, vRightGass;
        for (int i = 0; i < 7; i++) {
            if (xMinResult[i] > 0 && xMaxResult[i] > 0) {
                double dx = xMaxResult[i] - xMinResult[i];
                double dy = yMaxResult[i] - yMinResult[i];
                double dist = sqrt(dx * dx + dy * dy);
                vDist.push_back(dist);
            }
            if (xMinResult[i] > 0 && xMinGassResult[i] > 0) {
                double dx = xMinGassResult[i] - xMinResult[i];
                double dy = yMinGassResult[i] - yMinResult[i];
                double dist = sqrt(dx * dx + dy * dy);
                vLeftGass.push_back(dist);
            }
            if (xMaxResult[i] > 0 && xMaxGassResult[i] > 0) {
                double dx = xMaxResult[i] - xMaxGassResult[i];
                double dy = yMaxResult[i] - yMaxGassResult[i];
                double dist = sqrt(dx * dx + dy * dy);
                vRightGass.push_back(dist);
            }
        }
        double avgDist = 0.0f;
        int sz = (int)(vDist.size());
        if (sz > 3){
            for (int i = 0; i < sz - 1; i++) {
                for (int j = i + 1; j < sz; j++) {
                    if (vDist[i] > vDist[j]) {
                        double tmp = vDist[i];
                        vDist[i] = vDist[j];
                        vDist[j] = tmp;
                    }
                }
            }
            double avg = 0.0f;
            for (int i = 1; i < sz - 1; i++) {
                avg += vDist[i];
            }
            avgDist = avg / (sz - 2);
        }
        double avgLeftGass = 0.0f;
        sz = (int)(vLeftGass.size());
        if (sz > 3) {
            for (int i = 0; i < sz - 1; i++) {
                for (int j = i + 1; j < sz; j++) {
                    if (vLeftGass[i] > vLeftGass[j]) {
                        double tmp = vLeftGass[i];
                        vLeftGass[i] = vLeftGass[j];
                        vLeftGass[j] = tmp;
                    }
                }
            }
            double avg = 0.0f;
            for (int i = 1; i < sz - 1; i++) {
                avg += vLeftGass[i];
            }
            avgLeftGass = avg / (sz - 2);
        }
        double avgRightGass = 0.0f;
        sz = (int)(vRightGass.size());
        if (sz > 3) {
            for (int i = 0; i < sz - 1; i++) {
                for (int j = i + 1; j < sz; j++) {
                    if (vRightGass[i] > vRightGass[j]) {
                        double tmp = vRightGass[i];
                        vRightGass[i] = vRightGass[j];
                        vRightGass[j] = tmp;
                    }
                }
            }
            double avg = 0.0f;
            for (int i = 1; i < sz - 1; i++) {
                avg += vRightGass[i];
            }
            avgRightGass = avg / (sz - 2);
        }
        szDist = avgDist;
        leftGassDist = avgLeftGass;
        rightGassDist = avgRightGass;
        minEdgeX = xMinResult[3];
        minEdgeY = yMinResult[3];
        maxEdgeX = xMaxResult[3];
        maxEdgeY = yMaxResult[3];
        minGasX = minEdgeX + leftGassDist - 1;
        minGasY = minEdgeY;
        maxGasX = maxEdgeX - rightGassDist + 1;
        maxGasY = maxEdgeY;
        delete[] imgData;
        imgData = nullptr;
    }
    catch (...) {
        delete[] imgData;
        imgData = nullptr;
    }
}
bool CInspectCamera::MeasureResultProc(MeasurePoint* ptResult, int dotNum, int leftThres, int rightRes, int gasThres, double fzDist,
    double& minX, double& minY, double& maxX, double& maxY, double& minGasX, double& minGasY, double& maxGasX, double& maxGasY){
    /* code */
    minX = -1.0f;
    minY = -1.0f;
    maxX = -1.0f;
    maxY = -1.0f;
    minGasX = -1.0f;
    minGasY = -1.0f;
    if (dotNum < 2) return false;
    //1. 首先查找minX, minY
    bool bMinFin = false;
    minX = MAXINT;
    for (int i = 0; i < dotNum; i++) {
        if (fabs(ptResult[i].cy) > leftThres && ptResult[i].x < minX) {
            minX = ptResult[i].x;
            minY = ptResult[i].y;
            bMinFin = true;
        }
    }
    if (!bMinFin) {
        minX = -1.0f;
        minY = -1.0f;
    }
    //2. 查找左右点
    bool bMaxFind = false;
    maxX = -1.0f;
    for (int i = 0; i < dotNum; i++) {
        if (fabs(ptResult[i].cy) > rightRes && ptResult[i].x > maxX) {
            maxX = ptResult[i].x;
            maxY = ptResult[i].y;
            bMaxFind = true;
        }
    }
    if (!bMaxFind) {
        maxX = -1.0f;
        maxY = -1.0f;
    }
    //3. 查找最小气体点
    if (bMinFin) {
        bool bFind = false;
        minGasX = MAXINT;
        for (int i = 0; i < dotNum; i++) {
            double dx = ptResult[i].x - minX;
            double dy = ptResult[i].y - minY;
            double dist = sqrt(dx * dx + dy * dy);
            if (dist > fzDist) {
                if (fabs(ptResult[i].cy) > gasThres && ptResult[i].x < minGasX && ptResult[i].x > minX) {
                    minGasX = ptResult[i].x;
                    minGasY = ptResult[i].y;
                    bFind = true;
                }
            }
        }
        if (!bFind) {
            minGasX = -1.0f;
            minGasY = -1.0f;
        }
    }
    //4. 查找最大气体点
    if (bMaxFind) {
        bool bFind = false;
        maxGasX = -1.0f;
        for (int i = 0; i < dotNum; i++) {
            double dx = ptResult[i].x - maxX;
            double dy = ptResult[i].y - maxY;
            double dist = sqrt(dx * dx + dy * dy);
            if (dist > fzDist) {
                if (fabs(ptResult[i].cy) > gasThres && ptResult[i].x > maxGasX && ptResult[i].x < maxX) {
                    maxGasX = ptResult[i].x;
                    maxGasY = ptResult[i].y;
                    bFind = true;
                }
            }
        }
        if (!bFind) {
            maxGasX = -1.0f;
            maxGasY = -1.0f;
        }
    }
    return true;
}
int CInspectCamera::CutImageROI(uchar* img, DimensionDir eDim, int x1, int y1, int x2, int y2) {
    /* code */
    int iScan = m_pHardparm->GetScanToDimension(eDim);
    int width = x2 - x1 + 1;
    for (int i = y1; i <= y2; i++) {
        LPBYTE lp =    m_pGrabber->GetFrameHeaderLine(iScan, i);
        std::memcpy(img+ (i-y1) * width, lp+x1, width);
    }
    return 1;
}
BOOL CInspectCamera::CheckThreadEnd(int iThread, stFrameIndex stFrame)
@@ -6261,7 +6713,6 @@
        bool bIsRipSide = (emDim == DIMENSION_A_RIP || emDim == DIMENSION_B_RIP || emDim == DIMENSION_C_RIP || emDim == DIMENSION_D_RIP);
        if (bIsRipSide) {
            CRIP_THICKNESS_PARM& rip = m_pRecipe->m_SideParam[emDim].m_RipThk;
            return TRUE;
        }
EdgeInspector_App/Process/InspectCamera.h
@@ -139,6 +139,18 @@
    //13. 视觉功能
    void FinallyVisionProc(DimensionDir eDim);
    //14. 截图图像
    int CutImageROI(uchar* img, DimensionDir eDim, int x1, int y1, int x2, int y2);
    BOOL MeasureSideEdge_EI(DimensionDir eDim);
    void MeasureSideEdge_POS(DimensionDir eDim,
        int x1, int y1, int x2, int y2,
        int leftThres, int rightThres, int gassThres,
        double& minEdgeX, double& minEdgeY, double& maxEdgeX, double& maxEdgeY,
        double& minGasX, double& minGasY, double& maxGasX, double& maxGasY,
        double& szDist, double& leftGassDist, double& rightGassDist);
    bool MeasureResultProc(MeasurePoint* ptResult, int dotNum, int leftThres, int rightRes, int gasThres, double fzDist,
        double& minX, double& minY, double& maxX, double& maxY, double& minGasX, double& minGasY, double& maxGasX, double& maxGasY);
protected:    
    void                SaveFullImageCopy(int iScan);
EdgeInspector_App/Recipe/GlassRecipe.cpp
@@ -725,6 +725,8 @@
    for(int nUserDefectAreaIdx=0; nUserDefectAreaIdx<m_nUserDefectAreaCount; nUserDefectAreaIdx++)
        m_UserDefectPrm[nUserDefectAreaIdx].ReadRecipe(pFile, nSideIdx, nUserDefectAreaIdx);
    m_RipThk.ReadRecipe(pFile, nSideIdx);
    return TRUE;
}
@@ -894,6 +896,8 @@
    for(int nUserDefectAreaIdx=0; nUserDefectAreaIdx<m_nUserDefectAreaCount; nUserDefectAreaIdx++)
        m_UserDefectPrm[nUserDefectAreaIdx].WriteRecipe(pFile, nSideIdx, nUserDefectAreaIdx);
    m_RipThk.WriteRecipe(pFile, nSideIdx);
    return TRUE;
}