Click here to Skip to main content
15,885,141 members
Articles / Programming Languages / Visual Basic

Mathemathics Framework

Rate me:
Please Sign up or sign in to vote.
4.76/5 (56 votes)
16 Sep 2008CPOL6 min read 75.3K   6.2K   171  
.NET Mathematical Framework
Imports BV.Core
Imports BV.Math
Imports BV.TopLevel.Laplace
Imports IMidRange
Imports MidRange
'Imports BV.Controls
Imports GraphicsObjects
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Collections.Generic

''' <summary>
''' Toolbar que permite:
''' - Determinar el lugar de Raices de un dado par de LaplaceFuncion
''' - Agregar, Sacar y Mover Ra�ces
''' </summary>
''' <remarks></remarks>
Public Class RLStripToolBar
    Inherits ToolStripUtilitiesBase

    Protected ZoomR As PointF
    Protected TlBarBtnArea As ToolStripButton
    Protected RL As RootLocusBase
    Protected Alist As List(Of RootLocusBase)

    Protected TlBarBtnAllowInsertion, TlBarBtnAddAmp, TlBarBtnAddBeta As ToolStripButton
    Protected TlBarBtnMoveSing, TlBarBtnGetRL As ToolStripButton
    Protected TlBarBtnConjugate As ToolStripButton
    Protected Grid As GridBase
    Protected LapObj As LaplaceFunction
    Protected SelectedSing As Singularity


#Region "Constructor"

    Public Sub New(ByVal Visor2D As VisorComplexPlain, ByVal TlBar As ToolStripContainer)
        MyBase.New(Visor2D, TlBar)
        Alist = New List(Of RootLocusBase)
        Grid = New GridBase(Me.intVisor2D.XRange.dx, Me.intVisor2D.YRange.dx, 100)

        'RL = New RootLocus3
        'Me.Alist.Add(RL)

        Me.CreateNewRootLocus()
        InitializeToolBar()

        AddHandler Visor2D.MouseDown, AddressOf Me.CaptureClick
    End Sub

    Protected Overridable Sub InitializeToolBar()
        ImgLst = New ImageList
        ImgLst.ImageSize = New Size(32, 32)

        ImgLst.Images.Add(New Icon([GetType], "PolosConj.ico"))
        ImgLst.Images.Add(New Icon([GetType], "InsertPole.ico"))
        ImgLst.Images.Add(New Icon([GetType], "MovePole.ico"))
        ImgLst.Images.Add(New Icon([GetType], "GridLarge.ico"))
        ImgLst.Images.Add(New Icon([GetType], "gridSmall.ico"))

        ImgLst.Images.Add(New Icon([GetType], "AR-Amp.ico"))
        ImgLst.Images.Add(New Icon([GetType], "AR-Beta.ico"))
        ImgLst.Images.Add(New Icon([GetType], "GetRL.ico"))
        'ImgLst.Images.Add(New Icon([GetType], "ParamRun.ico"))

        Dim BvTlBarBtn As ToolStripButton

        Band = New ToolStrip
        Band.Name = "SingularityInsertionBand"
        Band.ImageList = Me.ImgLst

        Me.TlBarBtnAddAmp = New ToolStripButton
        Me.TlBarBtnAddAmp.ImageIndex = 5
        Me.TlBarBtnAddAmp.Enabled = False
        TlBarBtnAddAmp.ToolTipText = "Add Selected Laplace Function like Forward Transfer"
        Band.Items.Add(Me.TlBarBtnAddAmp)

        Me.TlBarBtnAddBeta = New ToolStripButton
        Me.TlBarBtnAddBeta.ImageIndex = 6
        Me.TlBarBtnAddBeta.Enabled = False
        TlBarBtnAddBeta.ToolTipText = "Add Selected Laplace Function like Reverse Beta Transfer"
        Band.Items.Add(Me.TlBarBtnAddBeta)

        Me.TlBarBtnGetRL = New ToolStripButton
        Me.TlBarBtnGetRL.ImageIndex = 7
        Me.TlBarBtnGetRL.Enabled = False
        TlBarBtnGetRL.ToolTipText = "Get the Root Locus for the pair of Laplace Functions"
        Band.Items.Add(Me.TlBarBtnGetRL)

        Band.Items.Add(New ToolStripSeparator)

        Me.TlBarBtnConjugate = New ToolStripButton
        Me.TlBarBtnConjugate.ImageIndex = 0
        TlBarBtnConjugate.CheckOnClick = True
        TlBarBtnConjugate.ToolTipText = "Insert Complex Conjugate Singularity"
        Band.Items.Add(Me.TlBarBtnConjugate)

        TlBarBtnAllowInsertion = New ToolStripButton
        TlBarBtnAllowInsertion.ImageIndex = 1
        TlBarBtnAllowInsertion.ToolTipText = "Allow Singularity Insertion"
        TlBarBtnAllowInsertion.CheckOnClick = True
        Band.Items.Add(TlBarBtnAllowInsertion)

        TlBarBtnMoveSing = New ToolStripButton
        TlBarBtnMoveSing.ImageIndex = 2
        TlBarBtnMoveSing.ToolTipText = "Move Singularity"
        TlBarBtnMoveSing.CheckOnClick = True
        Band.Items.Add(TlBarBtnMoveSing)

        Band.Items.Add(New ToolStripSeparator)

        BvTlBarBtn = Band.Items.Add("", Nothing, New EventHandler(AddressOf GridUp))
        BvTlBarBtn.ImageIndex = 3
        BvTlBarBtn.ToolTipText = "Grid Up, Setted to " & Me.Grid.XSpace


        BvTlBarBtn = Band.Items.Add("", Nothing, New EventHandler(AddressOf GridDown))
        BvTlBarBtn.ImageIndex = 4
        BvTlBarBtn.ToolTipText = "Grid Down, Setted to " & Me.Grid.XSpace

        TlBarBtnArea = Band.Items.Add("")
        TlBarBtnArea.Visible = False
        TlBarBtnArea.ToolTipText = "Zoom Area"

        Me.TlBar.TopToolStripPanel.Controls.Add(Band)
    End Sub

