Построить треугольник, описать и вписать окружность на C#

29 ноября 2009

В статье мы займемся рисованием, рисовать будем треугольник, вписанную и описанную окружность. Конечно, рисовать будет программа, код которой мы сейчас напишем.

Координаты вершин треугольника будут находиться в структуре “Pt”. Для этого создадим переменные для работы со структурой и саму структуру.

Pt m1, m2, v1, v2, b1, b2;
public struct Pt
{
	double x;
	double y;
	public Pt(double a, double b)
	{
		x = a;
		y = b;
	}
	public double X
	{
		get { return x; }
		set { x = value; }
	}
	public double Y
	{
		get { return y; }
		set { y = value; }
	}
};

Далее напишем функции для вычисления длин, углов треугольника и т.д. и процедуру для вывода графики на форму.
Пишем функцию нахождения длины строны треугольника по заданным координатам. Будем использовать формулу нахождения расстояния между двумя точками.
S = ((x2 - x1) ^2+ (y2-y1) ^2) ^ (1/2), где (x1, y1) и (x2, y2) - это координаты начала и конца отрезка.

double SideLength(double x1, double y1, double x2, double y2)
{
	double a = Math.Sqrt((x2 - x1) / 10 * (x2 - x1) / 10 + (y2 - y1) / 10 * (y2 - y1) / 10);
	return a * 10;
}

Чтобы найти углы треугольника воспользуемся формулой скалярного произведения векторов
cos(ang) = a/(s1*s2), где a - скалярное произведение векторов s1 и s2,а s1 и s2 - стороны треугольника (абсолютные величины векторов).

double Angles(Pt p1, Pt p2, Pt p3)
{
	double a = (p2.X - p1.X) * (p3.X - p1.X) + (p2.Y - p1.Y) * (p3.Y - p1.Y);
	double exp = a / SideLength(p1.X, p1.Y, p2.X, p2.Y) / SideLength(p1.X, p1.Y, p3.X, p3.Y);
	return Math.Acos(exp);
}

Периметр находим как сумма длин трех сторон треугольника.

double Perimetr(double s1, double s2, double s3)
{
	return (s1 + s2 + s3);
}

Площадь треугольника находится с помощью формулы Герона:

Sqr = (p * (p - s1) * (p - s2) * (p - s3)) ^ (1 / 2), где p - полупериметр треугольника.
double Sqare(double s1, double s2, double s3)
{
	double p;
	p = (Perimetr(s1, s2, s3)) / 2;
	return Math.Sqrt((p * (p - s1) * (p - s2) * (p - s3)));
}

Теперь найдем радиусы вписанной и описанной окружности.

double radius(double S, double p)
{
	return S / p;
}

double Radius(double S, double s1, double s2, double s3)
{
	return (s1 * s2 * s3) / (4 * S);
}

И, наконец, процедура, которая будет осуществлять конечные вычисления, и рисовать окружность на форме программы.

void DescrCircle(double R, int x01, int y01, int x02, int y02, double l1, double m1, double l2, double m2)
{
	double X, Y;
	if ((l1 != 0) && ((m1 / l1) - (m2 / l2) != 0) && (l2 != 0))
	{
		X = ((m1 / l1) * x01 - y01 - (m2 / l2) * x02 + y02) / ((m1 / l1) - (m2 / l2));
		Y = (m1 * X - m1 * x01 + l1 * y01) / l1;
		System.Drawing.Graphics graph = this.CreateGraphics();
		System.Drawing.Pen color = new Pen(Color.Blue, 1);
		graph.DrawEllipse(color, (int)X, (int)Y, 1, 1); //рисуем центр окружности
		graph.DrawEllipse(color, (int)X - (float)R, (int)Y - (float)R, (float)R * 2, (float)R * 2); //рисуем окружность
	}
}

Процедура кнопки, которая будет вызывать всю процедуру рисования треугольника и окружностей.

private void button1_Click_1(object sender, EventArgs e)

Объявим нужные переменные и занесем в структуру координаты вершин треугольника из текстовых полей на форме.

double s1 ,s2 ,s3 ,S ,p ,r, R, ang1, ang2, ang3, x1, x2, y1, y2, det;
znach.Items.Clear();

Pt[] a = new Pt[3];
a[0].X = Convert.ToDouble(Ax.Text);
a[0].Y = Convert.ToDouble(Ay.Text);
a[1].X = Convert.ToDouble(Bx.Text);
a[1].Y = Convert.ToDouble(By.Text);
a[2].X = Convert.ToDouble(Cx.Text);
a[2].Y = Convert.ToDouble(Cy.Text);

Нарисуем форме три линии, которые будут составлять наш треугольник и названия вершин A, B и C.

System.Drawing.Graphics graph = this.CreateGraphics();
System.Drawing.Pen red = new Pen(Color.Red, 1);

graph.DrawLine(red, (int)a[0].X, (int)a[0].Y, (int)a[1].X, (int)a[1].Y);
graph.DrawString("A", new Font("Times New Roman", 12), new SolidBrush(Color.Black), (int)a[0].X, (int)a[0].Y);
graph.DrawLine(red, (int)a[1].X, (int)a[1].Y, (int)a[2].X, (int)a[2].Y);
graph.DrawString("B", new Font("Times New Roman", 12), new SolidBrush(Color.Black), (int)a[1].X, (int)a[1].Y);
graph.DrawLine(red, (int)a[0].X, (int)a[0].Y, (int)a[2].X, (int)a[2].Y);
graph.DrawString("C", new Font("Times New Roman", 12), new SolidBrush(Color.Black), (int)a[2].X, (int)a[2].Y);

