Category Archives: Uncategorized

AABB для цилиндра

Данная запись продолжает тему предыдущей.

Единичным цилиндром будем называть декартово произведение отрезка [-1, 1] на единичный шар размерности (n-1). Цилиндром будем называть образ линейного отображения единичного цилиндра. Пусть это линейное отображение задано матрицей R.

Так как AABB нашего цилиндра опять же будет симметричным относительно нуля, то достаточно рассмотреть одну «крышку» исходного единичного цилиндра. Эту «крышку» можно считать сдвинутой на 1 по последней оси единичной сферой (внутренность нас, естественно, не интересует), которую перед сдвигом умножили на матрицу масштабирования D = \mathrm{diag}\,\{\,1, 1, \ldots, 1, 0\,\}. А это значит, что мы можем воспользоваться уже полученным результатом для определения AABB «крышки» как эллипсоида, заданного отображением RD = (r_1, r_2, \ldots, r_{n-1}, 0), где r_ii-й столбец матрицы R: обозначим координаты положительного угла этого AABB через b_j — это евклидовы длины строк указанной матрицы RD, т.е. евклидовы длины строк матрицы (r_1, r_2, \ldots, r_{n-1}).

В то же время, центр «крышки» имеет координаты R(0, 0, \ldots, 1)^\top = r_n.
Поскольку из-за сдвига мы теряем симметрию относительно нуля, нужно рассмотреть как положительный угол сдвинутого AABB, так и отрицательный угол. Элементарные рассуждения приводят нас к итоговому результату. Положительный угол AABB цилиндра может быть получен как (координаты точки):

(b_1 + |r_{n,1}|, b_2 + |r_{n,2}|, \ldots, b_n + |r_{n,n}|).

Отрицательный угол состоит из тех же координат, взятых с отрицательным знаком.

SDL + Win32 консоль

Как продолжение я выложу код очень маленькой программы, которая создаёт окно средствами SDL.

В случае Win32 мы подключаемся к консоли родительского процесса (через AttachConsole) или создаём свою консоль (AllocConsole) перед созданием отдельного окна средствами SDL. После подключения консоли привязываем к ней стандартные потоки ввода-вывода с помощью функции стандартной библиотеки C freopen. Никаких изменений процесса сборки это не требует.

Для протоколирования используется отдельный файл, поскольку это на практике удобнее, чем консоль.

// To enable Win32 console attachment:
#define WIN32_CONSOLE_ENABLE
#include <SDL2/SDL.h>
#include <fstream>

#ifdef WIN32_CONSOLE_ENABLE
  #include <iostream>
  #include <cstdio>
  #define WIN32_LEAN_AND_MEAN
  #include <Windows.h>
  #include <shellapi.h>
#endif

using namespace std;

// Constants.
int const WINDOW_WIDTH  = 640;
int const WINDOW_HEIGHT = 480;

// Global state.
ofstream col("app.log"); // logging file.

SDL_Window  * window;  // our sole window.
SDL_Surface * surface; /* "surface" contains 
    the picture that is shown in the window. */

// Entry point.
int main(int argc, char* args[])
{
  col << "Application started.\n";
  #ifdef WIN32_CONSOLE_ENABLE
  // Either attach to a parent console or
  // create a separate Win32 console in order
  // to enable standard in/out streams.
  if (AttachConsole(-1) || AllocConsole())
  {
    freopen("CONIN$", "r", stdin);
    freopen("CONOUT$", "w", stderr);
    freopen("CONOUT$", "w", stdout);
    cout << "Hello there!\n";
    if (!col.is_open())
      cerr << "Failed to open the logging file.\n";
  }
  else // allocating console failed.
  {
    col << "Allocating console failed with error code "
        << GetLastError() << '\n';
    // Proceed or exit.
  }
  #endif

  // Initialization.
  // http://wiki.libsdl.org/SDL_Init
  int e = SDL_Init(SDL_INIT_VIDEO);
  if (e != 0)
  { // http://wiki.libsdl.org/SDL_GetError
    col << "SDL_Init failure: " << SDL_GetError();
    return 1;
  }

  // http://wiki.libsdl.org/SDL_CreateWindow
  window = SDL_CreateWindow("SDL minimal application",
      SDL_WINDOWPOS_UNDEFINED,
      SDL_WINDOWPOS_UNDEFINED, 
      WINDOW_WIDTH, 
      WINDOW_HEIGHT,
      SDL_WINDOW_SHOWN);
  if (!window)
  {
    col << "SDL_CreateWindow failure: " 
        << SDL_GetError();
    return 2;
  }

  // http://wiki.libsdl.org/SDL_GetWindowSurface
  surface = SDL_GetWindowSurface(window);
  if (!surface)
  {
    col << "SDL_GetWindowSurface failure: " 
        << SDL_GetError();
    return 3;
  }

  // Fill the window with some color...
  // http://wiki.libsdl.org/SDL_FillRect
  SDL_FillRect(surface, nullptr,
      SDL_MapRGB(surface->format, 0x4F, 0x00, 0xEE));
      // http://wiki.libsdl.org/SDL_MapRGB
  // http://wiki.libsdl.org/SDL_UpdateWindowSurface
  SDL_UpdateWindowSurface(window);
  // ... and wait for two seconds.
  // http://wiki.libsdl.org/SDL_Delay
  SDL_Delay(2000);
  
  // We are done, finalizing.
  // http://wiki.libsdl.org/SDL_DestroyWindow
  SDL_DestroyWindow(window);
  // http://wiki.libsdl.org/SDL_Quit
  SDL_Quit();
  col << "Application finished.\n";
  return 0;
}

UPD. Могут быть проблемы с вводом при присоединении консоли процесса-предка. В этом случае рекомендуется оставить AllocConsole: пусть будет своя, но нормально работающая консоль.

Групповая операция на основе операции возведения в степень

Недавно наткнулся на пусть очевидный в общем-то при ближайшем рассмотрении, но всё же интересный факт:

(\forall a\in R)(\forall b\in R)\ a^{\ln{b}} = b^{\ln{a}},
R = \{\,x\in\mathbb R\mid x>0 \land x\neq 1\,\} = \mathbb R_+\setminus\{1\}.

Коммутативность данной операции

a\ast b\colon R\times R \to a^{\ln{b}}\colon R

очевидна ввиду тождества

a^{\ln{b}} \equiv \exp(\ln{a}\ln{b})

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

Нейтральный элемент e = \exp 1 (можно ввести аналоги для других оснований):

a\ast e = e\ast a = \exp{\ln{a}} = a.

Обратный элемент для некоторого a также получить не трудно:

a\ast b = e \Leftrightarrow b = \exp\dfrac{1}{\ln b} = e\ast \log_b{e}.

Обычная единица может играть роль нуля кольца (не имеет обратного элемента, аналогом сложения тогда выступает умножение, легко показать дистрибутивность) и при подстановке 1 в определение операции получаем:

1\ast a = a\ast 1 = 1.

Вообще, вся конструкция (\mathbb R_+, \cdot, \ast) образует поле.

Простые годы

18 век

1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789

19 век

1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889

20 век

1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999

21 век

2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099

Каждый механик должен знать …

… что декларирует государственный образовательный стандарт касательно его (механика) специальности (механика и математическое моделирование):