#End Region

#Region "Properties"

    ''' <summary>
    ''' Colleccion de lugares de ra�ces
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property RootLocuses() As ICollection(Of RootLocusBase)
        Get
            Return Alist.ToArray
        End Get
    End Property

    ''' <summary>
    ''' Lugar de ra�ces seleccionado
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property SelectedRootLocus() As RootLocusBase
        Get
            Return Me.RL
        End Get
        Set(ByVal value As RootLocusBase)
            Me.RL = value
        End Set
    End Property

    ''' <summary>
    ''' Singularidad Seleccionada
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property SelectedSingularity() As Singularity
        Get
            Return SelectedSing
        End Get
        Set(ByVal Value As Singularity)
            SelectedSing = Value
        End Set
    End Property

    ''' <summary>
    ''' Sistema de Laplace Seleccionado
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property LaplaceSelectedObject() As LaplaceFunction
        Get
            Return Me.LapObj
        End Get
        Set(ByVal value As LaplaceFunction)
            Me.LapObj = value
            If Me.LapObj Is Nothing Then
                Me.TlBarBtnAddAmp.Enabled = False
                Me.TlBarBtnAddBeta.Enabled = False
            Else
                If Me.RL.LaplaceDirectObject Is Me.LapObj OrElse Me.RL.LaplaceFeedbackObject Is Me.LapObj Then
                    Me.TlBarBtnAddAmp.Enabled = False
                    Me.TlBarBtnAddBeta.Enabled = False
                Else
                    Me.TlBarBtnAddAmp.Enabled = True
                    Me.TlBarBtnAddBeta.Enabled = True
                End If
            End If
        End Set
    End Property

    ''' <summary>
    ''' Sistema de Laplace de Transferencia Directa
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property LaplaceDirectObject() As LaplaceFunction
        Get
            Return Me.RL.LaplaceDirectObject
        End Get
        Set(ByVal value As LaplaceFunction)
            Me.RL.LaplaceDirectObject = value
            If Not Me.RL.LaplaceDirectObject Is Nothing AndAlso Not Me.RL.LaplaceFeedbackObject Is Nothing Then
                Me.TlBarBtnGetRL.Enabled = True
            Else
                Me.TlBarBtnGetRL.Enabled = False
            End If
        End Set
    End Property

    ''' <summary>
    ''' Sistema de Laplace de Transferencia Inversa
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property LaplaceFeedbackObject() As LaplaceFunction
        Get
            Return Me.RL.LaplaceFeedbackObject
        End Get
        Set(ByVal value As LaplaceFunction)
            Me.RL.LaplaceFeedbackObject = value
            If Not Me.RL.LaplaceDirectObject Is Nothing AndAlso Not Me.RL.LaplaceFeedbackObject Is Nothing Then
                Me.TlBarBtnGetRL.Enabled = True
            Else
                Me.TlBarBtnGetRL.Enabled = False
            End If
        End Set
    End Property

