геометрия — Использование стандартной формулы декартовой окружности для рисования окружности в графическом режиме (C ++)

Я хотел нарисовать круг, используя graphics.h в C ++, но не напрямую используя функцию circle (). Круг, который я хочу нарисовать, использует меньшие круги, так как это точки, т.е. Меньшие круги будут составлять окружность большего круга. Поэтому я подумал, что если бы я сделал что-то подобное, это сработало бы:

    {
int radius = 4;// Points at which smaller circles would be drawn
int x, y;int maxx = getmaxx();
int maxy = getmaxy();

// Co-ordinates of center of the larger circle (centre of the screen)
int h = maxx/2;
int k = maxy/2;

//Cartesian cirle formula >> (X-h)^2 + (Y-k)^2 = radius^2

//Effectively, this nested loop goes through every single coordinate on the screen

int gmode = DETECT;
int gdriver;

initgraph(&gmode, &gdriver, "");

for(x = 0; x<maxx; x++)
{
for(y = 0; y<maxy; y++)
{
if((((x-h)*(x-h)) + ((y-k)*(y-k))) == (radius*radius))
{
circle(x, y, 5) //Draw smaller circle with radius 5
}                   //at points which satisfy circle equation only!
}
}
getch();
}

Это когда я использую graphics.h на Turbo C ++ так как это тот компилятор, с которым мы учимся в школе.

Я знаю, что это древнее.

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

Однако, когда я пробую программу, я получаю четыре гиперболы (все они направлены к центру экрана), и когда я увеличиваю радиус, pointiness (из-за отсутствия лучшего слова) гипербол увеличиваются, пока, наконец, когда радиус равен 256 или более, две гиперболы в верхней и нижней части пересекаются, чтобы сделать большой крест на моем экране, как: «Вот оно, пользователь, я сдаюсь!»

Я пришел к значению 256, когда заметил, что из радиуса, кратного 4, цифры выглядели … лучше?

Я долго искал решение, но не мог получить никаких ответов, так что я здесь.

Какие-либо предложения???

РЕДАКТИРОВАТЬ >> Вот примерная схема вывода я получил …

Это грубый вывод

3

Решение

В вашем коде есть две проблемы:

Во-первых: вы должны действительно позвонить initgraph до ты звонишь getmaxx а также getmaxyиначе они не обязательно вернут правильные размеры графического режима. Это может или не может быть способствующим фактором в зависимости от вашей настройки.

Второе и самое главное: В Turbo C ++ int является 16-разрядным. Например, вот круг с радиусом 100 (после предыдущего initgraph проблема заказа была исправлена):

введите описание изображения здесь

Обратите внимание на беспризорные круги в четырех углах. Если мы сделаем небольшую отладку и добавим несколько распечаток (полезная стратегия, которую вы должны сохранить для дальнейшего использования):

if((((x-h)*(x-h)) + ((y-k)*(y-k))) == (radius*radius))
{
printf(": (%d-%d)^2 + (%d-%d)^2 = %d^2\n", x, h, y, k, radius);
circle(x, y, 5); //Draw smaller circle with radius
}                   //at points which satisfy circle equation only!

Вы можете видеть, что происходит (первая строка — maxx и maxy, не показанная в фрагменте выше):

введите описание изображения здесь

В частности, этот круг в (63, 139) является одним из углов. Если вы делаете математику, вы видите, что:

(63 — 319)2 + (139 — 239)2 = 75536

А поскольку ваши целые числа 16-битные, 75536 по модулю 65536 = 10000 = значение, которое в итоге будет рассчитано = 1002 = круг, где его не должно быть.

Простое решение этого состоит в том, чтобы просто изменить соответствующие переменные на long:

  • maxx, maxy
  • х, у
  • ч, к

Так:

long x, y;
...
initgraph(...);
...
long maxx = getmaxx();
long maxy = getmaxy();
...
long h = maxx / 2;
long k = maxy / 2;

И тогда вы получите правильный вывод:

введите описание изображения здесь

Обратите внимание конечно что нравится другие ответы указывают, так как вы используете целые, вы упустите много очков. Это может быть или не быть в порядке, но некоторые значения приведут к заметно худшим результатам (например, радиус 256, кажется, имеет только 4 целочисленных решения). Вы можете ввести толерантность, если хотите. Вы также можете использовать более прямой подход но это может победить цель вашего упражнения с формулой Декартова круга. Если вы в такой вещи, вот 24-страничный документ, содержащий кучу обсуждений, доказательств и свойств о целые числа, которые являются суммой двух квадратов.

Я не знаю достаточно о Turbo C ++, чтобы понять, можно ли использовать его для 32-битных целых, я оставлю это в качестве упражнения для вас.

4

Другие решения

Прежде всего, maxx и maxy являются целыми числами, которые вы инициализируете, используя некоторые функции, представляющие границы экрана, а затем позже используете их как функции. Просто удалите парантез:

    // Co-ordinates of center of the larger circle (centre of the screen)
int h = maxx/2;
int k = maxy/2;

Затем вы проверяете точное равенство, чтобы проверить, находится ли точка на окружности. Поскольку экран представляет собой сетку пикселей, многие ваши точки будут пропущены. Вам нужно добавить допуск, максимальное расстояние между проверяемой точкой и фактическим кругом. Так что измените эту строку:

if(((x-h)*(x-h)) + ((y-k)*(y-k)) == radius*radius)

к этому:

if(abs(((x-h)*(x-h)) + ((y-k)*(y-k)) - radius*radius) < 2)
1

Введение некоторого уровня толерантности решит проблему.

Но не стоит проверять все точки в графическом окне. Вы бы изменили подход? Вы можете нарисовать нужные маленькие кружки без чеков:

Заполнить всю окружность большого круга (с RBig радиус), вам нужно NCircles маленькие кружочки с RSmall радиус

NCircles = round to integer (Pi / ArcSin(RSmall / RBig));

Центр i-го малого круга находится в положении

cx = mx + Round(RBig * Cos(i * 2 * Pi / N));
cy = my + Round(RBig * Sin(i * 2 * Pi / N));

где mx, my — центр большого круга

1