Click here to Skip to main content
15,881,803 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Ok, this is going to take some explaining before I present the code. The algorithm Im implementing is called TLM [^]for short.

To construct the algorithm I have noticed that each cell or node, can communicate with 4 of its neighbors, called North, South, West and East for conviniance. In each of the directions it can send a pressure coeficcient and recieve a pressure coefficient for the neighbors, so each node will have 8 possible connections, that works sort of independent of each other.

In addition to the connections, each node will have a pressure at each point that is just the sum of the incoming waves.

The problem Im having is that it seems that the point of the source is moving to point 0,0 from the center of the matrix, and I cant figure out why. (Looks like there is a Doppler effect going on).

The code below is rather long (appologies) but ITs a complete functioning code, except for the doppler thing. I cant figur out why I dosnt work as it should... Can anybody see my mistake?

In XAML:
XML
<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Button Name="btnStart">Start</Button>
        <Border BorderThickness="2" BorderBrush="blue" HorizontalAlignment="Center" >
        <Canvas Name="cnvTLM" Background="White" Width="300" Height="300"></Canvas>
        </Border>
    </StackPanel>
</Window>


And the complete VB code:
VB
Imports System.Windows.Threading

Class MainWindow

    Private Dimensions As Integer = 200
    Private IncommingEast(Dimensions, Dimensions), InncommingNorth(Dimensions, Dimensions), IncommingWest(Dimensions, Dimensions), IncommingSouth(Dimensions, Dimensions), ScatteredEast(Dimensions, Dimensions), ScatteredNorth(Dimensions, Dimensions), ScatteredWest(Dimensions, Dimensions), ScatteredSouth(Dimensions, Dimensions) As Double
    Private CurrentPressure(Dimensions, Dimensions) As Double

    Dim SimulationTimer As DispatcherTimer

    Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
        FillInColorList()

        SimulationTimer = New DispatcherTimer()
        AddHandler SimulationTimer.Tick, AddressOf SimulationTimer_Tick
        SimulationTimer.Interval = New TimeSpan(0, 0, 0, 0, 100)

    End Sub
    Dim TT As Double = 1

    Private Sub SimulationTimer_Tick(ByVal sender As Object, ByVal e As EventArgs)
        ' Updating the Label which displays the current second
        For x As Integer = 1 To Dimensions - 2
            For y As Integer = 1 To Dimensions - 2
                If x = CInt(Dimensions / 2) And y = CInt(Dimensions / 2) Then
                    IncommingEast(x, y) = 30 * Math.Sin(2 * Math.PI * TT / 10) + IncommingEast(x, y)
                    IncommingWest(x, y) = 30 * Math.Sin(2 * Math.PI * TT / 10) + IncommingWest(x, y)
                    IncommingSouth(x, y) = 30 * Math.Sin(2 * Math.PI * TT / 10) + IncommingSouth(x, y)
                    InncommingNorth(x, y) = 30 * Math.Sin(2 * Math.PI * TT / 10) + InncommingNorth(x, y)
                End If

                ScatteredNorth(x, y) = 0.5 * (+IncommingEast(x, y) - InncommingNorth(x, y) + IncommingWest(x, y) + IncommingSouth(x, y))
                ScatteredEast(x, y) = 0.5 * (-IncommingEast(x, y) + InncommingNorth(x, y) + IncommingWest(x, y) + IncommingSouth(x, y))
                ScatteredWest(x, y) = 0.5 * (+IncommingEast(x, y) + InncommingNorth(x, y) - IncommingWest(x, y) + IncommingSouth(x, y))
                ScatteredSouth(x, y) = 0.5 * (+IncommingEast(x, y) + InncommingNorth(x, y) + IncommingWest(x, y) - IncommingSouth(x, y))

                IncommingEast(x, y) = ScatteredWest(x + 1, y)
                InncommingNorth(x, y) = ScatteredSouth(x, y + 1)
                IncommingWest(x, y) = ScatteredEast(x - 1, y)
                IncommingSouth(x, y) = ScatteredNorth(x, y - 1)

                CurrentPressure(x, y) = (0.5 * (ScatteredEast(x, y) + ScatteredNorth(x, y) + ScatteredWest(x, y) + ScatteredSouth(x, y)))
            Next

        Next
        TT += 1
        Dim img As New ImageBrush
        img.ImageSource = CreateBitmap(CurrentPressure, Dimensions, Dimensions)
        cnvTLM.Background = img

        ' Forcing the CommandManager to raise the RequerySuggested event
        CommandManager.InvalidateRequerySuggested()
    End Sub

    Private Sub btnStart_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles btnStart.Click
        If SimulationTimer.IsEnabled Then
            SimulationTimer.Stop()
        Else
            SimulationTimer.Start()
        End If

    End Sub

    Private Sub FillInColorList()

        Dim f As New SmoothColorGenerator
        SmoothColorList = f.ColorList
    End Sub

    Dim SmoothColorList As New List(Of Color)

    Private Function CreateBitmap(ByVal IntegerArray(,) As Double, ByVal Width As Integer, ByVal Height As Integer, Optional ByVal DistinctColorSettings As Boolean = False) As BitmapSource
        Dim buffer As New List(Of Byte)

        Dim ColList As List(Of Color)
        If DistinctColorSettings Then
            ColList = SmoothColorList
        Else
            ColList = SmoothColorList
        End If

        Dim B_MASK As Integer = 255
        Dim G_MASK As Integer = 255 << 8
        Dim R_MASK As Integer = 255 << 16

        For x As Integer = 0 To IntegerArray.GetLength(1) - 1
            For y As Integer = 0 To IntegerArray.GetLength(0) - 1
                Dim k As Integer = 0
                k = (IntegerArray(x, y) / 2 + 125)

                B_MASK = ColList(k).B
                G_MASK = ColList(k).G
                R_MASK = ColList(k).R


                buffer.Add(B_MASK)
                buffer.Add(G_MASK)
                buffer.Add(R_MASK)
                buffer.Add(255)

            Next
        Next

        Dim dpiX As Double = 96D
        Dim dpiY As Double = 96D
        Dim pixelFormat = PixelFormats.Pbgra32
        Dim bytesPerPixel = Math.Truncate(((pixelFormat.BitsPerPixel + 7) / 8))
        Dim stride = bytesPerPixel * IntegerArray.GetLength(0)

        Return BitmapSource.Create(IntegerArray.GetLength(0) - 1, IntegerArray.GetLength(1) - 1, dpiX, dpiY,
                                         pixelFormat, Nothing, buffer.ToArray, stride) '
    End Function


    Private Function CreateBitmap(ByVal IntegerArray(,) As Integer, ByVal Width As Integer, ByVal Height As Integer, Optional ByVal DistinctColorSettings As Boolean = False) As BitmapSource
        Dim buffer As New List(Of Byte)

        Dim ColList As List(Of Color)
        If DistinctColorSettings Then
            ColList = SmoothColorList
        Else
            ColList = SmoothColorList
        End If

        For i As Integer = 0 To Width - 1
            For j As Integer = 0 To Height - 1
                Dim k As Integer = IntegerArray(i, j)

                buffer.Add(ColList(k).R)
                buffer.Add(ColList(k).G)
                buffer.Add(ColList(k).B)
                buffer.Add(255)

            Next
        Next

        Dim dpiX As Double = 96D
        Dim dpiY As Double = 96D
        Dim pixelFormat = PixelFormats.Pbgra32
        Dim bytesPerPixel = Math.Truncate(((pixelFormat.BitsPerPixel + 7) / 8))
        Dim stride = bytesPerPixel * Width

        Return BitmapSource.Create(Width, Height, dpiX, dpiY,
                                         pixelFormat, Nothing, buffer.ToArray, stride) '
    End Function



