3

学位で抱えている問題を解決しようとしています。角度のリストであるデータを、標準の度数表記 (例: 26 度) で持っています。

通常、角度を扱う場合、角度が 360 度を超えると、角度は継続し、事実上「リセット」されます。つまり、角度は「再び開始」されます。たとえば、357 度、358 度、359 度、0 度、1 度などです。私が望んでいるのは、増加し続ける角度です。つまり、357 度、358 度、359 度、360 度、361 度などです。この変換されたデータが含まれるように、データを変更したいと考えています。

数値が 0 度の限界に近づくと、負の値になるようにします。つまり、3 度、2 度、1 度、0 度、-1 度、-2 度などです。

360 度の倍数 (正と負の両方) を使用して、720 度などの角度を続けたいと思います。

どのようなアプローチを取るべきかについて何か提案はありますか? 間違いなく、これを行うためのイライラするほど簡単な方法がありますが、私の現在の解決策は控えめに言っても面倒です.... ! これまでの私の最善の試みは、角度 n と角度 n - 1 のパーセンテージ差を調べることです。これが大きな差 (たとえば > 60%) である場合は、角度に 360 度を加算または減算して、これを修正する必要があります。以前の角度値に応じて、現在の値。つまり、前の角度が負の場合は 360 を引き、前の角度が正の場合は 360 を加算します。

これを改善するための提案はありますか?改善点はありますか?

4

6 に答える 6

2

あなたが話しているのは、unwrap一般化するアルゴリズムです(数値360に固有のものではありません... m = 2 * piのラジアンで実行できます)。これがjavascriptの1つです:

/*  symmetric modulo: 
 *  y = smod(x,m) = x+k*m where k is an integer,
 *  and y is always in the range [-0.5,0.5)*m
 */
function smod(x, m)
{
  return x-((Math.floor(x/m + 0.5))*m);
}

/*  unwrap:
 *  for all i, y[i] = x[i] + k*m where k is an integer,
 *  and for i > 0, the increment y[i]-y[i-1] is in the
 *  range [-0.5,0.5)*m as in smod().
 *
 *  the "init" parameter is optional (default to 0)
 *  and specifies the starting value for the unwrap state.
 */ 

function unwrap(x, m, init)
{
  var yi = init || 0;
  var y = [];
  for (i = 0; i < x.length; ++i)
  {
     yi += smod(x[i]-yi, m);
     y[i] = yi;
  }    
  return y;
}

出力例は次のとおりです。

js>unwrap([100, 200, 348, 359, 23, 37, 46, 10, 350, 190], 360)
100,200,348,359,383,397,406,370,350,190

m=100 の別のもの:

js>unwrap([99,1,7,60,80,22,30,20,90,88,61,23,2,87,50,12], 100, 1000)
999,1001,1007,960,980,1022,1030,1020,990,988,961,923,902,887,850,812

参考までに: C/Java などで。同様のアルゴリズムがビット拡張用に存在します。入力はたとえば 16 ビットで、出力は 32 ビットで、ラップアラウンド モジュラス m = 65536 = 入力値のスパンです。「smod」関数は必要ありません。符号付き数学を使用するだけです。

typedef short int16_t;
typedef long  int32_t;
// do typedefs as appropriate on your CPU

int32_t unwrap_extend(int32_t prev, int16_t input)
{
  int16_t delta = input - prev;
  return prev + delta;
}
于 2010-03-24T14:11:08.640 に答える
1

両方向で0/360を横切るときに正しい符号が得られるように、何らかの方法を使用して各角度と前の角度の差を取ります。次に、この差を、ロールオーバーしない現在の合計に追加します。

于 2010-03-23T14:04:18.657 に答える
1

すべての度数を加算/減算し続け、360 の最終結果に対して MODULUS 演算子を使用できますか。これにより、残りの度数が得られます。

于 2010-03-23T14:01:25.853 に答える
0

私が問題を正しく理解していれば、これはうまくいくかもしれません:

int prev=[first data piece in data set]
int total=prev
foreach data in [the rest of the data set]
    total+=data-prev
    prev=data
    data=total

次に、ループの最後に、データセットにすべてのデータが含まれ、指定したとおりに合計されます。

したがって、基本的にデータセットをループし、その差を現在の合計に追加します。反復すると、現在の合計が各データピースになります。

于 2010-03-23T14:03:53.837 に答える
0

モジュラス機能を使用する

static inline float GetAbsoluteModulous(float input ,float devisor )
{
    double output = (devisor==0)?input:fmod(input, devisor);
    return (output>0)?output:devisor+output;
} 

angle = GetAbsoluteModulous(angle,360);
于 2010-03-24T12:04:10.953 に答える
0

この C プログラムは、標準入力から 0 から 359 度の範囲の角度のリストを取得し、角度の変化を累積することによって、無制限の値を標準出力に出力します。ラップアラウンドは、入力ごとに可能な最大角度変化を想定することによって検出されます。

#include <stdio.h>
#include <stdlib.h>

int
main()
{
    const float MAX_DELTA = 180.f;          /* highest expected change */
    float previous, next, delta, output;

    /* set the initial value */
    if (EOF == scanf("%f", &next))
        exit(0);   
    previous = next;
    output = previous;

    do {
        /* calculate the change in angle and adjust if too big */
        delta = next - previous;
        if (MAX_DELTA < delta)
            delta -= 360.f;
        else if (-MAX_DELTA > delta)
            delta += 360.f;

        /* accumlate the changes without wrap-around */
        output += delta;
        printf("%f\n", output);

        /* store the value for calculating the next delta */
        previous = next;

        /* read angle values until end of file is reached */
    } while (EOF != scanf("%f", &next));

    exit(0);
}
于 2010-03-23T15:03:05.223 に答える