2

BGI ライブラリの「graphics.h」ヘッダーには、そのヘッダー ファイルに関数piesliceがあり、その構文は次のとおりです。

#include <graphics.h>

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

[x,y は円の中心、stangle と endangle はそれぞれ開始角度と終了角度]

BGI ライブラリの組み込み関数を使用せずに、C/C++ でパイスライスを作成できますか。助けてください。線と中点円の生成アルゴリズムを使って作ってみました。

これまでの私のコード:

#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。いくつかの助けがいいでしょう。前もって感謝します。

このプログラムの実行中に、次のエラーが発生します。

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


4

1 に答える 1

1

なぜベクトルを使わないのですか?

パイ

外接広場

したがって(0,0)、半径の中心円は次のrように決定されます。

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

CW/CCW は、3D 外積を計算し、結果の z 座標の符号を調べることによって決定されます...

そのため、円で囲まれた正方形内のすべてのピクセルを処理し、3 つの条件すべてに適合するすべてのピクセルをレンダリングします。

このようなもの:

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,syxs,ysPixels

ここでのプレビュー(xs2,ys2私の画面の真ん中です):

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

プレビュー

インデックス付きの 8 ビットの代わりに 32 ビットの RGB カラーがあり、角度は度単位であることに注意してください。また、私の y 軸は下を向いているので、角度の増分は x 軸から時計回り (右向き) になることに注意してください。

ただし、これは 180 度未満のパイに対してのみ機能します。より大きなものについては、塗りつぶされていないパイ部分の内側にないときにレンダリングするクロス積条件を反転する必要があります。代わりに、次のようにします。

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 サイクルで加算するように変更できます。for(...,xuy=x*uy;...;...,xuy+=uy)同じことが、外積条件の 4 つのサームすべてに当てはまります。

[編集1]より明確にするために、次のようなものがあります。

     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*uy)((x-1)*uy)+uy((x-1)*uy)

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

そのため、最初の乗算は一度だけ行われ、それ以降は足し算になります...

また、このレンダリング方法は完全に並列化可能です...

于 2019-10-05T08:26:16.057 に答える