Generate a "pieslice" in C without using the pieslice() of graphics.h
Asked Answered
V

1

2

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 are the center of the circle,stangle and endangle are the starting and end angles respectively]

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();
}

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)


Vedda answered 3/10, 2019 at 15:44 Comment(11)
There is no attempt to draw anything in your code.Lardon
@RichardCritten i am using the "gcc compiler"[ubuntu 16.0.4]Vedda
@Lardon "Don't use tools that are older than you are!" has now been added to my list of Great Life Quotes! (Along with such things as, "Never eat anything bigger than your head!")Alpenhorn
@Adrian I'm honorerd ;-). Bu apparently he uses gcc with grahics.h (don't ask be how), so I removed that part of my comment.Lardon
This sounds like you are expected to reinvent two Bresenham algorithms, Bresenham's line algorithm and the midpoint circle algorithm. A websearch for both should help point you to the logic required.Rafter
"tried making it with the help of the lines and arc function": show us that attempt.Lardon
Since this is running on Ubuntu, likely the SDL_BGI port.Rafter
@Lardon drawing the pieslice is the part i am struggling. As i have figured, in pieslice() there is a starting angle and ending angle,so i would use that parametric equation of the circle. The formula i used would generate the points from where to start the pixels and where to end. Its that how do i add it in the BGI library,i am not able to figure it out.Vedda
@NetranjitBorgohain you need to show us your failing code. The code in your question doesn't contain any attempt to draw anything, therefore we can't tell what's wrong.Lardon
@Lardon Added my codes. Sorry,i tried to use the Line and mid-point circle function.Not the arc function.Vedda
The circle function will not work out of the box because it ONLY makes a circle. You could erase the part of the circle you don't want by drawing over it, but you're probably better off using a draw arc function. An inferior alternative is to re-implement the circle function and stop part way, resulting in an arc.Rafter
S
1

why not use vectors?

pie

outscribed square

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

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

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

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; with your putpixel(sx,sy,c); and remove obsolete range check ifs for sx,sy. Also remove the resolution xs,ys and Pixels variables.

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

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

preview

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)

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;
        }
    }

preview big pie

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. The same goes for all 4 therms in the cross product conditions.

[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 }
       }

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...

Shawana answered 5/10, 2019 at 8:26 Comment(21)
I didn't get the for loop part,can you please explain that.Vedda
why did you use rr=r*r?i believe r is the radius,so why two different radius for one circle? Also,in x=a1-a0 where will a1 and a0 come from? Lastly, we have if (x<180) ,then what is the use of if(x<0) x=-x. I didn't understood the small pixel reference. And that if else statements have the same conditions. Shouldn't it be different?Vedda
@NetranjitBorgohain All is just BASIC MATH: 1. I got rr=r*r yes its the same radius but squared because filled circle equation is x^2 + y^2 <= r^2 so its just precomputed r^2 so I do not need to square it on each pixel ... 2. a0,a1 are the start and end angles of your pie passed as operands into the function. 3. the part of code you are asking x about holds x=abs(a1-a0) thats why if (x<0) x=-x its just abs value. it has nothing to do with pixels I just use x as temp variable because it was not used yet. the x<180 determines if your pie is smaller or bigger than 180 degrees.Shawana
Thanks,that cleared alot of my doubts. Will get back to you,if i encounter anymore. Thanks alot,you have helped me in my dark times.Vedda
Why did you use ux,ux,vx,vy instead of just u and v ?Vedda
@NetranjitBorgohain u and v are 2D vectors so each has its own (x,y) coordinate its a matter of convention so either to use ux,uy,vx,vy or u[2],v[2] or a 2D point structure/class instead ... You seem like a rookie and for those ux,uy,... is more understandableShawana
I am a rookie,tbh.Vedda
** [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. ** I am facing this error since yesterday. What to do?Vedda
@NetranjitBorgohain never heard of such error ... what OS compiler and BGI you have? I hope you are coding with English keyboard and not some national one those sometimes produce weird Unicode or control code characters that are not ASCII text which older compilers have problems to handle and those characters are usually invisible in code ... but it can be also anything else ...Shawana
I am using Ubuntu 16.0.4 and the compiler is gccVedda
Where did you run your code? I will use that compiler.Vedda
I am using Embarcadero (former Borland) BDS2006 Turbo C++ explorer under Windows. Its for free but the licensing server is down for years... any BCB or RAD would do ...Shawana
Can i run it in windows 10?Vedda
@NetranjitBorgohain never tried but the newer versions run on win10 ...Shawana
[pastebin.com/embed_js/McPB9ic4] this is as far as i could make it. Please look into my errors,i am in desperate need of your helpVedda
@NetranjitBorgohain why didnt you copy paste the pie function ... and use it as function. That would eliminate most of your typing errors. I can not test the scanf and BGI initialization but in the rest you got these errors I found: 1. you are not setting x0,y0 position nor color c so your pie is most probably located out of screen and or black on black. 2. at line 18 should be sin instead of cos otherwise it looks OK to me and is rendering the pie (after repairing) ... 3. delay(1000000); -> 1000 sec is too long and overflowing if 16bit variables are usedShawana
@NetranjitBorgohain PS I am setting the x0,y0 to center of my screen/window ... and c to 32bit color but in your case you have only 16 colors so set for example c=2 instead.Shawana
What should the DWORD be? It is showing "unknown type name"Vedda
@NetranjitBorgohain its 32bit unsigned int (you know BYTE,WORD,DWORD,QWORD used in programming for ages) but in your case you should use type that BGI is using for color my bet is int, unsigned int or char or unsigned char as your pixels are only 4 bit ... PS there is no DWORD in the pasted code of yours...Shawana
i added char c=2 and the compiler showing error, " error: expected ‘;’, ‘,’ or ‘)’ before ‘=’ token void pie(int x0,int y0,int r,int a0,int a1,char c=2) "Vedda
Let us continue this discussion in chat.Vedda

© 2022 - 2024 — McMap. All rights reserved.