2009-04-24

Circular Gauge chart with GdiPlusX

Drawing shapes with gdiplusx is super easy, and we can very easilly transport this to solve some of our chart needs.

Here we have a very primitive sample for creating circular gauge charts. Obviously I hope to apply the techniques shown here in FoxCharts. But FoxCharts is getting big, and I confess that learning from the methods in FoxCharts may not be easy for people that are not that familiar with GdiPlusX.

This is an unfinished sample. I'm posting it here to let people see that drawing is not that complicated. Just using some imagination, merging it with some geometrical thoughts, and voilá !



Download the gauge sample, unzip and run testgauge.scx ! I'm including the GdiplusX sources to let everybody immediately run the samples.

Notice that you can control the colors of the background and pointer.

The pointer shape can be modified too. Play with all the spinners to modify the shape and size!

Below is the relevant code for the circular gauge drawing. You'll find it in the "beforedraw()" event of the ImageCanvas class. It extracts the information from the form controls, and it's very easy to adapt it to your needs.




LOCAL lnangle, lnbasew, lnbasex, lnbasey, lntopw, lnheightpercent, lntopy
LOCAL lntype, lnpointclr, lnbackclr, lnticks
lnticks = Thisform.spnticks.VALUE
lntype = Thisform.optshape.VALUE
lnangle = Thisform.spnangle.VALUE
lnbasew = Thisform.spnbottomw.VALUE
lntopw = Thisform.spntopw.VALUE
lnbasex = This.WIDTH/2 -lnbasew/2
lnbasey = This.HEIGHT/2
lnheightpercent = Thisform.spnheight.VALUE / 100
lntopy = lnbasey - (lnbasey * lnheightpercent) + lntopw / 2
lnpointclr = Thisform.shppointercolor.BACKCOLOR
lnbackclr = Thisform.shpbackcolor.BACKCOLOR
LOCAL logfx AS xfcgraphics
logfx = This.ogfx

WITH _SCREEN.SYSTEM.drawing
 LOCAL lobrush AS xfcsolidbrush
 lobrush = .solidbrush.new(.COLOR.fromrgb(lnpointclr))

 logfx.CLEAR(.COLOR.fromrgb(Thisform.BACKCOLOR))

 * create a shape for the pointer
 LOCAL lopath AS xfcgraphicspath
 lopath = .drawing2d.graphicspath.new()
 lopath.startfigure()
 logfx.fillellipse(.solidbrush.new(.COLOR.fromrgb(lnbackclr)), ;
  This.rectangle)

 IF lntype = 1
  lopath.addarc(lnbasex, This.HEIGHT/2 -lnbasew/2, lnbasew, lnbasew, 0, 180)
 ENDIF

 lopath.ADDLINE(lnbasex, lnbasey, This.WIDTH/2 - lntopw/2, lntopy)
 IF lntype = 1
  LOCAL lapoints(3)
  lapoints(1) = .POINT.new(This.WIDTH/2 - lntopw/2, lntopy)
  lapoints(2) = .POINT.new(This.WIDTH/2 , lntopy - lntopw / 2)
  lapoints(3) = .POINT.new(This.WIDTH/2 + lntopw/2, lntopy)
  lopath.addcurve(@lapoints)
 ENDIF

 lopath.ADDLINE( This.WIDTH/2 + lntopw/2, lntopy, lnbasex + lnbasew, lnbasey)
 lopath.closefigure()

 * rotate the shape pointer
 logfx.translatetransform(This.WIDTH/2, This.HEIGHT/2)
 logfx.rotatetransform(lnangle)
 logfx.translatetransform(- This.WIDTH/2, - This.HEIGHT/2)

 * draw the pointer
 logfx.fillpath(lobrush, lopath)

 * restore the original gfx rotation state
 logfx.resettransform()

 IF lnticks > 0
  FOR lnangle = 0 TO 360 STEP 360 / lnticks

   * rotate the gfx
   logfx.translatetransform(This.WIDTH/2, This.HEIGHT/2)
   logfx.rotatetransform(lnangle)
   logfx.translatetransform(- This.WIDTH/2, - This.HEIGHT/2)

   * draw the ticks
   logfx.drawline(.pens.black, This.WIDTH/2, 0, This.WIDTH/2, 10)

   * restore the original gfx rotation state
   logfx.resettransform()
  ENDFOR
 ENDIF

ENDWITH




2 comments: