Results 1 to 19 of 19

Thread: Fast update of bitmap from polar coordinate data

Hybrid View

  1. #1

    Thread Starter
    New Member
    Join Date
    Sep 2011
    Location
    Portsmouth, England
    Posts
    8

    Fast update of bitmap from polar coordinate data

    Hi,

    I am producing a marine radar display in VB.Net and struggling to get the radar data to display quickly enough.

    The data is coming into my application from a callback from the radar maker's dll. Each dataset consists of an integer between 0 and 8191 denoting the angle from the datum (ship's head) that the dataset represents and a byte array with 480 elements containing data from ship's position (byte 0) to maximum range (byte 480). Each of these locations is a single byte, I want to set both red and green components of the relevant pixel in a 1000 x 1000 bitmap to this byte value. The dataset number increments round from 0 to 8191 as the radar scanner rotates.

    My first approach was to use math.sin and math.cos to convert polar coordinates to cartesian coordinates, and then use setPixel to set the colour of the relevant pixels but this is far too slow.

    I'm now trying to use Boop Boops 'FastPix' code:

    http://www.vbforums.com/showthread.php?t=586709

    Which looks like it should be much better, but I am wondering if there is a more efficient approach, for example cutting out the polar to cartesian conversion, or putting the data direct into a byte array?

    I am also running the radar picture processing code on a thread separate to the UI thread to keep the UI responsive - what is the best way to display the resultant bitmap onto the UI? I am currently using a delegate and putting the bitmap into a picturebox, and I am sure there must be a better way?

    Many Thanks

    Chris

  2. #2

    Re: Fast update of bitmap from polar coordinate data

    The suggestion I can make is that you show us a bit of your drawing code so we can see how it looks and offer suggestions for improvements there. FastPix is a good idea as well since it moves pretty fast.

    But, as another suggestion: I would handle all drawing code inside the PictureBox Paint method. You have direct access to the Graphics object which allows you to paint directly on the PictureBox. I would think you'd see a speed improvement there, and you wouldn't need to utilize FastPix or SetPixel as you would literally be drawing right to the PictureBox.

  3. #3

    Thread Starter
    New Member
    Join Date
    Sep 2011
    Location
    Portsmouth, England
    Posts
    8

    Re: Fast update of bitmap from polar coordinate data

    Thanks for the suggestions. Using fastpix is definitely better, but my code is still too slow:

    Code:
    Try
                Dim echo(scale) As Byte 'Create byte array to hold echo data
                Dim bm As New Bitmap(frmRadarInstance.PictureBox1.Image)
    
                FastPix.ConvertFormat(bm) 'convert bitmap to 32bppPArgb
    
                System.Runtime.InteropServices.Marshal.Copy(echoPtr, echo, 0, scale) 'Get the echo data
    
                dblAngleRad = angle / 8192 * (Math.PI * 2) 'Convert the scan number to an angle in radians
                dblAngleCos = Math.Cos(dblAngleRad)
                dblAngleSin = Math.Sin(dblAngleRad)
    
    
                Using fp As New FastPix(bm)
    
                    For radius As Integer = 0 To scale
    
                        Dim dimX As Integer = 500 + Convert.ToInt32(radius * dblAngleCos) 'Calculate cartesian coordinates with origin offset to 500,500
                        Dim dimY As Integer = 500 + Convert.ToInt32(radius * dblAngleSin)
                        
    
                        fp.SetPixel(dimX, dimY, Color.FromArgb(echo(radius), echo(radius), 0))
    
                    Next
                End Using
    
                frmRadarInstance.BeginInvoke(New UpdateBitmap( _
                     AddressOf frmRadarInstance.updateBitmap), New Object() _
                     {bm})
    
            Catch ex As Exception
                Debug.WriteLine(ex.ToString)
            End Try
    I will try using the PictureBox paint method. I am also inclined to try a lookup table for the conversion to cartesian coordinates?

    Thanks

    Chris

  4. #4
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Fast update of bitmap from polar coordinate data

    Hi chriscross,

    It's nice to see you are using FastPix. Here's a suggestion for what I think will be a more efficient approach. Instead of plotting the points directly to the picturebox Image, plot them to a single horizontal line:

    Code:
    Dim radialLine As New Bitmap(scale, 1)
    
    Using fp As New FastPix(radialLine)
       Dim Pixels() As Integer = fp.PixelArray
       For radius As Integer = 0 To Scale - 1
           Pixels(radius) = &HFF000000 + echo(radius) * 257 * 256 'I may have to explain this!
       Next
    End Using
    I've used my favourite FastPix version, the Integer array, because it's far away the most efficient. Still, I'm not certain that the above will actually be much faster than old-fashioned Bitmap.SetPixel, because the number of pixels involved is probably small and Lockbits/FastPix has an overhead.

    Now you have a horizontal line plotted in the correct colours. Next draw it at the required angle on your target bitmap. I'll assume you want to draw the full sweep circle, not just the single line. Otherwise use g.Clear to clear the graphics.

    Code:
    'At form level:
    Dim bm As New Bitmap(PictureBox1.Width, PictureBox1.Height)
    
    'In your sub:
    Using g As Graphics = Graphics.FromImage(bm)
         Using mtx As New Drawing2d.Matrix
               mtx.RotateAt(angle, New Point(500, 500)) 'no need to convert to radians
               g.Transform = mtx 'rotate the Graphics
         End Using
         g.DrawImageUnscaled(radialLine, 500, 500)
    End Using
    PictureBox1.Image = bm
    This is just a sketch and I haven't tried it out (yet) but I hope the idea is clear enough. You might gain some speed by doing your own maths and using a lookup table, but my impression is that GDI+ is pretty efficient with things like rotating the graphics. And I hope you'll agree this is much simpler.

    BB

  5. #5
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    Re: Fast update of bitmap from polar coordinate data

    I can't see a need, here, to draw to a bitmap. Draw directly to the drawing surface in a Paint or OnPaint method.
    "Ok, my response to that is pending a Google search" - Bucky Katt.
    "There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
    "Before you can 'think outside the box' you need to understand where the box is."

  6. #6

    Thread Starter
    New Member
    Join Date
    Sep 2011
    Location
    Portsmouth, England
    Posts
    8

    Re: Fast update of bitmap from polar coordinate data

    Quote Originally Posted by SJWhiteley View Post
    I can't see a need, here, to draw to a bitmap. Draw directly to the drawing surface in a Paint or OnPaint method.
    I did try this, but it made the UI very unresponsive. I assume I need to iterate through the whole data array within the paint event in order to display the full circle of data?

    Thanks

    Chris

  7. #7

    Thread Starter
    New Member
    Join Date
    Sep 2011
    Location
    Portsmouth, England
    Posts
    8

    Re: Fast update of bitmap from polar coordinate data

    Quote Originally Posted by boops boops View Post
    It's nice to see you are using FastPix. Here's a suggestion for what I think will be a more efficient approach. Instead of plotting the points directly to the picturebox Image, plot them to a single horizontal line:
    Hi BB,

    Thank you for the suggestion, that certainly appears to be a neater and simpler implementation, however I am having a few issues with it. In the line:

    Code:
    Pixels(i) = echo(radius) * 257 * 256 'I may have to explain this!
    Should pixels(i) be pixels(radius)?

    In the second section, should it be

    Code:
    Using g As Graphics = Graphics.FromImage(bm)
         Using mtx As New Drawing2d.Matrix
               mtx.RotateAt(angle, new PointF (500, 500)) 'no need to convert to radians
               g.Transform = mtx 'rotate the Graphics
         End Using
         g.Graphics.DrawImageUnscaled(radialLine, 500, 500)
    End Using
    PictureBox1.Image = bm
    I am not getting any exceptions, but it is not drawing anything to the picture box? The pixels array appears to have valid data in it, but I am not sure about either radialLine or bm.

    Many Thanks

    Chris

  8. #8
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Fast update of bitmap from polar coordinate data

    Quote Originally Posted by chriscross123 View Post
    Hi BB,
    Should pixels(i) be pixels(radius)?
    Yes, of course. I was in a bit of a hurry and didn't even check the syntax!

    Code:
    Using g As Graphics = Graphics.FromImage(bm)
               mtx.RotateAt(angle, new PointF (500, 500)) 'no need to convert to radians
    You're right again. Same excuse...

    EDIT: I've spotted the problem (plus another syntax correction). I forgot to set the Alpha byte! See the corrections in red in Post #4. I think you will find it's quick enough. I just did a test with "scale" set to 500 and 360 lines drawn at 1 degree intervals. On my rather average PC it took 41 milliseconds to complete -- and that included generating the random data and updating the PictureBox.Image.



    @SJWhiteley. The radar detects echoes in a single direction, but the aerial rotates to produce a usable picture. So the lines of data have to be accumulated somewhere. You could do that on a bitmap or in a collection. But to plot a point in the Paint event you have to draw a 1*1 pixel rectangle. Assuming a data line of 500 pixels and a rotary resolution of 1 degree, that would mean drawing 180,000 tiny rectangles in the Paint event. I haven't tried it but it doesn't sound very efficient to me. Anyway, what's wrong with using a bitmap?

    BB

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width