![]() |
Click here to advertise with us
|
|
|||||||
| VB.NET General Discussion VB.NET general discussion area |
![]() |
|
|
LinkBack | Thread Tools | Display Modes |
|
|||
|
Hello.
I have the following code which obtains the compass direction from a degree value. I'm new to VB.Net and was wondering what is the best way to store the values, in an Enum or an Array? Code:
Public Enum CardinalPoints
N = 1 Or 9
NE = 2
E = 3
SE = 4
S = 5
SW = 6
W = 7
NW = 8
End Enum
Public Class Helper
Public Function DegreesToCardinalMark(ByVal degrees As Double) As String
Dim compassPoint As Integer
If degrees > 360 Then Throw New ArgumentOutOfRangeException("Degrees cannot be greater than 360.")
If degrees < 0 Then Throw New ArgumentOutOfRangeException("Degrees cannot be less than 0.")
compassPoint = CInt(Math.Truncate(((degrees / 360) * 8) + 0.5) + 1)
Return CardinalPoints.GetName(GetType(CardinalPoints), compassPoint).ToString()
End Function
End Class
|
|
|||
|
Code:
Public Enum CardinalPoints
N = 1 Or 9
NE = 2
E = 3
SE = 4
S = 5
SW = 6
W = 7
NW = 8
End Enum
Enums work just fine. However, I would start by having N at 0, then going up from there. IOW, Code:
Public Enum CardinalPoints
N = 0
NE = 1
E = 2
SE = 3
S = 4
SW = 5
W = 6
NW = 7
End Enum
Code:
Public Class Helper
Public Function DegreesToCardinalMark(ByVal degrees As Double) As String
Dim compassPoint As Integer
If degrees > 360 Then Throw New ArgumentOutOfRangeException("Degrees cannot be greater than 360.")
If degrees < 0 Then Throw New ArgumentOutOfRangeException("Degrees cannot be less than 0.")
If degrees = 360 Then degrees = 0
compassPoint = CInt(Math.Truncate((degrees / 360) * 8) + 0.5)
Return CardinalPoints.GetName(GetType(CardinalPoints), compassPoint).ToString()
End Function
End Class
[ame=http://en.wikipedia.org/wiki/Compass_rose]Compass rose - Wikipedia, the free encyclopedia[/ame] [ame=http://en.wikipedia.org/wiki/Boxing_the_compass]Boxing the compass - Wikipedia, the free encyclopedia[/ame] NOTE about Boxing the compass: Although, step 4 of the instructions say to increment the result by 1, I would start the table's numbering scheme at 0 (to correspond to VB.NET's standards) Randy
|
|
|||
|
Thank you for the pointer - I will make the change.
The next thing I was planning on doing was adding the ability to specify how many points you want to use; 4, 8, 16, or 32. I have been struggling with this though. Do I create four different enums and then depending on how many points I want, I use that enum? That doesn't seem like the best approach. I tried to create an enum with all 32 points, like mentioned in the wiki article but I couldn't figure out a formula to choose the correct point based on the number of points you want to use. Any ideas? Stephen |
|
|||
|
There was an order of operation issue with your compassPoint calculation.
degrees Mod 360 will give you the degress on the compass you're looking for. (750.0 is really 30.0 etc.) If you're looking to give an option for 32, 16, 8, 4 points you should be able multiply your point number by 32/number of points to get the correct value out of the Enum. Haven't tested it exhaustively but it worked with several values using 4 and 8 points. Code:
Public Enum CardinalPoints N NbE NNE NEbN NE NEbE ENE EbN E EbS ESE SEbE SE SEbS SSE SbE S SbW SSW SWbS SW SWbW WSW WbS W WbN WNW NWbW NW NWbN NNW NbW End Enum Code:
Public Class Helper Public Function DegreesToCardinalMark(ByVal degrees As Double, ByVal numCardinalPoints As Integer) As String degrees = degrees Mod 360 Dim compassPoint As Integer = CInt(Math.Truncate((degrees / 360) * numCardinalPoints + 0.5) * 32 / numCardinalPoints) Mod 32 Return CardinalPoints.GetName(GetType(CardinalPoints), compassPoint).ToString() End Function End Class Code:
Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim a As New Helper MessageBox.Show(a.DegreesToCardinalMark(750.0, 8)) End Sub End Class |
|
|||
|
Sweet, thanks. I ran a bunch of different tests and it seems to be accurate. The only thing I don't understand is "degrees = degrees Mod 360". Why do you need that? Degrees (which I should rename to Course) should only ever be between 0 and 360, right?
Stephen |
|
|||
|
Quote:
The Mod 32 on the compassPoint is to give you a value of 0 in the case you would be passing in 0. |
|
|||
|
Makes sense. The mod 32 is a good idea because if you pass in 360 (which is what I think you meant to write) you actually get 32 returned, which is not a value in the enum. That is better then the way I did it with adding the extra one.
For validation, I have this: Code:
Public Class Direction
Private _course As Double
Public Sub New(ByVal course As Double)
Me.Course = course
End Sub
Public Property Course() As Double
Get
Return _course
End Get
Set(ByVal value As Double)
If value > 360 Then Throw New ArgumentOutOfRangeException("Course cannot be greater than 360.")
If value < 0 Then Throw New ArgumentOutOfRangeException("Course cannot be less than 0.")
_course = value
End Set
End Property
End Class
Stephen |
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|