#End Region

#Region "Zoom Methods"

    'Public Sub ZoomPlus()
    '    'Me.TlBarBtnPlus.checked = True
    '    Me.TlBarBtnMinus.checked = False
    '    Me.TlBarBtnArea.checked = False
    'End Sub

    'Public Sub ZoomMinus()
    '    'Me.TlBarBtnMinus.checked = True
    '    Me.TlBarBtnPlus.checked = False
    '    Me.TlBarBtnArea.checked = False
    'End Sub

    'Public Sub ZoomRegion()
    '    'Me.TlBarBtnArea.checked = True
    '    Me.TlBarBtnPlus.checked = False
    '    Me.TlBarBtnMinus.checked = False
    'End Sub

    'Public Sub ZoomPrevious()
    '    intVisor2D.Zoom(IMidRange.EZoomType.Previous)
    'End Sub

    'Public Sub ZoomFullY()
    '    intVisor2D.Zoom(IMidRange.EZoomType.FullY)
    'End Sub

    'Public Sub ZoomFull()
    '    intVisor2D.Zoom(IMidRange.EZoomType.Full)
    'End Sub



    'Public Sub PanFree()

    '    intVisor2D.Pan(New PointF)
    'End Sub

#End Region

    ''' <summary>
    ''' Calcula el lugar de ra�ces del sistema A-B dado
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub GetRootLocus()
        Me.RL.CalcRootLocus()
    End Sub

#Region "Events Managed"

