1 #Region "Microsoft.VisualBasic::caafb1f7e4829b52d05c2c8ad42bc96d, Microsoft.VisualBasic.Core\Extensions\Math\Trigonometric\Trigonometric.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     '     Module Trigonometric
35     
36     '         Function: Angle, (+2 Overloads) Distance, GetAngle, GetAngleVector, MovePoint
37     '                   NearestPoint, ToCartesianPoint, ToDegrees, ToRadians
38     
39     
40     ' /********************************************************************************/
41
42 #End Region
43
44 Imports System.Drawing
45 Imports System.Runtime.CompilerServices
46 Imports sys = System.Math
47
48 Namespace Math
49
50     Public Module Trigonometric
51
52         ''' <summary>
53         ''' Polar to cartesian coordinate system point.(将极坐标转换为笛卡尔坐标系直角坐标系)
54         ''' </summary>
55         ''' <param name="polar">(半径, 角度)</param>
56         ''' <param name="fromDegree">alpha角度参数是否是度为单位,默认是真,即函数会在这里自动转换为弧度</param>
57         ''' <returns></returns>
58         <Extension> Public Function ToCartesianPoint(polar As (r#, alpha!), Optional fromDegree As Boolean = TrueAs PointF
59             Dim alpha = polar.alpha
60
61             If fromDegree Then
62                 alpha = alpha * sys.PI / 180
63             End If
64
65             Dim x = polar.r * sys.Cos(alpha)
66             Dim y = polar.r * sys.Sin(alpha)
67
68             Return New PointF(x, y)
69         End Function
70
71         ''' <summary>
72         ''' 
73         ''' </summary>
74         ''' <param name="radian">``0 -> 2*<see cref="Math.PI"/>``</param>
75         ''' <returns></returns>
76         Public Function GetAngleVector(radian As SingleOptional r As Double = 1) As PointF
77             Dim x = sys.Cos(radian) * r
78             Dim y = sys.Sin(radian) * r
79
80             Return New PointF(x, y)
81         End Function
82
83         ''' <summary>
84         ''' 计算结果为角度
85         ''' </summary>
86         ''' <param name="p"></param>
87         ''' <returns></returns>
88         ''' 
89         <MethodImpl(MethodImplOptions.AggressiveInlining)>
90         <Extension>
91         Public Function Angle(p As PointF) As Double
92             Return sys.Atan2(p.Y, p.X)
93         End Function
94
95         <MethodImpl(MethodImplOptions.AggressiveInlining)>
96         Public Function Distance(a As Point, b As Point) As Double
97             Return sys.Sqrt((a.X - b.X) ^ 2 + (a.Y - b.Y) ^ 2)
98         End Function
99
100         <MethodImpl(MethodImplOptions.AggressiveInlining)>
101         Public Function Distance(a As PointF, b As PointF) As Double
102             Return sys.Sqrt((a.X - b.X) ^ 2 + (a.Y - b.Y) ^ 2)
103         End Function
104
105         Public Function GetAngle(p1 As Point, p2 As Point) As Double
106             Dim xDiff As Double = p2.X - p1.X
107             Dim yDiff As Double = p2.Y - p1.Y
108             Return 180 - (ToDegrees(sys.Atan2(yDiff, xDiff)) - 90)
109         End Function
110
111         <Extension>
112         Public Function MovePoint(p As Point, angle As Double, distance As IntegerAs Point
113             p = New Point(p)
114             p.X += distance * sys.Sin(angle)
115             p.Y += distance * sys.Cos(angle)
116
117             Return p
118         End Function
119
120         ''' <summary>
121         ''' Converts an angle measured in degrees to an approximately
122         ''' equivalent angle measured in radians.  The conversion from
123         ''' degrees to radians is generally inexact.
124         ''' </summary>
125         ''' <param name="angdeg">   an angle, in degrees </param>
126         ''' <returns>  the measurement of the angle {@code angdeg}
127         '''          in radians.
128         ''' @since   1.2 </returns>
129         ''' 
130         <MethodImpl(MethodImplOptions.AggressiveInlining)>
131         <Extension> Public Function ToRadians(angdeg As DoubleAs Double
132             Return angdeg / 180.0 * sys.PI
133         End Function
134
135         ''' <summary>
136         ''' Converts an angle measured in radians to an approximately
137         ''' equivalent angle measured in degrees.  The conversion from
138         ''' radians to degrees is generally inexact; users should
139         ''' <i>not</i> expect {@code cos(toRadians(90.0))} to exactly
140         ''' equal {@code 0.0}.
141         ''' </summary>
142         ''' <param name="angrad">   an angle, in radians </param>
143         ''' <returns>  the measurement of the angle {@code angrad}
144         '''          in degrees.
145         ''' @since   1.2 </returns>
146         ''' 
147         <MethodImpl(MethodImplOptions.AggressiveInlining)>
148         <Extension> Public Function ToDegrees(angrad As DoubleAs Double
149             Return angrad * 180.0 / sys.PI
150         End Function
151
152         <Extension>
153         Public Function NearestPoint(points As IEnumerable(Of Point), x%, y%, radius#) As Point
154             For Each pos As Point In points
155                 Dim dist = sys.Sqrt((x - pos.X) ^ 2 + (y - pos.Y) ^ 2)
156
157                 If dist <= radius Then
158                     Return pos
159                 End If
160             Next
161
162             Return Nothing
163         End Function
164     End Module
165 End Namespace