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.Diagnostics;
|
---|
7 | using System.ComponentModel;
|
---|
8 | using Microsoft.Research.DynamicDataDisplay.Common;
|
---|
9 |
|
---|
10 | namespace Microsoft.Research.DynamicDataDisplay.Charts
|
---|
11 | {
|
---|
12 | /// <summary>
|
---|
13 | /// An ordered pair of values, representing a segment.
|
---|
14 | /// </summary>
|
---|
15 | /// <typeparam name="T">Type of each of two values of range.</typeparam>
|
---|
16 | [Serializable]
|
---|
17 | [DebuggerDisplay(@"{Min} — {Max}")]
|
---|
18 | [TypeConverter(typeof(RangeConverter))]
|
---|
19 | public struct Range<T> : IEquatable<Range<T>>
|
---|
20 | {
|
---|
21 | /// <summary>
|
---|
22 | /// Initializes a new instance of the <see cref="Range<T>"/> struct.
|
---|
23 | /// </summary>
|
---|
24 | /// <param name="min">The minimal value of segment.</param>
|
---|
25 | /// <param name="max">The maximal value of segment.</param>
|
---|
26 | public Range(T min, T max)
|
---|
27 | {
|
---|
28 | this.min = min;
|
---|
29 | this.max = max;
|
---|
30 |
|
---|
31 | #if DEBUG
|
---|
32 | if (min is IComparable)
|
---|
33 | {
|
---|
34 | IComparable c1 = (IComparable)min;
|
---|
35 | IComparable c2 = (IComparable)max;
|
---|
36 |
|
---|
37 | DebugVerify.Is(c1.CompareTo(c2) <= 0);
|
---|
38 | }
|
---|
39 | #endif
|
---|
40 | }
|
---|
41 |
|
---|
42 | private readonly T min;
|
---|
43 | /// <summary>
|
---|
44 | /// Gets the minimal value of segment.
|
---|
45 | /// </summary>
|
---|
46 | /// <value>The min.</value>
|
---|
47 | public T Min
|
---|
48 | {
|
---|
49 | get { return min; }
|
---|
50 | }
|
---|
51 |
|
---|
52 | private readonly T max;
|
---|
53 | /// <summary>
|
---|
54 | /// Gets the maximal value of segment.
|
---|
55 | /// </summary>
|
---|
56 | /// <value>The max.</value>
|
---|
57 | public T Max
|
---|
58 | {
|
---|
59 | get { return max; }
|
---|
60 | }
|
---|
61 |
|
---|
62 | static float floatEps = (float)1e-10;
|
---|
63 | static double doubleEps = 1e-10;
|
---|
64 |
|
---|
65 |
|
---|
66 | public static bool operator ==(Range<T> first, Range<T> second)
|
---|
67 | {
|
---|
68 | return (first.min.Equals(second.min) && first.max.Equals(second.max) ||
|
---|
69 | first.IsEmpty && second.IsEmpty);
|
---|
70 | }
|
---|
71 |
|
---|
72 | public static bool operator !=(Range<T> first, Range<T> second)
|
---|
73 | {
|
---|
74 | return !(first == second);
|
---|
75 | }
|
---|
76 |
|
---|
77 | public static bool operator <(Range<T> first, Range<T> second)
|
---|
78 | {
|
---|
79 | IComparable<T> firstMin = first.min as IComparable<T>;
|
---|
80 |
|
---|
81 | if (firstMin == null)
|
---|
82 | throw new InvalidOperationException("Cannot compare ranges which are not IComparable.");
|
---|
83 |
|
---|
84 | IComparable<T> firstMax = first.max as IComparable<T>;
|
---|
85 |
|
---|
86 | return firstMin.CompareTo(second.Min) > 0 && firstMax.CompareTo(second.Max) < 0;
|
---|
87 | }
|
---|
88 |
|
---|
89 | public static bool operator >(Range<T> first, Range<T> second)
|
---|
90 | {
|
---|
91 | IComparable<T> firstMin = first.min as IComparable<T>;
|
---|
92 |
|
---|
93 | if (firstMin == null)
|
---|
94 | throw new InvalidOperationException("Cannot compare ranges which are not IComparable.");
|
---|
95 |
|
---|
96 | IComparable<T> firstMax = first.max as IComparable<T>;
|
---|
97 |
|
---|
98 | return firstMin.CompareTo(second.min) < 0 && firstMax.CompareTo(second.max) > 0;
|
---|
99 | }
|
---|
100 |
|
---|
101 | public static bool EqualEps(Range<double> first, Range<double> second, double eps)
|
---|
102 | {
|
---|
103 | double delta = Math.Min(first.GetLength(), second.GetLength());
|
---|
104 | return Math.Abs(first.Min - second.Min) < eps * delta &&
|
---|
105 | Math.Abs(first.Max - second.Max) < eps * delta;
|
---|
106 | }
|
---|
107 |
|
---|
108 | /// <summary>
|
---|
109 | /// Indicates whether this instance and a specified object are equal.
|
---|
110 | /// </summary>
|
---|
111 | /// <param name="obj">Another object to compare to.</param>
|
---|
112 | /// <returns>
|
---|
113 | /// true if <paramref name="obj"/> and this instance are the same type and represent the same value; otherwise, false.
|
---|
114 | /// </returns>
|
---|
115 | public override bool Equals(object obj)
|
---|
116 | {
|
---|
117 | if (obj is Range<T>)
|
---|
118 | {
|
---|
119 | Range<T> other = (Range<T>)obj;
|
---|
120 | return (min.Equals(other.min) && max.Equals(other.max) || IsEmpty && other.IsEmpty);
|
---|
121 | }
|
---|
122 | else
|
---|
123 | return false;
|
---|
124 | }
|
---|
125 |
|
---|
126 | /// <summary>
|
---|
127 | /// Returns the hash code for this instance.
|
---|
128 | /// </summary>
|
---|
129 | /// <returns>
|
---|
130 | /// A 32-bit signed integer that is the hash code for this instance.
|
---|
131 | /// </returns>
|
---|
132 | public override int GetHashCode()
|
---|
133 | {
|
---|
134 | return min.GetHashCode() ^ max.GetHashCode();
|
---|
135 | }
|
---|
136 |
|
---|
137 | /// <summary>
|
---|
138 | /// Returns the fully qualified type name of this instance.
|
---|
139 | /// </summary>
|
---|
140 | /// <returns>
|
---|
141 | /// A <see cref="T:System.String"/> containing a fully qualified type name.
|
---|
142 | /// </returns>
|
---|
143 | public override string ToString()
|
---|
144 | {
|
---|
145 | return String.Format("{0} — {1}", min, max);
|
---|
146 | }
|
---|
147 |
|
---|
148 | /// <summary>
|
---|
149 | /// Gets a value indicating whether this range is empty.
|
---|
150 | /// </summary>
|
---|
151 | /// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
|
---|
152 | public bool IsEmpty
|
---|
153 | {
|
---|
154 | get
|
---|
155 | {
|
---|
156 | if (typeof(T) is IComparable)
|
---|
157 | return ((IComparable)min).CompareTo(max) >= 0;
|
---|
158 | else
|
---|
159 | return min.Equals(max);
|
---|
160 | }
|
---|
161 | }
|
---|
162 |
|
---|
163 | /// <summary>
|
---|
164 | /// Indicates whether the current object is equal to another object of the same type.
|
---|
165 | /// </summary>
|
---|
166 | /// <param name="other">An object to compare with this object.</param>
|
---|
167 | /// <returns>
|
---|
168 | /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
|
---|
169 | /// </returns>
|
---|
170 | public bool Equals(Range<T> other)
|
---|
171 | {
|
---|
172 | return this == other;
|
---|
173 | }
|
---|
174 | }
|
---|
175 | }
|
---|