Используя написанные функции, найдем длины сторон, полупериметр, площадь, радиусы вписанной и описанной окружности и углы треугольника.

s1 = SideLength(a[0].X, a[0].Y, a[1].X, a[1].Y);
s2 = SideLength(a[1].X, a[1].Y, a[2].X, a[2].Y);
s3 = SideLength(a[2].X, a[2].Y, a[0].X, a[0].Y);

p = (Perimetr(s1, s2, s3)) / 2;
S = Sqare(s1, s2, s3);

r = radius(S, p);
R = Radius(S, s1, s2, s3);

ang1 = Angles(a[2], a[0], a[1]);
ang2 = Angles(a[0], a[1], a[2]);
ang3 = Angles(a[1], a[2], a[0]);

Выведем на форму все эти вычисленные значения в ListBox “znach”.

znach.Items.Add("Длина AB: " + s1);
znach.Items.Add("Длина BC: " + s2);
znach.Items.Add("Длина AC: " + s3);
znach.Items.Add("Полупериметр: " + p);
znach.Items.Add("Площадь: " + S);
znach.Items.Add("Радиус вписанной о.: " + r);
znach.Items.Add("Радиус описанной о.: " + R);
znach.Items.Add("Угл CAB: " + ang1);
znach.Items.Add("Угл ABC: " + ang2);
znach.Items.Add("Угл BCA: " + ang3);

Найдем середины сторон s1 и s2.

m1.X = (a[0].X + a[1].X) / 2;
m1.Y = (a[0].Y + a[1].Y) / 2;
m2.X = (a[1].X + a[2].X) / 2;
m2.Y = (a[1].Y + a[2].Y) / 2;

Необходимо повернуть точки на угол 90 градусов.
Поворачиваем точку а[2] вокруг середины стороны:

 x1 = a[2].X; y1 = a[2].Y;
x1 -= m2.X; y1 -= m2.Y;
b1.X = x1 * Math.Cos(Math.PI / 2) - y1 * Math.Sin(Math.PI / 2);
b1.Y = x1 * Math.Sin(Math.PI / 2) + y1 * Math.Cos(Math.PI / 2);
b1.X += m2.X; b1.Y += m2.Y;
v1.X = b1.X - m2.X; v1.Y = b1.Y - m2.Y;

Поворачиваем точку а[0] вокруг середины стороны s1:

x1 = a[0].X; y1 = a[0].Y;
x1 -= m1.X; y1 -= m1.Y;
b2.X = x1 * Math.Cos(Math.PI / 2) - y1 * Math.Sin(Math.PI / 2);
b2.Y = x1 * Math.Sin(Math.PI / 2) + y1 * Math.Cos(Math.PI / 2);
b2.X += m1.X; b2.Y += m1.Y;
v2.X = b2.X - m1.X; v2.Y = b2.Y - m1.Y;

Вызовем нашу процедуру для вывода графики и построим описанную окружность с центром в точке пересечения серединных перепендикуляров.

DescrCircle(R, (int)m1.X, (int)m1.Y, (int)m2.X, (int)m2.Y, v2.X, v2.Y, v1.X, v1.Y);

int coef1 = 1, coef2 = 1; //коэффициенты,указывающие напрвление поворота
Вычисляем знак третьей координаты векторного произведения векторов, между которыми строится биссектриса.

det = (a[1].X - a[0].X) * (a[2].Y - a[0].Y) - (a[2].X - a[0].X) * (a[1].Y - a[0].Y);
if (det > 0) coef1 = -1;
	det = (a[1].X - a[2].X) * (a[0].Y - a[2].Y) - (a[0].X - a[2].X) * (a[1].Y - a[2].Y);
if (det > 0)
	coef2 = -1;

Поворачиваем точку a[2] вокруг a[0] на угол равный половине угла ang2

x1 = a[2].X; y1 = a[2].Y;
x1 -= a[0].X; y1 -= a[0].Y;
b1.X = x1 * Math.Cos(coef1 * ang2 / 2) - y1 * Math.Sin(coef1 * ang2 / 2);
b1.Y = x1 * Math.Sin(coef1 * ang2 / 2) + y1 * Math.Cos(coef1 * ang2 / 2);
b1.X += a[0].X; b1.Y += a[0].Y;
v1.X = b1.X - a[0].X; v1.Y = b1.Y - a[0].Y;

x2 = a[0].X; y2 = a[0].Y;
x2 -= a[2].X; y2 -= a[2].Y;
b2.X = x2 * Math.Cos(coef2 * ang1 / 2) - y2 * Math.Sin(coef2 * ang1 / 2);
b2.Y = x2 * Math.Sin(coef2 * ang1 / 2) + y2 * Math.Cos(coef2 * ang1 / 2);
b2.X += a[2].X; b2.Y += a[2].Y;
v2.X = b2.X - a[2].X; v2.Y = b2.Y - a[2].Y; //v1.x v1.y- координаты направляющего вектора биссектрисы

И последнее, что мы делаем это выполняем построение вписанной окружности с центром в точке пересечения биссектрисс.

DescrCircle(r, (int)a[2].X, (int)a[2].Y, (int)a[0].X, (int)a[0].Y, v2.X, v2.Y, v1.X, v1.Y);
Построить треугольник, описать и вписать окружность

Построить треугольник, описать и вписать окружность

Треугольник и две окружности построены, для решения этой задачи нам понадобились небольшие знания C# и геометрии.
Автор: Евтеев Евгений Александрович