ROICircularArc.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. #include "ROICircularArc.h"
  2. ROICircularArc::ROICircularArc()
  3. {
  4. numHandles = 4; // midpoint handle + three handles on the arc
  5. activeHandleIdx = 0;
  6. circDir = "";
  7. TwoPI = 2 * PI;
  8. roiType = ROIType::CircleArc;
  9. }
  10. void ROICircularArc::createROI(double midX, double midY)
  11. {
  12. midR = midY;
  13. midC = midX;
  14. radius = 100;
  15. sizeR = midR;
  16. sizeC = midC - radius;
  17. startPhi = PI * 0.25;
  18. extentPhi = PI * 1.5;
  19. circDir = "positive";
  20. determineArcHandles();
  21. updateArrowHandle();
  22. updateStartRect2XLDHandle(handleWidth);
  23. }
  24. void ROICircularArc::drawROI(HTuple winID, double scaleFactor)
  25. {
  26. Q_UNUSED(scaleFactor);
  27. contour.GenCircleContourXld(HTuple(midR), HTuple(midC), HTuple(radius), HTuple(startPhi),
  28. HTuple((startPhi + extentPhi)), HTuple(circDir.toUtf8().data()), HTuple(1.0));
  29. DispObj(contour, winID);
  30. int width = handleWidth;
  31. //DispRectangle2(winID, sizeR, sizeC, 0, width, width);
  32. //DispRectangle2(winID, midR, midC, 0, width, width);
  33. HObject ho_Rectangle;
  34. GenRectangle2ContourXld(&ho_Rectangle, sizeR, sizeC, 0, width, width);
  35. DispObj(ho_Rectangle, winID);
  36. GenRectangle2ContourXld(&ho_Rectangle, midR, midC, 0, width, width);
  37. DispObj(ho_Rectangle, winID);
  38. //if (startRect2XLD.IsInitialized()==false)
  39. {
  40. updateStartRect2XLDHandle(handleWidth);
  41. }
  42. DispObj(startRect2XLD, winID);
  43. //if (arrowHandleXLD.IsInitialized()==false)
  44. {
  45. updateArrowHandle();
  46. }
  47. DispObj(arrowHandleXLD, winID);
  48. DispLine(winID, midR, midC, startR, startC);
  49. DispLine(winID, midR, midC, extentR, extentC);
  50. }
  51. double ROICircularArc::distToClosestHandle(double x, double y)
  52. {
  53. double max = 10000;
  54. double val[4];
  55. val[0] = HMisc::DistancePp(y, x, midR, midC); // midpoint
  56. val[1] = HMisc::DistancePp(y, x, sizeR, sizeC); // border handle
  57. val[2] = HMisc::DistancePp(y, x, startR, startC); // border handle
  58. val[3] = HMisc::DistancePp(y, x, extentR, extentC); // border handle
  59. for (int i = 0; i < numHandles; i++)
  60. {
  61. if (val[i] < max)
  62. {
  63. max = val[i];
  64. activeHandleIdx = i;
  65. }
  66. }// end of for
  67. return val[activeHandleIdx];
  68. }
  69. void ROICircularArc::displayActive(HTuple winID, double scaleFactor)
  70. {
  71. Q_UNUSED(scaleFactor);
  72. HObject ho_Rectangle;
  73. double width = handleWidth;
  74. switch (activeHandleIdx)
  75. {
  76. case 0:
  77. //DispRectangle2(winID, midR, midC, 0, width, width);
  78. GenRectangle2ContourXld(&ho_Rectangle, midR, midC, 0, width, width);
  79. DispObj(ho_Rectangle, winID);
  80. break;
  81. case 1:
  82. //DispRectangle2(winID, sizeR, sizeC, 0, width, width);
  83. GenRectangle2ContourXld(&ho_Rectangle, sizeR, sizeC, 0, width, width);
  84. DispObj(ho_Rectangle, winID);
  85. break;
  86. case 2:
  87. //window.DispRectangle2(startR, startC, startPhi, 10, 2);
  88. DispObj(startRect2XLD, winID);
  89. break;
  90. case 3:
  91. DispObj(arrowHandleXLD, winID);
  92. break;
  93. }
  94. }
  95. void ROICircularArc::moveByHandle(double newX, double newY)
  96. {
  97. double distance;
  98. double dirX, dirY, prior, next, valMax, valMin;
  99. switch (activeHandleIdx)
  100. {
  101. case 0: // midpoint
  102. dirY = midR - newY;
  103. dirX = midC - newX;
  104. midR = newY;
  105. midC = newX;
  106. sizeR -= dirY;
  107. sizeC -= dirX;
  108. determineArcHandles();
  109. break;
  110. case 1: // handle at circle border
  111. sizeR = newY;
  112. sizeC = newX;
  113. distance = HMisc::DistancePp(sizeR, sizeC,
  114. midR, midC);
  115. radius = distance;
  116. determineArcHandles();
  117. break;
  118. case 2: // start handle for arc
  119. dirY = newY - midR;
  120. dirX = newX - midC;
  121. startPhi = atan2(-dirY, dirX);
  122. if (startPhi < 0)
  123. startPhi = PI + (startPhi + PI);
  124. setStartHandle();
  125. prior = extentPhi;
  126. extentPhi = HMisc::AngleLl(midR, midC, startR, startC, midR, midC, extentR, extentC);
  127. if (extentPhi < 0 && prior > PI * 0.8)
  128. extentPhi = (PI + extentPhi) + PI;
  129. else if (extentPhi > 0 && prior < -PI * 0.7)
  130. extentPhi = -PI - (PI - extentPhi);
  131. break;
  132. case 3: // end handle for arc
  133. dirY = newY - midR;
  134. dirX = newX - midC;
  135. prior = extentPhi;
  136. next = atan2(-dirY, dirX);
  137. if (next < 0)
  138. next = PI + (next + PI);
  139. if (circDir == "positive" && startPhi >= next)
  140. extentPhi = (next + TwoPI) - startPhi;
  141. else if (circDir == "positive" && next > startPhi)
  142. extentPhi = next - startPhi;
  143. else if (circDir == "negative" && startPhi >= next)
  144. extentPhi = -1.0 * (startPhi - next);
  145. else if (circDir == "negative" && next > startPhi)
  146. extentPhi = -1.0 * (startPhi + TwoPI - next);
  147. valMax = std::max<double>(std::abs(prior), std::abs(extentPhi));
  148. valMin = std::max<double>(std::abs(prior), std::abs(extentPhi));
  149. if ((valMax - valMin) >= PI)
  150. {
  151. extentPhi = (circDir == "positive") ? -1.0 * valMin : valMin;
  152. }
  153. setExtentHandle();
  154. break;
  155. }
  156. circDir = (extentPhi < 0) ? "negative" : "positive";
  157. updateArrowHandle();
  158. updateStartRect2XLDHandle(handleWidth);
  159. }
  160. QCursor ROICircularArc::showByHandle()
  161. {
  162. QCursor cursor;
  163. switch (activeHandleIdx)
  164. {
  165. case 0: // 鼠标在圆上的一点时
  166. cursor = Qt::SizeAllCursor;
  167. break;
  168. case 1: // 鼠标在圆心上时
  169. cursor = Qt::SizeBDiagCursor;
  170. break;
  171. }
  172. return cursor;
  173. }
  174. HRegion ROICircularArc::getRegion()
  175. {
  176. HRegion region;
  177. contour.GenCircleContourXld(HTuple(midR), HTuple(midC),
  178. HTuple(radius), HTuple(startPhi), HTuple((startPhi + extentPhi)), HTuple(circDir.toUtf8().data()), HTuple(1.0));
  179. region = HRegion(contour);
  180. return region;
  181. }
  182. HTuple ROICircularArc::getROIData()
  183. {
  184. HTuple dat;
  185. dat.Clear();
  186. dat[0] = midR;
  187. dat[1] = midC;
  188. dat[2] = radius;
  189. dat[3] = startPhi;
  190. dat[4] = extentPhi;
  191. return dat;
  192. }
  193. void ROICircularArc::setROIData(HTuple dat)
  194. {
  195. Q_UNUSED(dat);
  196. }
  197. void ROICircularArc::save(QDataStream &dataStream)
  198. {
  199. ROI::save(dataStream);
  200. int paranum;//参数数量
  201. paranum = 14;
  202. dataStream << paranum;//先保存参数数量
  203. dataStream << (int)1 << midR;
  204. dataStream << (int)2 << midC;
  205. dataStream << (int)3 << sizeR;
  206. dataStream << (int)4 << sizeC;
  207. dataStream << (int)5 << startR;
  208. dataStream << (int)6 << startC;
  209. dataStream << (int)7 << extentR;
  210. dataStream << (int)8 << extentC;
  211. dataStream << (int)9 << radius;
  212. dataStream << (int)10 << startPhi;
  213. dataStream << (int)11 << extentPhi;
  214. dataStream << (int)12 << TwoPI;
  215. dataStream << (int)13 << circDir;
  216. dataStream << (int)14 << m_strTitle;
  217. }
  218. void ROICircularArc::load(QDataStream &dataStream)
  219. {
  220. ROI::load(dataStream);
  221. int paranum;//参数数量
  222. int para;
  223. dataStream >> paranum;//读取参数数量
  224. for (int i = 0; i < paranum; i++)
  225. {
  226. dataStream >> para;
  227. switch (para)
  228. {
  229. case 1: dataStream >> midR; break;
  230. case 2: dataStream >> midC; break;
  231. case 3: dataStream >> sizeR; break;
  232. case 4: dataStream >> sizeC; break;
  233. case 5: dataStream >> startR; break;
  234. case 6: dataStream >> startC; break;
  235. case 7: dataStream >> extentR; break;
  236. case 8: dataStream >> extentC; break;
  237. case 9: dataStream >> radius; break;
  238. case 10: dataStream >> startPhi; break;
  239. case 11: dataStream >> extentPhi; break;
  240. case 12: dataStream >> TwoPI; break;
  241. case 13: dataStream >> circDir; break;
  242. case 14: dataStream >> m_strTitle; break;
  243. default:
  244. {
  245. qWarning() << "配置文档错误!";
  246. }
  247. break;
  248. }
  249. }
  250. }
  251. void ROICircularArc::determineArcHandles()
  252. {
  253. setStartHandle();
  254. setExtentHandle();
  255. }
  256. void ROICircularArc::updateArrowHandle()
  257. {
  258. double row1, col1, row2, col2;
  259. double rowP1, colP1, rowP2, colP2;
  260. double length, dr, dc, halfHW, sign, angleRad;
  261. double headLength = handleWidth;
  262. double headWidth = handleWidth;
  263. row2 = extentR;
  264. col2 = extentC;
  265. angleRad = (startPhi + extentPhi) + PI * 0.5;
  266. sign = (circDir == "negative") ? -1.0 : 1.0;
  267. row1 = row2 + sign * sin(angleRad) * 20;
  268. col1 = col2 - sign * cos(angleRad) * 20;
  269. length = HMisc::DistancePp(row1, col1, row2, col2);
  270. if (length == 0)
  271. length = -1;
  272. dr = (row2 - row1) / length;
  273. dc = (col2 - col1) / length;
  274. halfHW = headWidth / 2.0;
  275. rowP1 = row1 + (length - headLength) * dr + halfHW * dc;
  276. rowP2 = row1 + (length - headLength) * dr - halfHW * dc;
  277. colP1 = col1 + (length - headLength) * dc - halfHW * dr;
  278. colP2 = col1 + (length - headLength) * dc + halfHW * dr;
  279. arrowHandleXLD.GenEmptyObj();
  280. if (length == -1)
  281. arrowHandleXLD.GenContourPolygonXld(row1, col1);
  282. else
  283. {
  284. double rTmpDouble[5] = { 1, 2, 3 };
  285. HTuple test(rTmpDouble, 5);
  286. HTuple rTmp;
  287. rTmp.Clear();
  288. rTmp[0] = row1;
  289. rTmp[1] = row2;
  290. rTmp[2] = rowP1;
  291. rTmp[3] = row2;
  292. rTmp[4] = rowP2;
  293. rTmp[5] = row2;
  294. HTuple cTmp;
  295. cTmp.Clear();
  296. cTmp[0] = col1;
  297. cTmp[1] = col2;
  298. cTmp[2] = colP1;
  299. cTmp[3] = col2;
  300. cTmp[4] = colP2;
  301. cTmp[5] = col2;
  302. arrowHandleXLD.GenContourPolygonXld(rTmp, cTmp);
  303. }
  304. }
  305. void ROICircularArc::updateStartRect2XLDHandle(int imageWidth)
  306. {
  307. startRect2XLD.GenEmptyObj();
  308. startRect2XLD.GenRectangle2ContourXld(startR, startC, startPhi, imageWidth, imageWidth / 5.0);
  309. }
  310. void ROICircularArc::setStartHandle()
  311. {
  312. startR = midR - radius * sin(startPhi);
  313. startC = midC + radius * cos(startPhi);
  314. }
  315. void ROICircularArc::setExtentHandle()
  316. {
  317. extentR = midR - radius * sin(startPhi + extentPhi);
  318. extentC = midC + radius *cos(startPhi + extentPhi);
  319. }
  320. #ifndef QT_NO_DATASTREAM
  321. QDataStream &operator>>(QDataStream &in, ROICircularArc &data)
  322. {
  323. in >> data.midR >> data.midC >> data.sizeR >> data.sizeC >> data.startR
  324. >> data.startC >> data.extentR >> data.extentC >> data.radius >> data.startPhi
  325. >> data.extentPhi >> data.circDir >> data.TwoPI;
  326. return in;
  327. }
  328. QDataStream &operator<<(QDataStream &out, ROICircularArc &data)
  329. {
  330. out << data.midR << data.midC << data.sizeR << data.sizeC << data.startR
  331. << data.startC << data.extentR << data.extentC << data.radius << data.startPhi
  332. << data.extentPhi << data.circDir << data.TwoPI;
  333. return out;
  334. }
  335. #endif