mike-obrien.net Resume Blog Labs
Sunday, September 03, 2006

The following function allows you to obtain (x,y) coordinates within a 3d perspective pie slice by specifying the pie dimensions, the radius (Distance from the pie origin out) and the inner angle (Degrees from the pie start angle, clockwise). The first step is to inverse our angle since our trig functions assume that degrees increase counter-clockwise from the x axis. The .NET pie function works in the opposite way, with degrees increasing clockwise from the x axis. Next we convert the degrees into radians. Then calulate the absolute coordinates of the pie origin so we can transform the relative corrdinates returned by the trig functions. Next we do the math; the the cosine of the target radian multipled by the radius gives us the X coordinate and the sine of the same gives us the Y coordinate. We need to inverse the Y coordinate since the trig functions assume a grid with an ascending Y axis above the X axis and Windows is the oppisite; ascending Y axis below the X axis. Note: This method does not work for the default pie behavior. This method only works when angles are transformed to a 3d perspective. 

The Get3dPiePoint and support functions:

Private Function Get3dPiePoint(ByVal Bounds As System.Drawing.Rectangle, _
   ByVal Angle As Single, _
   ByVal SweepAngle As Single, _
   ByVal XRadius As Integer, ByVal YRadius As Integer, _
   ByVal InnerAngle As Single) As Point

   Dim MidRadian As Single = ToRadian(GetInverseAngle(Angle, InnerAngle))
   Dim TransformX As Integer = Bounds.X + (Bounds.Width / 2)
   Dim TransformY As Integer = Bounds.Y + (Bounds.Height / 2)

   Return New Point((Math.Cos(MidRadian) * XRadius) + TransformX, (Math.Sin(MidRadian) * YRadius * -1) + TransformY)

End Function

Private Function GetInverseAngle(ByVal StartAngle As Single, _
   ByVal InnerAngle As Single) As Single

   Return 360 - (StartAngle + InnerAngle)

End Function

Private Function ToRadian(ByVal Angle As Single) As Single

   Return (Math.PI * Angle) / 180

End Function

The following code snippet demonstrates how to draw a text label in the center of a 3d perspective pie slice.

