Координаты центра отрезка на плоскости найти очень легко, нужно найти две точки: абсциссу (точку Х), ординату (точку Y). Придумали же названий. Есть отрезок, у него две точки, одна точка — точка его начала, другая точка — точка его конца. У каждой точки есть внутри два обозначения. Одно X, другое Y.
Вычисляется центр по формуле:
Для примера:
Отрезок (5,90;99,200);
Первая точка отрезка (5,90), вторая (99,200).
X = (5 + 99) / 2 = 52;
Y = (90 + 200) / 2 = 145;
Точка центра == (52,145);
Вот и вся премудрость нахождения. Просто не все это знают.
Вокруг произвольной точки (x0,y0) точку можно повернуть используя формулу:
Здесь:
— xn и yn — это две единые составляющие новой координаты. (Просто новый Х и новый Y)
— x и y — это две единые составляющие координаты той точки, которая вращается (будет вращаться).
— x0 и y0 — это две единые составляющие координаты той точки, вокруг которой вращается другая точка. (в нашем случае это две единые составляющие координаты центра отрезка)
— alpha — угол, на сколько вращаем.
Это всё, что достаточно знать для вращения отрезка на плоскости вокруг своего центра.
В примере использовано рисование с помощью WinApi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
#include <windows.h> #include <iostream> #include <cmath> using namespace std; HWND hwnd = GetConsoleWindow(); HDC dc = GetDC(hwnd); const double M_PI = 3.1415926535897932384626433832795; /*НАШ ОТРЕЗОК*/ class Line{ double X0,X1,Y0,Y1; //Точки начала и конца public: /*Конструкторы*/ Line():X0(1),Y0(1),X1(1),Y1(1){}; Line(const int T1,const int T2, const int T3, const int T4):X0(T1),X1(T3),Y0(T2),Y1(T4){}; /*Функции-члены для рисования*/ void Draw() const; //Рисовка void Clear() const; //Затирка void Rotate(const double &alpha); //Поворот }; /*Рисуем*/ void Line::Draw() const{ HPEN pen=CreatePen(PS_SOLID,1,RGB(255,255,255)); SelectObject(dc,pen); MoveToEx(dc,X0,Y0,(LPPOINT) NULL); LineTo(dc,X1,Y1); DeleteObject (pen); } /* Стираем */ void Line::Clear() const{ HPEN pen=CreatePen(PS_SOLID,1,RGB(0,0,0)); SelectObject(dc,pen); MoveToEx(dc,X0,Y0,(LPPOINT) NULL); LineTo(dc,X1,Y1); DeleteObject (pen); } /*Поворачиваем*/ void Line::Rotate(const double &alpha){ double eps = M_PI/180; //Это для последующего перевода в радианы double y0 = (Y0+Y1)/2; //Ищем точку Y центра отрезка double x0 = (X0+X1)/2; //Ищем точку X центра отрезка double y,x; //Это для удобства чтения double tempX0,tempX1,tempY0,tempY1; //Для того, чтобы сблизить функции draw() и clear() /*РАСЧЁТ ПО ПЕРВОЙ ТОЧКЕ*/ x = X0, y = Y0; tempX0 = -sin(alpha * eps) * (y-y0) + cos(alpha * eps) * (x-x0) + x0; tempY0 = cos(alpha * eps) * (y-y0) + sin(alpha * eps) * (x-x0) + y0; /*РАСЧЁТ ПО ВТОРОЙ ТОЧКЕ*/ x = X1, y =Y1; tempX1 = -sin(alpha * eps)*(y-y0)+cos(alpha * eps)*(x-x0)+x0; tempY1 = cos(alpha * eps)*(y-y0)+sin(alpha * eps)*(x-x0)+y0; Clear(); //Пока не обновились координаты, стираем нарисованное X0 = tempX0, X1 = tempX1, Y0 = tempY0, Y1 = tempY1; //обновление координат Draw(); //Рисуем с новыми координатами } int main(){ cout << "MyProg!"; Line line(200,200,500,230); //Какой-то отрезок line.Draw(); /*Выводим на экран*/ for (auto i = 0; i<360*50;i++){ dc = GetDC(hwnd); line.Rotate(1); Sleep(10); ReleaseDC (hwnd,dc); } } |
Основная угроза происходит из неявных преобразований. Так, можно напороться на вычисления с погрешностью, которая способна сильно повлиять на результат. Будьте внимательны, если делаете что-то своё, ориентируясь на эту статью.
Во время перерисовки лучше, чтобы функция стирания шла непосредственно перед функцией рисования, разделяясь обновлением координат. В противном случае вычисления могут повлиять на время работы, и это может сказаться, например на плавности анимации.
Добавить комментарий