#Region "Mouse Events Managed"

    Protected Overrides Sub OnRenderControl_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)

        If Not SelectedSing Is Nothing Then
            If TlBarBtnMoveSing.Checked Then
                If SelectedSing.IsConjugated Then
                    Me.SelectedSing.Value = New ComplexUndefinied(Me.intVisor2D.Cursor1Position.X, Me.intVisor2D.Cursor1Position.Y)
                Else
                    Me.SelectedSing.Value = New ComplexUndefinied(Me.intVisor2D.Cursor1Position.X, 0)
                End If
                Me.intVisor2D.Refresh()
            End If
        End If
        'If Me.TlBarBtnPlus.checked Then
        '    If e.Button = MouseButtons.Left Then
        '        intVisor2D.Zoom(1 / intZoomFactor, intVisor2D.Cursor1Position)
        '        Me.TlBarBtnPlus.checked = False
        '        intVisor2D.Refresh()
        '    End If
        'ElseIf Me.TlBarBtnMinus.checked Then
        '    If e.Button = MouseButtons.Left Then
        '        intVisor2D.Zoom(intZoomFactor, intVisor2D.Cursor1Position)
        '        Me.TlBarBtnMinus.checked = False
        '    End If
        'ElseIf Me.TlBarBtnArea.checked Then
        '    MousePos1 = New PointF(e.X, e.Y)
        '    If e.Button = MouseButtons.Left Then
        '        ZoomR = intVisor2D.Cursor1Position
        '    ElseIf e.Button = MouseButtons.Right Then
        '        ZoomR = intVisor2D.Cursor2Position
        '    End If
        'ElseIf Me.TlBarBtnFreePan.checked Then
        '    If e.Button = MouseButtons.Left Then
        '        MousePos1 = New PointF(e.X, e.Y)
        '    End If
        '    'Me.TlBarBtnFreePan.checked = False
        'End If

    End Sub

    Protected Overrides Sub OnRenderControl_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)  'Handles intVisor2D.OnRenderControlMouseUp
        If Not SelectedSing Is Nothing Then
            If TlBarBtnMoveSing.Checked AndAlso e.Button = Windows.Forms.MouseButtons.Left Then
                If SelectedSing.IsConjugated Then
                    Me.SelectedSing.Value = New ComplexUndefinied(Me.Grid.ConvertX(Me.intVisor2D.Cursor1Position.X), _
                                                                    Me.Grid.ConvertY(Me.intVisor2D.Cursor1Position.Y))
                Else
                    Me.SelectedSing.Value = New ComplexUndefinied(Me.Grid.ConvertX(Me.intVisor2D.Cursor1Position.X), 0)
                End If
                Me.intVisor2D.Refresh()
            End If
        End If
        'If Me.TlBarBtnArea.checked Then
        '    If e.Button = MouseButtons.Left Then
        '        intVisor2D.Zoom(ZoomR, intVisor2D.Cursor1Position)
        '    ElseIf e.Button = MouseButtons.Right Then
        '        intVisor2D.Zoom(ZoomR, intVisor2D.Cursor2Position)
        '    End If
        '    Me.TlBarBtnArea.checked = False
        '    Me.intRenderCtl.Cursor = Cursors.Default
        '    intVisor2D.Refresh()
        'End If
    End Sub

    Protected Overrides Sub OnRenderControl_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) 'Handles intVisor2D.OnRenderControlMouseMove
        'Static isWorking As Boolean

        'If isWorking Then
        '    MousePos1 = New PointF(e.X, e.Y)
        '    Exit Sub
        'End If
        'isWorking = True
        'If Me.TlBarBtnArea.checked Then
        '    If e.Button = MouseButtons.Left Or e.Button = MouseButtons.Right Then
        '        Dim x, y As Single
        '        If MousePos1.X < e.X Then
        '            x = MousePos1.X
        '        Else
        '            x = e.X
        '        End If
        '        If MousePos1.Y < e.Y Then
        '            y = MousePos1.Y
        '        Else
        '            y = e.Y
        '        End If
        '        'refresca la imagen anterior
        '        ZoomRect = New System.Drawing.Rectangle(x, y, Math.Abs(MousePos1.X - e.X), Math.Abs(MousePos1.Y - e.Y))
        '        'Me.intRenderCtl.Refresh()
        '        intMouseButtonIsPresseed = True
        '        Me.intVisor2D.Refresh()
        '    Else
        '        intMouseButtonIsPresseed = False
        '    End If
        'ElseIf Me.TlBarBtnPlus.checked Then
        '    Dim x, y, w, h, w2, h2 As Single
        '    x = 0.5 * (intVisor2D.DataRectangle.X + intVisor2D.DataRectangle.Right)
        '    x -= e.X
        '    y = 0.5 * (intVisor2D.DataRectangle.Y + intVisor2D.DataRectangle.Bottom)
        '    y -= e.Y
        '    w = intVisor2D.DataRectangle.Width
        '    w2 = w / Me.intZoomFactor
        '    h = intVisor2D.DataRectangle.Height
        '    h2 = h / Me.intZoomFactor
        '    ZoomRect = New System.Drawing.Rectangle(intVisor2D.DataRectangle.Left - x + (w - w2) / 2, _
        '                            intVisor2D.DataRectangle.Top - y + (h - h2) / 2, _
        '                            w2, _
        '                            h2)
        '    Me.intVisor2D.Refresh()
        'ElseIf Me.TlBarBtnFreePan.checked Then
        '    If e.Button = MouseButtons.Left Then
        '        If Me.intVisor2D.YIsLogaritmic OrElse Me.intVisor2D.XIsLogaritmic Then
        '            'le paso los corners de la zona nueva a mostrar, es 
        '            'mas facil de procesar y pasar el punto medio como en escalas lineales
        '            Dim dn, da As Single
        '            Dim n, m, a, b As Single

        '            If Me.MousePos1.X = e.X Then
        '                a = intVisor2D.XRange.Max
        '                b = intVisor2D.XRange.Min
        '            Else
        '                a = intVisor2D.UCalcXS(intVisor2D.XRange.Max)
        '                b = intVisor2D.UCalcXS(intVisor2D.XRange.Min)
        '                'da = a - b
        '                'a = a + intPanFactor * (Me.MousePos1.X - e.X) * da
        '                'b = b + intPanFactor * (Me.MousePos1.X - e.X) * da
        '                'debo sacar las decadas que representa desde el punto inicial del mouse
        '                'hasta el punto final. En eso se incrementara fi y ff
        '                da = Me.intVisor2D.SInvCalcX(Me.MousePos1.X)
        '                dn = Me.intVisor2D.SInvCalcX(e.X)
        '                da = intVisor2D.UCalcXS(da)
        '                dn = intVisor2D.UCalcXS(dn)
        '                a = a + da - dn
        '                b = b + da - dn
        '                a = intVisor2D.UInvCalcXS(a)
        '                b = intVisor2D.UInvCalcXS(b)
        '            End If

        '            If Me.MousePos1.Y = e.Y Then
        '                n = intVisor2D.YRange.Max
        '                m = intVisor2D.YRange.Min
        '            Else
        '                n = intVisor2D.UCalcYS(intVisor2D.YRange.Max)
        '                m = intVisor2D.UCalcYS(intVisor2D.YRange.Min)
        '                'dn = n - m
        '                da = Me.intVisor2D.SInvCalcY(Me.MousePos1.Y)
        '                dn = Me.intVisor2D.SInvCalcY(e.Y)
        '                da = intVisor2D.UCalcYS(da)
        '                dn = intVisor2D.UCalcYS(dn)
        '                n = n + da - dn
        '                m = m + da - dn
        '                'n = n - intPanFactor * (Me.MousePos1.Y - e.Y) * dn
        '                'm = m - intPanFactor * (Me.MousePos1.Y - e.Y) * dn
        '                n = intVisor2D.UInvCalcYS(n)
        '                m = intVisor2D.UInvCalcYS(m)
        '            End If
        '            intVisor2D.Zoom(New PointF(a, n), New PointF(b, m))
        '        Else
        '            intVisor2D.Pan(New PointF(intVisor2D.XRange.Center + CalcScaledDX(Me.MousePos1.X, e.X), _
        '                                        intVisor2D.YRange.Center + CalcScaledDY(Me.MousePos1.Y, e.Y)))
        '        End If
        '        Me.intVisor2D.Refresh()
        '        MousePos1 = New PointF(e.X, e.Y)
        '    End If
        'End If

        'isWorking = False
    End Sub

    'Protected Function UCalcY(ByVal Y As Single) As Single
    '    If TypeOf intVisor2D Is VisorXYAdvanced Then
    '        If CType(intVisor2D, VisorXYAdvanced).AutoScale = AutoScaleCplxTypes.YImaginary Then
    '            Return CType(intVisor2D, VisorXYAdvanced).UCalcYS(Y)
    '        Else
    '            Return intVisor2D.UCalcYS(Y)
    '        End If
    '    Else
    '        Return intVisor2D.UCalcYS(Y)
    '    End If
    'End Function

