помогите решить задачу на Си
Задан размер массива действительных чисел и значения его элементов. Считая, что пары элементов представляют собой координаты точек на плоскости, проверить, могут ли все данные точки лежать на одной окружности и, если да, найти ее радиус.
В программе количество точек и координаты должен вводить пользователь
Рекомендация от препода: Размер массива определяется исходя из условия индивидуального задания. В тех случаях, когда максимальный размер исходного массива не оговорен, полагать, что он равен 20.
вот код
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main() {
int n;
printf("Enter the number of points: ");
while ((scanf("%d", &n) != 1) || (n <= 0)) {
printf("Invalid input. Please enter a positive integer: ");
while (getchar() != '\n');
}
double x[n];
double y[n];
printf("Enter the coordinates of the points:\n");
for (int i = 0; i < n; i += 2) {
printf("Point %d: ", (i/2) + 1);
while (scanf("%lf %lf", &points[i], &points[i + 1]) != 2) {
printf("Invalid input. Please enter an integer: ");
while (getchar() != '\n');
}
}
double sum_x = 0, sum_y = 0;
for (int i = 0; i < 2 * n; i += 2) {
sum_x += points[i];
sum_y += points[i+1];
}
double center_x = sum_x / n;
double center_y = sum_y / n;
double radius = 0;
int S = 1;
double distances[n];
for (int i = 0; i < 2 * n; i += 2) {
distances[i / 2] = sqrt(pow(points[i] - center_x, 2) + pow(points[i + 1] - center_y, 2));
if (i == 0) {
radius = distances[0];
} else {
if (fabs(distances[i / 2] - radius) > 0) {
S = 0;
break;
}
}
}
if (S) {
printf("All points lie on the same circle.\n");
printf("Radius: %.2f\n", radius);
} else {
printf("The points do not lie on the same circle.\n");
}
system("pause");
return 0;
}
не понимаю как правильно расписать нахождение центра окружности, также преподаватель указал на то что неправильно объявлен массив, как можно это исправить?
Ответы (1 шт):
Нахождение центра окружности и её радиуса по 3 точкам.
Даны 3 точки: A(x1,y1), B(x2,y2) и C(x3,y3);
Пусть точка D(x0,y0) - центр окружности, а точки M(xm,ym) и N(xn,yn) - середины хорд AB и BC.
- В соответствие с теоремой о среднем перпендикуляре к хорде, линии DM и DN будут перпендикулярами.
- Запишем уравннение прямой AB: (x-x1) / (x2-x1) = (y-y1) / (y2-y1)
- Переходим от канонического уравнения прямой к уравнению с угловым коэффициентом (y = m_ab * x + b_ab): m_ab = (y2-y1) / (x2-x1); b_ab = y1 - x1(y2-y1)/(x2-x1)
- Соответственно, угловой коэффициент перпендикуляра DM к прямой AB будет равен: _m_ab = -1/m_ab = (x1-x2) / (y2-y1)
- Так же вычислим m_bc = (y3-y2) / (x3-x2) и _m_bc = (x2-x3) / (y3-y2)
- Запишем m_dm = (ym-y0) / (xm-x0); m_dn = (yn-y0) / (xn-x0)
- Составим систему { _m_ab = m_dm; _m_bc = m_dn }
- Получим: { y0 = (x1-x2)/(y2-y1) * x0 + ym - xm * (x1-x2)/(y2-y1); y0 = (x2-x3)/(y3-y2) * x0 + yn - xn * (x2-x3)/(y3-y2) }
- Пусть { y0 = am * x0 + dm; y0 = an * x0 + dn }
- Получим: x0 = (dn - dm) / (am - an); А y0 = am * x0 + dm, соответсвенно.
- Радиус равен дистанции между D и A; r = sqrt((x1-x0)^2 + (y1-y0)^2)
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void swap(double* a, double* b) {
double temp = *a;
*a = *b;
*b = temp;
}
bool has(double* beg, double* end, double x, double y) {
for(double* it = beg; it < end; it += 2)
if(*it == x && *(it + 1) == y)
return true;
return false;
}
double* scan(int* n) {
double x, y;
double *arr, *ptr;
printf("Enter the number of points: ");
scanf("%d", n);
while(*n < 3) {
printf("Wrong!!! Input must be greater or equal to 3!\nEnter the number of points: ");
scanf("%d", n);
}
arr = (double*) malloc((*n << 1) * sizeof(double));
ptr = arr;
printf("Enter the coordinates of the points:\n");
for(int i = 0; i < *n; ++i, ptr += 2) {
// Считываем x и y
printf("Point %d: ", i + 1);
scanf("%lf %lf", &x, &y);
// Проверка была ли точка уже введена
if(has(arr, ptr + 1, x, y)) {
printf("Point already exists! Input another one!\n");
ptr -= 2;
--i;
continue;
}
// Записываем точку в массива
*ptr = x;
*(ptr + 1) = y;
}
*n = *n << 1;
return arr;
}
// Проблема состоит в том, что иногда y2-y1 = 0 или y3-y2 = 0
// что приводит к x0 = NaN, y0 = NaN и r = NaN
// функция prep проходится по массиву и записывает в первые 6 ячеек
// массива значения которые не вызовут ошибок
void prep(double* arr, int n) {
for(int i = 2; i < 6; i += 2) {
if(arr[i - 1] != arr[i + 1]) { continue; }
for(int j = 0; j < n; j += 2) {
if(j == i || arr[i - 1] == arr[j + 1]) { continue; }
(void) swap(&arr[i], &arr[j]);
(void) swap(&arr[i + 1], &arr[j + 1]);
i = 2;
}
}
}
// По теореме Пифагора расстояние между двумя точками:
// dist = sqrt((xn - x0)^2 + (yn - y0)^2)
double dist(double x0, double y0, double xn, double yn) {
// Вычисляем (xn - x0)^2
xn -= x0; xn *= xn;
// Вычисляем (yn - y0)^2
yn -= y0; yn *= yn;
return sqrt(xn + yn);
}
void calc(double* arr, double* radius, double* x0, double* y0) {
double xm = (arr[0] + arr[2]) / 2;
double ym = (arr[1] + arr[3]) / 2;
double am = (arr[0] - arr[2]) / (arr[3] - arr[1]);
double dm = ym - xm * am;
double xn = (arr[2] + arr[4]) / 2;
double yn = (arr[3] + arr[5]) / 2;
double an = (arr[2] - arr[4]) / (arr[5] - arr[3]);
double dn = yn - xn * an;
*x0 = (dn - dm) / (am - an);
*y0 = am * (*x0) + dm;
*radius = dist(*x0, *y0, arr[0], arr[1]);
}
int main() {
int n;
double *arr;
double new_r, r, x0, y0;
arr = scan(&n);
(void) prep(arr, n);
(void) calc(arr, &r, &x0, &y0);
new_r = r;
for(int i = 6; i < n; i += 2) {
// Находим дистанцию от каждой новой точки до предполагаемого центра
new_r = dist(x0, y0, arr[i], arr[i + 1]);
// Если найденная дистанция не равна радиусу окружности
// значит данная точка не лежит на данной окружности
// выходим из цикла
if(new_r != r) { break; }
}
if(new_r == r) {
printf("All points are on the same circle!\n");
printf("Radius: %lf; Center: (%lf, %lf)\n", r, x0, y0);
}
else { printf("Not all points are on the same circle!\n"); }
free(arr);
return 0;
}
