Graphs - fully configurable Pie Chart
Posted: Sat May 03, 2003 12:07 am
				
				Part two of the story "How do I create charts in PureBasic?"...  
 
This time its a fully configurable Pie-Chart...
 
Feel free to play around with the Init values. Chart is fully resizable and can be positioned on an (existing) image, is possible to include different number of sectors with different values, offers several color-styles and much more....
			This time its a fully configurable Pie-Chart...
Feel free to play around with the Init values. Chart is fully resizable and can be positioned on an (existing) image, is possible to include different number of sectors with different values, offers several color-styles and much more....
Code: Select all
; ****  Pie Chart - Diagram  ****
; Created: 1st/2nd May 2003 by Andre Beer / PureBasic-Team (www.purebasic.com)
; Many thanks to David "Tinman" McMinn for fixing the filling routine :-)
;-Init
ImW.w = 500        ; Width of diagram in pixel   \ in this case also the (inner) window
ImH.w = 350        ; Height of diagram in pixel  / dimensions....
MaxValue.w = 1000  ; Maximum individual value stored in the diagramm values
Graphs.w = 10      ; Number of sectors (graphs) in the diagram
Values.l = 1       ; Decide, if the relating sector values will be printed inside the descriptions box
                   ; 0 = print only the sector name (in this example: Part 1, Part 2, etc.)
                   ; 1 = print the sector name as well the relating value (in this example: Part 1 (Value1), Part 2 (Value2), etc.)
Color.l = 2        ; Number of color-style, currently included only three:
                   ; 0 = blue style
                   ; 1 = brown style
                   ; 2 = green style
;-Structures
Structure Diagram
  Value.l      ; Value
  Text.s       ; Description of the individual charts sectors
  Color.l      ; Color for filling the area of this sector
EndStructure 
Structure Style
  Front1.l   ; 1st foreground color  (main)
  Front2.l   ; 2nd foreground color  (lighter)
  Front3.l   ; 3rd foreground color  (darker)
  Back1.l    ; 1st background color  (lighter)
  Back2.l    ; 2nd background color  (darker)
  Bottom.l   ; Color of the bottom bar
  Title.l    ; Title color
  Text.l     ; Text color (axis descriptions)
