ContourModifyExport.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. #include "ContourModifyExport.h"
  2. extern "C" bool GetRotationTransMat(const MyPoint pointFix, const MyPoint pointMoveBef, const MyPoint pointMoveAft, double * rotMatDatas)
  3. {
  4. try
  5. {
  6. Point2f center = Point2f(pointFix.x, pointFix.y);
  7. float angleBef = fastAtan2(pointMoveBef.y - pointFix.y, pointMoveBef.x - pointFix.x);
  8. float angleAft = fastAtan2(pointMoveAft.y - pointFix.y, pointMoveAft.x - pointFix.x);
  9. // 因为fastAtan2求出来的角度,从x正方向起,越往逆时针方向转,角度值越大
  10. // 但rotate矩阵中需要输入顺时针转的角度,因此这里的rotate要用bef-aft
  11. double rotate = angleBef - angleAft;
  12. double distanceBef = DistanceBetweenTwoPoints(pointMoveBef, pointFix);
  13. double distanceAft = DistanceBetweenTwoPoints(pointMoveAft, pointFix);
  14. double scale = distanceAft / distanceBef;
  15. Mat rotMat = getRotationMatrix2D(center, rotate, scale);
  16. rotMatDatas[0] = rotMat.at<double>(0, 0);
  17. rotMatDatas[1] = rotMat.at<double>(0, 1);
  18. rotMatDatas[2] = rotMat.at<double>(0, 2);
  19. rotMatDatas[3] = rotMat.at<double>(1, 0);
  20. rotMatDatas[4] = rotMat.at<double>(1, 1);
  21. rotMatDatas[5] = rotMat.at<double>(1, 2);
  22. return true;
  23. }
  24. catch (...)
  25. {
  26. return false;
  27. }
  28. }
  29. extern "C" bool RotateAndScalePoints(double* rotMatDatas, const int pointNum, MyPoint * pointsBef, MyPoint * pointsAft)
  30. {
  31. try
  32. {
  33. Mat rotMat(2, 3, CV_64FC1);
  34. rotMat.at<double>(0, 0) = rotMatDatas[0];
  35. rotMat.at<double>(0, 1) = rotMatDatas[1];
  36. rotMat.at<double>(0, 2) = rotMatDatas[2];
  37. rotMat.at<double>(1, 0) = rotMatDatas[3];
  38. rotMat.at<double>(1, 1) = rotMatDatas[4];
  39. rotMat.at<double>(1, 2) = rotMatDatas[5];
  40. std::vector<Point2f> vectBef(pointNum);
  41. std::vector<Point2f> vectAft(pointNum);
  42. for(int ni=0; ni<pointNum; ni++)
  43. {
  44. vectBef[ni].x = pointsBef[ni].x;
  45. vectBef[ni].y = pointsBef[ni].y;
  46. }
  47. transform(vectBef, vectAft, rotMat);
  48. for (int ni = 0; ni < pointNum; ni++)
  49. {
  50. pointsAft[ni].x = vectAft[ni].x;
  51. pointsAft[ni].y = vectAft[ni].y;
  52. }
  53. return true;
  54. }
  55. catch (...)
  56. {
  57. return false;
  58. }
  59. }
  60. extern "C" bool RotatePoints(const MyPoint pointCenter, double angle, const int pointNum, MyPoint * pointsBef, MyPoint * pointsAft)
  61. {
  62. try
  63. {
  64. Point2f center = Point2f(pointCenter.x, pointCenter.y);
  65. Mat rotMat = getRotationMatrix2D(center, angle, 1);
  66. std::vector<Point2f> vectBef(pointNum);
  67. std::vector<Point2f> vectAft(pointNum);
  68. for (int ni = 0; ni < pointNum; ni++)
  69. {
  70. vectBef[ni].x = pointsBef[ni].x;
  71. vectBef[ni].y = pointsBef[ni].y;
  72. }
  73. transform(vectBef, vectAft, rotMat);
  74. for (int ni = 0; ni < pointNum; ni++)
  75. {
  76. pointsAft[ni].x = vectAft[ni].x;
  77. pointsAft[ni].y = vectAft[ni].y;
  78. }
  79. return true;
  80. }
  81. catch (...)
  82. {
  83. return false;
  84. }
  85. }
  86. extern "C" bool AngleBetweenTwoLine(const MyPoint pointOrigin, const MyPoint pointAnyDir, const MyPoint pointXDir, double& angle)
  87. {
  88. try
  89. {
  90. float angleX = fastAtan2(pointXDir.y - pointOrigin.y, pointXDir.x - pointOrigin.x);
  91. float angleCur = fastAtan2(pointAnyDir.y - pointOrigin.y, pointAnyDir.x - pointOrigin.x);
  92. // 因为fastAtan2求出来的角度,从x正方向起,越往逆时针方向转,角度值越大
  93. angle = angleCur - angleX;
  94. if(angle < 0)
  95. {
  96. angle += 360;
  97. }
  98. return true;
  99. }
  100. catch (...)
  101. {
  102. return false;
  103. }
  104. }
  105. extern "C" bool ContourArea(const MyPoint * points,const int pointNum, int& area)
  106. {
  107. try
  108. {
  109. if(pointNum<=0)
  110. {
  111. return false;
  112. }
  113. MyRect boundBox = ContourBoundBox(points, pointNum);
  114. std::vector<Point> contour(pointNum);
  115. int x, y;
  116. for (int ni = 0; ni < pointNum; ni++)
  117. {
  118. x = points[ni].x;
  119. y = points[ni].y;
  120. contour[ni].x = x - boundBox.left;
  121. contour[ni].y = y - boundBox.top;
  122. }
  123. Mat img = Mat::zeros(boundBox.bottom - boundBox.top +1, boundBox.right - boundBox.left + 1, CV_8UC1);
  124. std::vector<std::vector<Point>> contours;
  125. contours.push_back(contour);
  126. cv::drawContours(img, contours,0, 255, FILLED, LINE_8);
  127. area = cv::countNonZero(img);
  128. img.release();
  129. return true;
  130. }
  131. catch (...)
  132. {
  133. return false;
  134. }
  135. }
  136. extern "C" bool GetContourPointByPoint(const MyPoint * pointsBef, const int pointNum, MyPoint * pointsAft, int& pointNumAft)
  137. {
  138. try
  139. {
  140. int kernelSize = 5;
  141. int blurSize = 3;
  142. int boundBoxExpandSize = max(kernelSize,blurSize) * 2+1;
  143. if (pointNum <= 0)
  144. {
  145. return false;
  146. }
  147. MyRect boundBox = ContourBoundBox(pointsBef, pointNum);
  148. boundBox.top -= boundBoxExpandSize;
  149. boundBox.left -= boundBoxExpandSize;
  150. boundBox.right += boundBoxExpandSize;
  151. boundBox.bottom += boundBoxExpandSize;
  152. std::vector<Point> contour(pointNum);
  153. int x, y;
  154. for (int ni = 0; ni < pointNum; ni++)
  155. {
  156. x = pointsBef[ni].x;
  157. y = pointsBef[ni].y;
  158. contour[ni].x = x - boundBox.left;
  159. contour[ni].y = y - boundBox.top;
  160. }
  161. Size imgSize = Size(boundBox.right - boundBox.left + 1,boundBox.bottom - boundBox.top + 1);
  162. Mat img = Mat::zeros(imgSize, CV_8UC1);
  163. std::vector<std::vector<Point>> contours;
  164. contours.push_back(contour);
  165. cv::drawContours(img, contours, 0,255, FILLED, LINE_AA);
  166. cv::medianBlur(img, img, blurSize);
  167. cv::threshold(img, img, 128, 255, THRESH_BINARY);
  168. std::vector<std::vector<Point>> contoursFound;
  169. std::vector<Vec4i> hierarchy;
  170. cv::findContours(img, contoursFound, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);
  171. int maxArea = 0;
  172. int index = -1;
  173. for(size_t ni=0; ni<contoursFound.size();ni++)
  174. {
  175. Mat imgSingleContour = Mat::zeros(imgSize, CV_8UC1);
  176. drawContours(imgSingleContour, contoursFound, ni, 255, FILLED, 0);
  177. int area = countNonZero(imgSingleContour);
  178. imgSingleContour.release();
  179. if(area > maxArea)
  180. {
  181. index = ni;
  182. maxArea = area;
  183. }
  184. }
  185. if(index!=-1)
  186. {
  187. std::vector<Point> contourSel = contoursFound[index];
  188. int len = contourSel.size();
  189. for(int ni=0; ni<len;ni++)
  190. {
  191. pointsAft[ni].x = contourSel[ni].x + boundBox.left;
  192. pointsAft[ni].y = contourSel[ni].y + boundBox.top;
  193. }
  194. pointNumAft = len;
  195. }
  196. img.release();
  197. return true;
  198. }
  199. catch (...)
  200. {
  201. return false;
  202. }
  203. }
  204. extern "C" bool GetContourWithLineAA(const MyPoint * pointsBef, const int pointNum, MyPoint * pointsAft, int& pointNumAft)
  205. {
  206. try
  207. {
  208. int boundBoxExpandSize = 1;
  209. if (pointNum <= 0)
  210. {
  211. return false;
  212. }
  213. MyRect boundBox = ContourBoundBox(pointsBef, pointNum);
  214. boundBox.top -= boundBoxExpandSize;
  215. boundBox.left -= boundBoxExpandSize;
  216. boundBox.right += boundBoxExpandSize;
  217. boundBox.bottom += boundBoxExpandSize;
  218. std::vector<Point> contour(pointNum);
  219. int x, y;
  220. for (int ni = 0; ni < pointNum; ni++)
  221. {
  222. x = pointsBef[ni].x;
  223. y = pointsBef[ni].y;
  224. contour[ni].x = x - boundBox.left;
  225. contour[ni].y = y - boundBox.top;
  226. }
  227. Size imgSize = Size(boundBox.right - boundBox.left + 1, boundBox.bottom - boundBox.top + 1);
  228. Mat img = Mat::zeros(imgSize, CV_8UC1);
  229. std::vector<std::vector<Point>> contours;
  230. contours.push_back(contour);
  231. cv::drawContours(img, contours, 0, 255, 1, LINE_AA);
  232. cv::threshold(img, img, 128, 255, THRESH_BINARY);
  233. std::vector<std::vector<Point>> contoursFound;
  234. std::vector<Vec4i> hierarchy;
  235. cv::findContours(img, contoursFound, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);
  236. int maxArea = 0;
  237. int index = -1;
  238. for (size_t ni = 0; ni < contoursFound.size(); ni++)
  239. {
  240. Mat imgSingleContour = Mat::zeros(imgSize, CV_8UC1);
  241. drawContours(imgSingleContour, contoursFound, ni, 255, 1, LINE_AA);
  242. int area = countNonZero(imgSingleContour);
  243. imgSingleContour.release();
  244. if (area > maxArea)
  245. {
  246. index = ni;
  247. maxArea = area;
  248. }
  249. }
  250. if (index != -1)
  251. {
  252. std::vector<Point> contourSel = contoursFound[index];
  253. int len = contourSel.size();
  254. for (int ni = 0; ni < len; ni++)
  255. {
  256. pointsAft[ni].x = contourSel[ni].x + boundBox.left;
  257. pointsAft[ni].y = contourSel[ni].y + boundBox.top;
  258. }
  259. pointNumAft = len;
  260. }
  261. img.release();
  262. return true;
  263. }
  264. catch (...)
  265. {
  266. return false;
  267. }
  268. }
  269. extern "C" bool GetContourPointByPointEliminateSelfCross(const MyPoint * pointsBef, const int pointNum, MyPoint * pointsAft, int& pointNumAft)
  270. {
  271. try
  272. {
  273. int blurSize = 3;
  274. int boundBoxExpandSize = blurSize * 2 + 1;
  275. if (pointNum <= 0)
  276. {
  277. return false;
  278. }
  279. // 插值,让轮廓线至少是逐像素相连的
  280. std::vector<MyPoint> pointsPixelByPixel;
  281. MyPoint pointPre, pointNi;
  282. for(int ni=0; ni<pointNum; ni++)
  283. {
  284. pointNi = pointsBef[ni];
  285. // 第0个点,直接添加
  286. if(ni==0)
  287. {
  288. pointsPixelByPixel.push_back(pointNi);
  289. pointPre = pointNi;
  290. continue;
  291. }
  292. // 判断当前点与之前点的距离,如果小于等于0,则不添加,如果不相邻,则需要插入多个点
  293. AddPointsPixelByPixel(pointsPixelByPixel, pointNi, pointPre);
  294. pointPre = pointNi;
  295. // 最后一个点,再需要判断与第0个点的距离
  296. if (ni == pointNum)
  297. {
  298. AddPointsPixelByPixel(pointsPixelByPixel, pointsBef[0], pointNi);
  299. }
  300. }
  301. // 判断每个点和之前已添加的轮廓点是否交叉,如果交叉,则记录下来
  302. // 为了避免将临近点检测成交叉区域,只在当前点往回退7个点后才开始判断
  303. // 为了避免在同一个位置连续添加多个点,添加一个点后,跳过临近点
  304. int preStartCount = 8;
  305. int newPointCount = pointsPixelByPixel.size();
  306. std::vector<std::pair<int,int>> crossPoints;
  307. for(int ni=0; ni< newPointCount;ni++)
  308. {
  309. int closePointIndex = 0;
  310. if(CheckIfContourSelfCrossed(pointsPixelByPixel, ni, preStartCount, closePointIndex))
  311. {
  312. MyPoint pointNow = pointsPixelByPixel[closePointIndex];
  313. // 起点和终点必须闭合,因此不要把起点和终点误判为一对交叉点
  314. MyPoint pointStart= pointsPixelByPixel[0];
  315. MyPoint pointEnd = pointsPixelByPixel[newPointCount-1];
  316. double distanceToStart = DistanceBetweenTwoPoints(pointNow, pointStart);
  317. double distanceToEnd = DistanceBetweenTwoPoints(pointNow, pointEnd);
  318. if(distanceToStart<1.5 && distanceToEnd<1.5)
  319. {
  320. continue;
  321. }
  322. int existCount = crossPoints.size();
  323. if(existCount>0)
  324. {
  325. // 不要在一个位置处重复添加交叉点对
  326. int prePointFirst = crossPoints[existCount - 1].first;
  327. int prePointSecond = crossPoints[existCount - 1].second;
  328. MyPoint pointPre = pointsPixelByPixel[prePointSecond];
  329. double distance = DistanceBetweenTwoPoints(pointNow, pointPre);
  330. if(ni - prePointFirst <preStartCount && distance<1.5)
  331. {
  332. continue;
  333. }
  334. }
  335. std::pair<int, int> cross;
  336. cross.first = ni;
  337. cross.second = closePointIndex;
  338. crossPoints.push_back(cross);
  339. }
  340. }
  341. // 整理所有交叉点,组成一对一对的,这一对轮廓线中,可以删除将较长的那一组中间的所有点吸附到较短的那一条上
  342. int crossPointCount = crossPoints.size();
  343. if(crossPointCount >0)
  344. {
  345. // 未完成,自交叉的可能情况比较多,暂未找到合适的方法清除掉自交叉的部分
  346. }
  347. // 计算所有轮廓点的外边框
  348. MyRect boundBox = ContourBoundBox(pointsBef, pointNum);
  349. boundBox.top -= boundBoxExpandSize;
  350. boundBox.left -= boundBoxExpandSize;
  351. boundBox.right += boundBoxExpandSize;
  352. boundBox.bottom += boundBoxExpandSize;
  353. std::vector<Point> contour(pointNum);
  354. int x, y;
  355. for (int ni = 0; ni < pointNum; ni++)
  356. {
  357. x = pointsBef[ni].x;
  358. y = pointsBef[ni].y;
  359. contour[ni].x = x - boundBox.left;
  360. contour[ni].y = y - boundBox.top;
  361. }
  362. Size imgSize = Size(boundBox.right - boundBox.left + 1, boundBox.bottom - boundBox.top + 1);
  363. Mat img = Mat::zeros(imgSize, CV_8UC1);
  364. std::vector<std::vector<Point>> contours;
  365. contours.push_back(contour);
  366. cv::drawContours(img, contours, 0, 255, FILLED, LINE_AA);
  367. cv::medianBlur(img, img, blurSize);
  368. cv::threshold(img, img, 128, 255, THRESH_BINARY);
  369. std::vector<std::vector<Point>> contoursFound;
  370. std::vector<Vec4i> hierarchy;
  371. cv::findContours(img, contoursFound, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);
  372. int maxArea = 0;
  373. int index = -1;
  374. for (size_t ni = 0; ni < contoursFound.size(); ni++)
  375. {
  376. Mat imgSingleContour = Mat::zeros(imgSize, CV_8UC1);
  377. drawContours(imgSingleContour, contoursFound, ni, 255, FILLED, 0);
  378. int area = countNonZero(imgSingleContour);
  379. imgSingleContour.release();
  380. if (area > maxArea)
  381. {
  382. index = ni;
  383. }
  384. }
  385. if (index != -1)
  386. {
  387. std::vector<Point> contourSel = contoursFound[index];
  388. int len = contourSel.size();
  389. for (int ni = 0; ni < len; ni++)
  390. {
  391. pointsAft[ni].x = contourSel[ni].x + boundBox.left;
  392. pointsAft[ni].y = contourSel[ni].y + boundBox.top;
  393. }
  394. pointNumAft = len;
  395. }
  396. img.release();
  397. return true;
  398. }
  399. catch (...)
  400. {
  401. return false;
  402. }
  403. }
  404. extern "C" bool LineContourIntersection(const MyPoint * points, const int pointNum, const MyPoint lineStart, const MyPoint lineEnd,
  405. const int touchDistance, bool extended, InterecttionsResults & results)
  406. {
  407. try
  408. {
  409. if (pointNum <= 0)
  410. {
  411. return false;
  412. }
  413. // 遍历轮廓上的点,当该点和直线的距离小于阈值,则认为是符合要求的点
  414. std::vector<InterecttionsDetails> intersections;
  415. double distanceStartToEnd = DistanceBetweenTwoPoints(lineStart, lineEnd);
  416. for(int ni=0;ni<pointNum;ni++)
  417. {
  418. MyPoint pointNi = points[ni];
  419. // 与start的距离
  420. double distanceToStart = DistanceBetweenTwoPoints(lineStart, pointNi);
  421. // 与end的距离
  422. double distanceToEnd= DistanceBetweenTwoPoints(lineEnd, pointNi);
  423. // 与start的夹角
  424. double angleWithStart = 0;
  425. AngleBetweenTwoLine(lineStart, pointNi, lineEnd, angleWithStart);
  426. if(angleWithStart>180)
  427. {
  428. angleWithStart = 360 - angleWithStart;
  429. }
  430. // 与直线的距离
  431. double distanceToLine = sin(DegToRad(angleWithStart)) * distanceToStart;
  432. if(distanceToLine <=touchDistance)
  433. {
  434. if(extended || distanceToEnd< touchDistance || distanceToStart<= touchDistance ||
  435. abs(distanceToEnd +distanceToStart - distanceStartToEnd)<=touchDistance )
  436. {
  437. InterecttionsDetails intersection;
  438. intersection.indexInContour = ni;
  439. intersection.distanceToLineStart = distanceToStart;
  440. intersection.distanceToLineEnd = distanceToEnd;
  441. intersections.push_back(intersection);
  442. }
  443. }
  444. }
  445. // 如果一个交点都没有,直接退出
  446. if (intersections.size() <= 0)
  447. {
  448. results.intersectWithLineStart = false;
  449. results.intersectWithLineEnd = false;
  450. results.indexInContourIntersectionStart = -1;
  451. results.indexInContourIntersectionEnd = -1;
  452. return true;
  453. }
  454. // 将交点按其与起点的距离排序
  455. sort(intersections.begin(), intersections.end(), SortIntersectionByDistanceToStartIncrease);
  456. // 找到离起点近的那个交点(必须是离start比离end近)
  457. std::vector<InterecttionsDetails> selected;
  458. if (intersections[0].distanceToLineStart <= intersections[0].distanceToLineEnd)
  459. {
  460. selected.push_back(intersections[0]);
  461. }
  462. // 将交点按其与终点的距离排序
  463. sort(intersections.begin(), intersections.end(), SortIntersectionByDistanceToEndIncrease);
  464. if (selected.size() > 0)
  465. {
  466. // 顺序将所有临近点删除
  467. std::vector<int> adjacent;
  468. bool preSearch = true;
  469. bool backSearch = true;
  470. int preIndex = selected[0].indexInContour;
  471. int backIndex = selected[0].indexInContour;
  472. adjacent.push_back(selected[0].indexInContour);
  473. while (preSearch || backSearch)
  474. {
  475. // 向前搜索
  476. if (preSearch)
  477. {
  478. // 循环自减(index 小于0时,需要注意反向)
  479. preIndex -= 1;
  480. if (preIndex < 0)
  481. {
  482. preIndex += pointNum;
  483. }
  484. bool contains = false;
  485. for (auto intersection : intersections)
  486. {
  487. if(intersection.indexInContour == preIndex)
  488. {
  489. contains = true;
  490. adjacent.push_back(preIndex);
  491. break;
  492. }
  493. }
  494. preSearch = contains;
  495. }
  496. // 向后搜索
  497. if (backSearch)
  498. {
  499. // 循环自增(index 大于keyPointNum时,需要注意反向)
  500. backIndex += 1;
  501. if(backIndex >= pointNum)
  502. {
  503. backIndex -= pointNum;
  504. }
  505. bool contains = false;
  506. for (auto intersection : intersections)
  507. {
  508. if (intersection.indexInContour == backIndex)
  509. {
  510. contains = true;
  511. adjacent.push_back(backIndex);
  512. break;
  513. }
  514. }
  515. backSearch = contains;
  516. if(adjacent.size()>= intersections.size())
  517. {
  518. break;
  519. }
  520. }
  521. }
  522. int pointToAddIndex = intersections[0].indexInContour;
  523. bool add = true;
  524. for (auto value : adjacent)
  525. {
  526. if(value == pointToAddIndex)
  527. {
  528. add = false;
  529. break;
  530. }
  531. }
  532. if(add)
  533. {
  534. selected.push_back(intersections[0]);
  535. }
  536. }
  537. else
  538. {
  539. if (intersections[0].distanceToLineEnd < intersections[0].distanceToLineStart)
  540. {
  541. selected.push_back(intersections[0]);
  542. }
  543. }
  544. if(selected.size()<=0)
  545. {
  546. results.intersectWithLineStart = false;
  547. results.intersectWithLineEnd = false;
  548. results.indexInContourIntersectionStart = -1;
  549. results.indexInContourIntersectionEnd = -1;
  550. return true;
  551. }
  552. else if(selected.size() == 2)
  553. {
  554. results.intersectWithLineStart = true;
  555. results.intersectWithLineEnd = true;
  556. results.indexInContourIntersectionStart = selected[0].indexInContour;
  557. results.indexInContourIntersectionEnd = selected[1].indexInContour;
  558. return true;
  559. }
  560. else
  561. {
  562. if(selected[0].distanceToLineStart <= selected[0].distanceToLineEnd)
  563. {
  564. results.intersectWithLineStart = true;
  565. results.intersectWithLineEnd = false;
  566. results.indexInContourIntersectionStart = selected[0].indexInContour;
  567. results.indexInContourIntersectionEnd = -1;
  568. }
  569. else
  570. {
  571. results.intersectWithLineEnd = true;
  572. results.intersectWithLineStart = false;
  573. results.indexInContourIntersectionEnd = selected[1].indexInContour;
  574. results.indexInContourIntersectionStart = -1;
  575. }
  576. return false;
  577. }
  578. }
  579. catch (...)
  580. {
  581. return false;
  582. }
  583. }
  584. MyRect ContourBoundBox(const MyPoint* points, const int pointNum)
  585. {
  586. int left = points[0].x;
  587. int right = points[0].x;
  588. int top = points[0].y;
  589. int bottom = points[0].y;
  590. int x, y;
  591. for (int ni = 1; ni < pointNum; ni++)
  592. {
  593. x = points[ni].x;
  594. y = points[ni].y;
  595. if (x < left)
  596. {
  597. left = x;
  598. }
  599. if(x>right)
  600. {
  601. right = x;
  602. }
  603. if(y<top)
  604. {
  605. top = y;
  606. }
  607. if(y>bottom)
  608. {
  609. bottom = y;
  610. }
  611. }
  612. MyRect boundBox;
  613. boundBox.left = left;
  614. boundBox.right = right;
  615. boundBox.top = top;
  616. boundBox.bottom = bottom;
  617. return boundBox;
  618. }
  619. double DistanceBetweenTwoPoints(const MyPoint pointOne, const MyPoint pointOther)
  620. {
  621. return sqrt(powf((pointOne.x - pointOther.x), 2) + powf((pointOne.y - pointOther.y), 2));
  622. }
  623. double DistanceBetweenTwoRect(const MyRect rectOne, const MyRect rectOther)
  624. {
  625. int left = max(rectOne.left, rectOther.left);
  626. int top = max(rectOne.top, rectOther.top);
  627. int right = min(rectOne.right, rectOther.right);
  628. int bottom = min(rectOne.bottom, rectOther.bottom);
  629. // 两个矩形有交集
  630. if(left<=right && top <=bottom)
  631. {
  632. return 0;
  633. }
  634. // x方向有平行区域
  635. if(left<=right)
  636. {
  637. return abs(bottom - top);
  638. }
  639. // y 方向有平行区域
  640. if(top<=bottom)
  641. {
  642. return abs(right - left);
  643. }
  644. // 没有交集,则left,top,right,bottom 构成的两个点之间的距离就是最短距离
  645. int disw = left - right;
  646. int dish = bottom - top;
  647. return sqrt(powf(disw, 2) + powf(dish, 2));
  648. }
  649. bool SortPointByDistanceIncrease(std::pair<double, MyPoint>a, std::pair<double, MyPoint>b)
  650. {
  651. return a.first < b.first;
  652. }
  653. bool SortIntersectionByDistanceToStartIncrease(InterecttionsDetails a, InterecttionsDetails b)
  654. {
  655. return a.distanceToLineStart < b.distanceToLineStart;
  656. }
  657. bool SortIntersectionByDistanceToEndIncrease(InterecttionsDetails a, InterecttionsDetails b)
  658. {
  659. return a.distanceToLineEnd < b.distanceToLineEnd;
  660. }
  661. bool AddPointsPixelByPixel(std::vector<MyPoint>& contours, MyPoint pointToAdd, MyPoint pointPre)
  662. {
  663. double distance = DistanceBetweenTwoPoints(pointToAdd, pointPre);
  664. // 距离为0,不添加
  665. if(distance<=0)
  666. {
  667. return false;
  668. }
  669. // 距离小于等于根号2,可以直接添加,不用插值
  670. if(distance < 1.5)
  671. {
  672. contours.push_back(pointToAdd);
  673. return true;
  674. }
  675. // 距离大于根号2,需要插值
  676. int deltaX = pointToAdd.x - pointPre.x;
  677. int deltaY = pointToAdd.y - pointPre.y;
  678. int deltaXAbs = abs(deltaX);
  679. int deltaYAbs = abs(deltaY);
  680. double ratio;
  681. // 看沿着哪个方向插值
  682. // x方向的差异较大,则沿着x方向插值
  683. if(deltaXAbs >deltaYAbs)
  684. {
  685. for(int ni=1; ni<deltaXAbs; ni++)
  686. {
  687. ratio = (double)ni / deltaXAbs;
  688. MyPoint pointNi;
  689. pointNi.x = pointPre.x + (int)(ratio * deltaX);
  690. pointNi.y = pointPre.y + (int)(ratio * deltaY);
  691. contours.push_back(pointNi);
  692. }
  693. contours.push_back(pointToAdd);
  694. }
  695. // y方向差异较大,则沿着y方向插值
  696. else
  697. {
  698. for (int ni = 1; ni < deltaYAbs; ni++)
  699. {
  700. ratio = (double)ni / deltaYAbs;
  701. MyPoint pointNi;
  702. pointNi.x = pointPre.x + (int)(ratio * deltaX);
  703. pointNi.y = pointPre.y + (int)(ratio * deltaY);
  704. contours.push_back(pointNi);
  705. }
  706. contours.push_back(pointToAdd);
  707. }
  708. return true;
  709. }
  710. bool CheckIfContourSelfCrossed(std::vector<MyPoint> contours, int curIndex, int preStartCount,int& indexOfClosePoint)
  711. {
  712. if(curIndex < preStartCount)
  713. {
  714. return false;
  715. }
  716. MyPoint pointCur = contours[curIndex];
  717. for(int ni=curIndex - preStartCount; ni>=0; ni--)
  718. {
  719. double distance = DistanceBetweenTwoPoints(pointCur, contours[ni]);
  720. if(distance<=1.5)
  721. {
  722. indexOfClosePoint = ni;
  723. return true;
  724. }
  725. }
  726. return false;
  727. }