Private Sub Form1_Paint(ByVal sender As Object, _
   ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

   Dim PieBounds As New Rectangle(20, 20, 400, 100)
   Dim PieAngle As Single = 150
   Dim PieSweepAngle As Single = 100
   Dim PieText As String = "Strongbadia (28%)"
   Dim PieTextFont As New Font("Arial", 10, FontStyle.Bold)
   Dim PieTextPoint As Point
   Dim PieTextXRadius As Single = PieBounds.Width / 4
   Dim PieTextYRadius As Single = PieBounds.Height / 4
   Dim PieTextAngle As Single = PieSweepAngle / 2
   Dim PieTextBounds As SizeF

   '--> Grab the centerline of the pie slice (Sweep angle div 2)
   '--> and half the radius (Diameter div 4)
   PieTextPoint = Get3dPiePoint(PieBounds, PieAngle, PieSweepAngle, PieTextXRadius, PieTextYRadius, PieTextAngle)

   '--> Grab the dimensions of the text
   PieTextBounds = e.Graphics.MeasureString(PieText, PieTextFont)

   '--> Determine the 3d angles
   PieSweepAngle = To3dSweepAngle(PieBounds, PieAngle, PieSweepAngle)
   PieAngle = To3dAngle(PieBounds, PieAngle)

   '--> Draw the pie
   e.Graphics.FillPie(Brushes.SteelBlue, PieBounds, PieAngle, PieSweepAngle)

   '--> Center the text over the mid point
   PieTextPoint.X -= PieTextBounds.Width / 2
   PieTextPoint.Y -= PieTextBounds.Height / 2

   '--> Draw the text
   e.Graphics.DrawString(PieText, PieTextFont, Brushes.White, PieTextPoint)

End Sub

Private Function To3dSweepAngle(ByVal Bounds As Rectangle, _
   ByVal Angle As Single, _
   ByVal SweepAngle As Single) As Single

   If SweepAngle Mod 180 <> 0 Then

      Dim Angle3d As Single = To3dAngle(Bounds, Angle)
      SweepAngle = To3dAngle(Bounds, Angle + SweepAngle) - Angle3d

   End If

   If SweepAngle < 0 Then

      SweepAngle += 360

   End If

   Return SweepAngle

End Function

Private Function To3dAngle(ByVal Bounds As System.Drawing.Rectangle, _
   ByVal Angle As Single) As Single

   Dim Radians As Single = ToRadian(Angle)
   Dim X As Double = Bounds.Width * Math.Cos(Radians)
   Dim Y As Double = Bounds.Height * Math.Sin(Radians)
   Dim Angle3D As Single = Math.Atan2(Y, X) * 180 / Math.PI

   If Angle3D < 0 Then

      Return Angle3D + 360

   Else

      Return Angle3D

   End If

End Function

 

Sunday, September 03, 2006 6:21:53 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Related posts:
“Parameter is not valid” when saving a Bitmap with EncoderParameters
Creating a 3d perspective pie slice
Gradient Pie Slices!
Adobe ImageStyler 1.0
Tracked by:
"Nice look" (Nice) [Trackback]
"Beatifully" (Hannah) [Trackback]
"Good news" (Matthew) [Trackback]
"Smile" (Emma) [Trackback]
"Beatifully" (Ethan) [Trackback]
"Beatifully" (Michael) [Trackback]
"Good news" (Christopher) [Trackback]
"Beatifully" (Samantha) [Trackback]
"Good news" (Anthony) [Trackback]
"Yep" (Isabella) [Trackback]
"Beatifully" (Hannah) [Trackback]
"Readed" (Emma) [Trackback]
"Readed" (Isabella) [Trackback]
"Nice" (Madison) [Trackback]
"Good news" (Andrew) [Trackback]
"Readed" (Samantha) [Trackback]
"Beatifully" (Matthew) [Trackback]
"Smile" (Hannah) [Trackback]
"Smile" (Jacob) [Trackback]
"Yep" (Daniel) [Trackback]
"Look good" (Ashley) [Trackback]
"Good news" (Joseph) [Trackback]
"Readed" (Samantha) [Trackback]
"Smile" (Jacob) [Trackback]
"Smile" (Matthew) [Trackback]
"Good news" (Emma) [Trackback]
"Beatifully" (Andrew) [Trackback]
"Readed" (Matthew) [Trackback]
"Good news" (Michael) [Trackback]
"Yep" (Christopher) [Trackback]
"Yep" (Andrew) [Trackback]
"Good news" (Joseph) [Trackback]
"Beatifully" (Ashley) [Trackback]
"Smile" (Samantha) [Trackback]
"Look good" (Samantha) [Trackback]
"Smile" (Matthew) [Trackback]
"Nice" (Hannah) [Trackback]
"Yep" (Daniel) [Trackback]
"Readed" (Emma) [Trackback]
"Beatifully" (Jacob) [Trackback]
"Nice" (Anthony) [Trackback]
"Readed" (Emma) [Trackback]
"Readed" (Andrew) [Trackback]
"Yep" (Joshua) [Trackback]
"Good news" (Samantha) [Trackback]
"Good news" (Hannah) [Trackback]
"Smile" (Hannah) [Trackback]
"Smile" (Matthew) [Trackback]
"Nice" (Emma) [Trackback]
"Yep" (Ethan) [Trackback]
"Nice" (Andrew) [Trackback]
"Nice" (Isabella) [Trackback]
"Beatifully" (Andrew) [Trackback]
"Nice" (Madison) [Trackback]
"Readed" (Samantha) [Trackback]
"Smile" (Matthew) [Trackback]
"Readed" (Michael) [Trackback]
"Smile" (Ashley) [Trackback]
"Look good" (Jacob) [Trackback]
"Good news" (Daniel) [Trackback]
"Readed" (Anthony) [Trackback]
"Yep" (Joseph) [Trackback]
"Beatifully" (Michael) [Trackback]
"Yep" (Matthew) [Trackback]
"Nice" (Olivia) [Trackback]
"Look good" (Abigail) [Trackback]
"Yep" (Ethan) [Trackback]
"Look good" (Ethan) [Trackback]
"Readed" (Jacob) [Trackback]
"Look good" (Matthew) [Trackback]
"Good news" (Abigail) [Trackback]
"Nice" (Ashley) [Trackback]
"Beatifully" (Madison) [Trackback]
"Beatifully" (Ashley) [Trackback]
"Good news" (Michael) [Trackback]
"Beatifully" (Hannah) [Trackback]
"Yep" (Andrew) [Trackback]
"Nice" (Joshua) [Trackback]
"Look good" (Emma) [Trackback]
"Readed" (Anthony) [Trackback]
"Beatifully" (Emma) [Trackback]
"Nice" (Madison) [Trackback]
"Nice" (Andrew) [Trackback]
"Nice" (Hannah) [Trackback]
"Yep" (Jacob) [Trackback]
"Yep" (Abigail) [Trackback]
"Nice" (Jacob) [Trackback]
"Nice" (Michael) [Trackback]
"Yep" (Hannah) [Trackback]
"Readed" (Anthony) [Trackback]
"Smile" (Ashley) [Trackback]
"Nice" (Joshua) [Trackback]
"Good news" (Matthew) [Trackback]
"Smile" (Daniel) [Trackback]
"Beatifully" (Abigail) [Trackback]
"Good news" (Matthew) [Trackback]
"Yep" (Andrew) [Trackback]
"Good news" (Jacob) [Trackback]
"Nice" (Anthony) [Trackback]
"Readed" (Isabella) [Trackback]
"Nice" (Joshua) [Trackback]
"Look good" (Matthew) [Trackback]
"Beatifully" (Christopher) [Trackback]
"Nice" (Ashley) [Trackback]

Comments are closed.