#End Region

    Protected Overridable Sub ToolBarMain_ButtonClick(ByVal sender As Object, ByVal e As ToolStripItemClickedEventArgs) Handles Band.ItemClicked
        If e.ClickedItem Is Me.TlBarBtnGetRL Then
            RL.FindingArea = New Areaf(Me.intVisor2D.XRange, Me.intVisor2D.YRange)
            RL.CalcRootLocus()
            If Not CType(Me.intVisor2D, VisorComplexPlain).Contains(RL) Then
                Me.intVisor2D.Add(RL)
            End If
            'Me.TlBarBtnGetRL.Enabled = False

        Else
            If e.ClickedItem Is Me.TlBarBtnAddAmp Then
                If Me.LapObj Is Nothing Then
                    Exit Sub
                End If
                Me.RL.LaplaceDirectObject = Me.LapObj
                Me.TlBarBtnAddAmp.Enabled = False
                Me.TlBarBtnAddBeta.Enabled = False
            ElseIf e.ClickedItem Is Me.TlBarBtnAddBeta Then
                If Me.LapObj Is Nothing Then
                    Exit Sub
                End If
                Me.RL.LaplaceFeedbackObject = Me.LapObj
                Me.TlBarBtnAddAmp.Enabled = False
                Me.TlBarBtnAddBeta.Enabled = False
            End If
            If Not Me.RL.LaplaceDirectObject Is Nothing AndAlso Not Me.RL.LaplaceFeedbackObject Is Nothing Then
                Me.TlBarBtnGetRL.Enabled = True
            Else
                Me.TlBarBtnGetRL.Enabled = False
            End If
        End If

    End Sub


