Drawing a compass

H

Hugh Janus

I am trying to draw a compass on a form but my maths is not up to
scratch! I have the disc with the bearing markers but have no idea how
to calculate the needle line based on the desired degree.

Does anyone know what the formula is to create it? If my circle is 50
by 50 I need to plot a line starting in the centre and going out to the
outer circle and touching it at the x degrees mark. Ideas??!

Thanks
 
C

Claes Bergefall

Try Graphics.DrawPie. Just pass a really small value for the sweepAngle
parameter (something like 0.0001 should do the trick)

/claes
 
C

Chris Dunaway

Hugh said:
I am trying to draw a compass on a form but my maths is not up to
scratch! I have the disc with the bearing markers but have no idea how
to calculate the needle line based on the desired degree.

Does anyone know what the formula is to create it? If my circle is 50
by 50 I need to plot a line starting in the centre and going out to the
outer circle and touching it at the x degrees mark. Ideas??!

Here is a function that takes a center point, a radius, and an angle in
degrees with North being 0, West being 90, South being 180 and East
being 270. It returns the point to draw the line to.

So if your Center is 50,50, and you want to draw a 50 unit line NW at
40 degrees, you would call it like this:

Dim center As New PointF(50.0F, 50.0F)
Dim endPoint As PointF = PointOnCircle(center, 50, 40)
g.DrawLine(Pens.Black, center, endPoint)


Private Function PointOnCircle(ByVal center As PointF, ByVal radius
As Double, ByVal angle As Double) As PointF

'NOTE: The center of the circle is passed in terms of GDI+
coordinates

'The angle passed in assumes North is 0 degrees. For the polar
coordinate calculations, we need to translate
'this so that East is zero:
Dim translatedAngle As Double = angle + 90.0
If translatedAngle > 360.0 Then
translatedAngle -= 360.0
End If

'Next convert degrees to radians
translatedAngle *= (Math.PI / 180.0)

'Next we need to calculate the polar coordinates:
Dim x As Double = radius * Math.Cos(translatedAngle)
Dim y As Double = radius * Math.Sin(translatedAngle)

'Convert doubles to Singles
Dim x2 As Single = Convert.ToSingle(x)
Dim y2 As Single = Convert.ToSingle(y)

'Finally create the PointF structure and adjust for the center
of the circle:
Return New PointF(x2 + center.X, -y2 + center.Y)

End Function

Hope this helps
 
H

Hugh Janus

Hugh said:
Here is a function that takes a center point, a radius, and an angle in
degrees with North being 0, West being 90, South being 180 and East
being 270. It returns the point to draw the line to.

So if your Center is 50,50, and you want to draw a 50 unit line NW at
40 degrees, you would call it like this:

Dim center As New PointF(50.0F, 50.0F)
Dim endPoint As PointF = PointOnCircle(center, 50, 40)
g.DrawLine(Pens.Black, center, endPoint)


Private Function PointOnCircle(ByVal center As PointF, ByVal radius
As Double, ByVal angle As Double) As PointF

'NOTE: The center of the circle is passed in terms of GDI+
coordinates

'The angle passed in assumes North is 0 degrees. For the polar
coordinate calculations, we need to translate
'this so that East is zero:
Dim translatedAngle As Double = angle + 90.0
If translatedAngle > 360.0 Then
translatedAngle -= 360.0
End If

'Next convert degrees to radians
translatedAngle *= (Math.PI / 180.0)

'Next we need to calculate the polar coordinates:
Dim x As Double = radius * Math.Cos(translatedAngle)
Dim y As Double = radius * Math.Sin(translatedAngle)

'Convert doubles to Singles
Dim x2 As Single = Convert.ToSingle(x)
Dim y2 As Single = Convert.ToSingle(y)

'Finally create the PointF structure and adjust for the center
of the circle:
Return New PointF(x2 + center.X, -y2 + center.Y)

End Function

Hope this helps

