1 | #Region "Microsoft.VisualBasic::4e3de488c27d37d9d84f4fc815ad6396, Microsoft.VisualBasic.Core\ComponentModel\Ranges\RangeModel\DoubleRange.vb" |
2 | |
3 | ' Author: |
4 | ' |
5 | ' asuka (amethyst.asuka@gcmodeller.org) |
6 | ' xie (genetics@smrucc.org) |
7 | ' xieguigang (xie.guigang@live.com) |
8 | ' |
9 | ' Copyright (c) 2018 GPL3 Licensed |
10 | ' |
11 | ' |
12 | ' GNU GENERAL PUBLIC LICENSE (GPL3) |
13 | ' |
14 | ' |
15 | ' This program is free software: you can redistribute it and/or modify |
16 | ' it under the terms of the GNU General Public License as published by |
17 | ' the Free Software Foundation, either version 3 of the License, or |
18 | ' (at your option) any later version. |
19 | ' |
20 | ' This program is distributed in the hope that it will be useful, |
21 | ' but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | ' GNU General Public License for more details. |
24 | ' |
25 | ' You should have received a copy of the GNU General Public License |
26 | ' along with this program. If not, see <http://www.gnu.org/licenses/>. |
27 | |
28 | |
29 | |
30 | ' /********************************************************************************/ |
31 | |
32 | ' Summaries: |
33 | |
34 | ' Class DoubleRange |
35 | ' |
36 | ' Properties: Length, Max, Min |
37 | ' |
38 | ' Constructor: (+6 Overloads) Sub New |
39 | ' Function: Enumerate, GetEnumerator, IEnumerable_GetEnumerator, (+3 Overloads) IsInside, (+2 Overloads) IsOverlapping |
40 | ' ScaleMapping, (+2 Overloads) ToString, TryParse |
41 | ' Operators: *, <>, = |
42 | ' |
43 | ' |
44 | ' /********************************************************************************/ |
45 | |
46 | #End Region |
47 | |
48 | ' AForge Library |
49 | ' |
50 | ' Copyright © Andrew Kirillov, 2006 |
51 | ' andrew.kirillov@gmail.com |
52 | ' |
53 | |
54 | Imports System.Runtime.CompilerServices |
55 | Imports System.Xml.Serialization |
56 | Imports Microsoft.VisualBasic.Language |
57 | Imports Microsoft.VisualBasic.Language.Vectorization |
58 | |
59 | Namespace ComponentModel.Ranges.Model |
60 | |
61 | ''' <summary> |
62 | ''' Represents a double range with minimum and maximum values |
63 | ''' </summary> |
64 | Public Class DoubleRange : Implements IRanges(Of Double) |
65 | Implements IEnumerable(Of Double) |
66 | |
67 | ''' <summary> |
68 | ''' Minimum value |
69 | ''' </summary> |
70 | ''' |
71 | <XmlAttribute("min")> |
72 | Public Property Min As Double Implements IRanges(Of Double).Min |
73 | |
74 | ''' <summary> |
75 | ''' Maximum value |
76 | ''' </summary> |
77 | ''' |
78 | <XmlAttribute("max")> |
79 | Public Property Max As Double Implements IRanges(Of Double).Max |
80 | |
81 | ''' <summary> |
82 | ''' Length of the range (deffirence between maximum and minimum values) |
83 | ''' </summary> |
84 | ''' |
85 | Public ReadOnly Property Length() As Double |
86 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
87 | Get |
88 | Return Max - Min |
89 | End Get |
90 | End Property |
91 | |
92 | ''' <summary> |
93 | ''' Initializes a new instance of the <see cref="DoubleRange"/> class |
94 | ''' </summary> |
95 | ''' |
96 | ''' <param name="min">Minimum value of the range</param> |
97 | ''' <param name="max">Maximum value of the range</param> |
98 | Public Sub New(min#, max#) |
99 | Me.Min = min |
100 | Me.Max = max |
101 | End Sub |
102 | |
103 | ''' <summary> |
104 | ''' 从一个任意的实数数组之中构建出一个实数区间范围 |
105 | ''' </summary> |
106 | ''' <param name="data"></param> |
107 | Sub New(data As Double()) |
108 | Call Me.New(data.Min, data.Max) |
109 | End Sub |
110 | |
111 | ''' <summary> |
112 | ''' 从一个任意的实数向量之中构建出一个实数区间范围 |
113 | ''' </summary> |
114 | ''' <param name="vector"></param> |
115 | Sub New(vector As IEnumerable(Of Double)) |
116 | Call Me.New(data:=vector.ToArray) |
117 | End Sub |
118 | |
119 | Sub New(range As IntRange) |
120 | Call Me.New(range.Min, range.Max) |
121 | End Sub |
122 | |
123 | ''' <summary> |
124 | ''' Value copy |
125 | ''' </summary> |
126 | ''' <param name="range"></param> |
127 | Sub New(range As DoubleRange) |
128 | Call Me.New(range.Min, range.Max) |
129 | End Sub |
130 | |
131 | ''' <summary> |
132 | ''' For xml serialization. |
133 | ''' </summary> |
134 | Sub New() |
135 | End Sub |
136 | |
137 | ''' <summary> |
138 | ''' |
139 | ''' </summary> |
140 | ''' <returns></returns> |
141 | ''' <remarks> |
142 | ''' 因为进行json序列化的话,因为这个实现了<see cref="IEnumerable(Of T)"/>接口,但是并没有实现Add方法, |
143 | ''' 所以会出错,这里取消使用json来生成<see cref="ToString"/>函数的结果 |
144 | ''' </remarks> |
145 | ''' |
146 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
147 | Public Overrides Function ToString() As String |
148 | Return ToString("G2") |
149 | End Function |
150 | |
151 | Public Overloads Function ToString(format As String) As String |
152 | Return $"[min={Min.ToString(format)}, max={Max.ToString(format)}]" |
153 | End Function |
154 | |
155 | ''' <summary> |
156 | ''' Check if the specified value is inside this range |
157 | ''' </summary> |
158 | ''' |
159 | ''' <param name="x">Value to check</param> |
160 | ''' |
161 | ''' <returns><b>True</b> if the specified value is inside this range or |
162 | ''' <b>false</b> otherwise.</returns> |
163 | ''' |
164 | Public Function IsInside(x As Double) As Boolean Implements IRanges(Of Double).IsInside |
165 | Return ((x >= Min) AndAlso (x <= Max)) |
166 | End Function |
167 | |
168 | ''' <summary> |
169 | ''' Check if the specified <paramref name="range"/> is inside this range. |
170 | ''' (如果函数参数<paramref name="range"/>在当前的这个range之中,则返回真) |
171 | ''' </summary> |
172 | ''' <param name="range">Range to check</param> |
173 | ''' <returns> |
174 | ''' + <b>True</b> if the specified input <paramref name="range"/> parameter is inside this range or |
175 | ''' + <b>false</b> otherwise.</returns> |
176 | Public Function IsInside(range As DoubleRange) As Boolean |
177 | Return ((IsInside(range.Min)) AndAlso (IsInside(range.Max))) |
178 | End Function |
179 | |
180 | ''' <summary> |
181 | ''' Check if the specified range overlaps with this range |
182 | ''' </summary> |
183 | ''' |
184 | ''' <param name="range">Range to check for overlapping</param> |
185 | ''' |
186 | ''' <returns><b>True</b> if the specified range overlaps with this range or |
187 | ''' <b>false</b> otherwise.</returns> |
188 | ''' |
189 | Public Function IsOverlapping(range As DoubleRange) As Boolean |
190 | Return ((IsInside(range.Min)) OrElse (IsInside(range.Max))) |
191 | End Function |
192 | |
193 | Public Function IsInside(range As IRanges(Of Double)) As Boolean Implements IRanges(Of Double).IsInside |
194 | Return ((IsInside(range.Min)) AndAlso (IsInside(range.Max))) |
195 | End Function |
196 | |
197 | Public Function IsOverlapping(range As IRanges(Of Double)) As Boolean Implements IRanges(Of Double).IsOverlapping |
198 | Return ((IsInside(range.Min)) OrElse (IsInside(range.Max))) |
199 | End Function |
200 | |
201 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
202 | Public Shared Widening Operator CType(exp As String) As DoubleRange |
203 | Dim r As New DoubleRange |
204 | Call exp.Parser(r.Min, r.Max) |
205 | Return r |
206 | End Operator |
207 | |
208 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
209 | Public Shared Widening Operator CType(data#()) As DoubleRange |
210 | With data |
211 | Return New DoubleRange(min:= .Min, max:= .Max) |
212 | End With |
213 | End Operator |
214 | |
215 | Public Shared Widening Operator CType(tuple As (min#, max#)) As DoubleRange |
216 | Return New DoubleRange(tuple.min, tuple.max) |
217 | End Operator |
218 | |
219 | Public Shared Widening Operator CType(tuple As (min!, max!)) As DoubleRange |
220 | Return New DoubleRange(tuple.min, tuple.max) |
221 | End Operator |
222 | |
223 | Public Shared Widening Operator CType(tuple As (min&, max&)) As DoubleRange |
224 | Return New DoubleRange(tuple.min, tuple.max) |
225 | End Operator |
226 | |
227 | Public Shared Widening Operator CType(data As VectorShadows(Of Single)) As DoubleRange |
228 | Return data _ |
229 | .Select(Function(s) CDbl(s)) _ |
230 | .ToArray |
231 | End Operator |
232 | |
233 | ''' <summary> |
234 | ''' Scale numeric range |
235 | ''' </summary> |
236 | ''' <param name="range"></param> |
237 | ''' <param name="factor#"></param> |
238 | ''' <returns></returns> |
239 | ''' |
240 | <MethodImpl(MethodImplOptions.AggressiveInlining)> |
241 | Public Shared Operator *(range As DoubleRange, factor#) As DoubleRange |
242 | With range |
243 | Dim delta = (.Length * factor - .Length) / 2 |
244 | Dim ar As Double() = { |
245 | .Min - delta, |
246 | .Max + delta |
247 | } |
248 | |
249 | Return New DoubleRange(ar) |
250 | End With |
251 | End Operator |
252 | |
253 | ''' <summary> |
254 | ''' 这个函数需要通过一个返回结果的元素个数参数来计算出step步长 |
255 | ''' </summary> |
256 | ''' <param name="n%">所返回来的数组的元素的个数</param> |
257 | ''' <returns></returns> |
258 | Public Function Enumerate(n%) As Double() |
259 | If Length = 0 Then |
260 | Return {} |
261 | Else |
262 | Dim delta# = Length / n |
263 | Dim out As New List(Of Double) |
264 | |
265 | For x As Double = Min To Max Step delta |
266 | out += x |
267 | Next |
268 | |
269 | Return out |
270 | End If |
271 | End Function |
272 | |
273 | ''' <summary> |
274 | ''' Transform a numeric value in this <see cref="DoubleRange"/> into |
275 | ''' target numeric range: ``<paramref name="valueRange"/>``. |
276 | ''' (将当前的范围内的一个实数映射到另外的一个范围内的实数区间之中) |
277 | ''' </summary> |
278 | ''' <param name="x#">A numeric value in this <see cref="DoubleRange"/></param> |
279 | ''' <param name="valueRange"></param> |
280 | ''' <returns></returns> |
281 | Public Function ScaleMapping(x#, valueRange As DoubleRange) As Double |
282 | Dim percent# = (x - Min) / Length |
283 | Dim value# = percent * valueRange.Length + valueRange.Min |
284 | Return value |
285 | End Function |
286 | |
287 | Public Overridable Iterator Function GetEnumerator() As IEnumerator(Of Double) Implements IEnumerable(Of Double).GetEnumerator |
288 | For Each x In Me.Enumerate(100) |
289 | Yield x |
290 | Next |
291 | End Function |
292 | |
293 | Private Iterator Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator |
294 | Yield GetEnumerator() |
295 | End Function |
296 | |
297 | Public Shared Operator =(range As DoubleRange, value#) As Boolean |
298 | If range Is Nothing AndAlso value = 0 Then |
299 | ' 假若将doublerange看作为double类型的数值的话,则数值类型的Nothing值为0, |
300 | ' 所以在这里将Nothing等价于右边的value 0 |
301 | Return True |
302 | Else |
303 | Return range.Length = 0 AndAlso range.Min = value |
304 | End If |
305 | End Operator |
306 | |
307 | Public Shared Operator <>(range As DoubleRange, value#) As Boolean |
308 | Return Not range = value |
309 | End Operator |
310 | |
311 | Public Shared Function TryParse(expression As String) As DoubleRange |
312 | If expression.StringEmpty Then |
313 | Return Nothing |
314 | End If |
315 | |
316 | Try |
317 | Return expression |
318 | Catch ex As Exception |
319 | Return Nothing |
320 | End Try |
321 | End Function |
322 | End Class |
323 | End Namespace |