End Class

#Region "GenerateColorListClasses"
 
Public Class SmoothColorGenerator

    Sub New()

        GradientStop.Add(Brushes.Red)
        GradientStop.Add(Brushes.White)
        GradientStop.Add(Brushes.Blue)

        For i As Integer = 0 To GradientStop.Count - 2
            GetGradients(GradientStop(i).Color, GradientStop(i + 1).Color, 125)
        Next

    End Sub

    Private pGradientStop As New List(Of SolidColorBrush)
    Public Property GradientStop() As List(Of SolidColorBrush)
        Get
            Return pGradientStop
        End Get
        Set(ByVal value As List(Of SolidColorBrush))
            pGradientStop = value
        End Set
    End Property

    Private pColorlist As New List(Of Color)
    Public Property ColorList() As List(Of Color)
        Get
            Return pColorlist
        End Get
        Set(ByVal value As List(Of Color))
            pColorlist = value
        End Set
    End Property

    Public Sub GetGradients(ByVal starts As Color, ByVal ends As Color, ByVal steps As Integer)
        Dim stepA As Integer = Math.Truncate((CInt(ends.A) - CInt(starts.A)) / (CInt(steps) - 1))
        Dim stepR As Integer = Math.Truncate((CInt(ends.R) - CInt(starts.R)) / (CInt(steps) - 1))
        Dim stepG As Integer = Math.Truncate((CInt(ends.G) - CInt(starts.G)) / (CInt(steps) - 1))
        Dim stepB As Integer = Math.Truncate((CInt(ends.B) - CInt(starts.B)) / (CInt(steps) - 1))

        For i As Integer = 0 To steps - 1

            ColorList.Add(Color.FromArgb(CInt(starts.A) + CInt(stepA) * CInt(i),
                            CInt(starts.R) + CInt(stepR) * CInt(i),
                            CInt(starts.G) + CInt(stepG) * CInt(i),
                            CInt(starts.B) + CInt(stepB) * CInt(i)))
        Next

    End Sub
