Матч
21, Фиксированная точка (FixedPoint)
Карта Байтляндии была создана следующими
тремя трансформациями:
1. Масштабирование с
коэффициентом scale. Каждая точка плоскости (x, y) перешла в точку (scale*x, scale*y).
2. Сдвиг на вектор translate.
Каждая точка плоскости (x, y) перешла в точку (x + translate[0], y + translate[1]).
3. Вращение на угол rotate (в радианах). Каждая точка
плоскости (x, y) перешла в точку (x * cos(rotate) – y*sin(rotate), y * cos(rotate) + x*sin(rotate)).
Фиксированной называется точка,
удовлетворяющая следующим условиям:
(scale * cos(rotate) – 1) * x – scale * sin(rotate) * y =
-translate[0] * cos(rotate) +
translate[1] * sin(rotate)
scale * sin(rotate) * x + (scale * cos(rotate) – 1) * y =
-translate[0] * sin(rotate) –
translate[1] * cos(rotate)
Решите систему и верните
координаты фиксированной точки в виде вектора из двух компонент (x, y).
Система всегда имеет единственное решение.
Класс: FixedPoint
Метод: vector<double>
find(double scale,
vector<double>
translate,double rotate)
Ограничения:
address1 и address2 содержат от 0 до 50
символов ‘a’ – ‘z’, ‘A’ – ‘Z’, ‘0’ – ‘9’.
Вход. Коэффициент масштабирования scale,
вектор параллельного переноса translate и угол поворота rotate.
Выход. Координаты фиксированной точки в виде вектора (x, y).
Пример входа
scale |
translate |
rotate |
0.5 |
{1, 0} |
1.5707963267948966 |
0.5 |
{2, 0} |
0 |
0.5 |
{1, 2} |
0.785398163397 |
Пример выхода
{-0.4, 0.8}
{4.0, 0.0}
{-2.223469992542095, 2.065452845425795}
РЕШЕНИЕ
алгебра, система линейных
уравнений, метод Крамера
Обозначим:
A = (scale * cos(rotate) – 1);
B = scale * sin(rotate);
C = -translate[0] * cos(rotate) + translate[1] * sin(rotate);
D = -translate[0] * sin(rotate) - translate[1] * cos(rotate);
Остается решить методом Крамера
систему линейных уравнений в действительных числах:
По условию задачи она всегда
имеет единственное решение.
ПРОГРАММА
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
void kramer(double a1,double b1, double c1,
double a2,double
b2, double c2,
double *x, double *y)
{
double d = a1 * b2 - a2 * b1;
double dx = c1 * b2 - c2 * b1;
double dy = a1 * c2 - a2 * c1;
*x = dx / d; *y = dy / d;
}
class FixedPoint
{
public:
vector<double> find(double scale, vector<double>
translate, double rotate)
{
vector<double> res(2);
double A = (scale * cos(rotate) - 1);
double B = scale * sin(rotate);
double C = -translate[0] * cos(rotate) +
translate[1] * sin(rotate);
double D = -translate[0] * sin(rotate) -
translate[1] * cos(rotate);
kramer(A,-B,C,B,A,D,&res[0],&res[1]);
return res;
}
};