The example Simulate mosquito populations in C# simulates a mosquito population. This example draws a graph showing the population during each generation.

When it calculates the populations for a new generation, it stores them in the following lists.

// Data for the graph. private List<Point> FemalePoints, RegularMalePoints, ModifiedMalePoints;

The following code shows how the program saves the new values.

// Save points representing the new values. FemalePoints.Add( new Point(GenerationNumber, NumFemales)); RegularMalePoints.Add( new Point(GenerationNumber, NumRegularMales)); ModifiedMalePoints.Add( new Point(GenerationNumber, NumModifiedMales));

After calculating each generation, the program refreshes its `PictureBox` to make the following `Paint` event handler graph the population data. (This is the fun part.)

// Graph the data. private void picGraph_Paint(object sender, PaintEventArgs e) { e.Graphics.Clear(picGraph.BackColor); if (FemalePoints == null) return; if (FemalePoints.Count < 2) return; // Use the next multiple of 10 generations int num_generations = 10 * (1 + (int)((GenerationNumber - 1) / 10.0)); // Transform the graph. Rectangle source_rect = new Rectangle( 0, 0, num_generations, (int)PopulationLimit); Point[] dest_points = { new Point(0, picGraph.ClientSize.Height), new Point(picGraph.ClientSize.Width, picGraph.ClientSize.Height), new Point(0, 0), }; e.Graphics.Transform = new Matrix( source_rect, dest_points); using (Pen thin_pen = new Pen(Color.Gray, 0)) { // Draw lines to show the generations. for (int i = 1; i < num_generations; i++) { e.Graphics.DrawLine(thin_pen, i, 0, i, (int)PopulationLimit); } // Draw the population data. thin_pen.Color = Color.Red; e.Graphics.DrawLines(thin_pen, FemalePoints.ToArray()); thin_pen.Color = Color.Green; e.Graphics.DrawLines(thin_pen, RegularMalePoints.ToArray()); thin_pen.Color = Color.Blue; e.Graphics.DrawLines(thin_pen, ModifiedMalePoints.ToArray()); } }

This code starts by clearing the `PictureBox`. If the data doesn’t contain at least two generations of values, the event handler exits.

The graph draws multiples of 10 generations at a time. In other words, if there are between 0 and 10 generations, the program makes room on the graph for 10 generations. (Except it doesn’t draw anything if there are fewer than 2 generations.) If there are between 11 and 20 generations of data, it makes room for 20 generations. If there are between 21 and 30 generations of data, it makes room for 30 generations, and so on. This approach means the program doesn’t need to resize the graph with every generation, which would be pretty distracting.

To determine how much room it needs, the program calculates 10 * (1 + (int)((`GenerationNumber` – 1) / 10.0)) to determine the smallest multiple of 10 greater than or equal to the number of generations of data. This calculation subtracts 1 and divides by 10, truncates to an integer, adds 1, and multiplies by 10.

For example, suppose `GenerationNumber` is 21. Then 21 – 1 = 20. Dividing by 10 and truncating gives 2. Adding 1 gives 3. Finally multiplying by 10 gives 30. This is correct because 30 is the smallest multiple of 10 that is at least 21.

For another example, suppose `GenerationNumber` is 30. Then 30 – 1 = 29. Dividing by 10 and truncating gives 2. Adding the 1 gives 3. Finally multiplying by 10 gives 30. This is also correct because 30 is the smallest multiple of 10 that is at least 30.

After it has calculated the number of generations it should display, the program creates a transformation to map a convenient coordinate system onto the `PictureBox`. First it creates a `Rectangle` to represent the graphing coordinate system. The `Rectangle` covers the area 0 ≤ X < `num_generations` (where `num_generations` is the multiple of 10 just calculated) and 0 ≤ Y < `PopulationLimit` (the largest allowed population).

The program then creates an array of `Point` to map the corners of the `Rectangle` onto the `PictureBox`. The three `Points` indicate where on the `PictureBox` the `Rectangle`‘s upper left, upper right, and lower left corners should go.

Next the code uses the `Rectangle` and `Points` to make a matrix operation to map the coordinates, and sets the `Graphics` object’s `Transform` property to that `Matrix`.

Finally the code can start to draw. It first makes a `Pen` with 0 thickness. The `Graphics` object draws a `Pen` that has 0 thickness as thin as it can be drawn (1 pixel wide) even if a transformation would otherwise change its width.

The code uses a loop to draw vertical lines showing the visible generations. It then simply draws the points stored in the `FemalePoints`, `RegularMalePoints`, and `ModifiedMalePoints` lists.

See the code for additional details.