FieldMgr.cpp 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  1. // FieldMgr.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "otsdataconst.h"
  5. #include "FieldMgr.h"
  6. #include "../OTSLog/COTSUtilityDllFunExport.h"
  7. namespace OTSIMGPROC {
  8. namespace {
  9. // fill the matrics with the spiral sequence number ,n*n is the largest fill number.
  10. // the row and col number should be odd number.
  11. void getSpiralMatrics(std::vector <std::vector <int>>& arrays,int row,int col)
  12. {
  13. int n = max(col, row);
  14. arrays.resize(n, std::vector<int>(n));
  15. int c = 0, i, j;
  16. int z = n * n;
  17. int ou = z;
  18. while (ou >= 1)
  19. {
  20. i = 0;
  21. j = 0;
  22. for (i += c, j += c; j < n - c; j++)//从左到右
  23. {
  24. if (ou > z) break;
  25. arrays[i][j] = ou--;
  26. }
  27. for (j--, i++; i < n - c; i++) // 从上到下
  28. {
  29. if (ou > z) break;
  30. arrays[i][j] = ou--;
  31. }
  32. for (i--, j--; j >= c; j--)//从右到左
  33. {
  34. if (ou > z) break;
  35. arrays[i][j] = ou--;
  36. }
  37. for (j++, i--; i >= c + 1; i--)//从下到上
  38. {
  39. if (ou > z) break;
  40. arrays[i][j] = ou--;
  41. }
  42. c++;
  43. }
  44. // if col<>row then shift the matrics so that the smallest number is in the center of the row*col's matrics.
  45. if (row > col)
  46. {
  47. int offset = (row - col) / 2;
  48. for (int k = 0; k < col; k++)//move mat to left (row-col)/2 cols.
  49. {
  50. for (int m = 0; m < row; m++)
  51. {
  52. arrays[m][k] = arrays[m][k + offset];
  53. }
  54. }
  55. }
  56. else if (col > row)
  57. {
  58. int offset = (col - row) / 2;
  59. for (int k = 0; k < row; k++)//move mat to up (col-row)/2 cols.
  60. {
  61. for (int m = 0; m < col; m++)
  62. {
  63. arrays[k][m] = arrays[k+offset][m];
  64. }
  65. }
  66. }
  67. }
  68. void getDownUpMeanderMatrics(std::vector <std::vector <int>>& arrays, int row, int col)
  69. {
  70. arrays.resize(row, std::vector<int>(col));
  71. for (int i = 0; i < row; i++)
  72. {
  73. for (int j = 0; j < col; j++)
  74. {
  75. if (i % 2 == 0)
  76. {
  77. arrays[i][j] = col * i + j+1;
  78. }
  79. else
  80. {
  81. arrays[i][j] = col * i+(col- j);
  82. }
  83. }
  84. }
  85. }
  86. void getUpDownMeanderMatrics(std::vector <std::vector <int>>& arrays, int row, int col)
  87. {
  88. arrays.resize(row, std::vector<int>(col));
  89. for (int i = 0; i <row; i++)
  90. {
  91. for (int j = 0; j < col; j++)
  92. {
  93. if (i % 2 == 0)
  94. {
  95. arrays[i][j] = col * (row-i) + j + 1;
  96. }
  97. else
  98. {
  99. arrays[i][j] = col *(row- i) + (col - j);
  100. }
  101. }
  102. }
  103. }
  104. }
  105. using namespace OTSDATA;
  106. // CFieldMgr
  107. CFieldMgr::CFieldMgr(int scanfieldsize)
  108. {
  109. m_ScanFieldSize = scanfieldsize;
  110. m_pMeasureArea=nullptr;
  111. }
  112. CFieldMgr::~CFieldMgr()
  113. {
  114. }
  115. // CFieldMgr member functions
  116. // public
  117. // initialization
  118. BOOL CFieldMgr::Init(CDomainPtr a_pMeasureArea, CSize a_ResolutionSize,int a_scanfieldsize,int a_FieldStartMode)
  119. {
  120. // input check
  121. ASSERT(a_pMeasureArea);
  122. // assign class member
  123. m_pMeasureArea = CDomainPtr(new CDomain(a_pMeasureArea.get()));
  124. m_ResolutionSize = a_ResolutionSize;
  125. m_fieldStartMode = a_FieldStartMode;
  126. m_ScanFieldSize = a_scanfieldsize;
  127. // calculate field centre points list
  128. // ok, return TRUE;
  129. return TRUE;
  130. }
  131. std::vector<CPoint> CFieldMgr::GetUnmeasuredFieldCentrePoints(std::vector<CPoint> a_listMeasuredFieldCentrePoints)
  132. {
  133. std::vector<CPoint> allPoints = CalculateFieldCentrePoints1();
  134. std::vector<CPoint> unmeasuredPoints;
  135. for(auto p:allPoints)
  136. if (!IsInMeasuredFieldList(p,a_listMeasuredFieldCentrePoints))
  137. {
  138. // add the field centre into the unmeasured field centre points list
  139. unmeasuredPoints.push_back(p);
  140. }
  141. return unmeasuredPoints;
  142. }
  143. // reset
  144. BOOL CFieldMgr::Reset(CDomainPtr a_pMeasureArea,
  145. CSize a_ResolutionSize, int a_FieldStartMode,
  146. int a_scanFieldSzie,
  147. std::vector<CPoint>& a_listMeasuredFieldCentrePoints)
  148. {
  149. // input check
  150. ASSERT(a_pMeasureArea);
  151. if (!a_pMeasureArea || a_pMeasureArea->IsInvalid())
  152. {
  153. LogErrorTrace(__FILE__, __LINE__, _T("Reset: invalid measure area poiter."));
  154. return FALSE;
  155. }
  156. // check member parameters
  157. //ASSERT(m_pMeasureArea && m_poImageScanParam && m_poSEMDataMsr);
  158. if (!m_pMeasureArea || m_ScanFieldSize==0)
  159. {
  160. // shouldn't happen
  161. LogErrorTrace(__FILE__, __LINE__, _T("Reset: invalid member parameter(s)."));
  162. return FALSE;
  163. }
  164. // check if need to re-do field centres calculation
  165. if (!(*(a_pMeasureArea.get()) == *(m_pMeasureArea.get())) || // measure domain has been changed
  166. a_FieldStartMode != m_fieldStartMode )
  167. {
  168. // need to re-do field centres calculation
  169. return Init(a_pMeasureArea, m_ResolutionSize, a_scanFieldSzie,m_fieldStartMode);
  170. }
  171. return TRUE;
  172. }
  173. // calculate total fields
  174. long CFieldMgr::CalculateTotalFields(CDomainPtr a_poMeasureArea, double a_dScanFieldSizeX, CSize a_sizePixelImage)
  175. {
  176. // total fields
  177. long nTotalFields = -1;
  178. // input check
  179. ASSERT(a_poMeasureArea);
  180. if (!a_poMeasureArea || a_poMeasureArea->IsInvalid())
  181. {
  182. LogErrorTrace(__FILE__, __LINE__, _T("CalculateTotalFields: invalid mesure area point."));
  183. return nTotalFields;
  184. }
  185. // calculate scan field size--Y
  186. double dScanFieldSizeY = a_dScanFieldSizeX * (double)a_sizePixelImage.cy / (double)a_sizePixelImage.cx;
  187. // calculate total columns
  188. long nTotalCols = (long)ceil((double)a_poMeasureArea->GetDomainRect().Width() / a_dScanFieldSizeX);
  189. // calculate total rows
  190. long nTotalRows = (long)ceil((double)a_poMeasureArea->GetDomainRect().Height() / dScanFieldSizeY);
  191. // calculate column on the right of the center column
  192. long nRightColumns = nTotalCols / 2;
  193. // calculate rows above the center row
  194. long nTopRows = nTotalRows / 2;
  195. // re-calculate total columns, total rows make sure they are odd numbers
  196. nTotalCols = nRightColumns * 2 + 1;
  197. nTotalRows = nTopRows * 2 + 1;
  198. // measure are is a rectangle?
  199. if (a_poMeasureArea->IsRect() || nTotalCols == 1 || nTopRows == 1)
  200. {
  201. // easy
  202. nTotalFields = nTotalCols * nTopRows;
  203. }
  204. else
  205. {
  206. // we need to do more calculation
  207. // centre row, centre column and centre field
  208. nTotalFields = nRightColumns * 2 + nTotalRows * 2 + 1;
  209. // calculate top right part
  210. int nTopRightPartFileds = 0;
  211. CPoint poi;
  212. // row by row
  213. for (int i = 1; i <= nTopRows; ++i)
  214. {
  215. // calculate row y position (field bottom)
  216. poi.y = a_poMeasureArea->GetDomainCenter().y + (int)dScanFieldSizeY * i - (int)dScanFieldSizeY / 2;
  217. // column by column
  218. for (int j = 1; j <= nRightColumns; ++j)
  219. {
  220. // calculate column x position (field left)
  221. poi.x = a_poMeasureArea->GetDomainCenter().x + (int)a_dScanFieldSizeX * i - (int)a_dScanFieldSizeX / 2;
  222. // test if this field is in the measure domain
  223. if (a_poMeasureArea->PtInDomain(poi))
  224. {
  225. // in the measure domain, count it.
  226. ++nTopRightPartFileds;
  227. }
  228. else
  229. {
  230. // not in the measure domain, get out row test
  231. break;
  232. }
  233. }
  234. }
  235. // add other fields (top right part fields times 4)
  236. nTotalFields += nTopRightPartFileds * 4;
  237. }
  238. // return total fields
  239. return nTotalFields;
  240. }
  241. // field centre points list
  242. BOOL CFieldMgr::GetFieldRectByIndex(int a_nIndex, CRect& a_rectField)
  243. {
  244. auto m_listFieldCentrePoints = CalculateFieldCentrePoints1();
  245. // check input
  246. if (a_nIndex < 0 || a_nIndex >(int)m_listFieldCentrePoints.size())
  247. {
  248. LogErrorTrace(__FILE__, __LINE__, _T("GetFieldRectByIndex: invalid intex value."));
  249. return FALSE;
  250. }
  251. // get image size
  252. CSize sizePixelImage = m_ResolutionSize;
  253. // scan field size (x, y)
  254. CSize sizeImage;
  255. sizeImage.cx = m_ScanFieldSize;
  256. sizeImage.cy = sizeImage.cx * sizePixelImage.cy / sizePixelImage.cx;
  257. // get left top
  258. CPoint ptLeftTop = m_listFieldCentrePoints[a_nIndex] - CPoint(sizeImage.cx / 2, sizeImage.cy / 2);
  259. // get field rectangle
  260. a_rectField = CRect(ptLeftTop, sizeImage);
  261. return TRUE;
  262. }
  263. // measure area
  264. void CFieldMgr::SetMeasureArea(CDomainPtr a_pMeasureArea)
  265. {
  266. // input check
  267. ASSERT(a_pMeasureArea);
  268. if (!a_pMeasureArea)
  269. {
  270. LogErrorTrace(__FILE__, __LINE__, _T("SetMeasureArea: invalid measure area poiter."));
  271. return;
  272. }
  273. m_pMeasureArea = CDomainPtr(new CDomain(a_pMeasureArea.get()));
  274. }
  275. COTSFieldDataPtr CFieldMgr::FindNeighborField(const COTSFieldDataList a_flds, COTSFieldDataPtr a_centerField, SORTING_DIRECTION a_direction)
  276. {
  277. COTSFieldDataPtr fld;
  278. double pixelsize;
  279. double mScanfieldsize_y = m_ScanFieldSize * m_ResolutionSize.cy / m_ResolutionSize.cx;
  280. for (auto f : a_flds)
  281. {
  282. SORTING_DIRECTION di;
  283. IsNeighborFieldCentre(f->GetPosition(), a_centerField->GetPosition(), m_ScanFieldSize, mScanfieldsize_y, di);
  284. if (di == a_direction)
  285. {
  286. return f;
  287. }
  288. }
  289. return fld;
  290. }
  291. // protected
  292. // calculate field centre points list
  293. std::vector<CPoint> CFieldMgr::CalculateFieldCentrePoints1()
  294. {
  295. // field centre points list
  296. std::vector<CPoint> m_listFieldCentrePoints;
  297. // clean up
  298. m_listFieldCentrePoints.clear();
  299. CSize ImageSizeByPixel = m_ResolutionSize;
  300. // scan field size (x, y)
  301. double pixelx = ImageSizeByPixel.cx ;
  302. double pixely = ImageSizeByPixel.cy;
  303. double dScanFiledSizeX = m_ScanFieldSize ;
  304. double dScanFiledSizeY = m_ScanFieldSize * pixely / pixelx;
  305. CSize sizeImage;
  306. sizeImage.cx = dScanFiledSizeX;
  307. sizeImage.cy = dScanFiledSizeY;
  308. // pixel size (micros)
  309. double dPixelSize = (double)dScanFiledSizeX / (double)sizeImage.cx;
  310. // the measure domain rectangle
  311. CRect rectMeasureDomain = m_pMeasureArea->GetDomainRect();
  312. // the measure domain centre
  313. CPoint poiDomainCentre = rectMeasureDomain.CenterPoint();
  314. // field centres need to be aligned with measured field centres
  315. //if (0 < (int)a_listHaveMeasuredFieldCentrePoints.size())
  316. //{ // get the first measured centre
  317. // CPoint poiMeasuredFieldCentre = a_listHaveMeasuredFieldCentrePoints[0];
  318. // // distance between the measure domain centre and the first measured field
  319. // int nDistanceX = abs(poiDomainCentre.x - poiMeasuredFieldCentre.x);
  320. // int nDistanceY = abs(poiDomainCentre.y - poiMeasuredFieldCentre.y);
  321. // // minimum shift
  322. // int nMinShiftX = 0;
  323. // int nMinShiftY = 0;
  324. // // x direction shift
  325. // if (nDistanceX != 0)
  326. // {// calculate shift distance
  327. // int nShiftX = nDistanceX % (int)(dScanFiledSizeX);
  328. // // need to move?
  329. // if (nShiftX != 0)
  330. // {
  331. // // need to shift on x direction
  332. // // calculate the minimum shift , there must be something wrong, one is number, one is mm
  333. // nMinShiftX = min(nShiftX, ((int)(dScanFiledSizeX)-nShiftX));
  334. // // check if domain centre on left side of the first measured centre
  335. // if (poiDomainCentre.x > poiMeasuredFieldCentre.x)
  336. // {
  337. // // shift domain centre left nShiftX should make the two aligned
  338. // // shift to left or right
  339. // if (nMinShiftX == nShiftX)
  340. // {
  341. // // left
  342. // poiDomainCentre.x -= nMinShiftX;
  343. // }
  344. // else
  345. // {
  346. // // right
  347. // poiDomainCentre.x += nMinShiftX;
  348. // }
  349. // }
  350. // else
  351. // {
  352. // // shift domain centre right nShiftX should make the two aligned
  353. // // shift to left or right
  354. // if (nMinShiftX != nShiftX)
  355. // {
  356. // // left
  357. // poiDomainCentre.x -= nMinShiftX;
  358. // }
  359. // else
  360. // {
  361. // // right
  362. // poiDomainCentre.x += nMinShiftX;
  363. // }
  364. // }
  365. // }
  366. // }
  367. // y direction shift
  368. //if (nDistanceY != 0)
  369. //{
  370. // // calculate shift distance
  371. // int nShiftY = nDistanceY % (int)(dScanFiledSizeY);
  372. // // need to move?
  373. // if (nShiftY != 0)
  374. // {
  375. // // need to shift on x direction
  376. // // calculate the minimum shift
  377. // nMinShiftY = min(nShiftY, ((int)(dScanFiledSizeY)-nShiftY));
  378. // // check if domain centre on top of the first measured centre
  379. // if (poiDomainCentre.y > poiMeasuredFieldCentre.y)
  380. // {
  381. // // shift domain centre down nShiftY should make the two aligned
  382. // // move down or up?
  383. // if (nMinShiftY == nShiftY)
  384. // {
  385. // // move down
  386. // poiDomainCentre.y -= nMinShiftY;
  387. // }
  388. // else
  389. // {
  390. // // move up
  391. // poiDomainCentre.y += nMinShiftY;
  392. // }
  393. // }
  394. // else
  395. // {
  396. // // shift domain centre up nShiftY should make the two aligned
  397. // // move down or up?
  398. // if (nMinShiftY == nShiftY)
  399. // {
  400. // // move up
  401. // poiDomainCentre.y += nMinShiftY;
  402. // }
  403. // else
  404. // {
  405. // // move down
  406. // poiDomainCentre.y -= nMinShiftY;
  407. // }
  408. // }
  409. // }
  410. //}
  411. // reset the measure domain rectangle
  412. // domain size
  413. /* CSize sizeMeasureDomain = rectMeasureDomain.Size();
  414. sizeMeasureDomain.cx += 2 * nMinShiftX;
  415. sizeMeasureDomain.cy += 2 * nMinShiftY;
  416. rectMeasureDomain = CRect(poiDomainCentre, sizeMeasureDomain);
  417. }*/
  418. // start mode
  419. OTS_GET_IMAGE_MODE nStartMode = (OTS_GET_IMAGE_MODE)m_fieldStartMode;
  420. // calculate total columns, rows and make sure the domain area be covered
  421. int nTotalCols = (int)(ceil((double)rectMeasureDomain.Width() / dScanFiledSizeX));
  422. int nTotalRows = (int)(ceil((double)rectMeasureDomain.Height() / dScanFiledSizeY));
  423. // calculate column on the left of the centre point
  424. int nLeftCols = nTotalCols / 2;
  425. int nRightCols = nLeftCols;
  426. // fields on top
  427. int nRowsOnTop = nTotalRows / 2;
  428. // sure total columns, rows are odd numbers
  429. nTotalCols = nLeftCols * 2 + 1;
  430. //nTotalRows = nTotalRows * 2 + 1;
  431. nTotalRows = nRowsOnTop * 2 + 1;
  432. // calculate left, right field column position (x only
  433. int nLeftMostColX = poiDomainCentre.x - nLeftCols * (int)dScanFiledSizeX;
  434. int nUpMostRowY = poiDomainCentre.y - nRowsOnTop * (int)dScanFiledSizeY;
  435. std::vector <std::vector <CPoint>> pointMatrics(nTotalRows, std::vector<CPoint>(nTotalCols));
  436. for (int i = 0; i < nTotalRows; i++)
  437. {
  438. for (int j = 0; j < nTotalCols; j++)
  439. {
  440. pointMatrics[i][j].x = nLeftMostColX + j * (int)dScanFiledSizeX;
  441. pointMatrics[i][j].y = nUpMostRowY + i * (int)dScanFiledSizeY;
  442. }
  443. }
  444. std::vector <std::vector <int>> sequenceMat; //construct an matrics map to the pointMatrics,but the content is the sequence number.
  445. switch (nStartMode)
  446. {
  447. case OTS_GET_IMAGE_MODE::FROM_CENTER:
  448. getSpiralMatrics(sequenceMat, nTotalRows,nTotalCols);
  449. break;
  450. case OTS_GET_IMAGE_MODE::UP_TO_DOWN :
  451. getUpDownMeanderMatrics(sequenceMat, nTotalRows, nTotalCols);
  452. break;
  453. case OTS_GET_IMAGE_MODE::DOWN_TO_UP :
  454. case OTS_GET_IMAGE_MODE::RANDOM :
  455. getDownUpMeanderMatrics(sequenceMat, nTotalRows, nTotalCols);
  456. break;
  457. }
  458. std::map <int, CPoint> mapCenterPoint;
  459. for (int i = 0; i < nTotalRows; i++)
  460. {
  461. for (int j = 0; j < nTotalCols; j++)
  462. {
  463. int sequenceNum = sequenceMat[i][j];
  464. CPoint p = pointMatrics[i][j];
  465. mapCenterPoint[sequenceNum] = p;// sorting all the field center point by the sequence number.
  466. }
  467. }
  468. // 判断当前样品获取帧图信息的测量区域为多边形
  469. if ((int)m_pMeasureArea->GetShape() > 1)
  470. {
  471. std::vector<CPoint> ptPolygon = m_pMeasureArea->GetPolygonPoint();
  472. for (auto itr : mapCenterPoint)
  473. {
  474. CPoint itrPoint = itr.second;
  475. if (IsInPolygonMeasureArea(itrPoint, sizeImage, ptPolygon))
  476. //if (PtInPolygon(itrPoint, ptPolygon))
  477. {
  478. m_listFieldCentrePoints.push_back(itr.second);
  479. }
  480. }
  481. }
  482. else
  483. {
  484. for (auto itr : mapCenterPoint)
  485. {
  486. if (IsInMeasureArea(itr.second, sizeImage))
  487. {
  488. m_listFieldCentrePoints.push_back(itr.second);
  489. //if (!IsInMeasuredFieldList(itr.second ))
  490. //{
  491. // // add the field centre into the unmeasured field centre points list
  492. // m_listUnmeasuredFieldCentrePoints.push_back(itr.second);
  493. //}
  494. }
  495. }
  496. }
  497. return m_listFieldCentrePoints;
  498. }
  499. // test if field is in or partly in the measure domain area
  500. BOOL CFieldMgr::IsInPolygonMeasureArea(CPoint a_poiField, CSize a_sizeImageSize, std::vector<CPoint> ptPolygon)
  501. {
  502. // check measure area parameter
  503. ASSERT(m_pMeasureArea);
  504. if (!m_pMeasureArea)
  505. {
  506. // shouldn't happen
  507. LogErrorTrace(__FILE__, __LINE__, _T("IsInDomainArea: invalid measure area parameter."));
  508. return FALSE;
  509. }
  510. // test field centre point first
  511. if (PtInPolygon(a_poiField, ptPolygon))
  512. {
  513. // centre in the measure domain area, return TRUE
  514. return TRUE;
  515. }
  516. // get measure field centre
  517. CPoint poiMsrAreaCentre = m_pMeasureArea->GetDomainCenter();
  518. // move to left top postion.
  519. a_poiField -= CPoint(a_sizeImageSize.cx / 2, a_sizeImageSize.cy / 2);
  520. // rectangle of the field
  521. CRect rectFiled(a_poiField, a_sizeImageSize);
  522. // // on the top left side, need to test the bottom right corner
  523. if (PtInPolygon(CPoint(rectFiled.right, rectFiled.top), ptPolygon))
  524. {
  525. return TRUE;
  526. }
  527. // // on the bottom left side, need to test the top right corner
  528. if (PtInPolygon(rectFiled.BottomRight(), ptPolygon))
  529. {
  530. return TRUE;
  531. }
  532. // // on the top left side, need to test the bottom right corner
  533. if (PtInPolygon(rectFiled.TopLeft(), ptPolygon))
  534. {
  535. return TRUE;
  536. }
  537. // // on the bottom left side, need to test the top right corner
  538. if (PtInPolygon(CPoint(rectFiled.left, rectFiled.bottom), ptPolygon))
  539. {
  540. return TRUE;
  541. }
  542. // this field is not in the area at all, return FALSE.
  543. return FALSE;
  544. }
  545. //作用:判断点是否在多边形内
  546. //p指目标点, ptPolygon指多边形的点集合, nCount指多边形的边数
  547. BOOL CFieldMgr::PtInPolygon(CPoint p, std::vector<CPoint> ptPolygon)
  548. {
  549. int nCount = ptPolygon.size();
  550. // 交点个数
  551. int nCross = 0;
  552. for (int i = 0; i < nCount; i++)
  553. {
  554. CPoint p1 = ptPolygon[i];
  555. CPoint p2 = ptPolygon[(i + 1) % nCount];// 点P1与P2形成连线
  556. if (p1.y == p2.y)
  557. continue;
  558. if (p.y < min(p1.y, p2.y))
  559. continue;
  560. if (p.y >= max(p1.y, p2.y))
  561. continue;
  562. // 求交点的x坐标(由直线两点式方程转化而来)
  563. double x = (double)(p.y - p1.y) * (double)(p2.x - p1.x) / (double)(p2.y - p1.y) + p1.x;
  564. // 只统计p1p2与p向右射线的交点
  565. if (x > p.x)
  566. {
  567. nCross++;
  568. }
  569. }
  570. // 交点为偶数,点在多边形之外
  571. // 交点为奇数,点在多边形之内
  572. if ((nCross % 2) == 1)
  573. {
  574. //true;
  575. return TRUE;
  576. }
  577. else
  578. {
  579. //false;
  580. return FALSE;
  581. }
  582. }
  583. // test if field is in or partly in the measure domain area
  584. BOOL CFieldMgr::IsInMeasureArea(CPoint a_poiField, CSize a_sizeImageSize)
  585. {
  586. // check measure area parameter
  587. ASSERT(m_pMeasureArea);
  588. if (!m_pMeasureArea)
  589. {
  590. // shouldn't happen
  591. LogErrorTrace(__FILE__, __LINE__, _T("IsInDomainArea: invalid measure area parameter."));
  592. return FALSE;
  593. }
  594. // test field centre point first
  595. if (m_pMeasureArea->PtInDomain(a_poiField))
  596. {
  597. // centre in the measure domain area, return TRUE
  598. return TRUE;
  599. }
  600. // get measure field centre
  601. CPoint poiMsrAreaCentre = m_pMeasureArea->GetDomainCenter();
  602. // move to left top postion.
  603. a_poiField -= CPoint(a_sizeImageSize.cx / 2, a_sizeImageSize.cy / 2);
  604. // rectangle of the field
  605. CRect rectFiled(a_poiField, a_sizeImageSize);
  606. // check field position
  607. if (rectFiled.left <= poiMsrAreaCentre.x && rectFiled.right >= poiMsrAreaCentre.x)
  608. {
  609. // centre column field or centre field
  610. return TRUE;
  611. }
  612. else if (rectFiled.top <= poiMsrAreaCentre.y && rectFiled.bottom >= poiMsrAreaCentre.y)
  613. {
  614. // centre row field?
  615. return TRUE;
  616. }
  617. else if ( rectFiled.right <= poiMsrAreaCentre.x)
  618. {
  619. // on the left side
  620. //up
  621. if (rectFiled.top >= poiMsrAreaCentre.y)
  622. {
  623. // on the top left side, need to test the bottom right corner
  624. if (m_pMeasureArea->PtInDomain(CPoint(rectFiled.right, rectFiled.top)))
  625. {
  626. return TRUE;
  627. }
  628. }
  629. else if(rectFiled.bottom <= poiMsrAreaCentre.y) //down//
  630. {
  631. // on the bottom left side, need to test the top right corner
  632. if (m_pMeasureArea->PtInDomain(rectFiled.BottomRight()))
  633. {
  634. return TRUE;
  635. }
  636. }
  637. }
  638. else if(rectFiled.left >= poiMsrAreaCentre.x)
  639. {
  640. // on the right side
  641. //up
  642. if (rectFiled.top >= poiMsrAreaCentre.y)
  643. {
  644. // on the top left side, need to test the bottom right corner
  645. if (m_pMeasureArea->PtInDomain(rectFiled.TopLeft()))
  646. {
  647. return TRUE;
  648. }
  649. }
  650. else if (rectFiled.bottom <= poiMsrAreaCentre.y) //down//
  651. {
  652. // on the bottom left side, need to test the top right corner
  653. if (m_pMeasureArea->PtInDomain(CPoint(rectFiled.left, rectFiled.bottom)))
  654. {
  655. return TRUE;
  656. }
  657. }
  658. }
  659. // this field is not in the area at all, return FALSE.
  660. return FALSE;
  661. }
  662. // test if field is in the measured field centre points list
  663. BOOL CFieldMgr::IsInMeasuredFieldList(CPoint a_poiField, std::vector<CPoint> m_listHaveMeasuredFieldCentrePoints)
  664. {
  665. // has to not be in the measured field centre points list
  666. auto itr = std::find(m_listHaveMeasuredFieldCentrePoints.begin(), m_listHaveMeasuredFieldCentrePoints.end(), a_poiField);
  667. if (itr != m_listHaveMeasuredFieldCentrePoints.end())
  668. {
  669. // in the measured field centre points list, this is a measured field, return TRUE
  670. return TRUE;
  671. }
  672. // ok, return FALSE
  673. return FALSE;
  674. }
  675. // find the next field centre
  676. BOOL CFieldMgr::FindNeighborFieldCentre(const std::vector<CPoint>& a_listFieldCentres,
  677. double a_dScanFieldSizeX,
  678. double a_dScanFieldSizeY,
  679. CPoint a_poiCurrent,
  680. SORTING_DIRECTION& a_nDirection,
  681. CPoint& a_poiNeighbor)
  682. {
  683. // assume no neighbor
  684. BOOL bFind = FALSE;
  685. // go through the field centres list
  686. for (const CPoint& poiFieldCentre : a_listFieldCentres)
  687. {
  688. // test if this is a neighbor field centre
  689. SORTING_DIRECTION nDirection;
  690. if (IsNeighborFieldCentre(poiFieldCentre, a_poiCurrent, a_dScanFieldSizeX, a_dScanFieldSizeY, nDirection))
  691. {
  692. // we find a neighbor field centre
  693. // let see if this is neighbor we are looking for
  694. switch (a_nDirection)
  695. {
  696. // last move is left
  697. case SORTING_DIRECTION::LEFT:
  698. {
  699. // we are looking for DOWN neighbor
  700. if (nDirection == SORTING_DIRECTION::DOWN)
  701. {
  702. // we find a neighbor below, get out
  703. a_poiNeighbor = poiFieldCentre;
  704. a_nDirection = SORTING_DIRECTION::DOWN;
  705. return TRUE;
  706. }
  707. }
  708. break;
  709. // last move is down
  710. case SORTING_DIRECTION::DOWN:
  711. {
  712. // we are looking for RIGHT neighbor
  713. if (nDirection == SORTING_DIRECTION::RIGHT)
  714. {
  715. // we find a neighbor on the right, get out
  716. a_poiNeighbor = poiFieldCentre;
  717. a_nDirection = SORTING_DIRECTION::RIGHT;
  718. return TRUE;
  719. }
  720. }
  721. break;
  722. // last move is right
  723. case SORTING_DIRECTION::RIGHT:
  724. {
  725. // we are looking for UP neighbor
  726. if (nDirection == SORTING_DIRECTION::UP)
  727. {
  728. // we find a neighbor above
  729. a_poiNeighbor = poiFieldCentre;
  730. a_nDirection = SORTING_DIRECTION::UP;
  731. return TRUE;
  732. }
  733. }
  734. break;
  735. // last move is up
  736. case SORTING_DIRECTION::UP:
  737. {
  738. // we are looking for LEFT neighbor
  739. if (nDirection == SORTING_DIRECTION::LEFT)
  740. {
  741. // we find a neighbor on the left, get out
  742. a_poiNeighbor = poiFieldCentre;
  743. a_nDirection = SORTING_DIRECTION::LEFT;
  744. return TRUE;
  745. }
  746. }
  747. break;
  748. }
  749. }
  750. }
  751. for (const CPoint& poiFieldCentre : a_listFieldCentres)
  752. {
  753. // test if this is a neighbor field centre
  754. SORTING_DIRECTION nDirection;
  755. if (IsNeighborFieldCentre(poiFieldCentre, a_poiCurrent, a_dScanFieldSizeX, a_dScanFieldSizeY, nDirection))
  756. {
  757. // we find a neighbor field centre
  758. // let see if this is neighbor we are looking for
  759. switch (a_nDirection)
  760. {
  761. // last move is left
  762. case SORTING_DIRECTION::LEFT:
  763. {
  764. // we are looking for DOWN neighbor , but not found
  765. // or LEFT neighbor otherwise
  766. if (nDirection == SORTING_DIRECTION::LEFT)
  767. {
  768. // we find a neighbor on the left, continue looking
  769. a_poiNeighbor = poiFieldCentre;
  770. return TRUE;
  771. }
  772. }
  773. break;
  774. // last move is down
  775. case SORTING_DIRECTION::DOWN:
  776. {
  777. // we are looking for RIGHT neighbor, but not found
  778. // or DOWN neighbor otherwise
  779. if (nDirection == SORTING_DIRECTION::DOWN)
  780. {
  781. // we find a neighbor below, continue looking
  782. a_poiNeighbor = poiFieldCentre;
  783. return TRUE;
  784. }
  785. }
  786. break;
  787. // last move is right
  788. case SORTING_DIRECTION::RIGHT:
  789. {
  790. // we are looking for UP neighbor, but not found
  791. // or RIGHT neighbor, otherwise
  792. if (nDirection == SORTING_DIRECTION::RIGHT)
  793. {
  794. // we find a neighbor on the right, continue looking
  795. a_poiNeighbor = poiFieldCentre;
  796. return TRUE;
  797. }
  798. }
  799. break;
  800. // last move is up
  801. case SORTING_DIRECTION::UP:
  802. {
  803. // we are looking for LEFT neighbor, but not found
  804. // or UP neighbor, otherwise
  805. if (nDirection == SORTING_DIRECTION::UP)
  806. {
  807. // we find a neighbor above, continue looking
  808. a_poiNeighbor = poiFieldCentre;
  809. return TRUE;
  810. }
  811. }
  812. break;
  813. }
  814. }
  815. }
  816. // return find result
  817. return bFind;
  818. }
  819. // find field centre closest to measure domain point
  820. BOOL CFieldMgr::FindFieldCentreClosestMeasureDomainCentre(const std::vector<CPoint>& a_listFieldCentres, CPoint a_poiMeasureDomain, CPoint& a_poi)
  821. {
  822. // distance ratio
  823. int nDisRadio = -1;
  824. for (const CPoint& poiFieldCentre : a_listFieldCentres)
  825. {
  826. // calculate current field centre distance ratio
  827. int nCurFiledDisRadio = (poiFieldCentre.x - a_poiMeasureDomain.x)*(poiFieldCentre.x - a_poiMeasureDomain.x) + (poiFieldCentre.y - a_poiMeasureDomain.y)*(poiFieldCentre.y - a_poiMeasureDomain.y);
  828. // pick one which more closer to centre
  829. if (nDisRadio > nCurFiledDisRadio || nDisRadio == -1)
  830. {
  831. a_poi = poiFieldCentre;
  832. nDisRadio = nCurFiledDisRadio;
  833. }
  834. }
  835. // nDisRadio != -1 means there still field centre in the a_listFieldCentres
  836. return nDisRadio != -1;
  837. }
  838. // find right far side field centre
  839. void CFieldMgr::FindRightMostFieldCentre(const std::vector<CPoint>& a_listFieldCentres, CPoint& a_poi)
  840. {
  841. for (auto& poi : a_listFieldCentres)
  842. {
  843. if (poi.y == a_poi.y && poi.x > a_poi.x)
  844. {
  845. a_poi = poi;
  846. }
  847. }
  848. }
  849. // find left far side field centre
  850. void CFieldMgr::FindLeftMostFieldCentre(const std::vector<CPoint>& a_listFieldCentres, CPoint& a_poi)
  851. {
  852. for (auto& poi : a_listFieldCentres)
  853. {
  854. if (poi.y == a_poi.y && poi.x < a_poi.x)
  855. {
  856. a_poi = poi;
  857. }
  858. }
  859. }
  860. // find top far side field centre
  861. void CFieldMgr::FindHeighestFieldCentre(const std::vector<CPoint>& a_listFieldCentres, CPoint& a_poi)
  862. {
  863. for (auto& poi : a_listFieldCentres)
  864. {
  865. if (poi.x == a_poi.x && poi.y > a_poi.y)
  866. {
  867. a_poi = poi;
  868. }
  869. }
  870. }
  871. // find bottom far side field centre
  872. void CFieldMgr::FindLowestFieldCentre(const std::vector<CPoint>& a_listFieldCentres, CPoint& a_poi)
  873. {
  874. for (auto& poi : a_listFieldCentres)
  875. {
  876. if (poi.x == a_poi.x && poi.y < a_poi.y)
  877. {
  878. a_poi = poi;
  879. }
  880. }
  881. }
  882. // check if this is a neighbor field centre
  883. BOOL CFieldMgr::IsNeighborFieldCentre(CPoint a_poiFieldCentre,
  884. CPoint a_poiCurrent,
  885. double a_dScanFieldSizeX,
  886. double a_dScanFieldSizeY,
  887. SORTING_DIRECTION& a_nDirection)
  888. {
  889. // x position of the tow field centres are the same, y positions have one field difference
  890. if (a_poiFieldCentre.x == a_poiCurrent.x && abs(a_poiFieldCentre.y - a_poiCurrent.y) == long(a_dScanFieldSizeY))
  891. {
  892. // test is above or below
  893. if (a_poiCurrent.y > a_poiFieldCentre.y)
  894. {
  895. // below
  896. a_nDirection = SORTING_DIRECTION::DOWN;
  897. }
  898. else
  899. {
  900. // above
  901. a_nDirection = SORTING_DIRECTION::UP;
  902. }
  903. // this is a neighbor field centre, return TRUE
  904. return TRUE;
  905. }
  906. // y position of the tow field centres are the same, x positions have one field difference
  907. else if (a_poiFieldCentre.y == a_poiCurrent.y && abs(a_poiFieldCentre.x - a_poiCurrent.x) == long(a_dScanFieldSizeX))
  908. {
  909. // test is on left or right
  910. if (a_poiCurrent.x > a_poiFieldCentre.x)
  911. {
  912. // on the left
  913. a_nDirection = SORTING_DIRECTION::LEFT;
  914. }
  915. else
  916. {
  917. // on the right
  918. a_nDirection = SORTING_DIRECTION::RIGHT;
  919. }
  920. // this is a neighbor field centre, return TRUE
  921. return TRUE;
  922. }
  923. // this is not a neighbor field centre, return FALSE
  924. return FALSE;
  925. }
  926. // get a random number in a given range
  927. int CFieldMgr::GetRangedRandNumber(int a_nRange_min, int a_nRange_max)
  928. {
  929. // return a random number
  930. int nRet;
  931. // get a random number in the given range
  932. nRet = long((double)rand() / (RAND_MAX + 1) * (a_nRange_max - a_nRange_min) + a_nRange_min);
  933. // return the random number
  934. return nRet;
  935. }
  936. }