Enum or Array or something else

subaru_sti

Active member
Joined
Jul 4, 2009
Messages
34
Programming Experience
Beginner
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?

VB.NET:
    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

Stephen
 
VB.NET:
    Public Enum CardinalPoints
        N = 1 Or 9
        NE = 2
        E = 3
        SE = 4
        S = 5
        SW = 6
        W = 7
        NW = 8
    End Enum

Stephen,

Enums work just fine. However, I would start by having N at 0, then going up from there. IOW,

VB.NET:
     Public Enum CardinalPoints
          N = 0
          NE = 1
          E = 2
          SE = 3
          S = 4
          SW = 5
          W = 6
          NW = 7
     End Enum

VB.NET:
    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.")

[COLOR="Red"]            If degrees = 360 Then degrees = 0
            compassPoint = CInt(Math.Truncate((degrees / 360) * 8) + 0.5)
[/COLOR]
            Return CardinalPoints.GetName(GetType(CardinalPoints), compassPoint).ToString()

        End Function
    End Class

Also, since you came up with the use of your program for compass directions, I'm a old-school navigator myself; those eight directions are not good enough for me. I'm going to include a couple of websites for myself and other people (although few and far between) would like:

[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.

VB.NET:
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

VB.NET:
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

VB.NET:
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
 
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

Technically you're correct but I've learned never to trust input. If will still give you a correct value of 0 if someone enters 360.

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:

VB.NET:
    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

Thanks again,

Stephen
 
Back
Top