Index Books FAQ Contact About Rod

# Title: Draw rating stars in C#

I recently rebuilt some book review posts and wanted to display rating stars. I looked around the internet and didn't find any that were quite what I wanted, so I decided to make this program. It's main requirements were to:

• Draw five rating stars
• Fill in between zero and five of the rating stars
• Have transparent background
• Save the results in PNG files (to preserve the transparent background)

I figured I would adjust the colors if necessary by modifying the code.

Enter the height that you want the stars to have and the number of stars that should be filled in. Then click Draw to draw the stars. The program saves the result in a file named after the number of stars as in 5stars.png.

# Geometry

Before I show you the code, it may help to understand the geometry of a five-pointed star. Take a look at Figure 1.

Let's call the distance from the star's center to one of it's points r.

Angle α is simply π / 5 = 72°.

Then β equals 90° - α = 18°.

Next γ equals α° - β = 72° - 18° = 54.

Now that we understand those angles, we can calculate the star's dimensions. You can see from Figure 1 that A = r cos(β) and B = r sin(γ).

We can use those values to calculate the star's dimensions.

width = 2 * A height = r + B = r + r sin(γ) = r * (1 + sin(γ))

With that geometry out of the way, it's time to look at the code.

# Code

This example uses the MakeStarPoints method described in the post Draw a star with a given number of points in C# to generate the points that define a star. See that post for details. (Figure 1 should help you understand that post.)

When you click Draw, the progam uses the following code to draw the stars.

private void btnDraw_Click(object sender, EventArgs e) { int num_filled = int.Parse(txtNumFilled.Text); int star_height = int.Parse(txtHeight.Text); double r = star_height / (1 + Math.Sin(ToRadians(54))); double star_width = 2 * r * Math.Cos(ToRadians(18)); double margin = star_width * 0.1; double x = margin; double ymin = margin; Rectangle rect = new Rectangle( (int)x, (int)ymin, (int)(2 * r), (int)(2 * r)); int bm_width = (int)(5 * star_width + 6 * margin); int bm_height = (int)(star_height + 2 * margin); Bitmap bm = new Bitmap(bm_width, bm_height); using (Graphics gr = Graphics.FromImage(bm)) { gr.Clear(Color.Transparent); gr.SmoothingMode = SmoothingMode.AntiAlias; //gr.DrawRectangle(Pens.Blue, rect); for (int i = 0; i < 5; i++) { PointF[] points = MakeStarPoints(-Math.PI / 2, 5, 2, rect); if (i < num_filled) gr.FillPolygon(Brushes.Yellow, points); else gr.FillPolygon(Brushes.White, points); gr.DrawPolygon(Pens.Black, points); x += star_width + margin; rect.X = (int)x; } } picStars.Image = bm; picStars.Visible = true; string filename = num_filled.ToString() + "stars.png"; SaveImage(bm, filename); }

The code first gets the values that you entered for the number of stars that should be filled and the height of the stars.

If you want the stars to have height star_height, then we can use the formula for height shown earlier and solve for r.

r = star_height / (1 + sin(γ)) = star_height / (1 + Math.Sin(ToRadians(54)))

Now that we know r, we can use it to calculate the star's width.

star_width = 2 * A = 2 * r * cos(β) = 2 * r * Math.Cos(ToRadians(18))

The code then sets a margin value to 0.2 times the star's width.

Having calculated those dimensions, the program can start drawing. First it creates a rectangle to define the area where the first star should be drawn. This rectangle is sized to a circle drawn inside it would touch the star's corners. (That's the rectangle that is needed by the MakeStarPoints method described in the earlier post. It is positioned so it's upper left corner is margin pixels from (0, 0), which is the upper left corner of the bitmap that the method makes shortly.

Next, the code creates a bitmap large enough to hold five stars plus margins around the edges and a margin between each jpair of adjacent stars. It clears the bitmap to give it a transparent background and sets the bitmap's smoothing mode.

Now the code loops through the star numbers 0 through 4. For each number, the code calls MakeStarPoints to get the points needed to draw the star inside the rectangle. It fills the star it if the star's number is less than the desired number of filled stars and then outlines the star. The code then adds the width of a star plus the margin to the rectangle's X coordinate to move the rectangle to the right. It then continues the loop to draw the next sar.

After it has finished drawing the stars, the code displays the bitmap in the picStars PictureBox and makes that control visible. It finishes by saving the bitmap into a PNG file.

This example is good enough for what I wanted, but there are many enhancements that you could make. Obviously you could change the colors. You could also change the way stars are filled to give them shading or a three-dimensional appearance. You could also fill some stars fractionally so, for example, you could give a rating of 3.7 stars.