Title: Draw an interesting pattern of circles in C#
This program uses the following code to draw the circles and connecting lines.
// Draw the pattern.
private Bitmap DrawPattern(int wid, int hgt)
{
Bitmap bm = new Bitmap(wid, hgt);
using (Graphics gr = Graphics.FromImage(bm))
{
gr.SmoothingMode = SmoothingMode.AntiAlias;
float margin = 10;
float diameter1 = (hgt - margin) / 5f;
float diameter2 =
(wid - margin) / (float)(1 + 2 * Math.Sqrt(3));
float diameter = Math.Min(diameter1, diameter2);
float radius = diameter / 2f;
float cx = wid / 2f;
float cy = hgt / 2f;
// Find the center circle's center.
List<PointF> centers = new List<PointF>();
centers.Add(new PointF(cx, cy));
// Add the other circles.
for (int ring_num = 0; ring_num < 2; ring_num++)
{
float ring_radius = diameter * (ring_num + 1);
double theta = Math.PI / 2.0;
double dtheta = Math.PI / 3.0;
for (int i = 0; i < 6; i++)
{
double x = cx + ring_radius * Math.Cos(theta);
double y = cy + ring_radius * Math.Sin(theta);
centers.Add(new PointF((float)x, (float)y));
theta += dtheta;
}
}
// Fill and outline the circles.
foreach (PointF center in centers)
{
float x = center.X - radius;
float y = center.Y - radius;
gr.FillEllipse(Brushes.LightBlue, x, y,
diameter, diameter);
gr.DrawEllipse(Pens.Blue, x, y, diameter, diameter);
}
// Connect the circle centers.
int num_circles = centers.Count;
for (int i = 0; i < num_circles; i++)
{
for (int j = i + 1; j < num_circles; j++)
{
gr.DrawLine(Pens.Blue, centers[i], centers[j]);
}
}
}
return bm;
}
The code mainly does two interesting things while drawing the circles. First it determines how big it can make the circles while making the picture fit in the available area. Second it positions and draws the circles.
If you look at the picture above, you can see that the pattern contains five circles vertically. That means if the pattern is limited by the available vertical height, the diameter of the circles must be that height divided by 5. That's the value saved in variable diameter1 in the code.
It's a bit harder to figure out how big the circles can be if the pattern is limited by the available width. To see how that calculation works, consider the red triangle in the picture on the right. Its vertical edge has a length of three circle diameters. Because this is a 30-60-90 triangle, its horizontal edge must have length 1/Sqrt(3) times that long or 3/Sqrt(3) = Sqrt(3). The total width of the pattern is twice that plus one circle diameter.
The code uses that fact to set diameter2 to the available width (minus a margin) divided by 1 + Sqrt(3).
The code then uses the smaller of the two calculated diameters as the final diameter for the circles.
Next the program calculates the locations for the centers of the circles and adds them to the list centers. The first circle is in the center of the image at position (cx, cy).
To remaining circles are contained in two rings with their centers 1 and 2 diameters from the middle of the image. The program loops through the two ring numbers. For each ring, it calculates the distance from the center of the image to the circles in the ring.
For each ring the program makes the value theta start at π/2 and increment by π/3. That separates the ring's circles by 60 degree increments around a circle.
For each value of theta, the code uses simple trigonometry to find the locations of the centers of the circles.
The last part of the code simply draws the circles and lines. It loops through the circles and draws them. It the loops through all pairs of the circle centers and draws lines between them.
Download the example to experiment with it and to see additional details.
|