Расчет вращения в> 360 град. ситуации - PullRequest
3 голосов
/ 23 марта 2010

Я пытаюсь решить проблему со степенями. У меня есть данные, которые представляют собой список углов в стандартном обозначении степени - например, 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, если предыдущий угол положительный.

Есть предложения по улучшению этого? Какие-нибудь улучшения?

Ответы [ 6 ]

2 голосов
/ 24 марта 2010

То, о чем вы говорите, - это алгоритм unwrap, который обобщает (не относится к числу 360 ... вы можете сделать это в радианах с m = 2 * pi). Вот один в JavaScript:

/*  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;
}
1 голос
/ 23 марта 2010

Возьмите разницу между каждым углом и предыдущим, используя некоторый метод, чтобы убедиться, что вы получаете правильный знак при пересечении 0/360 в обоих направлениях Затем добавьте эту разницу к промежуточной сумме, которая не переворачивается.

1 голос
/ 23 марта 2010

Можете ли вы просто добавлять / вычитать все свои градусы, а затем использовать оператор MODULUS для конечного результата с 360. Это даст вам оставшиеся градусы.

0 голосов
/ 24 марта 2010

Используйте модульную функцию

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);
0 голосов
/ 23 марта 2010

Эта программа на С принимает список углов в диапазоне от 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);
}
0 голосов
/ 23 марта 2010

Если я правильно понимаю проблему, это может сработать:

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

Затем в конце цикла набор данных будет содержать все данные, добавленные, как вы указали.

Так что, в основном, просматривайте набор данных и добавляйте разницу к промежуточному итогу. Промежуточный итог становится каждым элементом данных при итерации.

...