Обычно эта задача решается через уравнения круга, но для программирования нужно аналитическое решение (в виде формулы).
Если решать систему уравнений, пытаясь выразить все неизвестные величины через 6 координат известных точек, то можно получить выражения для Xo, Yo и R.
Но вид этих выражений и их последующая реализация в виде программного кода — мягко говоря — не вдохновляют начинать эту работу.
К счастью, есть алгебраический метод, сводящийся к ряду несложных поэтапных расчетов, которые позволяют вычислить искомые неизвестные.
Ниже прилагаю реализацию этого подхода в виде функции на javascript.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// на входе функция ожидает массив Z // с тремя точками-объектами вида {x: координата X, y: координата Y} // на выходе получим X, Y, R - центр круга и его радиус function getCircle(Z) { var A = Z[1].x - Z[0].x; var B = Z[1].y - Z[0].y; var C = Z[2].x - Z[0].x; var D = Z[2].y - Z[0].y; var E = A * (Z[0].x + Z[1].x) + B * (Z[0].y + Z[1].y); var F = C * (Z[0].x + Z[2].x) + D * (Z[0].y + Z[2].y); var G = 2 * (A * (Z[2].y - Z[1].y) - B * (Z[2].x - Z[1].x)); if (G == 0) { // если точки лежат на одной линии, // или их координаты совпадают, // то окружность вписать не получится return []; } // координаты центра var Cx = (D * E - B * F) / G; var Cy = (A * F - C * E) / G; // радиус var R = Math.sqrt(Math.pow(Z[0].x - Cx, 2) + Math.pow(Z[0].y - Cy, 2)); // вернем параметры круга return [Cx, Cy, R]; } |
Для тех, кому сложно читать код, и нужна чистая математика, привожу алгоритм рассчета:
Даны точки X(x1, y1), Y(x2, y3), Z(x3,y3), принадлежащие окружности с радиусом R и центром U(Cx, Cy).
1 2 3 4 5 6 7 8 9 10 |
A = x2 - x1; B = y2 - y1; C = x3 - x1; D = y3 - y1; E = A * (x1 + x2) + B * (y1 + y2); F = C * (x1 + x3) + D * (y1 + y3); G = 2 * (A * (y3 - y2) - B * (x3 - x2)); Если G = 0, это значит, что через данный набор точек провести окружность нельзя. Cx = (D * E - B * F) / G; Cy = (A * F - C * E) / G; |
Ну и останется найти радиус — как расстояние между одной из данных точек и найденным центром окружности.
Алгебраический метод считает неправильно. Надо было посчитать: (-130;130)(200;200)(54.5;-336) дает неверный ответ (79,382;-54,014)
Алгебраический метод считает правильно. Точки надо нумеровать в порядке возрастания по часовой стрелке.
Алгебраический метод считает правильно независимо от порядка нумерования точек. Ищи ошибку у себя в расчетах.