Построить треугольник, описать и вписать окружность на C#
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# и геометрии.
Автор: Евтеев Евгений Александрович
Email: evteev_e2003@mail.ru