#End Region

    Private Sub GridUp(ByVal sender As Object, ByVal e As EventArgs)
        Grid.GridUp()
    End Sub

    Private Sub GridDown(ByVal sender As Object, ByVal e As EventArgs)
        Grid.GridDown()
    End Sub

    Protected Sub CaptureClick(ByVal sender As Object, ByVal e As MouseEventArgs)
        If Me.TlBarBtnAllowInsertion.Checked AndAlso e.Button = MouseButtons.Left Then
            Dim x, y As Single
            x = Grid.ConvertX(Me.intVisor2D.Cursor1Position.X)
            y = Grid.ConvertY(Me.intVisor2D.Cursor1Position.Y)
            Me.Add(x, y)
            'Me.TlBarBtnAllowInsertion.checked = False
        End If
    End Sub

    Public Overrides Sub Redraw(ByVal sender As Object, ByVal p As PaintEventArgs)
        'If Me.TlBarBtnArea.Checked And intMouseButtonIsPresseed Then
        '    ControlPaint.DrawFocusRectangle(p.Graphics, ZoomRect, Color.Gray, Color.Transparent)
        'ElseIf Me.TlBarBtnPlus.Checked Then
        '    ControlPaint.DrawFocusRectangle(p.Graphics, ZoomRect, Color.Gray, Color.Transparent)
        'End If
    End Sub

#Region "Add & Remove Buttons Events"

    ''' <summary>
    ''' Crea un Nuevo lugar de Raices para analizar
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub CreateNewRootLocus()
        If Me.RL Is Nothing Then
            Me.RL = New RootLocus2
            Me.Alist.Add(RL)
        End If
    End Sub

    Public Sub Add(ByVal Real As Single, ByVal Imag As Single)
        If Me.LapObj Is Nothing Then
            Exit Sub
        End If
        If Me.TlBarBtnConjugate.Checked Then
            SelectedSing = New GraphicsSingularity(Real, Imag)

            Dim SelectedSing2 As GraphicsSingularity
            SelectedSing2 = New GraphicsSingularity
            SelectedSing2.Conjugate = SelectedSing
            Me.LapObj.Add(SelectedSing)
        Else
            SelectedSing = New GraphicsSingularity(Real, 0)
            Me.LapObj.Add(SelectedSing)
        End If
        SelectedSing = Nothing
    End Sub

    Public Sub Add()
        Add(-CInt(Rnd() * 100), CInt(Rnd() * 100))
    End Sub

    Public Sub Remove()
        If Not Me.SelectedSing Is Nothing Then
            Me.LapObj.Remove(SelectedSing)
            SelectedSing = Nothing
            Me.OnSendMessage(Me, New MessageEventArgs("First must select a singularity", MessageEventArgs.EMessageType.Info))
        End If
    End Sub

#End Region

End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer Universidad Tecnológica Nacional
Argentina Argentina
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions