2016-11-01 7 views
1

私はASCIIアートを描画するためのライブラリを構築しています。私は、各点がピクセルを表す3 x 3のグラフを持っているとしたら、点は0,0から始まり、2,2(左下の点から右上の点)に対角線になります。私はキャンバスを描く場合2D 3 x 3グリッド回転行列の対角線を回転させる必要がありますか?

が、それは次のようになります。

2 / Points: 2,0 2,1 2,2 
1/    1,0 1,1 2,1 
0/    0,0 1,0 2,0 
    0 1 2 

私が今までのラインを時計回りに回転させることができるアルゴリズムを構築したいので、私はラインにアルゴリズムを適用した場合、結果は次のようになります:

2   Points: 2,0 2,1 2,2 
1     1,0 1,1 2,1 
0 _ _ _   0,0 1,0 2,0 
    0 1 2 

したがって、基本的に行は右に45度回転し、結果として水平線になります。

http://mathworld.wolfram.com/RotationMatrix.htmlに記載されているように回転行列が必要だと思いますが、数学は私の頭より少し上です。

私の2次元座標系が与えられているとすれば、誰でも簡単な説明があります。疑似コードですか?

+0

あなたは常に起源についてはASCIIアートを回転させていますか? –

+0

@TimBiegeleisenあなたはローテーションの中心点は何ですか? – Max

+0

はい、これは私が求めていることです。 –

答えて

1

行列を使用するかどうかは関係ありません。ここでは、単純なC++、私は私のコメントに言及するものすべてを使用して行列をなし例:

//--------------------------------------------------------------------------- 
const int xs=32; 
const int ys=32; 
char pic[xs][ys]; 
//--------------------------------------------------------------------------- 
void cls(); 
void rot45cw(); 
void rot90cw(); 
//--------------------------------------------------------------------------- 
void cls() 
    { 
    int x,y; 
    // clear screen 
    for (y=0;y<ys;y++) 
    for (x=0;x<xs;x++) 
     pic[x][y]=' '; 
    // add diagonal line for testing 
    for (x=xs/2;(x<xs)&&(x<ys);x++) pic[x][x]='\\'; 
    } 
//--------------------------------------------------------------------------- 
void rot45cw() 
    { 
    int x,y,ix,iy,x0,y0; 
    float fx,fy,a,c,s; 
    char tmp[xs][ys],q; 
    a=-45.0*M_PI/180.0; // rotation angle [rad] 
    x0=xs/2;   // center of rotation 
    y0=ys/2; 
    c=cos(a); s=sin(a); 
    // copy pic to tmp 
    for (y=0;y<ys;y++) 
    for (x=0;x<xs;x++) 
     tmp[x][y]=pic[x][y]; 
    // rotate 
    for (y=0;y<ys;y++) 
    for (x=0;x<xs;x++) 
     { 
     // offset so (0,0) is center of rotation 
     fx=x-x0; 
     fy=y-y0; 
     // rotate (fx,fy) by ang 
     ix=float((fx*c)-(fy*s)); 
     iy=float((fx*s)+(fy*c)); 
     // offset back 
     ix+=x0; 
     iy+=y0; 
     // transform tmp to pic 
     if ((ix>=0)&&(ix<xs)&&(iy>=0)&&(iy<ys)) q=tmp[ix][iy]; else q=' '; 
      if (q=='/') q='\\'; 
     else if (q=='\\') q='/'; 
     else if (q=='-') q='|'; 
     else if (q=='|') q='-'; 
     pic[x][y]=q; 
     } 
    } 
//--------------------------------------------------------------------------- 
void rot90cw() 
    { 
    int x,y,ix,iy,x0,y0; 
    char tmp[xs][ys],q; 
    // center of rotation 
    x0=xs/2; 
    y0=ys/2; 
    // copy pic to tmp 
    for (y=0;y<ys;y++) 
    for (x=0;x<xs;x++) 
     tmp[x][y]=pic[x][y]; 
    // rotate 
    for (y=0;y<ys;y++) 
    for (x=0;x<xs;x++) 
     { 
     // rotate 
     iy=x0-(x-x0); 
     ix=y0+(y-y0); 
     // transform tmp to pic 
     if ((ix>=0)&&(ix<xs)&&(iy>=0)&&(iy<ys)) q=tmp[ix][iy]; else q=' '; 
      if (q=='-') q='\\'; 
     else if (q=='\\') q='|'; 
     else if (q=='|') q='/'; 
     else if (q=='/') q='-'; 
     pic[x][y]=q; 
     } 
    } 
//--------------------------------------------------------------------------- 

と使用方法:

// clear and add diagonal line for testing once: 
cls(); 
// and this do in some timer or whatever: 
//rot45cw(); 
rot90cw(); 

ここで90degプレビュー:

90cw

ここで45degプレビュー:

45cw

45度回転が問題になるのは1:1マッピングではないため、複数のセルにマップされるためです。固定解像度の場合、1:1のマッピングを手動で行うことはできますが、動的解像度でアルゴリズム的に簡単に実装できるかどうかは疑問です。

はい個々のピクセルをマップしたときに一部が再度コピーされるため、問題が解決しない場合、45度回転が可能なところで(3x3)マップを使用しています。 。

私はすべて一緒に入れた場合、私はむしろ、あなたがイメージのベクトル表現を持っていない限りだけ...

文字回転はLUTを

[EDIT1] 45度を高速化することができる90deg回転を使用しますrotation

私はもう少し教えて、45度回転の解決策を見つけます。異なる回転カーネルを使用する必要があります。円の周りには回転しません。ここでよりわかりやすいように、小さな例:

