[英]Generate a “pieslice” in C without using the pieslice() of graphics.h
In the BGI library's "graphics.h" header there is a function pieslice in that header file,its syntax is:在 BGI 库的 "graphics.h" header 中有一个 function pieslice在 header 文件中,它的语法是:
#include <graphics.h>
void pieslice(int x, int y, int stangle, int endangle, int radius);
[x,y are the center of the circle,stangle and endangle are the starting and end angles respectively] [x,y 是圆心,stangle 和 endangle 分别是起始角和结束角]
Can we make a pieslice in C/C++ without using this in-built function of the BGI library.Please help.我们可以在不使用 BGI 库的内置 function 的情况下用 C/C++ 制作一个 pieslice。请帮助。 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();
}
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.我能够完成使用圆参数方程的计算部分,但无法使用
graphics.h
生成图形。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)
why not use vectors?为什么不使用向量?
So (0,0)
centered pie of radius r
is determined by:因此,半径为
r
的(0,0)
中心饼图由下式确定:
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
the CW/CCW is determined by computing 3D cross product and examining the sign of results z coordinate...通过计算 3D 叉积并检查结果 z 坐标的符号来确定 CW/CCW...
so process all pixels in circle outscribed square and render all pixels that complies all 3 conditions.因此处理圆形外接正方形中的所有像素并渲染符合所有 3 个条件的所有像素。
Something like this:像这样的东西:
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
}
However I do not use BGI so just change the Pixels[sy][sx]=c;
但是我不使用 BGI,所以只需更改
Pixels[sy][sx]=c;
with your putpixel(sx,sy,c);
用你的
putpixel(sx,sy,c);
and remove obsolete range check ifs for sx,sy
.并删除
sx,sy
的过时范围检查 ifs。 Also remove the resolution xs,ys
and Pixels
variables.同时删除分辨率
xs,ys
和Pixels
变量。
Here preview for ( xs2,ys2
is mine middle of screen):这里预览(
xs2,ys2
是我的屏幕中间):
pie(xs2,ys2,ys2-200,10,50,0x00FF0000);
Note that I have 32 bit RGB color instead of your indexed 8 bit ones and angles are in degrees.请注意,我有 32 位 RGB 颜色而不是您的索引 8 位颜色,角度以度为单位。 Also note that mine y axis points down so incrementing angle is going clockwise starting from the x axis (pointing to right)
另请注意,我的 y 轴指向下方,因此增量角度从 x 轴开始顺时针方向(指向右侧)
This however works only for pies below 180 degrees.然而,这仅适用于 180 度以下的馅饼。 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);
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.代码可以进一步优化,例如
x*uy
可以更改为 for 循环中的加法,例如for(...,xuy=x*uy;...;...,xuy+=uy)
消除内部循环的慢乘法. The same goes for all 4 therms in the cross product conditions.叉积条件下的所有 4 个therm 也是如此。
[edit1] To be more clear we have something like this: [edit1]为了更清楚,我们有这样的事情:
for (x=-r,xx=x*x,sx=x0+x;x<=+r;x++,xx=x*x,sx++)
{
if (...(x*uy)...) { do something }
}
the (x*uy)
is computed on each iteration of x
. (x*uy)
在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. x
是递增的,所以我们可以从前一个值((x-1)*uy)+uy
计算(x*uy)
的值,这不需要乘法,因为((x-1)*uy)
是来自最后一次迭代。 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...这种渲染方式也是完全可并行的......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.