Hi chriscross,
Unfortunately I was mistaken about the XNA example. I found the demo that Jenner made (it was from this thread, post#10) but unfortunately the link is now dead. I dug out the code but I think it will take a lot of work to convert it to something you can use; there is too much I don't know about XNA.
Still, I made my own attempt at a "radar" screen which you might find interesting for comparison. With an angular resolution of 1 degree it takes me about 3-4 seconds to do a full 360 degree sweep. It uses random data for each echo line.
It seems that most of the time goes into updating the bitmap with the new line (not the rendering after all). I almost doubled the performance up by drawing 2 lines in each pass, and the speed could be further improved by increasing that to 3 or more.
I widened the line bitmap to 3 pixels to provide a kind of anti-aliasing. (The middle line has the data at full opacity, and the first and third lines the same data partly transparent). It seems this costs little extra time and the resulting scan is much smoother.
If you want to try it you can just copy the code below into a default form. There's no need to do anything in the designer. You can resize the form to enlarge the scan. The timing results are shown in the Output window.
BBCode:Public Class Form1 Private WithEvents tim As New Timer With {.Interval = 15} Private WithEvents pictureBox1 As New PictureBox Private sw As Stopwatch Private echo1() As Integer 'echo data array 1 Private echo2() As Integer 'echo data array 2 Private echoResolution As Integer 'was "scale" Private angleResolution As Single = 1 Private rnd As New Random Private scanBitmap As Bitmap 'was "bm" Private echoLine1 As Bitmap Private echoLine2 As Bitmap Private angle As Single Private refreshInterval As Integer = 1 Private fadeInterval As Integer = 4 Private refreshCount As Integer Private fadeCount As Integer 'setup in the load event: Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load Me.ClientSize = New Size(600, 600) PictureBox1.BackColor = Color.FromArgb(0, 50, 20) pictureBox1.Dock = DockStyle.Fill Me.Controls.Add(pictureBox1) tim.Start() End Sub 'some setup in the SizeChanged event, to allow user resizing Private Sub PictureBox1_SizeChanged(sender As Object, e As System.EventArgs) Handles pictureBox1.SizeChanged scanBitmap = New Bitmap(pictureBox1.Width, pictureBox1.Height) echoResolution = pictureBox1.Width \ 2 - 5 ReDim echo1(echoResolution - 1) ReDim echo2(echoResolution - 1) echoLine1 = New Bitmap(echoResolution, 3) echoLine2 = New Bitmap(echoResolution, 3) End Sub Private Sub PictureBox1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles pictureBox1.Paint 'draw a sweep indicator line e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias Dim centre As New Point(pictureBox1.Width \ 2, pictureBox1.Height \ 2) Using mtx As New Drawing2D.Matrix mtx.RotateAt(angle + 0.2F, centre) e.Graphics.Transform = mtx Using pn As New Pen(Color.LightGreen, 1) e.Graphics.DrawLine(pn, centre, New Point(pictureBox1.Width - 5, centre.Y)) End Using End Using End Sub Private Sub Timer1_Tick(sender As Object, e As System.EventArgs) Handles tim.Tick 'update the bitmap and depending on the refreshinterval, put it in the picture box UpdateScanBitmap() refreshCount = (refreshCount + 1) Mod refreshInterval If refreshCount = 0 Then pictureBox1.Image = scanBitmap fadeCount = (fadeCount + 1) Mod fadeInterval If fadeCount = 0 Then scanBitmap = FadeImage(scanBitmap, 98) End Sub 'Update the scan: Private Sub UpdateScanBitmap() If sw Is Nothing Then sw = Stopwatch.StartNew 'create a set of simulated data for the echo line: For d As Integer = 0 To echo1.Count - 1 echo1(d) = rnd.Next(0, 255) echo2(d) = rnd.Next(0, 255) Next 'conver the data to a line bitmap: echoLine1 = GetEchoBitmap(echo1, echoLine1) echoLine2 = GetEchoBitmap(echo2, echoLine2) 'draw the echo lines on the scan Using g As Graphics = Graphics.FromImage(scanBitmap) Dim centre As New Point(pictureBox1.Width \ 2, pictureBox1.Height \ 2) Using mtx As New Drawing2D.Matrix mtx.RotateAt(angle, centre) ' g.Transform = mtx 'rotate the Graphics g.DrawImageUnscaled(echoLine1, centre.X, centre.Y - 1) mtx.RotateAt(angleResolution, centre) g.Transform = mtx g.DrawImageUnscaled(echoLine2, centre.X, centre.Y - 1) End Using End Using 'update the angle angle = (angle + 2 * angleResolution) Mod 360.0F 'provide feedback in the Output window: If angle < angleResolution Then angle = angle Mod 360.0F Console.WriteLine("360 deg. sweep time = " & ((sw.ElapsedMilliseconds / 1000).ToString("N4"))) sw = Stopwatch.StartNew End If End Sub Private Function GetEchoBitmap(echo As Integer(), echoLine As Bitmap) As Bitmap Using fp As New FastPix(echoLine) Dim pixels() As Integer = fp.PixelArray For radius As Integer = 0 To echoResolution - 1 Dim data As Integer = echo(radius) * 256 pixels(radius) = &HAF000000 + data pixels(radius + echoResolution) = &HFF000000 + data pixels(radius + 2 * echoResolution) = &HAF000000 + data Next End Using Return echoLine End Function Private Function FadeImage(bmp As Bitmap, opacityPercent As Double) As Bitmap 'set the opacity of an image: If opacityPercent >= 0 AndAlso opacityPercent <= 100 Then Dim alphaRatio = opacityPercent / 100 Using fp As New FastPix(bmp) Dim pixels() = fp.PixelArray For i As Integer = 0 To pixels.Count - 1 Dim pixel = pixels(i) Dim alpha As Integer = (pixel >> 24) And &HFF alpha = CInt(alphaRatio * alpha) << 24 pixels(i) = pixel And &HFFFFFF Or alpha Next End Using Return bmp Else Console.WriteLine("FadeImage: opacityPercent must be in the range 0-100.") Return Nothing End If End Function End Class




Reply With Quote