How does scaling operator (*) work in PostgreSQL?

Viewed 108

I just started learning PostgreSQL and I cannot figure out how does scaling operator work on geometric types.

For example select '((1, 1), (0, 0))'::box * '(2, 0)'::point; returns ((2,2),(0,0))

and select '((1, 1), (0, 0))'::box * '(0, 2)'::point; returns ((0,2),(-2,0))

so in both cases box gets scaled by the factor of 2 (for both axes), but the way box is moved makes no sense to me.

Official documentation only shows one example of usage of this operator and nothing about how it works.

If someone knows a better resource for learning PostgreSQL please share it.

Thanks in advance.

1 Answers

Here is implementation of the function box_mul that stays behind the *(box, point) operator (from 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);
}

or translated to the more "human" language:

((x1, y1), (x2, y2)) * (x, y) :- ((x1*x - y1*y, x1*y + y1*x), (x2*x - y2*y, x2*y + y2*x))

For your example

((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))

and finally box_construct() transforms it to (0,2),(-2,0) (just check select '((-2,2),(0,0))'::box;)

If you know/remember the geometric meaning of those transformations - post your final answer here.

Related