End Class


#End Region
Posted

1 solution

Ok. I found out what was wrong, its the sequence of events.

First calculate all scatter, for all points, then propagate the sound pressure. Or in code:
VB
Private Sub SimulationTimer_Tick(ByVal sender As Object, ByVal e As EventArgs)
    ' Updating the Label which displays the current second
    For x As Integer = 1 To Dimensions - 2
        For y As Integer = 1 To Dimensions - 2
            If x = CInt(Dimensions / 2) And y = CInt(Dimensions / 2) Then
                IncommingEast(x, y) = 30 * Math.Sin(2 * Math.PI * TT / 10) + IncommingEast(x, y)
                IncommingWest(x, y) = 30 * Math.Sin(2 * Math.PI * TT / 10) + IncommingWest(x, y)
                IncommingSouth(x, y) = 30 * Math.Sin(2 * Math.PI * TT / 10) + IncommingSouth(x, y)
                InncommingNorth(x, y) = 30 * Math.Sin(2 * Math.PI * TT / 10) + InncommingNorth(x, y)
            End If

            ScatteredNorth(x, y) = 0.5 * (+IncommingEast(x, y) - InncommingNorth(x, y) + IncommingWest(x, y) + IncommingSouth(x, y))
            ScatteredEast(x, y) = 0.5 * (-IncommingEast(x, y) + InncommingNorth(x, y) + IncommingWest(x, y) + IncommingSouth(x, y))
            ScatteredWest(x, y) = 0.5 * (+IncommingEast(x, y) + InncommingNorth(x, y) - IncommingWest(x, y) + IncommingSouth(x, y))
            ScatteredSouth(x, y) = 0.5 * (+IncommingEast(x, y) + InncommingNorth(x, y) + IncommingWest(x, y) - IncommingSouth(x, y))

        Next
    Next

    For x As Integer = 1 To Dimensions - 2
        For y As Integer = 1 To Dimensions - 2

            IncommingEast(x, y) = ScatteredWest(x + 1, y)
            InncommingNorth(x, y) = ScatteredSouth(x, y + 1)
            IncommingWest(x, y) = ScatteredEast(x - 1, y)
            IncommingSouth(x, y) = ScatteredNorth(x, y - 1)

            CurrentPressure(x, y) = (0.5 * (ScatteredEast(x, y) + ScatteredNorth(x, y) + ScatteredWest(x, y) + ScatteredSouth(x, y)))
        Next

    Next

    TT += 1
    Dim img As New ImageBrush
    img.ImageSource = CreateBitmap(CurrentPressure, Dimensions, Dimensions)
    cnvTLM.Background = img

    ' Forcing the CommandManager to raise the RequerySuggested event
    CommandManager.InvalidateRequerySuggested()
End Sub
 
Share this answer
 

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900