Public Class SVPWMControl

    Private Const ONEDIVSQRT3 As Double = 0.57735026918962573

    Public Event NewValue As EventHandler(Of NewValueEventArgs)

    Public Property Alpha() As Double
        Get
            Return alphaValue
        End Get
        Set(ByVal value As Double)
            While value >= 360
                value -= 360
            End While
            alphaValue = value
            Me.Invalidate()
            RaiseEvent NewValue(Me, CalcABC)
        End Set
    End Property
    Private alphaValue As Double

    Public Property VoltageVector() As Double
        Get
            Return voltageVectorValue
        End Get
        Set(ByVal value As Double)
            voltageVectorValue = value
            Me.Invalidate()
            RaiseEvent NewValue(Me, CalcABC)
        End Set
    End Property
    Private voltageVectorValue As Double

    Public Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        Alpha = 20
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)

        Dim vectorPen As New Pen(Color.Blue, 2)
        Dim axisPen As New Pen(Color.Black, 1)
        Dim greyPen As New Pen(Color.LightGray, 1)
        Dim centerX As Integer = Me.Width / 2
        Dim centerY As Integer = Me.Height / 2

        ' Draw circle
        e.Graphics.DrawEllipse(greyPen, 0, 0, Me.Width - 1, Me.Height - 1)

        ' Draw axii
        Dim oldX As Integer = Me.Width / 2 * Math.Cos(Deg2Rad(300)) + centerX
        Dim oldY As Integer = Me.Height / 2 * Math.Sin(Deg2Rad(300)) + centerY

        For a = 0 To 360 Step 60
            Dim x2 As Integer = Me.Width / 2 * Math.Cos(Deg2Rad(a)) + centerX
            Dim y2 As Integer = Me.Height / 2 * Math.Sin(Deg2Rad(a)) + centerY
            e.Graphics.DrawLine(greyPen, centerX, centerY, x2, Me.Height - y2)
            e.Graphics.DrawLine(greyPen, oldX, Me.Height - oldY, x2, Me.Height - y2)
            oldX = x2
            oldY = y2
        Next

        ' Draw horizontal axis
        e.Graphics.DrawLine(axisPen, 0, CSng(Me.Height / 2), Me.Width, CSng(Me.Height / 2))

        ' Draw vertical axis
        e.Graphics.DrawLine(axisPen, CSng(Me.Width / 2), 0, CSng(Me.Width / 2), Me.Height)

        ' Draw Vector
        Dim x As Integer = VoltageVector * Math.Cos(Deg2Rad(Alpha)) + centerX
        Dim y As Integer = VoltageVector * Math.Sin(Deg2Rad(Alpha)) + centerY
        y = Me.Height - y
        e.Graphics.DrawLine(vectorPen, centerX, centerY, x, y)

    End Sub

    Private IsLeftMouseDown As Boolean = False

    Private Sub VectorControl_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
        IsLeftMouseDown = True
        setVectorLocalCoordinates(e.Location)
    End Sub

    Private Sub VectorControl_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
        If IsLeftMouseDown Then setVectorLocalCoordinates(e.Location)
    End Sub

    Private Sub VectorControl_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseLeave
        IsLeftMouseDown = False
    End Sub

    Private Sub VectorControl_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
        IsLeftMouseDown = False
    End Sub

    Private Sub setVectorLocalCoordinates(ByVal e As Point)
        Dim x As Integer = e.X - Me.Width / 2
        Dim y As Integer = (Me.Height - (e.Y)) - Me.Height / 2
        SetVectorXY(x, y)
    End Sub


    Public Property TrackBar() As Single
        Get

        End Get
        Set(ByVal value As Single)
            trackBarValue = value
            voltageVectorValue = trackBarValue * 7
            Dim eABC As NewValueEventArgs = CalcABC()
            Me.Invalidate()
            RaiseEvent NewValue(Me, eABC)
        End Set
    End Property
    Public trackBarValue As Single = 0

    Public newX, newY As Single

    Public Sub SetVectorXY(ByVal x As Integer, ByVal y As Integer)
        If x = 0 And y = 0 Then
            alphaValue = 0
        ElseIf x = 0 And y > 0 Then
            alphaValue = 90
        ElseIf x = 0 And y < 0 Then
            alphaValue = 270
        Else
            alphaValue = Rad2Deg(Math.Atan(y / x))
            If x < 0 Then alphaValue += 180
            If alphaValue < 0 Then alphaValue += 360
        End If

        voltageVectorValue = Math.Sqrt(x * x + y * y) 'trackBarValue * 7  '  Math.Sqrt(x * x + y * y)
        Dim eABC As NewValueEventArgs = CalcABC()
        Me.Invalidate()
        newX = x
        newY = y
        RaiseEvent NewValue(Me, eABC)
    End Sub


    Private Function CalcABC() As NewValueEventArgs
        Dim vector1 As UVector = Nothing
        Dim vector2 As UVector = Nothing
        Dim theta As Double = Alpha

        If Alpha < 60 Then
            vector1 = New UVector(True, False, False)   '+--    U0
            vector2 = New UVector(True, True, False)    '++-    U60 
        ElseIf Alpha >= 60 And Alpha < 120 Then
            vector1 = New UVector(True, True, False)    '++-    U60
            vector2 = New UVector(False, True, False)   '-+-    U120
            theta -= 60
        ElseIf Alpha >= 120 And Alpha < 180 Then
            vector1 = New UVector(False, True, False)   '-+-    U120
            vector2 = New UVector(False, True, True)    '-++    U180
            theta -= 120
        ElseIf Alpha >= 180 And Alpha < 240 Then
            vector1 = New UVector(False, True, True)    '-++    U180
            vector2 = New UVector(False, False, True)   '--+    U240
            theta -= 180
        ElseIf Alpha >= 240 And Alpha < 300 Then
            vector1 = New UVector(False, False, True)   '--+    U240
            vector2 = New UVector(True, False, True)    '+-+    U300
            theta -= 240
        ElseIf Alpha >= 300 Then
            vector1 = New UVector(True, False, True)    '+-+    U300
            vector2 = New UVector(True, False, False)   '+--    U0
            theta -= 300
        End If

        Dim ReferenceVector = Me.Width / 2 ' Magnitude of the V vector
        Dim factor As Single = VoltageVector / ReferenceVector

        Dim t1 As Double = factor * (Math.Cos(Deg2Rad(theta)) - ONEDIVSQRT3 * Math.Sin(Deg2Rad(theta)))
        Dim t2 As Double = 2 * factor * ONEDIVSQRT3 * Math.Sin(Deg2Rad(theta))
        Dim t0 As Double = 1 - t1 - t2

        Dim p(2), x(2), s(1), dx(2) As Single ' , x2(2), dx1(2), dx2(2), s(1) As Single

        Const MIN As Single = 0.07

        p(0) = Convert.ToSingle(vector1.T0) * t1 + Convert.ToSingle(vector2.T0) * t2 + 0.5 * t0
        p(1) = Convert.ToSingle(vector1.T2) * t1 + Convert.ToSingle(vector2.T2) * t2 + 0.5 * t0
        p(2) = Convert.ToSingle(vector1.T4) * t1 + Convert.ToSingle(vector2.T4) * t2 + 0.5 * t0

        For i As Integer = 0 To 2
            If p(i) < MIN Then p(i) = MIN
            If p(i) > (1 - MIN) Then p(i) = (1 - MIN)
        Next

        x(0) = (1 - p(0)) / 2
        x(1) = (1 - p(1)) / 2
        x(2) = (1 - p(2)) / 2

        Dim seq() As Integer = {2, 1, 0}
        If x(1) <= x(0) And x(1) <= x(2) Then seq(0) = 1
        If x(0) <= x(1) And x(0) <= x(2) Then seq(0) = 0
        If x(1) >= x(0) And x(1) >= x(2) Then seq(2) = 1
        If x(2) >= x(0) And x(2) >= x(1) Then seq(2) = 2
        seq(1) = 3 - seq(0) - seq(2)

        If x(seq(1)) - x(seq(0)) < MIN Then
            x(seq(0)) = -MIN + x(seq(1))
        End If

        If x(seq(2)) - x(seq(1)) < MIN Then
            x(seq(2)) = MIN + x(seq(1))
        End If

        If x(seq(0)) < 0 Then
            x(seq(1)) -= x(seq(0))
            x(seq(0)) = 0
        End If
        If x(seq(2)) + p(seq(2)) > 1 Then
            x(seq(1)) -= 1 - (x(seq(2)) + p(seq(2)))
            x(seq(2)) -= 1 - (x(seq(2)) + p(seq(2)))
        End If

        s(0) = x(seq(0)) + MIN / 2
        s(1) = x(seq(1)) + MIN / 2

        Return New NewValueEventArgs(x(0), x(0) + p(0), x(1), x(1) + p(1), x(2), x(2) + p(2), s(0), s(1))
    End Function

    Private Class UVector
        Public T0 As Boolean
        Public T2 As Boolean
        Public T4 As Boolean

        Public Sub New(ByVal t0value As Boolean, _
                       ByVal t2value As Boolean, _
                       ByVal t4value As Boolean)
            T0 = t0value
            T2 = t2value
            T4 = t4value
        End Sub
    End Class

    Public Class NewValueEventArgs
        Inherits EventArgs

        Public Property A1() As Double
            Get
                Return a1Value
            End Get
            Set(ByVal value As Double)
                a1Value = value
            End Set
        End Property
        Private a1Value As Double

        Public Property A2() As Double
            Get
                Return a2Value
            End Get
            Set(ByVal value As Double)
                a2Value = value
            End Set
        End Property
        Private a2Value As Double


        Public Property B1() As Double
            Get
                Return b1Value
            End Get
            Set(ByVal value As Double)
                b1Value = value
            End Set
        End Property
        Private b1Value As Double

        Public Property B2() As Double
            Get
                Return b2Value
            End Get
            Set(ByVal value As Double)
                b2Value = value
            End Set
        End Property
        Private b2Value As Double

        Public Property C1() As Double
            Get
                Return c1Value
            End Get
            Set(ByVal value As Double)
                c1Value = value
            End Set
        End Property
        Private c1Value As Double

        Public Property C2() As Double
            Get
                Return c2Value
            End Get
            Set(ByVal value As Double)
                c2Value = value
            End Set
        End Property
        Private c2Value As Double


        Public Property ADCPoint1() As Double
            Get
                Return adcPoint1Value
            End Get
            Set(ByVal value As Double)
                adcPoint1Value = value
            End Set
        End Property
        Private adcPoint1Value As Double

        Public Property ADCPoint2() As Double
            Get
                Return adcPoint2Value
            End Get
            Set(ByVal value As Double)
                adcPoint2Value = value
            End Set
        End Property
        Private adcPoint2Value As Double

        Public Sub New(ByVal a1 As Double, _
                       ByVal a2 As Double, _
                       ByVal b1 As Double, _
                       ByVal b2 As Double, _
                       ByVal c1 As Double, _
                       ByVal c2 As Double, _
                       ByVal adcp1 As Double, _
                       ByVal adcp2 As Double)
            a1Value = a1
            b1Value = b1
            c1Value = c1
            a2Value = a2
            b2Value = b2
            c2Value = c2
            adcPoint1Value = adcp1
            adcPoint2Value = adcp2
        End Sub
    End Class

End Class