Results 1 to 9 of 9

Thread: [RESOLVED] Math Problem :[

  1. #1

    Thread Starter
    Hyperactive Member Skatebone's Avatar
    Join Date
    Jan 2009
    Location
    Malta
    Posts
    279

    Resolved [RESOLVED] Math Problem :[

    Hey guys

    I have a problem with math rather than vb.

    My aim is to imitate the hand of a clock i.e. rotate a line from a fixed point.

    I thought it was easy trigonometry but Im really really tired and I cant figure it out so after I searched google with no success I decided to ask along.

    Here is what I managed yet:

    Code:
    Public Class Form1
        Dim Pt1 As Point = New Point(100, 100)
        Dim Pt2 As Point = New Point(100, 75)
        Dim Pt3 As Point = New Point(125, 100)
    
    
        Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            e.Graphics.FillEllipse(Brushes.White, 75, 75, 50, 50)
            e.Graphics.DrawEllipse(Pens.Black, 75, 75, 50, 50)
            e.Graphics.DrawLine(Pens.Black, Pt1, Pt2)
            'Variable triangle
            e.Graphics.DrawLine(Pens.Black, Pt1, Vary(90))
        End Sub
        Private Function Vary(ByVal variable As Integer) As Point
            Dim height As Integer = 0
            Dim Rads As Integer = (variable / 180) * 3.146
    
            height = 25 * Math.Sin(Rads)
    
            Dim tmpPt As Point = New Point(100 - height, 100 + height)
            Return tmpPt
        End Function
    End Class
    PS: Its in a kinda mess cause its just whats coming in my mind at that instance. What I want is to change the angle from 0 to 360 (Cos) and get the coords of the line.

    Thanks in advance,
    Skate
    Life runs on code

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

    Re: Math Problem :[

    Hi Skatebone, here's a few things you need to fix:

    1. Make Rads a Double rather an Integer, because otherwise it will only range from 0 to 7 which would be a bit odd for a clock!

    2. To draw an angled line, you set the height to the Sin of the angle and the width to the Cos.

    I've marked these points in your code below:

    Quote Originally Posted by Skatebone View Post
    Code:
    Public Class Form1
        Dim Pt1 As Point = New Point(100, 100)
        Dim Pt2 As Point = New Point(100, 75)
        Dim Pt3 As Point = New Point(125, 100)
    
    
        Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
            e.Graphics.FillEllipse(Brushes.White, 75, 75, 50, 50)
            e.Graphics.DrawEllipse(Pens.Black, 75, 75, 50, 50)
            e.Graphics.DrawLine(Pens.Black, Pt1, Pt2)
            'Variable triangle
            e.Graphics.DrawLine(Pens.Black, Pt1, Vary(90))
        End Sub
        Private Function Vary(ByVal variable As Integer) As Point
    
            Dim width As Integer
            Dim height As Integer = 0  
            Dim Rads As Double = (variable / 180) * 3.146
    
            width = Cint(25 * Math.Cos(Rads)
           height = Cint(25 * Math.Sin(Rads))
     
            Dim tmpPt As Point = New Point(100 - width, 100 + height)
            Return tmpPt
        End Function
    End Class
    You should find it works with those changes. I think it's a good idea to work with Option Strict On, especially with Math(s), which is why I added the Cint in the code.

    BB

  3. #3

    Thread Starter
    Hyperactive Member Skatebone's Avatar
    Join Date
    Jan 2009
    Location
    Malta
    Posts
    279

    Re: Math Problem :[

    Quote Originally Posted by boops boops View Post
    Hi Skatebone, here's a few things you need to fix:

    1. Make Rads a Double rather an Integer, because otherwise it will only range from 0 to 7 which would be a bit odd for a clock!

    2. To draw an angled line, you set the height to the Sin of the angle and the width to the Cos.

    I've marked these points in your code below:



    You should find it works with those changes. I think it's a good idea to work with Option Strict On, especially with Math(s), which is why I added the Cint in the code.

    BB
    Thanks alot dude

    A very strange thing is happening though.

    When I put 0 degrees, i get an angle of 270
    When I put 90 degrees I get and angle of 180
    Wehn I put 180 degrees I get an angle of 90

    Therefore there is a shift of -90degrees

    Now:

    Sin(0)=0
    Cos(0)=1

    Hmm I cant see why this is happening
    Life runs on code

  4. #4
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Math Problem :[

    Positive angles are incremented in the clockwise direction since the point (0;0) is in the top left corner by default.
    And separate your logic angles with the graphics angles.
    Take sin() and cos() from your logic angle and only then subtract 90 degrees and reverse the sign to reflect in in graphics.

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

    Re: Math Problem :[

    I'm not sure I understood Cicatrix's comment but I'm sure he's right. Anyway, it's because of 100 - width, which you should change to 100 + width to make it work the way you want.

    Then you have to remember that all angles in DotNet are measured from the positive x-axis. That means 0 degrees is the 3 o'clock position. So if you want your clock hand to start from 12 o'clock, the starting value should be 270 degrees or -90 degrees.

    BB

  6. #6
    Fanatic Member
    Join Date
    Aug 2010
    Posts
    624

    Re: Math Problem :[

    Well I'm not sure if this is resolved yet, but I wrote this out for my own benefit because I wanted to see if I could do it. This is for the "seconds" hand. I call this sub on a timer every second.

    Code:
        Private curAngle As Integer = 270 'start at the top (measuring clockwise where 0 degrees is a horizontal line)
        Private mGraph As Graphics = Me.CreateGraphics 'create some graphics.
        Private initialPoint As New Point(128, 113) 'this was the start point i chose within my form. The values matter little.
    
        Private Sub DoGraphics()
            mGraph.Clear(Me.BackColor) 'clear previous graphics
            mGraph.DrawEllipse(Pens.Black, New Rectangle(initialPoint.X - 50, initialPoint.Y - 50, 100, 100)) 'draw the clock face.
            curAngle += 6 'increase the "degrees" angle by 6
            Dim inRads As Double = (curAngle * Math.PI) / 180 'convert to radians
            Dim NewX As Integer = CInt(50 * Math.Cos(inRads)) 'calculate new X2 position
            Dim NewY As Integer = CInt(50 * Math.Sin(inRads)) 'calculate new Y2 position
            mGraph.DrawLine(Pens.Black, initialPoint.X, initialPoint.Y, initialPoint.X + NewX, initialPoint.Y + NewY) 'draw the line!
        End Sub
    If I helped you out, please take the time to rate me

  7. #7
    I'm about to be a PowerPoster! Hack's Avatar
    Join Date
    Aug 2001
    Location
    Searching for mendhak
    Posts
    58,333

    Re: Math Problem :[

    Quote Originally Posted by Skatebone
    I have a problem with math rather than vb.
    And as such, it would be better suited for the Math Forum.

    Moved.

  8. #8
    PowerPoster cicatrix's Avatar
    Join Date
    Dec 2009
    Location
    Moscow, Russia
    Posts
    3,654

    Re: Math Problem :[

    Pity it was moved because the problem is not with math.
    What seems to be missing is the ability to apply 2d transformations for GDI+

    You can prepare a logic co-ordinate space to your liking.

    See this example.
    In the Form_Paint we create a transformation matrix and apply certain transformations to it:
    1. We move the (0,0) coordinate to the center of the form
    2. We scale down the form so that we have logical coordinates instead of physical pixels
    3. We rotate the matrix -90 degrees so that zero was at 12 o'clock.
    4. We draw the hands using ordinary maths without pain.

    vb Code:
    1. Imports System.Math
    2. Imports System.Drawing.Drawing2D
    3.  
    4. Public Class frmClock
    5.  
    6.     Private cp As PointF  ' Center point
    7.     'Private rct As RectangleF  ' Bounding rect
    8.     Private tmr As Timer
    9.  
    10.     Private smallerside As Integer ' Whatever is smaller - width or height of the form
    11.     Private pixelwidth As Single ' Used to determine the scalefactor for a pixel
    12.     Private hrspen, minpen, secpen, dialpen As Pen ' individual pens for the hands
    13.  
    14.     ' A hour hand makes 1 full turn per 12 hours or 12 * 3600 = 43200 seconds
    15.     Private Const H_INCREMENT As Double = 2 * PI / 43200
    16.  
    17.     ' A minute hand makes 1 full turn per 3600 seconds
    18.     Private Const M_INCREMENT As Double = 2 * PI / 3600
    19.  
    20.     ' A second hand makes 1 full turn per 60 seconds
    21.     Private Const S_INCREMENT As Double = 2 * PI / 60
    22.  
    23.     Private Const H_LENGTH As Double = 0.5  ' Length of the hours hand
    24.     Private Const M_LENGTH As Double = 0.7  ' Length of the minutes hand
    25.     Private Const S_LENGTH As Double = 0.79 ' Length of the seconds hand
    26.  
    27.  
    28.     Private Sub frmClock_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    29.         ' Creating a timer
    30.         tmr = New Timer With {.Interval = 1000, .Enabled = True}
    31.  
    32.         ' Lambda for the handling of Timer.Tick
    33.         AddHandler tmr.Tick, Sub(timersender As Object, timere As EventArgs)
    34.                                  Me.Invalidate()
    35.                              End Sub
    36.     End Sub
    37.  
    38.     Private Sub frmClock_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
    39.         ' Find the central point
    40.         cp = New PointF(CSng(Me.ClientSize.Width / 2), CSng(Me.ClientSize.Height / 2))
    41.  
    42.         ' Determine whatever is smaller - width or height
    43.         smallerside = CInt(IIf(Me.ClientSize.Width >= Me.ClientSize.Height, Me.ClientSize.Height, Me.ClientSize.Width))
    44.  
    45.         ' Find out what will be a pixel size in our logic coordinates:
    46.         pixelwidth = CSng(1 / smallerside)
    47.  
    48.         ' Preparing pens for each hand and the dial:
    49.         hrspen = New Pen(Brushes.Blue, 8 * pixelwidth)
    50.         minpen = New Pen(Brushes.Green, 4 * pixelwidth)
    51.         secpen = New Pen(Brushes.Red, 1 * pixelwidth)
    52.         dialpen = New Pen(Brushes.Black, 4 * pixelwidth)
    53.  
    54.         ' Re-drawing the form
    55.         Me.Invalidate()
    56.     End Sub
    57.  
    58.     Private Sub frmClock_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    59.         Me.Text = Now.ToString
    60.  
    61.         Dim h_angle, m_angle, s_angle As Double ' For angles of each hand
    62.  
    63.         ' The transformation matrix
    64.         Dim mtrx As New Matrix
    65.  
    66.         ' Moving (0,0) to the center of the form
    67.         mtrx.Translate(cp.X, cp.Y)
    68.  
    69.         ' Scaling up the form (zoom in)
    70.         mtrx.Scale(smallerside * 0.5F, smallerside * 0.5F)
    71.  
    72.         ' Rotating -90 degrees
    73.         mtrx.Rotate(-90)
    74.  
    75.         ' Applying transformation
    76.         ' Now we have a coordinate space
    77.         ' with the center at (0,0) and
    78.         ' the dial diameter of 0.9 of the smaller dimension of the form.
    79.         ' And the angles are incremented CLOCKWISE!
    80.         e.Graphics.Transform = mtrx
    81.  
    82.         Dim h, m, s As Double
    83.  
    84.         ' For 10:30 the hours will be 10.5 so that the hand was between 10 and 11
    85.         s = Now.Second
    86.         m = Now.Minute + s / 60
    87.         ' 24 hour format requires removing 12 hours:
    88.         h = CDbl(IIf(Now.Hour > 12, Now.Hour - 12, Now.Hour)) + m / 60
    89.  
    90.         ' Determine the angle of each hand.
    91.         h_angle = h * 3600 * H_INCREMENT
    92.         m_angle = m * 60 * M_INCREMENT
    93.         s_angle = s * S_INCREMENT
    94.  
    95.         ' Calculating the coordinates of each hand:
    96.         Dim hpt As PointF = New PointF(CSng(Cos(h_angle) * H_LENGTH), CSng(Sin(h_angle) * H_LENGTH))
    97.         Dim mpt As PointF = New PointF(CSng(Cos(m_angle) * M_LENGTH), CSng(Sin(m_angle) * M_LENGTH))
    98.         Dim spt As PointF = New PointF(CSng(Cos(s_angle) * S_LENGTH), CSng(Sin(s_angle) * S_LENGTH))
    99.  
    100.         ' Center of the dial:
    101.         Dim stpt As Point = New Point(0, 0)
    102.  
    103.         ' Drawing the dial:
    104.         e.Graphics.DrawEllipse(dialpen, -0.9, -0.9, 1.8, 1.8)
    105.  
    106.         ' Drawing the hands:
    107.         e.Graphics.DrawLine(hrspen, stpt, hpt)
    108.         e.Graphics.DrawLine(minpen, stpt, mpt)
    109.         e.Graphics.DrawLine(secpen, stpt, spt)
    110.  
    111.  
    112.     End Sub
    113.  
    114.  
    115. End Class

  9. #9

    Thread Starter
    Hyperactive Member Skatebone's Avatar
    Join Date
    Jan 2009
    Location
    Malta
    Posts
    279

    Re: Math Problem :[

    This is all the help I could ever get

    Thanks all guys really helped
    Life runs on code

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