PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Main/src/DynamicDataDisplay/Charts/Isolines/CellInfo.cs

#
C# | 399 lines | 294 code | 49 blank | 56 comment | 39 complexity | 56df94dfa6289290548c06decfd26880 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Diagnostics;
  6. using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
  7. using System.Windows;
  8. namespace Microsoft.Research.DynamicDataDisplay.Charts.Isolines
  9. {
  10. /// <summary>
  11. /// Isoline's grid cell
  12. /// </summary>
  13. internal interface ICell
  14. {
  15. Vector LeftTop { get; }
  16. Vector LeftBottom { get; }
  17. Vector RightTop { get; }
  18. Vector RightBottom { get; }
  19. }
  20. internal sealed class IrregularCell : ICell
  21. {
  22. public IrregularCell(Vector leftBottom, Vector rightBottom, Vector rightTop, Vector leftTop)
  23. {
  24. this.leftBottom = leftBottom;
  25. this.rightBottom = rightBottom;
  26. this.rightTop = rightTop;
  27. this.leftTop = leftTop;
  28. }
  29. public IrregularCell(Point lb, Point rb, Point rt, Point lt)
  30. {
  31. leftTop = lt.ToVector();
  32. leftBottom = lb.ToVector();
  33. rightTop = rt.ToVector();
  34. rightBottom = rb.ToVector();
  35. }
  36. #region ICell Members
  37. private readonly Vector leftTop;
  38. public Vector LeftTop
  39. {
  40. get { return leftTop; }
  41. }
  42. private readonly Vector leftBottom;
  43. public Vector LeftBottom
  44. {
  45. get { return leftBottom; }
  46. }
  47. private readonly Vector rightTop;
  48. public Vector RightTop
  49. {
  50. get { return rightTop; }
  51. }
  52. private readonly Vector rightBottom;
  53. public Vector RightBottom
  54. {
  55. get { return rightBottom; }
  56. }
  57. #endregion
  58. #region Sides
  59. public Vector LeftSide
  60. {
  61. get { return (leftBottom + leftTop) / 2; }
  62. }
  63. public Vector RightSide
  64. {
  65. get { return (rightBottom + rightTop) / 2; }
  66. }
  67. public Vector TopSide
  68. {
  69. get { return (leftTop + rightTop) / 2; }
  70. }
  71. public Vector BottomSide
  72. {
  73. get { return (leftBottom + rightBottom) / 2; }
  74. }
  75. #endregion
  76. public Point Center
  77. {
  78. get { return ((LeftSide + RightSide) / 2).ToPoint(); }
  79. }
  80. public IrregularCell GetSubRect(SubCell sub)
  81. {
  82. switch (sub)
  83. {
  84. case SubCell.LeftBottom:
  85. return new IrregularCell(LeftBottom, BottomSide, Center.ToVector(), LeftSide);
  86. case SubCell.LeftTop:
  87. return new IrregularCell(LeftSide, Center.ToVector(), TopSide, LeftTop);
  88. case SubCell.RightBottom:
  89. return new IrregularCell(BottomSide, RightBottom, RightSide, Center.ToVector());
  90. case SubCell.RightTop:
  91. default:
  92. return new IrregularCell(Center.ToVector(), RightSide, RightTop, TopSide);
  93. }
  94. }
  95. }
  96. internal enum SubCell
  97. {
  98. LeftBottom = 0,
  99. LeftTop = 1,
  100. RightBottom = 2,
  101. RightTop = 3
  102. }
  103. internal class ValuesInCell
  104. {
  105. double min = Double.MaxValue, max = Double.MinValue;
  106. /// <summary>Initializes values in four corners of cell</summary>
  107. /// <param name="leftBottom"></param>
  108. /// <param name="rightBottom"></param>
  109. /// <param name="rightTop"></param>
  110. /// <param name="leftTop"></param>
  111. /// <remarks>Some or all values can be NaN. That means that value is not specified (misssing)</remarks>
  112. public ValuesInCell(double leftBottom, double rightBottom, double rightTop, double leftTop)
  113. {
  114. this.leftTop = leftTop;
  115. this.leftBottom = leftBottom;
  116. this.rightTop = rightTop;
  117. this.rightBottom = rightBottom;
  118. // Find max and min values (with respect to possible NaN values)
  119. if (!Double.IsNaN(leftTop))
  120. {
  121. if (min > leftTop)
  122. min = leftTop;
  123. if (max < leftTop)
  124. max = leftTop;
  125. }
  126. if (!Double.IsNaN(leftBottom))
  127. {
  128. if (min > leftBottom)
  129. min = leftBottom;
  130. if (max < leftBottom)
  131. max = leftBottom;
  132. }
  133. if (!Double.IsNaN(rightTop))
  134. {
  135. if (min > rightTop)
  136. min = rightTop;
  137. if (max < rightTop)
  138. max = rightTop;
  139. }
  140. if (!Double.IsNaN(rightBottom))
  141. {
  142. if (min > rightBottom)
  143. min = rightBottom;
  144. if (max < rightBottom)
  145. max = rightBottom;
  146. }
  147. left = (leftTop + leftBottom) / 2;
  148. bottom = (leftBottom + rightBottom) / 2;
  149. right = (rightTop + rightBottom) / 2;
  150. top = (rightTop + leftTop) / 2;
  151. }
  152. public ValuesInCell(double leftBottom, double rightBottom, double rightTop, double leftTop, double missingValue)
  153. {
  154. DebugVerify.IsNotNaN(leftBottom);
  155. DebugVerify.IsNotNaN(rightBottom);
  156. DebugVerify.IsNotNaN(rightTop);
  157. DebugVerify.IsNotNaN(leftTop);
  158. // Copy values and find min and max with respect to possible missing values
  159. if (leftTop != missingValue)
  160. {
  161. this.leftTop = leftTop;
  162. if (min > leftTop)
  163. min = leftTop;
  164. if (max < leftTop)
  165. max = leftTop;
  166. }
  167. else
  168. this.leftTop = Double.NaN;
  169. if (leftBottom != missingValue)
  170. {
  171. this.leftBottom = leftBottom;
  172. if (min > leftBottom)
  173. min = leftBottom;
  174. if (max < leftBottom)
  175. max = leftBottom;
  176. }
  177. else
  178. this.leftBottom = Double.NaN;
  179. if (rightTop != missingValue)
  180. {
  181. this.rightTop = rightTop;
  182. if (min > rightTop)
  183. min = rightTop;
  184. if (max < rightTop)
  185. max = rightTop;
  186. }
  187. else
  188. this.rightTop = Double.NaN;
  189. if (rightBottom != missingValue)
  190. {
  191. this.rightBottom = rightBottom;
  192. if (min > rightBottom)
  193. min = rightBottom;
  194. if (max < rightBottom)
  195. max = rightBottom;
  196. }
  197. else
  198. this.rightBottom = Double.NaN;
  199. left = (this.leftTop + this.leftBottom) / 2;
  200. bottom = (this.leftBottom + this.rightBottom) / 2;
  201. right = (this.rightTop + this.rightBottom) / 2;
  202. top = (this.rightTop + this.leftTop) / 2;
  203. /*
  204. if (leftTop != missingValue && )
  205. {
  206. if (leftBottom != missingValue)
  207. left = (leftTop + leftBottom) / 2;
  208. else
  209. left = Double.NaN;
  210. if (rightTop != missingValue)
  211. top = (leftTop + rightTop) / 2;
  212. else
  213. top = Double.NaN;
  214. }
  215. if (rightBottom != missingValue)
  216. {
  217. if (leftBottom != missingValue)
  218. bottom = (leftBottom + rightBottom) / 2;
  219. else
  220. bottom = Double.NaN;
  221. if (rightTop != missingValue)
  222. right = (rightTop + rightBottom) / 2;
  223. else
  224. right = Double.NaN;
  225. }*/
  226. }
  227. /*internal bool ValueBelongTo(double value)
  228. {
  229. IEnumerable<double> values = new double[] { leftTop, leftBottom, rightTop, rightBottom };
  230. return !(values.All(v => v > value) || values.All(v => v < value));
  231. }*/
  232. internal bool ValueBelongTo(double value)
  233. {
  234. return (min <= value && value <= max);
  235. }
  236. #region Edges
  237. [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  238. private readonly double leftTop;
  239. public double LeftTop { get { return leftTop; } }
  240. [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  241. private readonly double leftBottom;
  242. public double LeftBottom { get { return leftBottom; } }
  243. [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  244. private readonly double rightTop;
  245. public double RightTop
  246. {
  247. get { return rightTop; }
  248. }
  249. [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  250. private readonly double rightBottom;
  251. public double RightBottom
  252. {
  253. get { return rightBottom; }
  254. }
  255. #endregion
  256. #region Sides & center
  257. [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  258. private readonly double left;
  259. public double Left
  260. {
  261. get { return left; }
  262. }
  263. [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  264. private readonly double right;
  265. public double Right
  266. {
  267. get { return right; }
  268. }
  269. [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  270. private readonly double top;
  271. public double Top
  272. {
  273. get { return top; }
  274. }
  275. [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  276. private readonly double bottom;
  277. public double Bottom
  278. {
  279. get { return bottom; }
  280. }
  281. public double Center
  282. {
  283. get { return (Left + Right) * 0.5; }
  284. }
  285. #endregion
  286. #region SubCells
  287. public ValuesInCell LeftTopCell
  288. {
  289. get { return new ValuesInCell(Left, Center, Top, LeftTop); }
  290. }
  291. public ValuesInCell RightTopCell
  292. {
  293. get { return new ValuesInCell(Center, Right, RightTop, Top); }
  294. }
  295. public ValuesInCell RightBottomCell
  296. {
  297. get { return new ValuesInCell(Bottom, RightBottom, Right, Center); }
  298. }
  299. public ValuesInCell LeftBottomCell
  300. {
  301. get { return new ValuesInCell(LeftBottom, Bottom, Center, Left); }
  302. }
  303. public ValuesInCell GetSubCell(SubCell subCell)
  304. {
  305. switch (subCell)
  306. {
  307. case SubCell.LeftBottom:
  308. return LeftBottomCell;
  309. case SubCell.LeftTop:
  310. return LeftTopCell;
  311. case SubCell.RightBottom:
  312. return RightBottomCell;
  313. case SubCell.RightTop:
  314. default:
  315. return RightTopCell;
  316. }
  317. }
  318. #endregion
  319. /// <summary>
  320. /// Returns bitmask of comparison of values at cell corners with reference value.
  321. /// Corresponding bit is set to one if value at cell corner is greater than reference value.
  322. /// a------b
  323. /// | Cell |
  324. /// d------c
  325. /// </summary>
  326. /// <param name="a">Value at corner (see figure)</param>
  327. /// <param name="b">Value at corner (see figure)</param>
  328. /// <param name="c">Value at corner (see figure)</param>
  329. /// <param name="d">Value at corner (see figure)</param>
  330. /// <param name="value">Reference value</param>
  331. /// <returns>Bitmask</returns>
  332. public CellBitmask GetCellValue(double value)
  333. {
  334. CellBitmask n = CellBitmask.None;
  335. if (!Double.IsNaN(leftTop) && leftTop > value)
  336. n |= CellBitmask.LeftTop;
  337. if (!Double.IsNaN(leftBottom) && leftBottom > value)
  338. n |= CellBitmask.LeftBottom;
  339. if (!Double.IsNaN(rightBottom) && rightBottom > value)
  340. n |= CellBitmask.RightBottom;
  341. if (!Double.IsNaN(rightTop) && rightTop > value)
  342. n |= CellBitmask.RightTop;
  343. return n;
  344. }
  345. }
  346. }