PageRenderTime 46ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/Main/src/DynamicDataDisplay/Charts/Axes/Numeric/NumericTicksProvider.cs

#
C# | 167 lines | 128 code | 26 blank | 13 comment | 19 complexity | 50b207a79bda5dacb64269c296978fc4 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 Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
  6. using System.Collections.ObjectModel;
  7. namespace Microsoft.Research.DynamicDataDisplay.Charts
  8. {
  9. /// <summary>
  10. /// Represents a ticks provider for <see cref="System.Double"/> values.
  11. /// </summary>
  12. public sealed class NumericTicksProvider : ITicksProvider<double>
  13. {
  14. /// <summary>
  15. /// Initializes a new instance of the <see cref="NumericTicksProvider"/> class.
  16. /// </summary>
  17. public NumericTicksProvider()
  18. {
  19. minorProvider = new MinorNumericTicksProvider(this);
  20. minorProvider.Changed += minorProvider_Changed;
  21. minorProvider.Coeffs = new double[] { 0.3, 0.3, 0.3, 0.3, 0.6, 0.3, 0.3, 0.3, 0.3 };
  22. }
  23. private void minorProvider_Changed(object sender, EventArgs e)
  24. {
  25. Changed.Raise(this);
  26. }
  27. public event EventHandler Changed;
  28. private void RaiseChangedEvent()
  29. {
  30. Changed.Raise(this);
  31. }
  32. private double minStep = 0.0;
  33. /// <summary>
  34. /// Gets or sets the minimal step between ticks.
  35. /// </summary>
  36. /// <value>The min step.</value>
  37. public double MinStep
  38. {
  39. get { return minStep; }
  40. set
  41. {
  42. Verify.IsTrue(value >= 0.0, "value");
  43. if (minStep != value)
  44. {
  45. minStep = value;
  46. RaiseChangedEvent();
  47. }
  48. }
  49. }
  50. private double[] ticks;
  51. public ITicksInfo<double> GetTicks(Range<double> range, int ticksCount)
  52. {
  53. double start = range.Min;
  54. double finish = range.Max;
  55. double delta = finish - start;
  56. int log = (int)Math.Round(Math.Log10(delta));
  57. double newStart = RoundingHelper.Round(start, log);
  58. double newFinish = RoundingHelper.Round(finish, log);
  59. if (newStart == newFinish)
  60. {
  61. log--;
  62. newStart = RoundingHelper.Round(start, log);
  63. newFinish = RoundingHelper.Round(finish, log);
  64. }
  65. // calculating step between ticks
  66. double unroundedStep = (newFinish - newStart) / ticksCount;
  67. int stepLog = log;
  68. // trying to round step
  69. double step = RoundingHelper.Round(unroundedStep, stepLog);
  70. if (step == 0)
  71. {
  72. stepLog--;
  73. step = RoundingHelper.Round(unroundedStep, stepLog);
  74. if (step == 0)
  75. {
  76. // step will not be rounded if attempts to be rounded to zero.
  77. step = unroundedStep;
  78. }
  79. }
  80. if (step < minStep)
  81. step = minStep;
  82. if (step != 0.0)
  83. {
  84. ticks = CreateTicks(start, finish, step);
  85. }
  86. else
  87. {
  88. ticks = new double[] { };
  89. }
  90. TicksInfo<double> res = new TicksInfo<double> { Info = log, Ticks = ticks };
  91. return res;
  92. }
  93. private static double[] CreateTicks(double start, double finish, double step)
  94. {
  95. DebugVerify.Is(step != 0.0);
  96. double x = step * Math.Floor(start / step);
  97. if (x == x + step)
  98. {
  99. return new double[0];
  100. }
  101. List<double> res = new List<double>();
  102. double increasedFinish = finish + step * 1.05;
  103. while (x <= increasedFinish)
  104. {
  105. res.Add(x);
  106. DebugVerify.Is(res.Count < 2000);
  107. x += step;
  108. }
  109. return res.ToArray();
  110. }
  111. private static int[] tickCounts = new int[] { 20, 10, 5, 4, 2, 1 };
  112. public const int DefaultPreferredTicksCount = 10;
  113. public int DecreaseTickCount(int ticksCount)
  114. {
  115. return tickCounts.FirstOrDefault(tick => tick < ticksCount);
  116. }
  117. public int IncreaseTickCount(int ticksCount)
  118. {
  119. int newTickCount = tickCounts.Reverse().FirstOrDefault(tick => tick > ticksCount);
  120. if (newTickCount == 0)
  121. newTickCount = tickCounts[0];
  122. return newTickCount;
  123. }
  124. private readonly MinorNumericTicksProvider minorProvider;
  125. public ITicksProvider<double> MinorProvider
  126. {
  127. get
  128. {
  129. if (ticks != null)
  130. {
  131. minorProvider.SetRanges(ticks.GetPairs());
  132. }
  133. return minorProvider;
  134. }
  135. }
  136. public ITicksProvider<double> MajorProvider
  137. {
  138. get { return null; }
  139. }
  140. }
  141. }