This example shows how to draw a conic section from its polynomial equation. A previous series of posts explained how to find the intersection between two ellipses. See these posts for more information about that:

- See where two ellipses intersect in C#, Part 1
- See where two ellipses intersect in C#, Part 2
- See where two ellipses intersect in C#, Part 3
- See where two ellipses intersect in C#, Part 4

The method those articles described actually works for any conic section, not just ellipses, so I wanted to extend the method a bit. That begged two questions:

- How do you draw a general conic section?
- How do you let the user select a general conic section?

This post addresses the first of those questions.

The following equation defines any conic section (ellipse, parabola, or hyperbola):

If you group the y terms and plug their coefficients into the quadratic formula, you get the following equation giving y in terms of x:

The ± leads to two equations: one where you use the + sign and one where you use the – sign.

Depending on the type of conic section and its orientation, this can lead the following five situations:

The green curves show equations that use the positive roots and the red curves show equations that use negative roots.

When you enter a conic section’s parameters and click Graph, the program parses the values you entered and then uses the following `DrawConicSection` method to draw the curve.

// Draw the conic section. private void DrawConicSection(Graphics gr, float A, float B, float C, float D, float E, float F) { // Get the X coordinate bounds. float xmin = 0; float xmax = xmin + picGraph.ClientSize.Width; // Find the smallest X coordinate with a real value. for (float x = xmin; x < xmax; x++) { float y = G1(x, A, B, C, D, E, F, -1f); if (IsNumber(y)) { xmin = x; break; } } // Find the largest X coordinate with a real value. for (float x = xmax; x > xmin; x--) { float y = G1(x, A, B, C, D, E, F, -1f); if (IsNumber(y)) { xmax = x; break; } } // Get points for the negative root on the left. List<PointF> ln_points = new List<PointF>(); float xmid1 = xmax; for (float x = xmin; x < xmax; x++) { float y = G1(x, A, B, C, D, E, F, -1f); if (!IsNumber(y)) { xmid1 = x - 1; break; } ln_points.Add(new PointF(x, y)); } // Get points for the positive root on the left. List<PointF> lp_points = new List<PointF>(); for (float x = xmid1; x >= xmin; x--) { float y = G1(x, A, B, C, D, E, F, +1f); if (IsNumber(y)) lp_points.Add(new PointF(x, y)); } // Make the curves on the right if needed. List<PointF> rp_points = new List<PointF>(); List<PointF> rn_points = new List<PointF>(); float xmid2 = xmax; if (xmid1 < xmax) { // Get points for the positive root on the right. for (float x = xmax; x > xmid1; x--) { float y = G1(x, A, B, C, D, E, F, +1f); if (!IsNumber(y)) { xmid2 = x + 1; break; } rp_points.Add(new PointF(x, y)); } // Get points for the negative root on the right. for (float x = xmid2; x <= xmax; x++) { float y = G1(x, A, B, C, D, E, F, -1f); if (IsNumber(y)) rn_points.Add(new PointF(x, y)); } } // Connect curves if appropriate. // Connect the left curves on the left. if (xmin > 0) lp_points.Add(ln_points[0]); // Connect the left curves on the right. if (xmid1 < picGraph.ClientSize.Width) ln_points.Add(lp_points[0]); // Make sure we have the right curves. if (rp_points.Count > 0) { // Connect the right curves on the left. rp_points.Add(rn_points[0]); // Connect the right curves on the right. if (xmax < picGraph.ClientSize.Width) rn_points.Add(rp_points[0]); } // Draw the curves. using (Pen thick_pen = new Pen(Color.Red, 2)) { thick_pen.Color = Color.Red; if (ln_points.Count > 1) gr.DrawLines(thick_pen, ln_points.ToArray()); thick_pen.Color = Color.Green; if (lp_points.Count > 1) gr.DrawLines(thick_pen, lp_points.ToArray()); thick_pen.Color = Color.Blue; if (rp_points.Count > 1) gr.DrawLines(thick_pen, rp_points.ToArray()); thick_pen.Color = Color.Orange; if (rn_points.Count > 1) gr.DrawLines(thick_pen, rn_points.ToArray()); } }

The method starts by finding the smallest and largest X coordinate values within the `PictureBox` for which the function G_{1} is defined. For example, the ellipse’s equations are only defined within a limited range of X (and Y) coordinate values. (The curve doesn’t extend all the way to the left and right edges of the `PictureBox`.) The method finds the minimum defined X value by looping over values from 0 to the width of the `PictureBox` until it finds a defined value for G_{1}. It then finds the maximum defined X value by looping over values from the width of the `PictureBox` down to 0 until it finds a defined value for G_{1}.

Next the method loops over the function G_{1} for its positive and negative roots. First it loops over increasing X values starting at the value `xmin` and using the negative root. One of two things can happen.

First, the function G_{1} may be defined until x reaches the maximum X coordinate value `xmax`. This happens for the upward/downward opening hyperbola and the upward opening parabola. (It doesn’t happen for the downward opening parabola because that case uses the positive root in the function G_{1} and the code hasn’t gotten to that case yet.)

Second, the function G_{1} may be undefined for some x value. This happens for the ellipse and the left/right opening hyperbola. In this case, the code saves the X coordinate that gave the last defined value in variable `xmid1` and breaks out of the loop.

As the method loops over the X coordinates, it saves the function’s points in the list `ln_points` (“ln” stands for Left Negative).

The most instructive situation to think about is the case of the left/right opening hyperbola. In that case, `xmid1` gives the X coordinate for the rightmost point on the red curve on the left half of the hyperbola.

Having found the points for the negative root on the left of the curve, the method loops over X coordinate values starting at `xmid1` and decreasing to `xmin`, this time finding points with the positive root of G_{1}. This time the method saves the function’s points in the list `lp_points` (“lp” stands for Left Positive).

If the curve is an ellipse, upward/downward opening hyperbola, upward opening parabola, or downward opening parabola, the points captured so far cover the entire curve. The remaining case is the left/right opening hyperbola. In that case, `xmid1` is less than `xmax` and the method needs to find the right half of the curve.

The code uses the positive root of G_{1} while looping over X coordinates starting at `xmax` and decreasing until it finds an undefined value. It then loops back from that point to `xmax` recording points generated by using the negative root of G_{1}.

The image on the right shows the order in which the points are generated. The points are generated in this order:

- Negative root on the left as X increases
- Positive root on the left as X decreases
- Positive root on the right as X decreases
- Negative root on the right as X increases

Note that some of the point lists may be empty. For example, the upward opening parabola is defined only by the G_{1} with the negative root so the other four lists are empty.

There’s only one issue remaining: The lists holding points generated with positive and negative roots generally do not connect exactly. For example, consider the left/right opening hyperbola. The points generated with the positive and negative roots for the left side of the curve should connect, but unless the program got very lucky and evaluated the equation G_{1} at exactly the rightmost X coordinate for that part of the curve, there will be a small gap between the two pieces.

The next piece of the method connects any curves that should be connected. For example, if `xmin` is not at the very left edge of the `PictureBox`, then the positive and negative left curves should be connected at their left edges. To make that connection, the code adds the negative curve’s first point to the end of the positive curve’s points.

The code uses similar tests to connect the right sides of the left curves, the left sides of the right curves, and the right sides of the right curves.

Finally the method draws the points that define the curves, at least for the lists of points that are not empty.

Can you tell me the topics for kypv examination?

Sorry but I have no idea. You might try searching the internet for “kypv exam topics.”