Thanks, this seems to work (sort of!). I have one question. In your
post, you say that West is 90 degrees, but it should be 270. Why is
that?

Hugh
 
C

Chris Dunaway

Hugh said:
Thanks, this seems to work (sort of!). I have one question. In your
post, you say that West is 90 degrees, but it should be 270. Why is
that?

No reason, that's just the way I did it. If you need to have it work a
different way, you need to change the way the translated angle is
computed. The formula for polar coordinates that is used assumes that
0 degrees is to the East.

So If you want 270 degrees to be West, then the translated angle should
be 180. I think the formula for the translated angle would be this:

Dim translatedAngle As Double
If angle <= 90 Then
translatedAngle = 90.0F - angle
Else
translatedAngle = (360.0F - angle) + 90.0F
End If
 
J

Jay B. Harlow [MVP - Outlook]

Hugh,
For a "speedometer" that I draw in one of my applications I use is
Graphics.TranslateTransform, followed by a couple of
Graphics.RotateTransform.

The TranslateTransform moves the "center" point to the middle of my control.

The first RotateTransform rotates orients the needle to the starting angle.

The second RotateTransform sets the position of the needle:

Something like (untested, extracted code):

gr.TranslateTransform(CSng(Me.ClientSize.Width) / 2,
CSng(Me.ClientSize.Height) / 2)
gr.RotateTransform(180)

Dim length As Integer = Math.Max(Me.ClientSize.Width \ 2,
Me.ClientSize.Height \ 2)

gr.RotateTransform(Value)

gr.DrawLine(pen, 0, 0, length, 0)

Instead of DrawLine, you could use DrawPath or something fancy if you wanted
a fanciful needle.

--
Hope this helps
Jay B. Harlow [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


|I am trying to draw a compass on a form but my maths is not up to
| scratch! I have the disc with the bearing markers but have no idea how
| to calculate the needle line based on the desired degree.
|
| Does anyone know what the formula is to create it? If my circle is 50
| by 50 I need to plot a line starting in the centre and going out to the
| outer circle and touching it at the x degrees mark. Ideas??!
|
| Thanks
|
 
H

Hugh Janus

Chris said:
So If you want 270 degrees to be West, then the translated angle should
be 180. I think the formula for the translated angle would be this:

Dim translatedAngle As Double
If angle <= 90 Then
translatedAngle = 90.0F - angle
Else
translatedAngle = (360.0F - angle) + 90.0F
End If

Thanks this is working great now. 1 question, I've not seen it before
where you have that "F" next to a number. What does it mean?

Thanks, Jay, i'll keep your code in mind as well for a different part
of my code.

Hugh
 
C

Chris Dunaway

Hugh said:
Thanks this is working great now. 1 question, I've not seen it before
where you have that "F" next to a number. What does it mean?

I believe by default, numeric literals such as 90.0 would be a double
type. The F specifies the literal as type Single. I'm not sure if
they are necessary here.

Chris
 
J

Jay B. Harlow [MVP - Outlook]

Hugh,
| Thanks this is working great now. 1 question, I've not seen it before
| where you have that "F" next to a number. What does it mean?
As Chris suggests the "F" indicates a Single literal. I understand that the
"F" stands for Float, which traditionally has been the same size as
Single...

The list of literal type characters is available here:
http://msdn2.microsoft.com/en-us/library/s9cz43ek.aspx

--
Hope this helps
Jay B. Harlow [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| Chris Dunaway wrote:
| >
| > So If you want 270 degrees to be West, then the translated angle should
| > be 180. I think the formula for the translated angle would be this:
| >
| > Dim translatedAngle As Double
| > If angle <= 90 Then
| > translatedAngle = 90.0F - angle
| > Else
| > translatedAngle = (360.0F - angle) + 90.0F
| > End If
|
| Thanks this is working great now. 1 question, I've not seen it before
| where you have that "F" next to a number. What does it mean?
|
| Thanks, Jay, i'll keep your code in mind as well for a different part
| of my code.
|
| Hugh
|
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top