EndStructure
; Init array  (item 0 is used for general settings, item 1 until Graphs+1 contains the diagram data
Dim Stats.Diagram(Graphs+1) 
;-ColorStyles
Dim Colors.Style(3)
; Set blue color-style
Colors(0)\Front1 = RGB(71,71,108)
Colors(0)\Front2 = RGB(140,140,183)
Colors(0)\Front3 = RGB(49,49,75)
Colors(0)\Back1  = RGB(201,211,233)
Colors(0)\Back2  = RGB(184,197,226)
Colors(0)\Bottom = RGB(255,255,255)
Colors(0)\Title  = RGB(0,0,255)
Colors(0)\Text   = RGB(0,0,0)
; Set red-brown color-style
Colors(1)\Front1 = RGB(108,71,71)
Colors(1)\Front2 = RGB(183,120,120)
Colors(1)\Front3 = RGB(75,49,49)
Colors(1)\Back1  = RGB(233,211,201)
Colors(1)\Back2  = RGB(226,197,184)
Colors(1)\Bottom = RGB(243,232,226)
Colors(1)\Title  = RGB(255,0,0)
Colors(1)\Text   = RGB(240,0,0)
; Set green color-style
Colors(2)\Front1 = RGB(71,108,71)
Colors(2)\Front2 = RGB(120,183,120)
Colors(2)\Front3 = RGB(49,75,49)
Colors(2)\Back1  = RGB(201,233,211)
Colors(2)\Back2  = RGB(184,226,197)
Colors(2)\Bottom = RGB(223,242,228)
Colors(2)\Title  = RGB(49,75,49)
Colors(2)\Text   = RGB(24,58,35)
;-Procedure
Procedure Pie(ID.l, Count.l, x.l, y.l, Width.l, Height.l, Color.l, Title.s) 
  ; ID     = Output-ID for drawing operations (e.g. WindowOutput, ImageOutput, etc.)
  ; Count  = Value-/Bars-number
  ; x, y   = top-left corner of the diagram in pixel
  ; Width  = Width of diagram in pixel
  ; Height = Height of diagram in pixel, including title line and text line
  ; Color  = number of color-style
  ; Title  = String with the text, which should be printed as title line
  ; Initial values
  #Pi.f = 3.141593
  #Resolution.f = 65     ; Resolution is the part used for the pie-chart in percent, the other part is used for the description on the right side
  #Border = 10           ; Border (in pixel) on left and right side of the pie-chart
  AngleStart.f = -#Pi    ; needed later for calculating the circle-parts
  AngleEnd.f = 0         ; defines where the drawing starts: 0 = right, #Pi = left, #Pi/2 = bottom, -#Pi/2 = top
  #TitleBar = 20         ; Height of the Title bar area
  #TitleFontHeight = 10  ; Font height of the Title text
  #TextFontHeight = 8    ; Font height of the Description text
  #White = 16777215      ; Set the value of RGB(255,255,255) to a white color constant
  
  ; Calculate initial chart values
  LeftWidth = Width * #Resolution / 100
  temp1.l = (LeftWidth - #Border - 5) / 2
  temp2.l = (Height - #TitleBar - 5) / 2
  If temp1 < temp2
    Radius.l = temp1
  Else
    Radius.l = temp2
  EndIf  
  MX.l = x + #Border + ((LeftWidth-#Border) / 2)
  MY.l = y + temp2 + #TitleBar
  ; Count the sum of all graphs value (=100%)
  For a=1 To Count
    Sum.l + Stats(a)\Value
  Next
  ; Load fonts
  FontID.l = LoadFont(1, "ARIAL", #TitleFontHeight, #PB_Font_Bold | #PB_Font_HighQuality)
  FontID2.l = LoadFont(1, "ARIAL", #TextFontHeight, #PB_Font_HighQuality)
  StartDrawing(ID) 
  
  ; Paint background  (used similar one as in Bars-Chart example, I was too lazy to create a new one  ;-)
  #Title   = 24
  #Bottom  = 15
  Box(x,y,Width,Height,Colors(Color)\Back1)                   ; paint lighter background fullsize
  Box(x,y,#Border,Height,Colors(Color)\Back2)                 ; paint darker bar at left 
  Box(x+Width-#Border,y,#Border,Height,Colors(Color)\Back2)   ; paint darker bar at right
  For a = y+25 To Height Step 50
    Box(x+#Border+1,a,Width-(2*#Border)-2,25)                 ; paint darker background bars
  Next a
  ; Paint title string
  FrontColor(Red(Colors(Color)\Title),Green(Colors(Color)\Title),Blue(Colors(Color)\Title))
  DrawingMode(1)     ; set drawing-mode to 1 for transparent text drawing
  DrawingFont(FontID)
  Locate(x+(Width-TextLength(Title))/2, y)
  DrawText(Title)
  FrontColor(0,0,0) 
  
  For id=1 To Count
    AngleStart = AngleEnd
    AngleEnd = AngleStart + (Stats(id)\Value * 2 * #Pi / Sum)
    ; Set black as default color for all border lines
    FrontColor(0,0,0)
       
    ; Draw the lines from inside the circle to the border
    LineXY(MX,MY,Cos(AngleStart)*(Radius+1)+MX,Sin(AngleStart)*(Radius+1)+MY)    ; note: Radius must be increases by 1 here,
    LineXY(MX,MY,Cos(AngleEnd)*(Radius+1)+MX,Sin(AngleEnd)*(Radius+1)+MY)        ; because otherwise sometimes misses a pixel
    ; Draw the circle     
    For a.l = AngleStart * Radius To AngleEnd * Radius  ;Step 2 
      px.l = Cos(a / Radius) * Radius + MX 
      py.l = Sin(a / Radius) * Radius + MY 
      Plot(px, py) 
    Next 
    
    ; Calc the coordinates for filling point and finally fill the selected area
    px = Cos((AngleEnd + AngleStart) / 2)*(Radius / 2) + MX
    py = Sin((AngleEnd + AngleStart) / 2)*(Radius / 2) + MY
    FillArea(px,py,0,Stats(id)\Color)
  Next  
  
  ; Now draw the descriptions on the right side
  #LineHeight = #TextFontHeight + 4
  #LineSpace = 5
  ; Find the widthest string
  For id=1 To Count
    temp1 = TextLength(Stats(id)\Text)
  Next
  temp1 + #LineHeight
  temp2 = (Width - LeftWidth - temp1) / 2
  If temp2 <=0 : temp2 = 0 : EndIf
  px = x + LeftWidth + temp2
  temp2 = (#LineHeight * Count) + (#LineSpace * (Count-1))
  py = y + #TitleBar + ((Height - temp2 - #TitleBar) / 2)  ; Image height decreased by needed height for the text descriptions
  DrawingFont(FontID2)
  ; paint white background box with black borders
  DrawingMode(0)
  Box(px-4,py-4,temp1,(#LineHeight+#LineSpace)*Count+4,#White)
  DrawingMode(4)
  Box(px-5,py-5,temp1+2,(#LineHeight+#LineSpace)*Count+5,0)
  Line(px-3+temp1,py-4,0,(#LineHeight+#LineSpace)*Count+5)
  Line(px-4,py+(#LineHeight+#LineSpace)*Count,temp1,0)
  ; paint the color boxes with relating description
  For id=1 To Count
    Box(px,py,#LineHeight,#LineHeight,0)
    DrawingMode(0)
    Box(px+1,py+1,#LineHeight-2,#LineHeight-2,Stats(id)\Color)
    DrawingMode(1)
    FrontColor(Red(Colors(Color)\Text),Green(Colors(Color)\Text),Blue(Colors(Color)\Text))
    Locate(px + #LineHeight + 4, py-1)
    DrawText(Stats(id)\Text)
    py + #LineHeight + #LineSpace
  Next
  
  StopDrawing() 
EndProcedure 
;- Diagram data
; Store some general values
Stats(0)\Value = MaxValue  ; value is relating to 100% diagram height, must correspond to (at least) the greatest individual value!!!
; Fill data array
For a=1 To Graphs
  ; Fill value
  Value = Random(MaxValue-1)+1       ; the values should be at least 2
  Stats(a)\Value = Value
  ; Fill x-Axis
  If Values=0
    Stats(a)\Text = "Part "+Str(a)
  Else
    Stats(a)\Text = "Part "+Str(a)+" ("+Str(Value)+")"
  EndIf
  ; Fill color
  Red   = Random(255)
  Green = Random(255)
  Blue  = Random(255)
  Stats(a)\Color = RGB(Red,Green,Blue)      ; currently here are used random colors, feel free to set your own's ;-)
Next a
; Set some fixed values instead of random numbers  (delete the ";" in front of the lines if wanted)
;Stats(1)\Value = 10
;Stats(2)\Value = 20
;Stats(3)\Value = 30
;-Main Programm 
OpenWindow(0,100,200,ImW,ImH,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Diagrams... ;-)    <written May 2003 by Andre Beer>") 
;-Create Image
If CreateImage(0,ImW,ImH)
  StartDrawing(ImageOutput())
  Box(0,0,ImW,ImH,$FFFFFF)
  StopDrawing()
Else
  Debug "Error when creating image..."
  End
EndIf
;-Call Diagram
; Parameters: OutputID, Elements, x, y, Width, Height, Colorstyle, Title-String
Pie(ImageOutput(), Graphs, 0, 0, ImW, ImH, Color, "Pie Chart Example")         
WinID.l = WindowID()
If CreateGadgetList(WinID)
  ImageGadget(0,2,2,300,220,ImageID())
EndIf
;- Main loop
Repeat 
   Event = WaitWindowEvent() 
   Select Event 
      Case #PB_EventCloseWindow 
         Quit = #True 
   EndSelect 
Until Quit 
End 
