使用标准笛卡尔圆公式在图形模式下绘制圆(C ++)

时间:2016-10-11 05:24:46

标签: c++ geometry turbo-c++ cartesian-coordinates bgi

我想在C ++中使用graphics.h绘制一个圆,但不是直接使用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();
    }

这是我在Turbo C ++上使用graphics.h的时候,因为这是我们在学校学习的编译器。

我知道这很古老。

所以,理论上,由于嵌套for循环检查屏幕上的所有点,并在每个满足圆方程的点上画一个小圆圈,我想我会得到一个大圆半径,输入的圆周构成我在for循环中制作的较小圆圈。

然而,当我尝试该程序时,我得到四个双曲线(都指向屏幕的中心),当我增加半径时, pointiness (缺少一个更好的词)双曲线增加,直到最后,当半径为256或更大时,顶部和底部的两个双曲线相交,在我的屏幕上形成一个大十字架,如:“就是这样,用户,我放弃!”

我达到值256,因为我注意到半径是4的倍数看起来......更好?

我在很长一段时间内寻找解决方案,但无法得到任何答案,所以我在这里。

任何建议???

编辑&gt;&gt;这是我得到的输出的粗略图表......

This is the rough output

3 个答案:

答案 0 :(得分:4)

您的代码中存在两个问题:

首先:您应该在调用initgraphgetmaxx之前致电getmaxy ,否则他们不一定会返回图形模式的正确尺寸。根据您的设置,这可能是也可能不是影响因素。

其次,最重要的是:在Turbo C ++中,int是16位。例如,这里是半径为100的圆(在上一个initgraph订单问题修复之后):

enter image description here

注意四个角落的杂散圆圈。如果我们做一些调试并添加一些打印输出(一个有用的策略,你应该提交以备将来参考):

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,未在上面的代码段中显示):

enter image description here

特别是(63,139)处的圆是其中一个角。如果你做数学计算,你会看到:

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

由于你的整数是16位,75536模数65536 = 10000 =最终计算的值= 100 2 =一个圆圈,它不应该是。

一个简单的解决方案是将相关变量更改为long

  • maxx,maxy
  • x,y
  • h,k

所以:

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

然后你会得到正确的输出:

enter image description here

当然要注意像other answers point out一样,因为你使用的是int,所以你会错过很多分数。这可能是也可能不是,但是某些值会产生明显较差的结果(例如,半径256似乎只有4个整数解)。如果需要,您可以引入容差。您也可以使用a more direct approach,但这可能会使用笛卡尔圆公式破坏您的练习目的。如果你是这样的话,这里有一个24页的文档,其中包含一堆关于integers that are the sum of two squares的讨论,证明和属性。

我不太了解Turbo C ++是否可以让它使用32位整数,我会把它作为练习留给你。

答案 1 :(得分:1)

首先,maxx和maxy是整数,您可以使用表示屏幕边框的某些函数进行初始化,然后将它们用作函数。只需删除paranthesis:

    // 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)

答案 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 - 大圆圈的中心