これは1:1マッピングなので問題ありません。C++のコードは次のようになります。

//--------------------------------------------------------------------------- 
void rot45cw() 
    { 
    int x0,y0,ax,ay,ad,bx,by,bd,a,b,i,r,rs; 
    char tmp[xs][ys],q; 
    // rotation kernel 4 directions 
    const int dx[4]={ 0,-1, 0,+1}; 
    const int dy[4]={-1, 0,+1, 0}; 
    // center of rotation 
    x0=xs/2; 
    y0=ys/2; 
    // copy pic to tmp 
    for (ay=0;ay<ys;ay++) 
    for (ax=0;ax<xs;ax++) 
     tmp[ax][ay]=pic[ax][ay]; 
    // rotate all "screws" to fill entire map 
    rs=xs; if (rs<ys) rs=ys; 
    for (r=1;r<rs;r++) 
     { 
     ax=x0+r; ay=y0+r; ad=0; a=0; // start position a 
     bx=x0 ; by=y0+r; bd=3; b=r; // start position b 
     for (i=8*r;i>0;i--)   // process one screw 
      { 
      // fetch and convert processed character 
      if ((ax>=0)&&(ax<xs)&&(ay>=0)&&(ay<ys)) 
      if ((bx>=0)&&(bx<xs)&&(by>=0)&&(by<ys)) 
       { 
       q=tmp[ax][ay]; 
        if (q=='-') q='\\'; 
       else if (q=='\\') q='|'; 
       else if (q=='|') q='/'; 
       else if (q=='/') q='-'; 
       pic[bx][by]=q; 
       } 
      // update position 
      ax+=dx[ad]; bx+=dx[bd]; 
      ay+=dy[ad]; by+=dy[bd]; 
      // update direction 
      a++; if (a>=r+r) { a=0; ad=(ad+1)&3; } 
      b++; if (b>=r+r) { b=0; bd=(bd+1)&3; } 
      } 
     } 
    // fetch and convert center of rotation 
    if ((x0>=0)&&(x0<xs)&&(y0>=0)&&(y0<ys)) 
     { 
     q=pic[x0][y0]; 
      if (q=='-') q='\\'; 
     else if (q=='\\') q='|'; 
     else if (q=='|') q='/'; 
     else if (q=='/') q='-'; 
     pic[x0][y0]=q; 
     } 
    } 
//--------------------------------------------------------------------------- 
void rot45ccw() 
    { 
    int x0,y0,ax,ay,ad,bx,by,bd,a,b,i,r,rs; 
    char tmp[xs][ys],q; 
    // rotation kernel 4 directions 
    const int dx[4]={ 0,-1, 0,+1}; 
    const int dy[4]={-1, 0,+1, 0}; 
    // center of rotation 
    x0=xs/2; 
    y0=ys/2; 
    // copy pic to tmp 
    for (ay=0;ay<ys;ay++) 
    for (ax=0;ax<xs;ax++) 
     tmp[ax][ay]=pic[ax][ay]; 
    // rotate all "screws" to fill entire map 
    rs=xs; if (rs<ys) rs=ys; 
    for (r=1;r<rs;r++) 
     { 
     ax=x0+r; ay=y0+r; ad=0; a=0; // start position a 
     bx=x0 ; by=y0+r; bd=3; b=r; // start position b 
     for (i=8*r;i>0;i--)   // process one screw 
      { 
      // fetch and convert processed character 
      if ((ax>=0)&&(ax<xs)&&(ay>=0)&&(ay<ys)) 
      if ((bx>=0)&&(bx<xs)&&(by>=0)&&(by<ys)) 
       { 
       q=tmp[bx][by]; 
        if (q=='-') q='/'; 
       else if (q=='/') q='|'; 
       else if (q=='|') q='\\'; 
       else if (q=='\\') q='-'; 
       pic[ax][ay]=q; 
       } 
      // update position 
      ax+=dx[ad]; bx+=dx[bd]; 
      ay+=dy[ad]; by+=dy[bd]; 
      // update direction 
      a++; if (a>=r+r) { a=0; ad=(ad+1)&3; } 
      b++; if (b>=r+r) { b=0; bd=(bd+1)&3; } 
      } 
     } 
    // fetch and convert center of rotation 
    if ((x0>=0)&&(x0<xs)&&(y0>=0)&&(y0<ys)) 
     { 
     q=pic[x0][y0]; 
      if (q=='-') q='/'; 
     else if (q=='/') q='|'; 
     else if (q=='|') q='\\'; 
     else if (q=='\\') q='-'; 
     pic[x0][y0]=q; 
     } 
    } 
//--------------------------------------------------------------------------- 

dx,dyテーブルは単にsincosと同様です。

rot45cw square kernel

が、粗いのあなたは、その中心の周りの正方形を回転させる場合は、予想通り、それはないだろう!!!:最後にここにプレビューがありますここでCCWの例:

rectangle

+0

ありがとう!これはとても素敵な要約ですが、私は90度の回転で行っています。それは私の小さなペットプロジェクトにとってははるかに簡単です。イメージをASCIIアートに変換して書く例はまったくありません。私もそれを試してみたいです! – Max

+0

@Maxは助けになることをうれしく思っています...もしあなたがrot90ccwを作って、代わりに他の座標を否定したいのであれば... – Spektre

+0

母は超クールです!ありがとうございました。 :)それを見て、私が必要とするコードを適応させようとします。あなたは本当にASCIIグラフィックで遊んでいるようです! – Max

関連する問題