На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! правила раздела Алгоритмы
1. Помните, что название темы должно хоть как-то отражать ее содержимое (не создавайте темы с заголовком ПОМОГИТЕ, HELP и т.д.). Злоупотребление заглавными буквами в заголовках тем ЗАПРЕЩЕНО.
2. При создании темы постарайтесь, как можно более точно описать проблему, а не ограничиваться общими понятиями и определениями.
3. Приводимые фрагменты исходного кода старайтесь выделять тегами code.../code
4. Помните, чем подробнее Вы опишете свою проблему, тем быстрее получите вразумительный совет
5. Запрещено поднимать неактуальные темы (ПРИМЕР: запрещено отвечать на вопрос из серии "срочно надо", заданный в 2003 году)
6. И не забывайте о кнопочках TRANSLIT и РУССКАЯ КЛАВИАТУРА, если не можете писать в русской раскладке :)
Модераторы: Akina, shadeofgray
  
> Разница между 2 углами , Надо найти очень быстро
    Всем доброго времени суток

    Подскажите, существует ли способ быстро (очень быстро) определить превышает ли разница между 2 углами pi/2, или к примеру pi/6

    Под разницей я понимаю минимальное расстояние (радианах) между 2 углами на тригонометрической окружности.
    Т.е. если есть 2 угла 10 и 350 градусов, разница между ними равна 20 градусов

    Углы даны в радианах

    Заранее спасибо
      ИМХО быстрее чем тупо посчитать угол и сравнить не получится.

      ExpandedWrap disabled
        #define PI 3.1415
         
        float distance(float a, float b) // считает разницу между двумя углами
        {
          float r1, r2;
          if (a>b) { r1 = a-b; r2 = b-a+2*PI } else { r1 = b-a; r2=a-b+2*PI; }
          return (r1>r2) ? r2 : r1;
        }

      Недостаточно быстро?
      Сообщение отредактировано: Yakudza -
        Цитата Yakudza @
        ИМХО быстрее чем тупо посчитать угол и сравнить не получится.

        ExpandedWrap disabled
          #define PI 3.1415
           
          float distance(float a, float b) // считает разницу между двумя углами
          {
            float r1, r2;
            if (a>b) { r1 = a-b; r2 = b-a+2*PI } else { r1 = b-a; r2=a-b+2*PI; }
            return (r1>r2) ? r2 : r1;
          }

        Недостаточно быстро?

        Примерно так и считаю, хотелось бы пошустрее конечно. (речь идет о тысячах таких операций в секунду)
          Цитата Daiver @
          хотелось бы пошустрее конечно

          Быстрее только таблицу готовую сделать. Можешь заинлайнить еще.

          Добавлено
          Цитата Daiver @
          речь идет о тысячах таких операций в секунду

          Несколько тысяч вызовов этой функции отработают на порядок быстрее 1 сек.
          Сообщение отредактировано: shm -
            shm Насчет таблицы - можно поподробней?

            Пускай не тысячи, а десятки тысяч, плюс все пишется на питоне

            Добавлено
            Важно даже не получить точную разницу, а узнать что эта разница больше/меньше определенного угла (pi/6 к примеру)
              Цитата Daiver @
              Насчет таблицы - можно поподробней?

              Да все банально: создаешь двухмерный массив n*n, чем больше n, тем больше будет точность, но тем больше потребуется памяти. Пусть столбцы будут первым углом, а стоки вторым. Ну и заполняешь эту матрицу своей функцией. Потом дял получения искомого результата пользуешься уже вычисленным значением. Правда не знаю как это будет выглядеть на питоне.
              Сообщение отредактировано: shm -
                Цитата shm @
                Да все банально: создаешь двухмерный массив n*n, чем больше n, тем больше будет точность

                Я бы создавал одномерный и индексировал его по (a-b). Так и памяти меньше и индексировать проще.

                С другой стороны будет ли залезть в этот массив быстрее? Еще же углы нужно к индексам привести, проинтерполировать между соседними точками... Исходная функция-то дешевенькая. Хотя если сделать плотный массив, приведеие к индексу свести к приведению типа и брать первый попавшийся элемент без интерполяции, то должно помочь. Хотя, если в некоторых вычислительных пакетах пришли к тому, что интеграл быстрее лишний раз взять численно, чем из памяти его доставать...

                Если совсем проблема будет с ускорением, то можно на С модуль к питону (плагин? как оно называется) написать и просить эту функцию. :lol:
                Сообщение отредактировано: Yakudza -
                  Yakudza Боюсь что сам вызов сишной ф-ии будет слишком дорогой
                    Если развивать идею с хешем.

                    Если набор углов фиксирован, то ускорения можно добиться тупо массивом bool.

                    ExpandedWrap disabled
                      bool hash_half_pi[720];
                      // fill for pi/2
                      for (int i = 0; i < 90; ++i) hash_half_pi[i] = false;
                      for (int i = 90; i < 270; ++i) hash_half_pi[i] = true;
                      for (int i = 270; i < 450; ++i) hash_half_pi[i] = false;
                      for (int i = 450; i < 630; ++i) hash_half_pi[i] = true;
                      for (int i = 630; i < 720; ++i) hash_half_pi[i] = false;
                       
                      bool is_larger(float a, float b, bool* hash)
                      {
                        return hash[int(a-b)+360];
                      }


                    Но на границах может врать.
                      откуда берутся эти углы и какова более общая задача?
                      А то, может, углы вычисляются через arc-функции...
                        Yakudza Хэш не совсем пойдет, т.к. углы могут быть произвольными

                        MBo Гм, в общем-то да, углы вычисляются через arctan2. Так я ищу угол наклона градиента

                        А задача - реализация SWT-оператора с последующей фильтрацией. Углы сравниваются на этапе отслеживания лучей
                          Daiver
                          Получается, что есть два вектора? Тогда угол между ними можно найти, не вычисляя угол наклона каждого по отдельности. Кроме того, для проверки попадания угла в диапазон и арктангенс не понадобится, достаточно будет найти отношение векторного и скалярного произведений векторов
                            Пожалуй, самый быстрый способ найти угол между двумя углами (лучами) это:
                            ExpandedWrap disabled
                              da = a1 - a2 # Ищем разность
                              if da < -pi: da += 2*pi # и загоняем её в промежуток +-pi
                              elif da > pi: da -= 2*pi

                            Цитата MBo @
                            достаточно будет найти отношение векторного и скалярного произведений векторов
                            Не совсем, можно нарваться на ошибку деления на ноль. Так что лучше раскрывать пропорцию.

                            Но действительно, вычислять арктангенс, даже если предполагается сравнивать каждый угол с каждым незачем. Это дольше, чем сравнивать пропорции.
                              Цитата Daiver @
                              Под разницей я понимаю минимальное расстояние (радианах) между 2 углами на тригонометрической окружности

                              Так и флаг в руки
                              Цитата
                              const double TOLERANCE = 0.0001;
                              if (deltaAngle > TOLERANCE) {
                              }
                              else {
                              }

                              А уж что на вход дельтаУгол - сам решай. Мне хватает двух точек - точки вставки (база) и точки ориентации (направление).
                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                              0 пользователей:


                              Рейтинг@Mail.ru
                              [ Script execution time: 0,0373 ]   [ 15 queries used ]   [ Generated: 27.04.24, 18:25 GMT ]