生成一个“切片".在C中不使用graphics.h的pieslice() [英] Generate a "pieslice" in C without using the pieslice() of graphics.h

查看:75
本文介绍了生成一个“切片".在C中不使用graphics.h的pieslice()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在BGI库的"graphics.h"标头中,该标头文件中有一个函数 pieslice ,其语法为:

In the BGI library's "graphics.h" header there is a function pieslice in that header file,its syntax is:

#include <graphics.h>

void pieslice(int x, int y, int stangle, int endangle, int radius);

[x,y是圆的中心,角和终止角分别是起始角和终止角]

[x,y are the center of the circle,stangle and endangle are the starting and end angles respectively]

我们可以在不使用BGI库的内置函数的情况下用C/C ++制作pilice吗?请提供帮助.尝试借助直线和中点圆生成算法使其实现.

Can we make a pieslice in C/C++ without using this in-built function of the BGI library.Please help. Tried making it with the help of the lines and mid-point circle generation algorithms.

到目前为止,我的代码:

My code so far:

#include<stdio.h>
#include<graphics.h>


static const double PI =3.141592

int main()
{
    int gd=DETECT,gm;
    initgraph(&gd,&gm,NULL);
    int xc,yc,r,st_angle,ed_angle,k;
    printf("Enter the centers of pieslice:\n");
    scanf("%d %d",&xc,&yc);
    printf("Enter the radius:\n");
    scanf("%d",&r);
    printf("Enter the starting angle:\n");
    scanf("%d",&st_angle);
    printf("Enter the end angle:\n");
    scanf("%d",&ed_angle);


    for(k=st_angle; k<=ed_angle;k++)
    {   
        double radians =(PI /180.0) * k;
        int X = xc+ cos(radians) * r;
        int Y = yc+ sin(radians) * r;
        putpixel(x,y,WHITE);
        delay(5000);

    }
void wait_for_char()
{

    //Wait for a key press
    int in = 0;

    while (in == 0) {
        in = getchar();
    }
}
getch();
}

我可以在使用圆的参数方程式的情况下进行计算,但是无法使用 graphics.h 函数生成图形.一些帮助会很好.预先谢谢你.

I was able to do the calculation part where i used the parametric equation of circle,but unable to generate the figure using the graphics.h function. Some help would be nice. Thank you in advance.

在运行该程序时,出现此错误:

While running this program,i am getting this error:

