2014年4月8日火曜日

atan2の変換テーブル

atan2を変換する整数テーブルを作ってみました

      1 #include <stdio.h>
      2 #include <math.h>
      3 #include <stdint.h>
      4
      5 #define PI (3.14159265358979323846264338327950288)
      6
      7 /*             Row  Col  */
      8 int atan2table[100][100];
      9 const int tableSize   = (int) (sizeof(atan2table   ) / sizeof(atan2table[0][0]));
     10 const int tableColumn = (int) (sizeof(atan2table[0]) / sizeof(atan2table[0][0]));
     11 const int tableRow    = (int)((sizeof(atan2table   ) / sizeof(atan2table[0][0])) /
     12                               (sizeof(atan2table[0]) / sizeof(atan2table[0][0])));
     13
     14 void createTable(void) {
     15     int x, y;
     16
     17     for (x = 0; x < tableRow; x++) {
     18         for (y = 0; y < tableColumn; y++)
     19         { atan2table[x][y] = (int)((atan2(y + 1, x + 1) * (180.0 / PI)) * 1000); }
     20     }
     21 }
     22
     23 int ATAN2(y, x) {
     24     int xp = 1;
     25     int yp = 1;
     26
     27     if (!x && !y)  { return(0); }
     28
     29     if (!x) { if (y > 0) { return(90000); } else { return(-90000); } }
     30     if (!y) { if (x > 0) { return( 0); }    else { return(180000); } }
     31
     32     if (x < 0) { x = -x; xp = -1; }
     33     if (y < 0) { y = -y; yp = -1; }
     34
     35     x--; y--;
     36
     37     if (x >= tableRow)    { return(0); }
     38     if (y >= tableColumn) { return(0); }
     39
     40     int deg = atan2table[x][y];
     41
     42     if (xp == -1) { deg = 180000 - deg; }
     43     if (yp == -1) { deg = -deg; }
     44
     45     return(deg);
     46 }
     47
     48 int main(void) {
     49     int i;
     50
     51     createTable();
     52
     53     for (i = 0; i < 360; i += 5) {
     54         int x = sin(i * (PI / 180.0)) * 95;
     55         int y = cos(i * (PI / 180.0)) * 95;
     56         double _atan2 = atan2(y, x) * (180.0 / PI);
     57         double _ATAN2 = ATAN2(y, x) * 0.001;
     58
     59         printf("deg:%3d, ", i);
     60         printf("x:%3d, y:%3d, ", x, y);
     61         printf("%8.3lf, ", _atan2);
     62         printf("%8.3lf, ", _ATAN2);
     63         printf("%6.3lf, ", _atan2 - _ATAN2);
     64         printf("\n");
     65     }
     66
     67     return(0);
     68 }
     69

入力範囲はx,y共に-100 - +100の間です(デフォルトのテーブルサイズでは)
このコードでは予めmatn.hのatan2でテーブルを作成していますが、組み込み用途向けの場合は予めテーブルをCSVとして作成しておき、配列に読み込んでROMに焼く という方法が使えます
また、入力がテーブルを超えた場合はテーブルに収まるように除算してから処理する というアルゴリズムにすれば精度は落ちますが広い範囲の入力を受けることができます

このコードではハードコードされた値があるため、intの代わりにshortにしようと思うとちょっと面倒ですが、uint16_tでテーブルを作った場合、100x100だと20kByteくらいのROMが必要になります

精度は悪く、ifの連続なので処理速度も期待できませんが、ソフトウェアで浮動小数点を計算するとか、そもそも浮動小数点が使えない環境では使えるかも

0 件のコメント:

コメントを投稿