ROICircularArc.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. using System;
  2. using HalconDotNet;
  3. using System.Xml.Serialization;
  4. namespace ViewWindow.Model
  5. {
  6. /// <summary>
  7. /// This class implements an ROI shaped as a circular
  8. /// arc. ROICircularArc inherits from the base class ROI and
  9. /// implements (besides other auxiliary methods) all virtual methods
  10. /// defined in ROI.cs.
  11. /// </summary>
  12. public class ROICircularArc : ROI
  13. {
  14. public double Row
  15. {
  16. get { return this.midR; }
  17. set { this.midR = value; }
  18. }
  19. [XmlElement(ElementName = "Column")]
  20. public double Column
  21. {
  22. get { return this.midC; }
  23. set { this.midC = value; }
  24. }
  25. [XmlElement(ElementName = "Radius")]
  26. public double Radius
  27. {
  28. get { return this.radius; }
  29. set { this.radius = value; }
  30. }
  31. [XmlElement(ElementName = "StartPhi")]
  32. public double StartPhi
  33. {
  34. get { return this.startPhi; }
  35. set { this.startPhi = value; }
  36. }
  37. [XmlElement(ElementName = "ExtentPhi")]
  38. public double ExtentPhi
  39. {
  40. get { return this.extentPhi; }
  41. set { this.extentPhi = value; }
  42. }
  43. //handles
  44. private double midR, midC; // 0. handle: midpoint
  45. private double sizeR, sizeC; // 1. handle
  46. private double startR, startC; // 2. handle
  47. private double extentR, extentC; // 3. handle
  48. //model data to specify the arc
  49. private double radius;
  50. private double startPhi, extentPhi; // -2*PI <= x <= 2*PI
  51. //display attributes
  52. private HXLDCont contour;
  53. private HXLDCont arrowHandleXLD;
  54. private string circDir;
  55. private double TwoPI;
  56. private double PI;
  57. public ROICircularArc()
  58. {
  59. NumHandles = 4; // midpoint handle + three handles on the arc
  60. activeHandleIdx = 0;
  61. contour = new HXLDCont();
  62. circDir = "";
  63. TwoPI = 2 * Math.PI;
  64. PI = Math.PI;
  65. arrowHandleXLD = new HXLDCont();
  66. arrowHandleXLD.GenEmptyObj();
  67. }
  68. public ROICircularArc(double row, double col, double radius, double startPhi, double extentPhi)
  69. {
  70. createCircularArc(row, col, radius, startPhi, extentPhi, "positive");
  71. }
  72. public override void createCircularArc(double row, double col, double radius, double startPhi, double extentPhi,string direct)
  73. {
  74. base.createCircularArc(row, col, radius, startPhi, extentPhi, direct);
  75. midR = row;
  76. midC = col;
  77. this.radius = radius;
  78. sizeR = midR;
  79. sizeC = midC - radius;
  80. this.startPhi = startPhi;
  81. if (direct == "positive")
  82. {
  83. this.extentPhi = extentPhi;
  84. }
  85. else
  86. {
  87. this.extentPhi = extentPhi;
  88. }
  89. // circDir = "positive";
  90. circDir = direct;
  91. determineArcHandles();
  92. updateArrowHandle();
  93. }
  94. /// <summary>Creates a new ROI instance at the mouse position</summary>
  95. public override void createROI(double midX, double midY)
  96. {
  97. midR = midY;
  98. midC = midX;
  99. radius = 100;
  100. sizeR = midR;
  101. sizeC = midC - radius;
  102. startPhi = PI * 0.25;
  103. extentPhi = PI * 1.5;
  104. circDir = "positive";
  105. determineArcHandles();
  106. updateArrowHandle();
  107. }
  108. /// <summary>Paints the ROI into the supplied window</summary>
  109. /// <param name="window">HALCON window</param>
  110. public override void draw(HalconDotNet.HWindow window, int imageWidth, int imageHeight)
  111. {
  112. contour.Dispose();
  113. contour.GenCircleContourXld(midR, midC, radius, startPhi,
  114. (startPhi + extentPhi), circDir, 1.0);
  115. double littleRecSize = 0;
  116. if (imageHeight < 300) littleRecSize = 1;
  117. else if (imageHeight < 600) littleRecSize = 2;
  118. else if (imageHeight < 900) littleRecSize = 3;
  119. else if (imageHeight < 1200) littleRecSize = 4;
  120. else if (imageHeight < 1500) littleRecSize = 5;
  121. else if (imageHeight < 1800) littleRecSize = 6;
  122. else if (imageHeight < 2100) littleRecSize = 7;
  123. else if (imageHeight < 2400) littleRecSize = 8;
  124. else if (imageHeight < 2700) littleRecSize = 9;
  125. else if (imageHeight < 3000) littleRecSize = 10;
  126. else if (imageHeight < 3300) littleRecSize = 11;
  127. else if (imageHeight < 3600) littleRecSize = 12;
  128. else if (imageHeight < 3900) littleRecSize = 13;
  129. else if (imageHeight < 4200) littleRecSize = 14;
  130. else if (imageHeight < 4500) littleRecSize = 15;
  131. else if (imageHeight < 4800) littleRecSize = 16;
  132. else if (imageHeight < 5100) littleRecSize = 17;
  133. else littleRecSize = 18;
  134. window.DispObj(contour);
  135. window.DispRectangle2(sizeR, sizeC, 0, littleRecSize, littleRecSize);
  136. window.DispRectangle2(midR, midC, 0, littleRecSize, littleRecSize);
  137. window.DispRectangle2(startR, startC, startPhi, littleRecSize, littleRecSize);
  138. window.DispRectangle2(extentR , extentC , 0, littleRecSize, littleRecSize);
  139. window.DispLine(startR, startC, midR, midC);
  140. window.DispLine(extentR , extentC , midR, midC);
  141. }
  142. /// <summary>
  143. /// Returns the distance of the ROI handle being
  144. /// closest to the image point(x,y)
  145. /// </summary>
  146. public override double distToClosestHandle(double x, double y)
  147. {
  148. double max = 10000;
  149. double [] val = new double[NumHandles];
  150. val[0] = HMisc.DistancePp(y, x, midR, midC); // midpoint
  151. val[1] = HMisc.DistancePp(y, x, sizeR, sizeC); // border handle
  152. val[2] = HMisc.DistancePp(y, x, startR, startC); // border handle
  153. val[3] = HMisc.DistancePp(y, x, extentR, extentC); // border handle
  154. for (int i=0; i < NumHandles; i++)
  155. {
  156. if (val[i] < max)
  157. {
  158. max = val[i];
  159. activeHandleIdx = i;
  160. }
  161. }// end of for
  162. return val[activeHandleIdx];
  163. }
  164. /// <summary>
  165. /// Paints the active handle of the ROI object into the supplied window
  166. /// </summary>
  167. public override void displayActive(HalconDotNet.HWindow window, int imageWidth, int imageHeight)
  168. {
  169. double littleRecSize = 0;
  170. if (imageHeight < 300) littleRecSize = 1;
  171. else if (imageHeight < 600) littleRecSize = 2;
  172. else if (imageHeight < 900) littleRecSize = 3;
  173. else if (imageHeight < 1200) littleRecSize = 4;
  174. else if (imageHeight < 1500) littleRecSize = 5;
  175. else if (imageHeight < 1800) littleRecSize = 6;
  176. else if (imageHeight < 2100) littleRecSize = 7;
  177. else if (imageHeight < 2400) littleRecSize = 8;
  178. else if (imageHeight < 2700) littleRecSize = 9;
  179. else if (imageHeight < 3000) littleRecSize = 10;
  180. else if (imageHeight < 3300) littleRecSize = 11;
  181. else if (imageHeight < 3600) littleRecSize = 12;
  182. else if (imageHeight < 3900) littleRecSize = 13;
  183. else if (imageHeight < 4200) littleRecSize = 14;
  184. else if (imageHeight < 4500) littleRecSize = 15;
  185. else if (imageHeight < 4800) littleRecSize = 16;
  186. else if (imageHeight < 5100) littleRecSize = 17;
  187. else littleRecSize = 18;
  188. switch (activeHandleIdx)
  189. {
  190. case 0:
  191. window.DispRectangle2(midR, midC, 0, littleRecSize, littleRecSize);
  192. break;
  193. case 1:
  194. window.DispRectangle2(sizeR, sizeC, 0, littleRecSize, littleRecSize);
  195. break;
  196. case 2:
  197. window.DispRectangle2(startR, startC, startPhi, littleRecSize, littleRecSize);
  198. break;
  199. case 3:
  200. window.DispRectangle2(extentR , extentC , 0, littleRecSize, littleRecSize);
  201. break;
  202. }
  203. }
  204. /// <summary>
  205. /// Recalculates the shape of the ROI. Translation is
  206. /// performed at the active handle of the ROI object
  207. /// for the image coordinate (x,y)
  208. /// </summary>
  209. public override void moveByHandle(double newX, double newY, HWindowControl window)
  210. {
  211. HTuple distance;
  212. double dirX, dirY, prior, next, valMax, valMin;
  213. switch (activeHandleIdx)
  214. {
  215. case 0: // midpoint
  216. dirY = midR - newY;
  217. dirX = midC - newX;
  218. midR = newY;
  219. midC = newX;
  220. sizeR -= dirY;
  221. sizeC -= dirX;
  222. determineArcHandles();
  223. break;
  224. case 1: // handle at circle border
  225. sizeR = newY;
  226. sizeC = newX;
  227. HOperatorSet.DistancePp(new HTuple(sizeR), new HTuple(sizeC),
  228. new HTuple(midR), new HTuple(midC), out distance);
  229. radius = distance[0].D;
  230. determineArcHandles();
  231. break;
  232. case 2: // start handle for arc
  233. dirY = newY - midR;
  234. dirX = newX - midC;
  235. startPhi = Math.Atan2(-dirY, dirX);
  236. if (startPhi < 0)
  237. startPhi = PI + (startPhi + PI);
  238. setStartHandle();
  239. prior = extentPhi;
  240. extentPhi = HMisc.AngleLl(midR, midC, startR, startC, midR, midC, extentR, extentC);
  241. if (extentPhi < 0 && prior > PI * 0.8)
  242. extentPhi = (PI + extentPhi) + PI;
  243. else if (extentPhi > 0 && prior < -PI * 0.7)
  244. extentPhi = -PI - (PI - extentPhi);
  245. break;
  246. case 3: // end handle for arc
  247. dirY = newY - midR;
  248. dirX = newX - midC;
  249. prior = extentPhi;
  250. next = Math.Atan2(-dirY, dirX);
  251. if (next < 0)
  252. next = PI + (next + PI);
  253. if (circDir == "positive" && startPhi >= next)
  254. extentPhi = (next + TwoPI) - startPhi;
  255. else if (circDir == "positive" && next > startPhi)
  256. extentPhi = next - startPhi;
  257. else if (circDir == "negative" && startPhi >= next)
  258. extentPhi = -1.0 * (startPhi - next);
  259. else if (circDir == "negative" && next > startPhi)
  260. extentPhi = -1.0 * (startPhi + TwoPI - next);
  261. valMax = Math.Max(Math.Abs(prior), Math.Abs(extentPhi));
  262. valMin = Math.Min(Math.Abs(prior), Math.Abs(extentPhi));
  263. if ((valMax - valMin) >= PI)
  264. extentPhi = (circDir == "positive") ? -1.0 * valMin : valMin;
  265. setExtentHandle();
  266. break;
  267. }
  268. circDir = (extentPhi < 0) ? "negative" : "positive";
  269. updateArrowHandle();
  270. }
  271. /// <summary>Gets the HALCON region described by the ROI</summary>
  272. public override HRegion getRegion()
  273. {
  274. HRegion region;
  275. contour.Dispose();
  276. contour.GenCircleContourXld(midR, midC, radius, startPhi, (startPhi + extentPhi), circDir, 1.0);
  277. region = new HRegion(contour);
  278. return region;
  279. }
  280. /// <summary>
  281. /// Gets the model information described by the ROI
  282. /// </summary>
  283. public override HTuple getModelData()
  284. {
  285. return new HTuple(new double[] { midR, midC, radius, startPhi, extentPhi });
  286. }
  287. /// <summary>
  288. /// Auxiliary method to determine the positions of the second and
  289. /// third handle.
  290. /// </summary>
  291. private void determineArcHandles()
  292. {
  293. setStartHandle();
  294. setExtentHandle();
  295. }
  296. /// <summary>
  297. /// Auxiliary method to recalculate the start handle for the arc
  298. /// </summary>
  299. private void setStartHandle()
  300. {
  301. startR = midR - radius * Math.Sin(startPhi);
  302. startC = midC + radius * Math.Cos(startPhi);
  303. }
  304. /// <summary>
  305. /// Auxiliary method to recalculate the extent handle for the arc
  306. /// </summary>
  307. private void setExtentHandle()
  308. {
  309. extentR = midR - radius * Math.Sin(startPhi + extentPhi);
  310. extentC = midC + radius * Math.Cos(startPhi + extentPhi);
  311. }
  312. /// <summary>
  313. /// Auxiliary method to display an arrow at the extent arc position
  314. /// </summary>
  315. private void updateArrowHandle()
  316. {
  317. double row1, col1, row2, col2;
  318. double rowP1, colP1, rowP2, colP2;
  319. double length,dr,dc, halfHW, sign, angleRad;
  320. double headLength = 15;
  321. double headWidth = 15;
  322. arrowHandleXLD.Dispose();
  323. arrowHandleXLD.GenEmptyObj();
  324. row2 = extentR;
  325. col2 = extentC;
  326. angleRad = (startPhi + extentPhi) + Math.PI * 0.5;
  327. sign = (circDir == "negative") ? -1.0 : 1.0;
  328. row1 = row2 + sign * Math.Sin(angleRad) * 20;
  329. col1 = col2 - sign * Math.Cos(angleRad) * 20;
  330. length = HMisc.DistancePp(row1, col1, row2, col2);
  331. if (length == 0)
  332. length = -1;
  333. dr = (row2 - row1) / length;
  334. dc = (col2 - col1) / length;
  335. halfHW = headWidth / 2.0;
  336. rowP1 = row1 + (length - headLength) * dr + halfHW * dc;
  337. rowP2 = row1 + (length - headLength) * dr - halfHW * dc;
  338. colP1 = col1 + (length - headLength) * dc - halfHW * dr;
  339. colP2 = col1 + (length - headLength) * dc + halfHW * dr;
  340. if (length == -1)
  341. arrowHandleXLD.GenContourPolygonXld(row1, col1);
  342. else
  343. arrowHandleXLD.GenContourPolygonXld(new HTuple(new double[] { row1, row2, rowP1, row2, rowP2, row2 }),
  344. new HTuple(new double[] { col1, col2, colP1, col2, colP2, col2 }));
  345. }
  346. }//end of class
  347. }//end of namespace