Draw arc in system.drawing C#

87 Views Asked by At

I have 2 points A(x1, y1) and B(x2, y2) on a circle and the angle between them alpha(example = 70 degree) I would like to find the center of the circle and radius I use System.Drawing namespace of C#

enter image description here

Please help me solve this problem.

1

There are 1 best solutions below

0
Olivier Jacot-Descombes On BEST ANSWER

Let's draw some lines: enter image description here

We have a right triangle with a hypotenuse R, an angle of 35° and an opposite side h. This results in the relation:

h / R = Sin(35°)

We can resolve by R:

R = h / Sin(35°)

h is the half distance between A and B. We can calculate it by using the Phytagorean theorem:

h = Sqrt((B.x - A.x)2 + (B.y - A.y)2) / 2

Note that MathF.Sin expects a argument given in radians. We can convert degrees to radians with:

radians = degrees / 180 * Math.Pi

The center is a bit more complicated. Idea: Take the midpoint M between A and B and move along the neighbor in the triangle.

Given h and R the length of the neighbor is (let's call it r)

r = Sqrt(R2 - h2)

Observation (with the center O):

(A.y - B.y) / (A.x - B.x) = -(M.x - O.x) / (M.y - O.y)

(I hope I got the signs right)

I.e.,

-(M.x - O.x) = (A.y - B.y) / d * r

and

(M.y - O.y) = (A.x - B.x) / d * r

Midpoint M:

M = ( (A.x + B.x) / 2, (A.y + B.y) / 2)

O.x = (A.x + B.x) / 2 - (A.y - B.y) / d * r
O.y = (A.y + B.y) / 2 + (A.x - B.x) / d * r

With C# and the following usings:

using System.Numerics;
using static System.MathF;

We can write:

/// <summary>
/// Calculates the center O and the radius R of a circle given two points A and B
/// on the circle and the center angle phi between the two radiuses to A and B.
/// </summary>
/// <param name="A">Some point on the circle</param>
/// <param name="B">Another point on the circle (A != B)</param>
/// <param name="phi">Center angle in degrees</param>
/// <returns>Center O and radius R as tuple (O, R)</returns>
public static (Vector2 O, float R) Center(Vector2 A, Vector2 B, float phi)
{
    phi = phi / 180 * PI;
    float d = (A - B).Length();
    float h = d / 2;
    float R = h / Sin(phi / 2);

    float r = Sqrt(Sqr(R) - Sqr(h));
    Vector2 M = (A + B) / 2;
    Vector2 O = new Vector2(M.X - (A.Y - B.Y) / d * r, M.Y + (A.X - B.X) / d * r);
    return (O, R);
}

static float Sqr(float x) => x * x;

Note that the Vector2 struct does some calculations for us, like calculating the distance AB.

Test:

public static void Test()
{
    Vector2 A = new(0, 0);
    Vector2 B = new(462, -84);
    float phi = 70f;
    Console.WriteLine($"A = ({A.X:n2}, {A.Y:n2}), B = ({B.X:n2}, {B.Y:n2}), phi = {phi}°");

    var (O, R) = Center(A, B, phi);
    Console.WriteLine($"O = ({O.X:n2}, {O.Y:n2})");
    Console.ReadKey();
}

Prints:

A = (0.00, 0.00), B = (462.00, -84.00), phi = 70°
O = (171.02, -371.90)

Note that the angle in your image is not 70°, so we cannot measure there to test if this is correct. Therefore, I have drawn this example on a piece of paper and measured the result. The function seems to work correctly.