none
Request for Vector objects RRS feed

  • Question

  • Can we get a Vector2 and Vector3 class added to the Sytem.Math class?

    These are pretty commonly used objects and Microsoft has already written some Vector2 and Vector3 objects into the XNA framework. I am kind of shocked with each release of the .net framework that it hasn't been added.

    It would be nice to not have to install XNA in order to use vector objects...

    Thursday, May 9, 2013 6:19 PM

Answers

  • Feature requests should be posted in Connect (http://connect.microsoft.com).
    Thursday, May 9, 2013 7:10 PM
    Moderator
  • Its also very easy to spin your own VectorN structure.

    I agree, it seems like it should be included naturally - I've always been bugged by PointF and SizeF conversions...

    Here's a Vector2 object that I often use (well, technically I also have a "Geometry" class that contains other helper methods but I've moved the relevant ones into the Vector2 structure to make one code file to post).  You can implement as much or as little functionality as you like.

    Option Strict On
    Option Explicit On
    
    Imports System.Drawing
    
    Public Structure Vector2
        Implements IEquatable(Of Vector2)
        Implements IComparable(Of Vector2)
        Implements IComparable
    
        Public Shared ReadOnly Empty As New Vector2
    
        Public Function AreVectorsCollinear(ByVal vectorA As Vector2, ByVal vectorB As Vector2, ByVal vectorC As Vector2, ByVal tolerance As Single) As Boolean
            Return Between(GetArea(vectorA, vectorB, vectorC), -tolerance, tolerance)
        End Function
    
        Public Shared Function Between(ByVal value As Single, ByVal min As Single, ByVal max As Single) As Boolean
            Return value >= min AndAlso value <= max
        End Function
    
        Public Shared Function DegreesToRadians(ByVal degrees As Single) As Single
            Return CSng(degrees * (Math.PI / 180))
        End Function
    
        Public Shared Function GetAngleTo(ByVal source As Vector2, ByVal target As Vector2) As Single
            Return RadiansToDegrees(Vector2.GetRadiansTo(source, target))
        End Function
    
        Public Function GetArea(ByVal vectorA As Vector2, ByVal vectorB As Vector2, ByVal vectorC As Vector2) As Single
            Return vectorA.X * (vectorB.Y - vectorC.Y) + vectorB.X * (vectorC.Y - vectorA.Y) + vectorC.X * (vectorA.Y - vectorB.Y)
        End Function
    
        Public Shared Function GetCrossProduct(ByVal source As Vector2, ByVal target As Vector2) As Single
            Return source.X * target.Y - source.Y * target.X
        End Function
    
        Public Shared Function GetDistance(ByVal source As Vector2, ByVal target As Vector2) As Single
            Dim squareX As Double = CDbl(target.X - source.X)
            squareX *= squareX
            Dim squareY As Double = CDbl(target.Y - source.Y)
            squareY *= squareY
            Return CSng(System.Math.Sqrt(squareX + squareY))
        End Function
    
        Public Shared Function GetDotProduct(ByVal source As Vector2, ByVal target As Vector2) As Single
            Return source.X * target.X + source.Y * target.Y
        End Function
    
        Public Shared Function GetMagnitude(ByVal source As Vector2) As Single
            Return CSng(Math.Sqrt(Math.Pow(source.X, 2) + Math.Pow(source.Y, 2)))
        End Function
    
        Public Shared Function GetNormalized(ByVal source As Vector2) As Vector2
            Dim delta As Single = Vector2.GetMagnitude(source)
            Return New Vector2(source.X / delta, source.Y / delta)
        End Function
    
        Public Shared Function GetRadiansTo(ByVal source As Vector2, ByVal target As Vector2) As Single
            Return WrapAngle(CSng(Math.Atan2(target.Y - source.Y, target.X - source.X)))
        End Function
    
        Public Shared Function GetSlope(vectorOne As Vector2, vectorTwo As Vector2) As Single
            Return (vectorTwo.Y - vectorOne.Y) / (vectorTwo.X - vectorOne.X)
        End Function
    
        Public Shared Function GetVectorToward(ByVal source As Vector2, ByVal target As Vector2, ByVal distance As Single) As Vector2
            Dim angle As Single = Vector2.GetRadiansTo(source, target)
            Return GetVectorToward(source, angle, distance)
        End Function
    
        Public Shared Function GetVectorToward(ByVal source As Vector2, ByVal angleRadians As Single, ByVal distance As Single) As Vector2
            Return source + New Vector2(CSng(Math.Cos(angleRadians) * distance), CSng(Math.Sin(angleRadians) * distance))
        End Function
    
        Public Shared Function RadiansToDegrees(ByVal radians As Single) As Single
            Return CSng(radians * (180 / Math.PI))
        End Function
    
        Public Shared Function WrapAngle(ByVal radians As Single) As Single
            While radians < -Math.PI
                radians = CSng(radians + (Math.PI * 2))
            End While
            While radians > Math.PI
                radians = CSng(radians - (Math.PI * 2))
            End While
            Return radians
        End Function
    
        Public X As Single
        Public Y As Single
    
        Public Property Horizontal As Single
            Get
                Return X
            End Get
            Set(ByVal value As Single)
                X = value
            End Set
        End Property
    
        Public Property Vertical As Single
            Get
                Return Y
            End Get
            Set(ByVal value As Single)
                Y = value
            End Set
        End Property
    
        Public Sub New(ByVal xValue As Single, ByVal yValue As Single)
            X = xValue
            Y = yValue
        End Sub
    
        Public Sub New(ByVal bothValues As Single)
            Me.New(bothValues, bothValues)
        End Sub
    
        Public Sub New(ByVal pointValue As PointF)
            Me.New(pointValue.X, pointValue.Y)
        End Sub
    
        Public Sub New(ByVal pointValue As Point)
            Me.New(CSng(pointValue.X), CSng(pointValue.Y))
        End Sub
    
        Public Function IsInfinite() As Boolean
            Return Single.IsInfinity(X) OrElse Single.IsInfinity(Y)
        End Function
    
        Public Function DistanceTo(ByVal target As Vector2) As Single
            Return Vector2.GetDistance(Me, target)
        End Function
    
        Public Function AngleTo(ByVal target As Vector2) As Single
            Return Vector2.GetAngleTo(Me, target)
        End Function
    
        Public Function RadiansTo(ByVal target As Vector2) As Single
            Return Vector2.GetRadiansTo(Me, target)
        End Function
    
        Public Function VectorToward(ByVal target As Vector2, ByVal distance As Single) As Vector2
            Return Vector2.GetVectorToward(Me, target, distance)
        End Function
    
        Public Function VectorToward(ByVal angle As Single, ByVal distance As Single) As Vector2
            Return Vector2.GetVectorToward(Me, angle, distance)
        End Function
    
        Public Function Magnitude() As Single
            Return Vector2.GetMagnitude(Me)
        End Function
    
        Public Function Normalize() As Vector2
            Return Vector2.GetNormalized(Me)
        End Function
    
        Public Function ToPoint() As Point
            Return New Point(CInt(X), CInt(Y))
        End Function
    
        Public Function ToPointF() As PointF
            Return New PointF(X, Y)
        End Function
    
        Public Overrides Function ToString() As String
            Return String.Format("[X={0:n2}/Y={1:n2}]", X, Y)
        End Function
    
        Public Function Truncate() As Point
            Return New Point(CInt(System.Math.Floor(X)), CInt(System.Math.Floor(Y)))
        End Function
    
        Public Overloads Function ToString(ByVal format As String) As String
            Return String.Format(format, X, Y)
        End Function
    
        Public Shared Operator =(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return source.X = target.X AndAlso source.Y = target.Y
        End Operator
    
        Public Shared Operator <>(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return Not (source = target)
        End Operator
    
        Public Shared Operator +(ByVal source As Vector2, ByVal target As Vector2) As Vector2
            Return New Vector2(source.X + target.X, source.Y + target.Y)
        End Operator
    
        Public Shared Operator -(ByVal source As Vector2, ByVal target As Vector2) As Vector2
            Return New Vector2(source.X - target.X, source.Y - target.Y)
        End Operator
    
        Public Shared Operator *(ByVal source As Vector2, ByVal target As Vector2) As Vector2
            Return New Vector2(source.X * target.X, source.Y * target.Y)
        End Operator
    
        Public Shared Operator /(ByVal source As Vector2, ByVal target As Vector2) As Vector2
            Return New Vector2(source.X / target.X, source.Y / target.Y)
        End Operator
    
        Public Shared Operator +(ByVal source As Vector2, ByVal target As Single) As Vector2
            Return New Vector2(source.X + target, source.Y + target)
        End Operator
    
        Public Shared Operator -(ByVal source As Vector2, ByVal target As Single) As Vector2
            Return New Vector2(source.X - target, source.Y - target)
        End Operator
    
        Public Shared Operator *(ByVal source As Vector2, ByVal target As Single) As Vector2
            Return New Vector2(source.X * target, source.Y * target)
        End Operator
    
        Public Shared Operator /(ByVal source As Vector2, ByVal target As Single) As Vector2
            Return New Vector2(source.X / target, source.Y / target)
        End Operator
    
        Public Shared Operator >(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return source.CompareTo(target) > 0
        End Operator
    
        Public Shared Operator <(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return source.CompareTo(target) < 0
        End Operator
    
        Public Shared Operator >=(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return source.CompareTo(target) >= 0
        End Operator
    
        Public Shared Operator <=(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return source.CompareTo(target) <= 0
        End Operator
    
        Public Shared Narrowing Operator CType(ByVal source As Vector2) As PointF
            Return source.ToPointF
        End Operator
    
        Public Shared Narrowing Operator CType(ByVal source As Vector2) As Point
            Return source.ToPoint
        End Operator
    
        Public Shared Widening Operator CType(ByVal source As PointF) As Vector2
            Return New Vector2(source.X, source.Y)
        End Operator
    
        Public Shared Widening Operator CType(ByVal source As Point) As Vector2
            Return New Vector2(CSng(source.X), CSng(source.Y))
        End Operator
    
        Public Overloads Function Equals(ByVal other As Vector2) As Boolean Implements System.IEquatable(Of Vector2).Equals
            Return Me = other
        End Function
    
        Public Function CompareTo(ByVal other As Vector2) As Integer Implements System.IComparable(Of Vector2).CompareTo
            Dim thisMag As Single = Magnitude()
            Dim otherMag As Single = other.Magnitude()
            If thisMag = otherMag Then
                Return (X + Y).CompareTo(other.X + other.Y)
            End If
            Return thisMag.CompareTo(otherMag)
        End Function
    
        Public Function CompareTo(ByVal obj As Object) As Integer Implements System.IComparable.CompareTo
            If TypeOf obj Is Vector2 Then
                Return CompareTo(DirectCast(obj, Vector2))
            ElseIf TypeOf obj Is PointF Then
                Return CompareTo(New Vector2(DirectCast(obj, PointF)))
            ElseIf TypeOf obj Is Point Then
                Return CompareTo(New Vector2(DirectCast(obj, Point)))
            ElseIf TypeOf obj Is IComparable Then
                Return DirectCast(obj, IComparable).CompareTo(Me)
            Else
                Return -1
            End If
        End Function
    End Structure

    I definately would not add a reference to XNA just to get these basic structures.... recreate them instead.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Thursday, May 9, 2013 7:37 PM
    Moderator

All replies

  • Feature requests should be posted in Connect (http://connect.microsoft.com).
    Thursday, May 9, 2013 7:10 PM
    Moderator
  • Its also very easy to spin your own VectorN structure.

    I agree, it seems like it should be included naturally - I've always been bugged by PointF and SizeF conversions...

    Here's a Vector2 object that I often use (well, technically I also have a "Geometry" class that contains other helper methods but I've moved the relevant ones into the Vector2 structure to make one code file to post).  You can implement as much or as little functionality as you like.

    Option Strict On
    Option Explicit On
    
    Imports System.Drawing
    
    Public Structure Vector2
        Implements IEquatable(Of Vector2)
        Implements IComparable(Of Vector2)
        Implements IComparable
    
        Public Shared ReadOnly Empty As New Vector2
    
        Public Function AreVectorsCollinear(ByVal vectorA As Vector2, ByVal vectorB As Vector2, ByVal vectorC As Vector2, ByVal tolerance As Single) As Boolean
            Return Between(GetArea(vectorA, vectorB, vectorC), -tolerance, tolerance)
        End Function
    
        Public Shared Function Between(ByVal value As Single, ByVal min As Single, ByVal max As Single) As Boolean
            Return value >= min AndAlso value <= max
        End Function
    
        Public Shared Function DegreesToRadians(ByVal degrees As Single) As Single
            Return CSng(degrees * (Math.PI / 180))
        End Function
    
        Public Shared Function GetAngleTo(ByVal source As Vector2, ByVal target As Vector2) As Single
            Return RadiansToDegrees(Vector2.GetRadiansTo(source, target))
        End Function
    
        Public Function GetArea(ByVal vectorA As Vector2, ByVal vectorB As Vector2, ByVal vectorC As Vector2) As Single
            Return vectorA.X * (vectorB.Y - vectorC.Y) + vectorB.X * (vectorC.Y - vectorA.Y) + vectorC.X * (vectorA.Y - vectorB.Y)
        End Function
    
        Public Shared Function GetCrossProduct(ByVal source As Vector2, ByVal target As Vector2) As Single
            Return source.X * target.Y - source.Y * target.X
        End Function
    
        Public Shared Function GetDistance(ByVal source As Vector2, ByVal target As Vector2) As Single
            Dim squareX As Double = CDbl(target.X - source.X)
            squareX *= squareX
            Dim squareY As Double = CDbl(target.Y - source.Y)
            squareY *= squareY
            Return CSng(System.Math.Sqrt(squareX + squareY))
        End Function
    
        Public Shared Function GetDotProduct(ByVal source As Vector2, ByVal target As Vector2) As Single
            Return source.X * target.X + source.Y * target.Y
        End Function
    
        Public Shared Function GetMagnitude(ByVal source As Vector2) As Single
            Return CSng(Math.Sqrt(Math.Pow(source.X, 2) + Math.Pow(source.Y, 2)))
        End Function
    
        Public Shared Function GetNormalized(ByVal source As Vector2) As Vector2
            Dim delta As Single = Vector2.GetMagnitude(source)
            Return New Vector2(source.X / delta, source.Y / delta)
        End Function
    
        Public Shared Function GetRadiansTo(ByVal source As Vector2, ByVal target As Vector2) As Single
            Return WrapAngle(CSng(Math.Atan2(target.Y - source.Y, target.X - source.X)))
        End Function
    
        Public Shared Function GetSlope(vectorOne As Vector2, vectorTwo As Vector2) As Single
            Return (vectorTwo.Y - vectorOne.Y) / (vectorTwo.X - vectorOne.X)
        End Function
    
        Public Shared Function GetVectorToward(ByVal source As Vector2, ByVal target As Vector2, ByVal distance As Single) As Vector2
            Dim angle As Single = Vector2.GetRadiansTo(source, target)
            Return GetVectorToward(source, angle, distance)
        End Function
    
        Public Shared Function GetVectorToward(ByVal source As Vector2, ByVal angleRadians As Single, ByVal distance As Single) As Vector2
            Return source + New Vector2(CSng(Math.Cos(angleRadians) * distance), CSng(Math.Sin(angleRadians) * distance))
        End Function
    
        Public Shared Function RadiansToDegrees(ByVal radians As Single) As Single
            Return CSng(radians * (180 / Math.PI))
        End Function
    
        Public Shared Function WrapAngle(ByVal radians As Single) As Single
            While radians < -Math.PI
                radians = CSng(radians + (Math.PI * 2))
            End While
            While radians > Math.PI
                radians = CSng(radians - (Math.PI * 2))
            End While
            Return radians
        End Function
    
        Public X As Single
        Public Y As Single
    
        Public Property Horizontal As Single
            Get
                Return X
            End Get
            Set(ByVal value As Single)
                X = value
            End Set
        End Property
    
        Public Property Vertical As Single
            Get
                Return Y
            End Get
            Set(ByVal value As Single)
                Y = value
            End Set
        End Property
    
        Public Sub New(ByVal xValue As Single, ByVal yValue As Single)
            X = xValue
            Y = yValue
        End Sub
    
        Public Sub New(ByVal bothValues As Single)
            Me.New(bothValues, bothValues)
        End Sub
    
        Public Sub New(ByVal pointValue As PointF)
            Me.New(pointValue.X, pointValue.Y)
        End Sub
    
        Public Sub New(ByVal pointValue As Point)
            Me.New(CSng(pointValue.X), CSng(pointValue.Y))
        End Sub
    
        Public Function IsInfinite() As Boolean
            Return Single.IsInfinity(X) OrElse Single.IsInfinity(Y)
        End Function
    
        Public Function DistanceTo(ByVal target As Vector2) As Single
            Return Vector2.GetDistance(Me, target)
        End Function
    
        Public Function AngleTo(ByVal target As Vector2) As Single
            Return Vector2.GetAngleTo(Me, target)
        End Function
    
        Public Function RadiansTo(ByVal target As Vector2) As Single
            Return Vector2.GetRadiansTo(Me, target)
        End Function
    
        Public Function VectorToward(ByVal target As Vector2, ByVal distance As Single) As Vector2
            Return Vector2.GetVectorToward(Me, target, distance)
        End Function
    
        Public Function VectorToward(ByVal angle As Single, ByVal distance As Single) As Vector2
            Return Vector2.GetVectorToward(Me, angle, distance)
        End Function
    
        Public Function Magnitude() As Single
            Return Vector2.GetMagnitude(Me)
        End Function
    
        Public Function Normalize() As Vector2
            Return Vector2.GetNormalized(Me)
        End Function
    
        Public Function ToPoint() As Point
            Return New Point(CInt(X), CInt(Y))
        End Function
    
        Public Function ToPointF() As PointF
            Return New PointF(X, Y)
        End Function
    
        Public Overrides Function ToString() As String
            Return String.Format("[X={0:n2}/Y={1:n2}]", X, Y)
        End Function
    
        Public Function Truncate() As Point
            Return New Point(CInt(System.Math.Floor(X)), CInt(System.Math.Floor(Y)))
        End Function
    
        Public Overloads Function ToString(ByVal format As String) As String
            Return String.Format(format, X, Y)
        End Function
    
        Public Shared Operator =(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return source.X = target.X AndAlso source.Y = target.Y
        End Operator
    
        Public Shared Operator <>(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return Not (source = target)
        End Operator
    
        Public Shared Operator +(ByVal source As Vector2, ByVal target As Vector2) As Vector2
            Return New Vector2(source.X + target.X, source.Y + target.Y)
        End Operator
    
        Public Shared Operator -(ByVal source As Vector2, ByVal target As Vector2) As Vector2
            Return New Vector2(source.X - target.X, source.Y - target.Y)
        End Operator
    
        Public Shared Operator *(ByVal source As Vector2, ByVal target As Vector2) As Vector2
            Return New Vector2(source.X * target.X, source.Y * target.Y)
        End Operator
    
        Public Shared Operator /(ByVal source As Vector2, ByVal target As Vector2) As Vector2
            Return New Vector2(source.X / target.X, source.Y / target.Y)
        End Operator
    
        Public Shared Operator +(ByVal source As Vector2, ByVal target As Single) As Vector2
            Return New Vector2(source.X + target, source.Y + target)
        End Operator
    
        Public Shared Operator -(ByVal source As Vector2, ByVal target As Single) As Vector2
            Return New Vector2(source.X - target, source.Y - target)
        End Operator
    
        Public Shared Operator *(ByVal source As Vector2, ByVal target As Single) As Vector2
            Return New Vector2(source.X * target, source.Y * target)
        End Operator
    
        Public Shared Operator /(ByVal source As Vector2, ByVal target As Single) As Vector2
            Return New Vector2(source.X / target, source.Y / target)
        End Operator
    
        Public Shared Operator >(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return source.CompareTo(target) > 0
        End Operator
    
        Public Shared Operator <(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return source.CompareTo(target) < 0
        End Operator
    
        Public Shared Operator >=(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return source.CompareTo(target) >= 0
        End Operator
    
        Public Shared Operator <=(ByVal source As Vector2, ByVal target As Vector2) As Boolean
            Return source.CompareTo(target) <= 0
        End Operator
    
        Public Shared Narrowing Operator CType(ByVal source As Vector2) As PointF
            Return source.ToPointF
        End Operator
    
        Public Shared Narrowing Operator CType(ByVal source As Vector2) As Point
            Return source.ToPoint
        End Operator
    
        Public Shared Widening Operator CType(ByVal source As PointF) As Vector2
            Return New Vector2(source.X, source.Y)
        End Operator
    
        Public Shared Widening Operator CType(ByVal source As Point) As Vector2
            Return New Vector2(CSng(source.X), CSng(source.Y))
        End Operator
    
        Public Overloads Function Equals(ByVal other As Vector2) As Boolean Implements System.IEquatable(Of Vector2).Equals
            Return Me = other
        End Function
    
        Public Function CompareTo(ByVal other As Vector2) As Integer Implements System.IComparable(Of Vector2).CompareTo
            Dim thisMag As Single = Magnitude()
            Dim otherMag As Single = other.Magnitude()
            If thisMag = otherMag Then
                Return (X + Y).CompareTo(other.X + other.Y)
            End If
            Return thisMag.CompareTo(otherMag)
        End Function
    
        Public Function CompareTo(ByVal obj As Object) As Integer Implements System.IComparable.CompareTo
            If TypeOf obj Is Vector2 Then
                Return CompareTo(DirectCast(obj, Vector2))
            ElseIf TypeOf obj Is PointF Then
                Return CompareTo(New Vector2(DirectCast(obj, PointF)))
            ElseIf TypeOf obj Is Point Then
                Return CompareTo(New Vector2(DirectCast(obj, Point)))
            ElseIf TypeOf obj Is IComparable Then
                Return DirectCast(obj, IComparable).CompareTo(Me)
            Else
                Return -1
            End If
        End Function
    End Structure

    I definately would not add a reference to XNA just to get these basic structures.... recreate them instead.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Thursday, May 9, 2013 7:37 PM
    Moderator