Basic 2D pie charts for programmers
jeremybb
jeremy@bergsman.org
Function SimplePieChart(CenterX, CenterY, Radius, Values, Labels)
//Potentially useful demonstration function for the associated pie-chart functions
//Designed to create a pie chart at the given coordinates and size, from paired text and numeric waves containing the values and labels
//Values assumed to represent 100% of data
//Wedge "colors" limited to up to 5 shades of gray
//Some effort is spent to make the shading work out nicely for arbitrary numbers of wedges
//I have been using in the absolute coordinate system, may need some fixing to be coordinate-system agnostic
Variable CenterX, CenterY, Radius
Wave Values
Wave /T Labels
Variable Loop1, NumShades, Color, AltTags=.03, ArcMidPnt //AltTags value is the amount to space out a tag from the pie when it gets too crowded
Duplicate /O Values, Degrees
Integrate/P Values /D=Degrees
Degrees=Degrees*360/sum(Values)
if (numpnts(Values)<6)
NumShades=numpnts(Values)
AltTags=0
else
if (mod(numpnts(Values),5)!=1) //what's bad is if there is one left at the end, which would get the starting color
NumShades=5
else
if (mod(numpnts(Values),4)!=1)
NumShades=4
else
NumShades=3
endif
endif
endif
DrawWedge(CenterX, CenterY, 0, Degrees[0], Radius, 36000, 36000, 36000)
ArcMidPnt=Degrees[0]/2
LabelWedge("\Z08"+Labels[0], CenterX, CenterY, ArcMidPnt, Radius, AltTags*((Degrees[1]-Degrees[0])<30))
for (Loop1=0;Loop1<numpnts(Values)-1;Loop1+=1)
Color=36000+mod(Loop1+1,NumShades)*(24000/(NumShades-1))
DrawWedge(CenterX, CenterY, Degrees[Loop1], Degrees[Loop1+1], Radius, Color, Color, Color)
ArcMidPnt=(Degrees[Loop1]+Degrees[Loop1+1])/2
LabelWedge("\Z08"+Labels[Loop1+1], CenterX, CenterY, ArcMidPnt, Radius, AltTags*mod(Loop1,2)*((Degrees[Loop1+1]-Degrees[Loop1])<30))
endfor
End
Function DrawWedge(CenterX, CenterY, StartAngle, EndAngle, Radius, Red, Green, Blue)
//Draw a wedge with the given center position through the given angles
//Wedges have black line border and the given color
//Angles in degrees, Center and radius graph relative
//End Angle must be > Start Angle
Variable CenterX, CenterY, StartAngle, EndAngle, Radius, Red, Green, Blue
if (EndAngle-StartAngle>180)
SetDrawEnv fillfgc=(Red,Green,Blue), linethick=0
DrawPoly CenterX, CenterY, 1, 1, {0, 0, Radius*cos((StartAngle+180)*pi/180), Radius*sin((StartAngle+180)*pi/180), Radius*cos(EndAngle*pi/180), Radius*sin(EndAngle*pi/180), 0, 0}
SetDrawEnv fillfgc=(Red,Green,Blue)
DrawArc /X/Y CenterX, CenterY, Radius, StartAngle, StartAngle+180
SetDrawEnv fillfgc=(Red,Green,Blue)
DrawArc /X/Y CenterX, CenterY, Radius, StartAngle+180, EndAngle
else
SetDrawEnv fillfgc=(Red,Green,Blue), linethick=0
DrawPoly CenterX, CenterY, 1, 1, {0, 0, Radius*cos(StartAngle*pi/180), Radius*sin(StartAngle*pi/180), Radius*cos(EndAngle*pi/180), Radius*sin(EndAngle*pi/180), 0, 0}
SetDrawEnv fillfgc=(Red,Green,Blue)
DrawArc /X/Y CenterX, CenterY, Radius, StartAngle, EndAngle
endif
DrawLine CenterX, CenterY, CenterX+Radius*cos(StartAngle*pi/180), CenterY+Radius*sin(StartAngle*pi/180)
DrawLine CenterX, CenterY, CenterX+Radius*cos(EndAngle*pi/180), CenterY+Radius*sin(EndAngle*pi/180)
End
Function LabelWedge(LabelText, CenterX, CenterY, ArcMidPnt, Radius, Offset)
//Place a text label on a wedge.
//Location is coded using the same kind of variables as DrawWedge for convenience
//If Offset is non-zero, the label is placed at radius+offset, connected to the point at radius with a line
String LabelText
Variable CenterX, CenterY, ArcMidPnt, Radius, Offset
if (Offset>0)
DrawLine CenterX+Radius*cos(ArcMidPnt*pi/180), CenterY+Radius*sin(ArcMidPnt*pi/180), CenterX+(Offset+Radius)*cos(ArcMidPnt*pi/180), CenterY+(Offset+Radius)*sin(ArcMidPnt*pi/180)
Radius+=Offset
endif
if ((ArcMidPnt>0)&&(ArcMidPnt<=90)) //This could be improved by creating 4 more compass points for angles very near 0, 90...
TextBox /A=LT/B=1/E=2/F=0/X=(100*(CenterX+Radius*cos((ArcMidPnt)*pi/180)))/Y=(100*(CenterY+Radius*sin((ArcMidPnt)*pi/180))) LabelText
elseif ((ArcMidPnt>90)&&(ArcMidPnt<=180))
TextBox /A=RT/B=1/E=2/F=0/X=(100*(1-CenterX-Radius*cos((ArcMidPnt)*pi/180)))/Y=(100*(CenterY+Radius*sin((ArcMidPnt)*pi/180))) LabelText
elseif ((ArcMidPnt>180)&&(ArcMidPnt<=270))
TextBox /A=RB/B=1/E=2/F=0/X=(100*(1-CenterX-Radius*cos((ArcMidPnt)*pi/180)))/Y=(100*(1-CenterY-Radius*sin((ArcMidPnt)*pi/180))) LabelText
elseif ((ArcMidPnt>270)&&(ArcMidPnt<=360))
TextBox /A=LB/B=1/E=2/F=0/X=(100*(CenterX+Radius*cos((ArcMidPnt)*pi/180)))/Y=(100*(1-CenterY-Radius*sin((ArcMidPnt)*pi/180))) LabelText
endif
End
//Potentially useful demonstration function for the associated pie-chart functions
//Designed to create a pie chart at the given coordinates and size, from paired text and numeric waves containing the values and labels
//Values assumed to represent 100% of data
//Wedge "colors" limited to up to 5 shades of gray
//Some effort is spent to make the shading work out nicely for arbitrary numbers of wedges
//I have been using in the absolute coordinate system, may need some fixing to be coordinate-system agnostic
Variable CenterX, CenterY, Radius
Wave Values
Wave /T Labels
Variable Loop1, NumShades, Color, AltTags=.03, ArcMidPnt //AltTags value is the amount to space out a tag from the pie when it gets too crowded
Duplicate /O Values, Degrees
Integrate/P Values /D=Degrees
Degrees=Degrees*360/sum(Values)
if (numpnts(Values)<6)
NumShades=numpnts(Values)
AltTags=0
else
if (mod(numpnts(Values),5)!=1) //what's bad is if there is one left at the end, which would get the starting color
NumShades=5
else
if (mod(numpnts(Values),4)!=1)
NumShades=4
else
NumShades=3
endif
endif
endif
DrawWedge(CenterX, CenterY, 0, Degrees[0], Radius, 36000, 36000, 36000)
ArcMidPnt=Degrees[0]/2
LabelWedge("\Z08"+Labels[0], CenterX, CenterY, ArcMidPnt, Radius, AltTags*((Degrees[1]-Degrees[0])<30))
for (Loop1=0;Loop1<numpnts(Values)-1;Loop1+=1)
Color=36000+mod(Loop1+1,NumShades)*(24000/(NumShades-1))
DrawWedge(CenterX, CenterY, Degrees[Loop1], Degrees[Loop1+1], Radius, Color, Color, Color)
ArcMidPnt=(Degrees[Loop1]+Degrees[Loop1+1])/2
LabelWedge("\Z08"+Labels[Loop1+1], CenterX, CenterY, ArcMidPnt, Radius, AltTags*mod(Loop1,2)*((Degrees[Loop1+1]-Degrees[Loop1])<30))
endfor
End
Function DrawWedge(CenterX, CenterY, StartAngle, EndAngle, Radius, Red, Green, Blue)
//Draw a wedge with the given center position through the given angles
//Wedges have black line border and the given color
//Angles in degrees, Center and radius graph relative
//End Angle must be > Start Angle
Variable CenterX, CenterY, StartAngle, EndAngle, Radius, Red, Green, Blue
if (EndAngle-StartAngle>180)
SetDrawEnv fillfgc=(Red,Green,Blue), linethick=0
DrawPoly CenterX, CenterY, 1, 1, {0, 0, Radius*cos((StartAngle+180)*pi/180), Radius*sin((StartAngle+180)*pi/180), Radius*cos(EndAngle*pi/180), Radius*sin(EndAngle*pi/180), 0, 0}
SetDrawEnv fillfgc=(Red,Green,Blue)
DrawArc /X/Y CenterX, CenterY, Radius, StartAngle, StartAngle+180
SetDrawEnv fillfgc=(Red,Green,Blue)
DrawArc /X/Y CenterX, CenterY, Radius, StartAngle+180, EndAngle
else
SetDrawEnv fillfgc=(Red,Green,Blue), linethick=0
DrawPoly CenterX, CenterY, 1, 1, {0, 0, Radius*cos(StartAngle*pi/180), Radius*sin(StartAngle*pi/180), Radius*cos(EndAngle*pi/180), Radius*sin(EndAngle*pi/180), 0, 0}
SetDrawEnv fillfgc=(Red,Green,Blue)
DrawArc /X/Y CenterX, CenterY, Radius, StartAngle, EndAngle
endif
DrawLine CenterX, CenterY, CenterX+Radius*cos(StartAngle*pi/180), CenterY+Radius*sin(StartAngle*pi/180)
DrawLine CenterX, CenterY, CenterX+Radius*cos(EndAngle*pi/180), CenterY+Radius*sin(EndAngle*pi/180)
End
Function LabelWedge(LabelText, CenterX, CenterY, ArcMidPnt, Radius, Offset)
//Place a text label on a wedge.
//Location is coded using the same kind of variables as DrawWedge for convenience
//If Offset is non-zero, the label is placed at radius+offset, connected to the point at radius with a line
String LabelText
Variable CenterX, CenterY, ArcMidPnt, Radius, Offset
if (Offset>0)
DrawLine CenterX+Radius*cos(ArcMidPnt*pi/180), CenterY+Radius*sin(ArcMidPnt*pi/180), CenterX+(Offset+Radius)*cos(ArcMidPnt*pi/180), CenterY+(Offset+Radius)*sin(ArcMidPnt*pi/180)
Radius+=Offset
endif
if ((ArcMidPnt>0)&&(ArcMidPnt<=90)) //This could be improved by creating 4 more compass points for angles very near 0, 90...
TextBox /A=LT/B=1/E=2/F=0/X=(100*(CenterX+Radius*cos((ArcMidPnt)*pi/180)))/Y=(100*(CenterY+Radius*sin((ArcMidPnt)*pi/180))) LabelText
elseif ((ArcMidPnt>90)&&(ArcMidPnt<=180))
TextBox /A=RT/B=1/E=2/F=0/X=(100*(1-CenterX-Radius*cos((ArcMidPnt)*pi/180)))/Y=(100*(CenterY+Radius*sin((ArcMidPnt)*pi/180))) LabelText
elseif ((ArcMidPnt>180)&&(ArcMidPnt<=270))
TextBox /A=RB/B=1/E=2/F=0/X=(100*(1-CenterX-Radius*cos((ArcMidPnt)*pi/180)))/Y=(100*(1-CenterY-Radius*sin((ArcMidPnt)*pi/180))) LabelText
elseif ((ArcMidPnt>270)&&(ArcMidPnt<=360))
TextBox /A=LB/B=1/E=2/F=0/X=(100*(CenterX+Radius*cos((ArcMidPnt)*pi/180)))/Y=(100*(1-CenterY-Radius*sin((ArcMidPnt)*pi/180))) LabelText
endif
End
Forum
Support
Gallery
Igor Pro 9
Learn More
Igor XOP Toolkit
Learn More
Igor NIDAQ Tools MX
Learn More