Smart questions
Smart answers
Smart people
Join Tek-Tips Forums
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Member Login




Remember Me
Forgot Password?
Join Us!

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips now!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

Join Tek-Tips
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.
Jobs from Indeed

Link To This Forum!

Partner Button
Add Stickiness To Your Site By Linking To This Professionally Managed Technical Forum.
Just copy and paste the
code below into your site.

Varga (TechnicalUser) (OP)
1 Feb 10 23:12
Hello,

I'm trying to make a VB form that has a compass display on it.
I want to display the reading from a digital compass sensor on a form and I am using Visual Basic 6.0.

I can't find any built-in compass gauges, except for expensive downloads in Aviation packs, and wondered how I could do it.

I thought of using a pic of a compass and changing the rotation as the signal changed, but I only found the options to rotate by 90degree increments with xy flipping.

Is there no way to rotate an image in small increments?

Or to simulate a compass reading?

I would like to set the desired direction of the robot with another compass dial, or preferably a combo compass dial/indicator.


Any help would be appreciated.
Thanks
Varga
Helpful Member!  strongm (MIS)
2 Feb 10 4:48

Quote:

I only found the options to rotate by 90degree increments with xy flipping.

Is there no way to rotate an image in small increments?

Yes, that 90º increment limitation is a problem. And, whilst there are plenty of VB solutions to samll incremental rotations they all predominantly involve a point by point scanning of the source image and applying a mathematical transform to each point - so they are slow and cumbersome (well, actually some are quite elegant, but they are still slow)

However, over in the VB5&6 forum I illustrated a technique some 7 years ago in thread222-535523: rotate bitmap which is dramatically faster and a more powerful (it can scale, and mirror quite happily as well for example)

thread222-1459552: How do I make a realistic analogue clock? contains a more recent version of the example, illustrating rotation about a specific point
Varga (TechnicalUser) (OP)
3 Feb 10 9:45
Hey,
Thanks for the help strongm.

I messed around with some of those methods, but the redraw "raster" was slow and low quality, and I couldn't get the transformworld one to work.

The solution I cam up with was to use a compass face image, and save 18 versions of the gif at 5degree rotation increments from 0 - 85 degrees. (I'm testing it with a trackbar 0-360 range.) I use Mod to figure out which image, and then a division to determine the quadrant and set the proper RotateFlipType.

I'm updating the picture every timer tick, and have it set to 200ms
Do you have any suggestions to speedup or improve on my idea?

See the code below.

----------------------------------------------------------

Public Class Form1
Dim bmp As Bitmap

Private Sub TrackBar1_Change(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TrackBar1.Scroll
        CompassAngle.Text = TrackBar1.Value
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        CompassAngle.Text = 0
        Timer1.Enabled = True
End Sub

Private Sub UpdateCompass()
        Dim pic As String
        Dim quadrant As Double
        Dim tempInt As Integer
        Dim tempMod As Integer

        '5 degree increments
        tempInt = Int(TrackBar1.Value / 5)

        '18 increments per quadrant
        tempMod = tempInt Mod 18    

        If tempMod = 0 Then
            pic = "C:\Images\Compass_0degrees.gif"
        ElseIf tempMod = 1 Then
            pic = "B:\Images\Compass_5degrees.gif"
        ElseIf tempMod = 2 Then
            pic = "B:\Images\Compass_10degrees.gif"
        ElseIf tempMod = 3 Then
            pic = "B:\Images\Compass_15degrees.gif"
        ElseIf tempMod = 4 Then
            ...

        ElseIf tempMod = 16 Then
            pic = "B:\Images\Compass_80degrees.gif"
        ElseIf tempMod = 17 Then
            pic = "B:\Images\Compass_85degrees.gif"
        End If

        'quadrant has 18 increments
        quadrant = tempInt / 18

        bmp = System.Drawing.Bitmap.FromFile(pic)
        PictureBox1.Image = bmp

        If quadrant < 1 Then
PictureBox1.Image.RotateFlip(RotateFlipType.RotateNoneFlipNone)
        ElseIf quadrant < 2 Then
PictureBox1.Image.RotateFlip(RotateFlipType.Rotate270FlipNone)
        ElseIf quadrant < 3 Then
PictureBox1.Image.RotateFlip(RotateFlipType.Rotate180FlipNone)
        ElseIf quadrant < 4 Then
PictureBox1.Image.RotateFlip(RotateFlipType.Rotate90FlipNone)
        Else     '= 360
PictureBox1.Image.RotateFlip(RotateFlipType.RotateNoneFlipNone)
        End If
End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Call UpdateCompass()
End Sub
End Class

----------------------------------------------------

Thanx again for the help,
Varga
strongm (MIS)
3 Feb 10 11:04
What problem are you having with the SetWorldTransform method?

I'm guessing that you can't get t working as written in my examples because you are, it now appears, actually using VB.NET, and not as you said "I am using Visual Basic 6.0"
 
Varga (TechnicalUser) (OP)
3 Feb 10 12:29
Hey strongm,

Sorry I forgot I upgraded to, and am now using, Visual Basic 2008 Express.

That's the main reason why the SetWorldTransform wouldn't work as certain commands were not recognized...

My method works, crude as it is, but would the SetWorldTransform be better/faster/more efficient?


I am willing to take another stab at SetWorldTransform if you think it would be better...

Please let me know,
Thanks
Varga
strongm (MIS)
3 Feb 10 13:09
If you've switched to VB 2008, then you are using .NET which means you can use the Graphics class of the System.Drawing namespace, which has transform methods built-in that do the same thing as SetWorldTransform (e.g. MultiplyTransform, ResetTransform, RotateTransform, ScaleTransform, TransformPoints and TranslateTransform) and a Transform property.

Here's the MSDN page that documents these
Varga (TechnicalUser) (OP)
3 Feb 10 20:45
Hey strongm,
I'm trying all that stuff, but so frustrated I'm ready to give up.

I finally got the e.Graphics.Drawing stuff to draw something. (Thanks to http://www.bobpowell.net/transformations.htm)
...but I couldn't get anything more than a circle and square, and need to rotate an image.
(So that led me to 'Drawing.Graphics.FromImage')

I don't understand the "e" PaintEvent args...
I can get the code below to run, but how do I call the main function? What do I put as an "e" argument in the call line?

If I get my image into a drawing, then get the drawing output to output on the form, then transform/rotate it (about it's center point), then I'll be happy.

(And do I just put the 'Compass.jpg' file in the bin or root folder? Or do I need the full path?)

Imports graphics
Public Class Form1
    Public Shared Function FromImage( _
        ByVal image As Image _
    ) As Drawing.Graphics

    End Function
  
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'FromImageImage2(???)
    End Sub
    Private Sub FromImageImage2(ByVal e As PaintEventArgs)

        ' Create image.
        Dim imageFile As Image = Image.FromFile("Compass.bmp")

        ' Create graphics object for alteration.
        Dim newGraphics As Drawing.Graphics = Drawing.Graphics.FromImage(imageFile)

        ' Alter image.
        newGraphics.FillRectangle(New SolidBrush(Color.Black), _
        100, 50, 100, 100)

        ' Draw image to screen.
        e.Graphics.DrawImage(imageFile, New PointF(0.0F, 0.0F))

        ' Dispose of graphics object.
        newGraphics.Dispose()
    End Sub

End Class


Your help IS appreciated.
Thanks
Varga
strongm (MIS)
4 Feb 10 7:01
Here's what I hope is a pretty straightforward example. You simply need a form with a timer, and then paste in the following code. Note that I am deliberately using a relatively large image (500 * 472 pixels) to show that applying the transforms is quick.

CODE

Public Class Form1
    ' Lazily use some form-wide variables for this example
    Private myImage As Image 'to contain our source image
    Private myGraphics As Drawing.Graphics 'represents our drawing canvas that we can manipulate

    ' Each tick increases the rotation
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Static Angle As Long

        PictureBox1.Refresh()
        myGraphics.ResetTransform()

        '' calculated centre for general images that we want to rotate around their centre point
        'myGraphics.TranslateTransform(myImage.Width / 2, myImage.Height / 2) ' move drawing origin
        'myGraphics.RotateTransform(Angle) ' apply a rotation transform of Angle degrees
        '' Now draw our source image with the above two transforms applied
        'myGraphics.DrawImage(myImage, New Rectangle(-myImage.Width / 2, -myImage.Height / 2, myImage.Width, myImage.Height)) ' CInt(-myImage.Width / 2), CInt(-myImage.Height / 2))

        ' if using the compass picture referenced above the actual centre of the compass
        ' is not quite in the centre of the image, so we use a hard-coded point for the centre
        ' rather than calculated centre
        myGraphics.TranslateTransform(247, 239)  ' move drawing origin
        myGraphics.RotateTransform(Angle) ' apply a rotation transform of Angle degrees
        ' Now draw our source image with the above two transforms applied
        myGraphics.DrawImage(myImage, New Rectangle(-247, -239, myImage.Width, myImage.Height)) ' CInt(-myImage.Width / 2), CInt(-myImage.Height / 2))

        myGraphics.RotateTransform(-Angle)
        Dim point0 As New Point(0, 5)
        Dim point1 As New Point(-5, 0)
        Dim point3 As New Point(5, 0)
        Dim point2 As New Point(0, -myImage.Height / 2.5)
        Dim Pointer As Point() = {point0, point1, point2, point3}
        myGraphics.FillPolygon(Brushes.Red, Pointer)

        Angle = (Angle + 3) Mod 360
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim filename As String

        ' Initialise variables ready for example
        filename = "c:\transair_compass_rose.jpg" 'sourced for this example from http://www.transair.co.uk/images/2007images/transair_compass_rose.jpg
        myImage = Image.FromFile(filename)

        PictureBox1.Width = myImage.Width
        PictureBox1.Height = myImage.Height
        myGraphics = PictureBox1.CreateGraphics
        ' Uncommenting the below line will slow the drawing of the rotated image down but increase its visual quality
        ' Note that you can select a different InterpolationMode settings to balance speed against quality
        ' myGraphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
        myGraphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality ' high quality antialiasing will be applied to line drawing
        Timer1.Interval = 250
        Timer1.Enabled = True
    End Sub
End Class
strongm (MIS)
4 Feb 10 10:33
Oops... a form with a timer and a picturebox ...   
Varga (TechnicalUser) (OP)
4 Feb 10 15:56
Hey strongm,

Awesome. I tries it out and it works.
And I understand it enough that I should be able to modify it for my purposes.

You've been a great help!

Thanks
Varga
strongm (MIS)
4 Feb 10 17:55
Glad it helped

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Back To Forum

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close