Title: Draw many circles that intersect two points in C#
As I mentioned in my earlier post Connect two points with elliptical arcs in C#, an infinite number of circles (or ellipses) can pass through two points. This example draws some of them to produce an interesting pattern.
This example only draws one kind of the circles that intersect two points. These circles have centers that lie along the perpendicular bisector of the line connecting the two points.
The following section explains the algorithm for finding these circles. The section after that shows the example program's circle-finding code.
The picture on the right shows the geometry of the situation.
In this picture, we have selected the two points A and B. To find a circle passing through the two points, follow these steps.
- Find the dashed green segment connecting points A and B.
- Find the midpoint M of the dashed green segment.
- Find a perpendicular bisector (the dashed blue segment) of the green segment passing through point M.
- Pick any point C on the perpendicular bisector. This is the center of the circle.
- Calculate the distance from point C to point A to get the radius of the circle.
(If you're particularly mathy, note that there are not only an infinite number of such circles, but there are uncountably many such circles. You can use any point on the blue dashed line as the circle's center and there are uncountably many points on a line. If you don't know what any of that means, don't worry about it.)
The following FindCircles method returns a list of RectangleF structures that define circles that intersect two given points.
// Find circles centered on a line perpendicular to the segment
// between the two points and that intersect those points.
private List<RectangleF> FindCircles(
PointF point1, PointF point2, int num_circles)
// Get a scaled vector between the two points.
float dx = point2.X - point1.X;
float dy = point2.Y - point1.Y;
float length = Distance(point1, point2);
const float scale = 10;
dx *= scale / length;
dy *= scale / length;
// Get the perpendicular vector.
float p1x = -dy;
float p1y = dx;
float p2x = dy;
float p2y = -dx;
// Find the center point.
float cx = (point1.X + point2.X) / 2f;
float cy = (point1.Y + point2.Y) / 2f;
// Generate circles.
List<RectangleF> rects = new List<RectangleF>();
for (int i = 0; i < num_circles; i++)
float new_cx = cx + i * p1x;
float new_cy = cy + i * p1y;
float radius = Distance(new PointF(new_cx, new_cy), point1);
new_cx - radius, new_cy - radius,
2 * radius, 2 * radius));
This method simply follows the algorithm described earlier. First it subtracts the two points' X and Y coordinates to get a vector <dx, dy> pointing from point2 to point1. It divides dx and dy by the length of the vector to get a vector with length 1.
For any vector <dx, dy>, the two vectors <dy, -dx> and <-dy, dx> are perpendicular to it. The method calculates those two vectors and saves them as <p1x, p1y> and <p2x, p2y>. (Although the program only uses the vector <p1x, p1y>.)
The method then averages the coordinates of points point1 and point2 to find the midpoint M = (cx, cy).
The code then loops through the desired number of circles. For each circle the loop adds the vector <p1x, p1y> times the circle number to the center point M to find the center of this circle. The program then calls the Distance helper method to find the distance from the new center to point1 and uses it as the circle's radius. The method uses the new circle's center point and radius to define its bounding rectangle and adds it to the rects list.
After it has found all of the circles, the method returns the rects list.
That's the only really interesting part of the program. Download the example to see the rest.
If you like, try making the program find another set of circles by using the other perpendicular vector <p2x, p2y>. See if you can figure out what those circles will look like first. Then try drawing them in green.
Download the example to experiment with it and to see additional details.