// FieldMgr.cpp : implementation file // #include "stdafx.h" #include "OTSModel.h" #include "FieldMgr.h" #include "COTSUtilityDllFunExport.h" #include "otsdataconst.h" namespace OTSMODEL { namespace { // fill the matrics with the spiral sequence number ,n*n is the largest fill number. // the row and col number should be odd number. void getSpiralMatrics(std::vector >& arrays,int row,int col) { int n = max(col, row); arrays.resize(n, std::vector(n)); int c = 0, i, j; int z = n * n; int ou = z; while (ou >= 1) { i = 0; j = 0; for (i += c, j += c; j < n - c; j++)//从左到右 { if (ou > z) break; arrays[i][j] = ou--; } for (j--, i++; i < n - c; i++) // 从上到下 { if (ou > z) break; arrays[i][j] = ou--; } for (i--, j--; j >= c; j--)//从右到左 { if (ou > z) break; arrays[i][j] = ou--; } for (j++, i--; i >= c + 1; i--)//从下到上 { if (ou > z) break; arrays[i][j] = ou--; } c++; } // if col<>row then shift the matrics so that the smallest number is in the center of the row*col's matrics. if (row > col) { int offset = (row - col) / 2; for (int k = 0; k < col; k++)//move mat to left (row-col)/2 cols. { for (int m = 0; m < row; m++) { arrays[m][k] = arrays[m][k + offset]; } } } else if (col > row) { int offset = (col - row) / 2; for (int k = 0; k < row; k++)//move mat to up (col-row)/2 cols. { for (int m = 0; m < col; m++) { arrays[k][m] = arrays[k+offset][m]; } } } } void getDownUpMeanderMatrics(std::vector >& arrays, int row, int col) { arrays.resize(row, std::vector(col)); for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (i % 2 == 0) { arrays[i][j] = col * i + j+1; } else { arrays[i][j] = col * i+(col- j); } } } } void getUpDownMeanderMatrics(std::vector >& arrays, int row, int col) { arrays.resize(row, std::vector(col)); for (int i = 0; i & a_listMeasuredFieldCentrePoints) { // input check ASSERT(a_pMeasureArea); ASSERT(a_poImageScanParam); ASSERT(a_poSEMDataMsr); // assign class member m_pMeasureArea = CDomainPtr(new CDomain(a_pMeasureArea.get())); m_poImageScanParam = COTSImageScanParamPtr(new COTSImageScanParam(a_poImageScanParam.get())); m_poSEMDataMsr = CSEMDataMsrPtr(new CSEMDataMsr(a_poSEMDataMsr.get())); // calculate field centre points list if (!CalculateFieldCentrePoints1(a_listMeasuredFieldCentrePoints)) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMsr: failed to call CalculateFieldCentrePoints method.")); return FALSE; } // ok, return TRUE; return TRUE; } // reset BOOL CFieldMgr::Reset(CDomainPtr a_pMeasureArea, COTSImageScanParamPtr a_poImageScanParam, CSEMDataMsrPtr a_poSEMDataMsr, std::vector& a_listMeasuredFieldCentrePoints) { // input check ASSERT(a_pMeasureArea); if (!a_pMeasureArea || a_pMeasureArea->IsInvalid()) { LogErrorTrace(__FILE__, __LINE__, _T("Reset: invalid measure area poiter.")); return FALSE; } ASSERT(a_poImageScanParam); if (!a_poImageScanParam) { LogErrorTrace(__FILE__, __LINE__, _T("Reset: invalid image scan parameter poiter.")); return FALSE; } ASSERT(a_poSEMDataMsr); if (!a_poSEMDataMsr || (*(a_poSEMDataMsr.get()) == CSEMDataMsr())) { LogErrorTrace(__FILE__, __LINE__, _T("Reset: invalid SEM data (measurement) poiter.")); return FALSE; } // check member parameters ASSERT(m_pMeasureArea && m_poImageScanParam && m_poSEMDataMsr); if (!m_pMeasureArea || !m_poImageScanParam || !m_poSEMDataMsr) { // shouldn't happen LogErrorTrace(__FILE__, __LINE__, _T("Reset: invalid member parameter(s).")); return FALSE; } // check if need to re-do field centres calculation if (!(*(a_pMeasureArea.get()) == *(m_pMeasureArea.get())) || // measure domain has been changed a_poImageScanParam->GetStartImageMode() != m_poImageScanParam->GetStartImageMode() || // start mode has been changed a_poSEMDataMsr->GetScanFieldSize() != m_poSEMDataMsr->GetScanFieldSize()) { // need to re-do field centres calculation return Init(a_pMeasureArea, a_poImageScanParam, a_poSEMDataMsr, a_listMeasuredFieldCentrePoints); } // reset measured field centre points list m_listMeasuredFieldCentrePoints = a_listMeasuredFieldCentrePoints; // reset unmeasured field centre points list m_listUnmeasuredFieldCentrePoints.clear(); // go through field centre points list for (auto poiFieldCentre : m_listFieldCentrePoints) { // make sure the centre field is not in the measured field centre points list if (!IsInMeasuredFieldList(poiFieldCentre)) { // add the field centre into the unmeasured field centre points list m_listUnmeasuredFieldCentrePoints.push_back(poiFieldCentre); } } // ok, return TRUE; return TRUE; } // calculate total fields long CFieldMgr::CalculateTotalFields(CDomainPtr a_poMeasureArea, double a_dScanFieldSizeX, CSize a_sizePixelImage) { // total fields long nTotalFields = -1; // input check ASSERT(a_poMeasureArea); if (!a_poMeasureArea || a_poMeasureArea->IsInvalid()) { LogErrorTrace(__FILE__, __LINE__, _T("CalculateTotalFields: invalid mesure area point.")); return nTotalFields; } // calculate scan field size--Y double dScanFieldSizeY = a_dScanFieldSizeX * (double)a_sizePixelImage.cy / (double)a_sizePixelImage.cx; // calculate total columns long nTotalCols = (long)ceil((double)a_poMeasureArea->GetDomainRect().Width() / a_dScanFieldSizeX); // calculate total rows long nTotalRows = (long)ceil((double)a_poMeasureArea->GetDomainRect().Height() / dScanFieldSizeY); // calculate column on the right of the center column long nRightColumns = nTotalCols / 2; // calculate rows above the center row long nTopRows = nTotalRows / 2; // re-calculate total columns, total rows make sure they are odd numbers nTotalCols = nRightColumns * 2 + 1; nTotalRows = nTopRows * 2 + 1; // measure are is a rectangle? if (a_poMeasureArea->IsRect() || nTotalCols == 1 || nTopRows == 1) { // easy nTotalFields = nTotalCols * nTopRows; } else { // we need to do more calculation // centre row, centre column and centre field nTotalFields = nRightColumns * 2 + nTotalRows * 2 + 1; // calculate top right part int nTopRightPartFileds = 0; CPoint poi; // row by row for (int i = 1; i <= nTopRows; ++i) { // calculate row y position (field bottom) poi.y = a_poMeasureArea->GetDomainCenter().y + (int)dScanFieldSizeY * i - (int)dScanFieldSizeY / 2; // column by column for (int j = 1; j <= nRightColumns; ++j) { // calculate column x position (field left) poi.x = a_poMeasureArea->GetDomainCenter().x + (int)a_dScanFieldSizeX * i - (int)a_dScanFieldSizeX / 2; // test if this field is in the measure domain if (a_poMeasureArea->PtInDomain(poi)) { // in the measure domain, count it. ++nTopRightPartFileds; } else { // not in the measure domain, get out row test break; } } } // add other fields (top right part fields times 4) nTotalFields += nTopRightPartFileds * 4; } // return total fields return nTotalFields; } // field centre points list BOOL CFieldMgr::GetFieldRectByIndex(int a_nIndex, CRect& a_rectField) { // check input if (a_nIndex < 0 || a_nIndex >(int)m_listFieldCentrePoints.size()) { LogErrorTrace(__FILE__, __LINE__, _T("GetFieldRectByIndex: invalid intex value.")); return FALSE; } // check member parameters ASSERT( m_poImageScanParam && m_poSEMDataMsr); if (!m_poImageScanParam || !m_poSEMDataMsr) { // shouldn't happen LogErrorTrace(__FILE__, __LINE__, _T("GetFieldRectByIndex: invalid member parameter(s).")); return FALSE; } // get image size OTS_FIVE_TIES_OPTIONS nImageSizeId = m_poImageScanParam->GetImagePixelSize(); int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId; CSize sizePixelImage = RESOLUTION_VALUE[nResulotionId]; // scan field size (x, y) CSize sizeImage; sizeImage.cx = m_poSEMDataMsr->GetScanFieldSize(); sizeImage.cy = sizeImage.cx * sizePixelImage.cy / sizePixelImage.cx; // get left top CPoint ptLeftTop = m_listFieldCentrePoints[a_nIndex] - CPoint(sizeImage.cx / 2, sizeImage.cy / 2); // get field rectangle a_rectField = CRect(ptLeftTop, sizeImage); return TRUE; } // unmeasured field centre points list BOOL CFieldMgr::UnmeasuredGetNextField(CRect& a_rectField) { // any unmeasured field left? if (m_listUnmeasuredFieldCentrePoints.empty()) { // no field left, return FALSE return FALSE; } // check member parameters ASSERT(m_poImageScanParam && m_poSEMDataMsr); if (!m_poImageScanParam || !m_poSEMDataMsr) { // shouldn't happen LogErrorTrace(__FILE__, __LINE__, _T("GetNextField: invalid member parameter(s).")); return FALSE; } // get image size OTS_FIVE_TIES_OPTIONS nImageSizeId = m_poImageScanParam->GetImagePixelSize(); int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId; CSize sizePixelImage = RESOLUTION_VALUE[nResulotionId].cx; // scan field size (x, y) CSize sizeImage; sizeImage.cx = m_poSEMDataMsr->GetScanFieldSize(); sizeImage.cy = sizeImage.cx * sizePixelImage.cy / sizePixelImage.cx; // get field rectangle a_rectField = CRect(m_listUnmeasuredFieldCentrePoints[0], sizeImage); return TRUE; } BOOL CFieldMgr::GetUnmeasuredRandemField(CRect& a_rectField) { // any field left? if (m_listUnmeasuredFieldCentrePoints.empty()) { // no field left, return FALSE return FALSE; } // check member parameters ASSERT(m_poImageScanParam && m_poSEMDataMsr); if (!m_poImageScanParam || !m_poSEMDataMsr) { // shouldn't happen LogErrorTrace(__FILE__, __LINE__, _T("GetNextField: invalid member parameter(s).")); return FALSE; } // get image size OTS_FIVE_TIES_OPTIONS nImageSizeId = m_poImageScanParam->GetImagePixelSize(); int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId; CSize sizePixelImage = RESOLUTION_VALUE[nResulotionId].cx; // scan field size (x, y) CSize sizeImage; sizeImage.cx = m_poSEMDataMsr->GetScanFieldSize(); sizeImage.cy = sizeImage.cx * sizePixelImage.cy / sizePixelImage.cx; // get the first field if there is only one field left in the field list int nIndex = 0; if ((int)m_listUnmeasuredFieldCentrePoints.size() >= 2) { // get a random number (less than the unmeasured field indexes vector size) nIndex = GetRangedRandNumber(0, (int)m_listUnmeasuredFieldCentrePoints.size() - 1); } // get field rectangle a_rectField = CRect(m_listUnmeasuredFieldCentrePoints[nIndex], sizeImage); // ok, return TRUE return TRUE; } void CFieldMgr::SetFieldCentrePoints(std::vector listPoint) { for (auto opt : listPoint) { m_listFieldCentrePoints.push_back(opt); } } void CFieldMgr::SetUnmeasuredFieldCentrePoints(std::vector listPoint) { for (auto opt : listPoint) { m_listUnmeasuredFieldCentrePoints.push_back(opt); } } // measured field centre points list void CFieldMgr::SetMeasuredFieldCentrePoints(std::vector listPoint) { for (auto opt : listPoint) { m_listMeasuredFieldCentrePoints.push_back(opt); } } // measure area void CFieldMgr::SetMeasureArea(CDomainPtr a_pMeasureArea) { // input check ASSERT(a_pMeasureArea); if (!a_pMeasureArea) { LogErrorTrace(__FILE__, __LINE__, _T("SetMeasureArea: invalid measure area poiter.")); return; } m_pMeasureArea = CDomainPtr(new CDomain(a_pMeasureArea.get())); } // image scan parameter void CFieldMgr::SetImageScanParam(COTSImageScanParamPtr a_poImageScanParam) { // input check ASSERT(a_poImageScanParam); if (!a_poImageScanParam) { LogErrorTrace(__FILE__, __LINE__, _T("SetImageScanParam: invalid image scan parameter poiter.")); return; } m_poImageScanParam = COTSImageScanParamPtr(new COTSImageScanParam(a_poImageScanParam.get())); } // SEM data (measurement) void CFieldMgr::SetSEMDataMsr(CSEMDataMsrPtr a_poSEMDataMsr) { // input check ASSERT(a_poSEMDataMsr); if (!a_poSEMDataMsr) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMsr: invalid SEM data (measurement) poiter.")); return; } m_poSEMDataMsr = CSEMDataMsrPtr(new CSEMDataMsr(a_poSEMDataMsr.get())); } // protected // calculate field centre points list BOOL CFieldMgr::CalculateFieldCentrePoints1(std::vector& a_listMeasuredFieldCentrePoints) { // check member parameters ASSERT(m_pMeasureArea && m_poImageScanParam && m_poSEMDataMsr); if (!m_pMeasureArea || !m_poImageScanParam || !m_poSEMDataMsr) { // shouldn't happen LogErrorTrace(__FILE__, __LINE__, _T("CalculateFieldCentrePoints: invalid member parameter(s).")); return FALSE; } // clean up m_listFieldCentrePoints.clear(); m_listUnmeasuredFieldCentrePoints.clear(); m_listMeasuredFieldCentrePoints.clear(); // set measured field centre points list m_listMeasuredFieldCentrePoints = a_listMeasuredFieldCentrePoints; // prepare necessary parameters // get image size OTS_FIVE_TIES_OPTIONS nImageSizeId = m_poImageScanParam->GetImagePixelSize(); int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId; CSize sizePixelImage = RESOLUTION_VALUE[nResulotionId]; // scan field size (x, y) CSize sizeImage; sizeImage.cx = m_poSEMDataMsr->GetScanFieldSize(); sizeImage.cy = sizeImage.cx * sizePixelImage.cy / sizePixelImage.cx; double dScanFiledSizeX = (double)sizeImage.cx; double dScanFiledSizeY = (double)sizeImage.cy; // pixel size (micros) double dPixelSize = (double)dScanFiledSizeX / (double)sizeImage.cx; // the measure domain rectangle CRect rectMeasureDomain = m_pMeasureArea->GetDomainRect(); // the measure domain centre CPoint poiDomainCentre = rectMeasureDomain.CenterPoint(); // field centres need to be aligned with measured field centres if (0 < (int)a_listMeasuredFieldCentrePoints.size()) { // get the first measured centre CPoint poiMeasuredFieldCentre = a_listMeasuredFieldCentrePoints[0]; // distance between the measure domain centre and the first measured field int nDistanceX = abs(poiDomainCentre.x - poiMeasuredFieldCentre.x); int nDistanceY = abs(poiDomainCentre.y - poiMeasuredFieldCentre.y); // minimum shift int nMinShiftX = 0; int nMinShiftY = 0; // x direction shift if (nDistanceX != 0) {// calculate shift distance int nShiftX = nDistanceX % (int)(dScanFiledSizeX); // need to move? if (nShiftX != 0) { // need to shift on x direction // calculate the minimum shift , there must be something wrong, one is number, one is mm nMinShiftX = min(nShiftX, ((int)(dScanFiledSizeX)-nShiftX)); // check if domain centre on left side of the first measured centre if (poiDomainCentre.x > poiMeasuredFieldCentre.x) { // shift domain centre left nShiftX should make the two aligned // shift to left or right if (nMinShiftX == nShiftX) { // left poiDomainCentre.x -= nMinShiftX; } else { // right poiDomainCentre.x += nMinShiftX; } } else { // shift domain centre right nShiftX should make the two aligned // shift to left or right if (nMinShiftX != nShiftX) { // left poiDomainCentre.x -= nMinShiftX; } else { // right poiDomainCentre.x += nMinShiftX; } } } } // y direction shift if (nDistanceY != 0) { // calculate shift distance int nShiftY = nDistanceY % (int)(dScanFiledSizeY); // need to move? if (nShiftY != 0) { // need to shift on x direction // calculate the minimum shift nMinShiftY = min(nShiftY, ((int)(dScanFiledSizeY)-nShiftY)); // check if domain centre on top of the first measured centre if (poiDomainCentre.y > poiMeasuredFieldCentre.y) { // shift domain centre down nShiftY should make the two aligned // move down or up? if (nMinShiftY == nShiftY) { // move down poiDomainCentre.y -= nMinShiftY; } else { // move up poiDomainCentre.y += nMinShiftY; } } else { // shift domain centre up nShiftY should make the two aligned // move down or up? if (nMinShiftY == nShiftY) { // move up poiDomainCentre.y += nMinShiftY; } else { // move down poiDomainCentre.y -= nMinShiftY; } } } } // reset the measure domain rectangle // domain size CSize sizeMeasureDomain = rectMeasureDomain.Size(); sizeMeasureDomain.cx += 2 * nMinShiftX; sizeMeasureDomain.cy += 2 * nMinShiftY; rectMeasureDomain = CRect(poiDomainCentre, sizeMeasureDomain); } // start mode OTS_GET_IMAGE_MODE nStartMode = m_poImageScanParam->GetStartImageMode(); // calculate total columns, rows and make sure the domain area be covered int nTotalCols = (int)(ceil((double)rectMeasureDomain.Width() / dScanFiledSizeX)); int nTotalRows = (int)(ceil((double)rectMeasureDomain.Height() / dScanFiledSizeY)); // calculate column on the left of the centre point int nLeftCols = nTotalCols / 2; int nRightCols = nLeftCols; // fields on top int nRowsOnTop = nTotalRows / 2; // sure total columns, rows are odd numbers nTotalCols = nLeftCols * 2 + 1; //nTotalRows = nTotalRows * 2 + 1; nTotalRows = nRowsOnTop * 2 + 1; // calculate left, right field column position (x only int nLeftMostColX = poiDomainCentre.x - nLeftCols * (int)dScanFiledSizeX; int nUpMostRowY = poiDomainCentre.y - nRowsOnTop * (int)dScanFiledSizeY; std::vector > pointMatrics(nTotalRows, std::vector(nTotalCols)); for (int i = 0; i < nTotalRows; i++) { for (int j = 0; j < nTotalCols; j++) { pointMatrics[i][j].x = nLeftMostColX + j * (int)dScanFiledSizeX; pointMatrics[i][j].y = nUpMostRowY + i * (int)dScanFiledSizeY; } } std::vector > sequenceMat; //construct an matrics map to the pointMatrics,but the content is the sequence number. switch (nStartMode) { case OTS_GET_IMAGE_MODE::FROM_CENTER: getSpiralMatrics(sequenceMat, nTotalRows,nTotalCols); break; case OTS_GET_IMAGE_MODE::UP_TO_DOWN : getUpDownMeanderMatrics(sequenceMat, nTotalRows, nTotalCols); break; case OTS_GET_IMAGE_MODE::DOWN_TO_UP : case OTS_GET_IMAGE_MODE::RANDOM : getDownUpMeanderMatrics(sequenceMat, nTotalRows, nTotalCols); break; } std::map mapCenterPoint; for (int i = 0; i < nTotalRows; i++) { for (int j = 0; j < nTotalCols; j++) { int sequenceNum = sequenceMat[i][j]; CPoint p = pointMatrics[i][j]; mapCenterPoint[sequenceNum] = p;// sorting all the field center point by the sequence number. } } // 判断当前样品获取帧图信息的测量区域为多边形 if (m_pMeasureArea->GetPolygonPoint().size() > 0) { std::vector ptPolygon = m_pMeasureArea->GetPolygonPoint(); for (auto itr : mapCenterPoint) { CPoint itrPoint = itr.second; if (IsInPolygonMeasureArea(itrPoint, sizeImage, ptPolygon)) //if (PtInPolygon(itrPoint, ptPolygon)) { m_listFieldCentrePoints.push_back(itr.second); if (!IsInMeasuredFieldList(itr.second)) { // add the field centre into the unmeasured field centre points list m_listUnmeasuredFieldCentrePoints.push_back(itr.second); } } } } else { for (auto itr : mapCenterPoint) { if (IsInMeasureArea(itr.second, sizeImage)) { m_listFieldCentrePoints.push_back(itr.second); if (!IsInMeasuredFieldList(itr.second )) { // add the field centre into the unmeasured field centre points list m_listUnmeasuredFieldCentrePoints.push_back(itr.second); } } } } return TRUE; } // test if field is in or partly in the measure domain area BOOL CFieldMgr::IsInPolygonMeasureArea(CPoint a_poiField, CSize a_sizeImageSize, std::vector ptPolygon) { // check measure area parameter ASSERT(m_pMeasureArea); if (!m_pMeasureArea) { // shouldn't happen LogErrorTrace(__FILE__, __LINE__, _T("IsInDomainArea: invalid measure area parameter.")); return FALSE; } // test field centre point first if (PtInPolygon(a_poiField, ptPolygon)) { // centre in the measure domain area, return TRUE return TRUE; } // get measure field centre CPoint poiMsrAreaCentre = m_pMeasureArea->GetDomainCenter(); // move to left top postion. a_poiField -= CPoint(a_sizeImageSize.cx / 2, a_sizeImageSize.cy / 2); // rectangle of the field CRect rectFiled(a_poiField, a_sizeImageSize); //// check field position //if (rectFiled.left <= poiMsrAreaCentre.x && rectFiled.right >= poiMsrAreaCentre.x) //{ // // centre column field or centre field // return TRUE; //} //else if (rectFiled.top <= poiMsrAreaCentre.y && rectFiled.bottom >= poiMsrAreaCentre.y) //{ // // centre row field? // return TRUE; //} //else if (rectFiled.right <= poiMsrAreaCentre.x) //{ // // on the left side // //up // if (rectFiled.top >= poiMsrAreaCentre.y) // { // // on the top left side, need to test the bottom right corner if (PtInPolygon(CPoint(rectFiled.right, rectFiled.top), ptPolygon)) { return TRUE; } // } // else if (rectFiled.bottom <= poiMsrAreaCentre.y) //down// // { // // on the bottom left side, need to test the top right corner if (PtInPolygon(rectFiled.BottomRight(), ptPolygon)) { return TRUE; } // } //} //else if (rectFiled.left >= poiMsrAreaCentre.x) //{ // // on the right side // //up // if (rectFiled.top >= poiMsrAreaCentre.y) // { // // on the top left side, need to test the bottom right corner if (PtInPolygon(rectFiled.TopLeft(), ptPolygon)) { return TRUE; } // } // else if (rectFiled.bottom <= poiMsrAreaCentre.y) //down// // { // // on the bottom left side, need to test the top right corner if (PtInPolygon(CPoint(rectFiled.left, rectFiled.bottom), ptPolygon)) { return TRUE; } // } //} // this field is not in the area at all, return FALSE. return FALSE; } //作用:判断点是否在多边形内 //p指目标点, ptPolygon指多边形的点集合, nCount指多边形的边数 BOOL CFieldMgr::PtInPolygon(CPoint p, std::vector ptPolygon) { int nCount = ptPolygon.size(); // 交点个数 int nCross = 0; for (int i = 0; i < nCount; i++) { CPoint p1 = ptPolygon[i]; CPoint p2 = ptPolygon[(i + 1) % nCount];// 点P1与P2形成连线 if (p1.y == p2.y) continue; if (p.y < min(p1.y, p2.y)) continue; if (p.y >= max(p1.y, p2.y)) continue; // 求交点的x坐标(由直线两点式方程转化而来) double x = (double)(p.y - p1.y) * (double)(p2.x - p1.x) / (double)(p2.y - p1.y) + p1.x; // 只统计p1p2与p向右射线的交点 if (x > p.x) { nCross++; } } // 交点为偶数,点在多边形之外 // 交点为奇数,点在多边形之内 if ((nCross % 2) == 1) { //true; return TRUE; } else { //false; return FALSE; } } // test if field is in or partly in the measure domain area BOOL CFieldMgr::IsInMeasureArea(CPoint a_poiField, CSize a_sizeImageSize) { // check measure area parameter ASSERT(m_pMeasureArea); if (!m_pMeasureArea) { // shouldn't happen LogErrorTrace(__FILE__, __LINE__, _T("IsInDomainArea: invalid measure area parameter.")); return FALSE; } // test field centre point first if (m_pMeasureArea->PtInDomain(a_poiField)) { // centre in the measure domain area, return TRUE return TRUE; } // get measure field centre CPoint poiMsrAreaCentre = m_pMeasureArea->GetDomainCenter(); // move to left top postion. a_poiField -= CPoint(a_sizeImageSize.cx / 2, a_sizeImageSize.cy / 2); // rectangle of the field CRect rectFiled(a_poiField, a_sizeImageSize); // check field position if (rectFiled.left <= poiMsrAreaCentre.x && rectFiled.right >= poiMsrAreaCentre.x) { // centre column field or centre field return TRUE; } else if (rectFiled.top <= poiMsrAreaCentre.y && rectFiled.bottom >= poiMsrAreaCentre.y) { // centre row field? return TRUE; } else if ( rectFiled.right <= poiMsrAreaCentre.x) { // on the left side //up if (rectFiled.top >= poiMsrAreaCentre.y) { // on the top left side, need to test the bottom right corner if (m_pMeasureArea->PtInDomain(CPoint(rectFiled.right, rectFiled.top))) { return TRUE; } } else if(rectFiled.bottom <= poiMsrAreaCentre.y) //down// { // on the bottom left side, need to test the top right corner if (m_pMeasureArea->PtInDomain(rectFiled.BottomRight())) { return TRUE; } } } else if(rectFiled.left >= poiMsrAreaCentre.x) { // on the right side //up if (rectFiled.top >= poiMsrAreaCentre.y) { // on the top left side, need to test the bottom right corner if (m_pMeasureArea->PtInDomain(rectFiled.TopLeft())) { return TRUE; } } else if (rectFiled.bottom <= poiMsrAreaCentre.y) //down// { // on the bottom left side, need to test the top right corner if (m_pMeasureArea->PtInDomain(CPoint(rectFiled.left, rectFiled.bottom))) { return TRUE; } } } // this field is not in the area at all, return FALSE. return FALSE; } // test if field is in the measured field centre points list BOOL CFieldMgr::IsInMeasuredFieldList(CPoint a_poiField) { // has to not be in the measured field centre points list auto itr = std::find(m_listMeasuredFieldCentrePoints.begin(), m_listMeasuredFieldCentrePoints.end(), a_poiField); if (itr != m_listMeasuredFieldCentrePoints.end()) { // in the measured field centre points list, this is a measured field, return TRUE return TRUE; } // ok, return FALSE return FALSE; } // get a random number in a given range int CFieldMgr::GetRangedRandNumber(int a_nRange_min, int a_nRange_max) { // return a random number int nRet; // get a random number in the given range nRet = long((double)rand() / (RAND_MAX + 1) * (a_nRange_max - a_nRange_min) + a_nRange_min); // return the random number return nRet; } }