Как работает оператор масштабирования (*) в PostgreSQL? - PullRequest
0 голосов
/ 29 августа 2018

Я только начал изучать PostgreSQL и не могу понять, как работает оператор масштабирования для геометрических типов.

Например select '((1, 1), (0, 0))'::box * '(2, 0)'::point; возвращает ((2,2),(0,0))

и select '((1, 1), (0, 0))'::box * '(0, 2)'::point; возвращает ((0,2),(-2,0))

так что в обоих случаях окно масштабируется в 2 раза (для обеих осей), но способ перемещения ящика для меня не имеет смысла.

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

Если кто-то знает лучший ресурс для изучения PostgreSQL, поделитесь им.

Заранее спасибо.

1 Ответ

0 голосов
/ 29 августа 2018

Вот реализация функции box_mul, которая стоит за оператором *(box, point) (от https://github.com/postgres/postgres/blob/master/src/backend/utils/adt/geo_ops.c):

static inline void
point_mul_point(Point *result, Point *pt1, Point *pt2)
{
    point_construct(result,
                    float8_mi(float8_mul(pt1->x, pt2->x),
                              float8_mul(pt1->y, pt2->y)),
                    float8_pl(float8_mul(pt1->x, pt2->y),
                              float8_mul(pt1->y, pt2->x)));
}

Datum
box_mul(PG_FUNCTION_ARGS)
{
    BOX        *box = PG_GETARG_BOX_P(0);
    Point      *p = PG_GETARG_POINT_P(1);
    BOX        *result;
    Point       high,
                low;

    result = (BOX *) palloc(sizeof(BOX));

    point_mul_point(&high, &box->high, p);
    point_mul_point(&low, &box->low, p);

    box_construct(result, &high, &low);

    PG_RETURN_BOX_P(result);
}

или переведено на более "человеческий" язык:

((x<sub>1</sub>, y<sub>1</sub>), (x<sub>2</sub>, y<sub>2</sub>)) * (x, y) :- ((x<sub>1</sub>*x - y<sub>1</sub>*y, x<sub>1</sub>*y + y<sub>1</sub>*x), (x<sub>2</sub>*x - y<sub>2</sub>*y, x<sub>2</sub>*y + y<sub>2</sub>*x))

Для вашего примера

((1,1),(0,0)) * (0,2) = ((1*0 - 1*2, 1*2 + 1*0), (0*0 - 0*2, 0*2 + 0 * 0)) = ((-2,2),(0,0))

и, наконец, box_construct() преобразует его в (0,2),(-2,0) (просто отметьте select '((-2,2),(0,0))'::box;)

Если вы знаете / помните геометрический смысл этих преобразований - опубликуйте свой окончательный ответ здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...