[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
a.out: ../../src/xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
a.out: ../../src/xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
Aborted (core dumped)


推荐答案

为什么不使用向量?

因此,半径 r (0,0)居中饼由以下条件确定:

So (0,0) centered pie of radius r is determined by:

u = (cos(a0),sin(a0))
v = (cos(a1),sin(a1))
x^2 + y^2 <= r^2 // circle
(x,y) x u ->  CW
(x,y) x v -> CCW

通过计算3D叉积并检查结果z坐标的符号来确定CW/CCW ...

the CW/CCW is determined by computing 3D cross product and examining the sign of results z coordinate...

因此要处理圆外方正方形中的所有像素,并渲染符合所有3个条件的所有像​​素.

so process all pixels in circle outscribed square and render all pixels that complies all 3 conditions.

类似这样的东西:

void pie(int x0,int y0,int r,int a0,int a1,DWORD c)
    {
    // variables
    int  x, y,      // circle centered point
        xx,yy,rr,   // x^2,y^2,r^2
        ux,uy,      // u
        vx,vy,      // v
        sx,sy;      // pixel position
    // my Pixel access (remove these 3 lines)
    int **Pixels=Main->pyx;         // Pixels[y][x]
    int   xs=Main->xs;              // resolution
    int   ys=Main->ys;
    // init variables
    rr=r*r;
    ux=double(r)*cos(double(a0)*M_PI/180.0);
    uy=double(r)*sin(double(a0)*M_PI/180.0);
    vx=double(r)*cos(double(a1)*M_PI/180.0);
    vy=double(r)*sin(double(a1)*M_PI/180.0);
    // render                                       |<-- remove these -->|
    for (y=-r,yy=y*y,sy=y0+y;y<=+r;y++,yy=y*y,sy++) if ((sy>=0)&&(sy<ys))
     for (x=-r,xx=x*x,sx=x0+x;x<=+r;x++,xx=x*x,sx++) if ((sx>=0)&&(sx<xs))
      if (xx+yy<=rr)          // inside circle
       if ((x*uy)-(y*ux)<=0)  // x,y is above a0 in clockwise direction
        if ((x*vy)-(y*vx)>=0) // x,y is below a1 in counter clockwise direction
         Pixels[sy][sx]=c; // change for putpixel
    }

但是我不使用BGI,所以只需将 Pixels [sy] [sx] = c; 更改为您的 putpixel(sx,sy,c); 并删除已过时的范围检查 sx,sy 的ifs.还要删除分辨率 xs,ys Pixels 变量.

However I do not use BGI so just change the Pixels[sy][sx]=c; with your putpixel(sx,sy,c); and remove obsolete range check ifs for sx,sy. Also remove the resolution xs,ys and Pixels variables.

此处的预览( xs2,ys2 在屏幕的中间)

Here preview for (xs2,ys2 is mine middle of screen):

pie(xs2,ys2,ys2-200,10,50,0x00FF0000);

请注意,我使用的是32位RGB颜色,而不是索引的8位RGB颜色,并且角度以度为单位.另外请注意,我的y轴指向下方,因此增量角度从x轴开始(指向右侧)为顺时针方向

Note that I have 32 bit RGB color instead of your indexed 8 bit ones and angles are in degrees. Also note that mine y axis points down so incrementing angle is going clockwise starting from the x axis (pointing to right)

这仅适用于180度以下的饼.对于较大的饼,您需要反转叉积条件以在不在未填充的饼图部分中时进行渲染,例如:

This however works only for pies below 180 degrees. For bigger ones you need to invert the cross product conditions to render when not inside the not filled pie part instead something like this:

void pie(int x0,int y0,int r,int a0,int a1,DWORD c) // a0 < a1
    {
    // variables
    int  x, y,      // circle centered point
        xx,yy,rr,   // x^2,y^2,r^2
        ux,uy,      // u
        vx,vy,      // v
        sx,sy;      // pixel position
    // my Pixel access
    int **Pixels=Main->pyx;         // Pixels[y][x]
    int   xs=Main->xs;              // resolution
    int   ys=Main->ys;
    // init variables
    rr=r*r;
    ux=double(r)*cos(double(a0)*M_PI/180.0);
    uy=double(r)*sin(double(a0)*M_PI/180.0);
    vx=double(r)*cos(double(a1)*M_PI/180.0);
    vy=double(r)*sin(double(a1)*M_PI/180.0);
    // handle big/small pies
    x=a1-a0;
    if (x<0) x=-x;
    // render small pies
    if (x<180)
        {
        for (y=-r,yy=y*y,sy=y0+y;y<=+r;y++,yy=y*y,sy++) if ((sy>=0)&&(sy<ys))
         for (x=-r,xx=x*x,sx=x0+x;x<=+r;x++,xx=x*x,sx++) if ((sx>=0)&&(sx<xs))
          if (xx+yy<=rr)           // inside circle
           if (((x*uy)-(y*ux)<=0)  // x,y is above a0 in clockwise direction
             &&((x*vy)-(y*vx)>=0)) // x,y is below a1 in counter clockwise direction
             Pixels[sy][sx]=c;
        }
    else{
        for (y=-r,yy=y*y,sy=y0+y;y<=+r;y++,yy=y*y,sy++) if ((sy>=0)&&(sy<ys))
         for (x=-r,xx=x*x,sx=x0+x;x<=+r;x++,xx=x*x,sx++) if ((sx>=0)&&(sx<xs))
          if (xx+yy<=rr)           // inside circle
           if (((x*uy)-(y*ux)<=0)  // x,y is above a0 in clockwise direction
             ||((x*vy)-(y*vx)>=0)) // x,y is below a1 in counter clockwise direction
             Pixels[sy][sx]=c;
        }
    }

pie(xs2,ys2,ys2-200,50,340,0x00FF0000);

可以进一步优化代码,例如可以将 x * uy 更改为加法,例如 for(...,xuy = x * uy; ...;...,xuy + = uy)消除了内部循环中的缓慢乘法.交叉乘积条件下的所有四个热敏电阻也一样.

The code can be further optimized for example x*uy can be changed to addition in for cycle like for(...,xuy=x*uy;...;...,xuy+=uy) eliminating slow multiplication from inner loops. The same goes for all 4 therms in the cross product conditions.

[edit1] 为了更清楚一点,我们有这样的内容:

[edit1] To be more clear we have something like this:

     for (x=-r,xx=x*x,sx=x0+x;x<=+r;x++,xx=x*x,sx++)
       {
       if (...(x*uy)...) { do something }
       }

(x * uy)是在 x 的每次迭代中计算的. x 正在递增,因此我们可以从先前的值((x-1)* uy)+ uy 来计算(x * uy)的值(] [ux)是上次迭代的值.因此,添加包含它的单个变量可以消除重复的乘法:

the (x*uy) is computed on each iteration of x. The x is incrementing so we can compute the value of (x*uy) from the previous value ((x-1)*uy)+uy which does not need multiplication as ((x-1)*uy) is the value from last iteration. So adding single variable that holds it can get rid of the repeated multiplication:

     int xuy; //              ********                       *******
     for (x=-r,xx=x*x,sx=x0+x,xuy=x*uy;x<=+r;x++,xx=x*x,sx++,xuy+=uy)
       {
       if (...(xuy)...) { do something }
       }

所以初始乘法只执行一次,然后再进行一次加法...

so the initial multiplication is done just once and from then its just addition ...

这种渲染方式也是完全并行的...

Also this way of rendering is fully parallelisable...

这篇关于生成一个“切片".在C中不使用graphics.h的pieslice()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