ГЛАВНАЯ RU typewriter

older-tomato

Вращаем квадрат на плоскости

Линейная алгебра • Матрица поворота 05.01.2023

Напишем алгоритм на JavaScript для поворота квадрата на угол вокруг своего центра, повторим программу средней школы. Для расчётов будем использовать класс Math, а для отображения результатов — Canvas.

Развитие мысли, объёмная модель: Вращаем куб в пространстве.

Поворот точки на плоскости #

Рассчитываем координаты новой точки по формулам матрицы поворота для двухмерного пространства. Поворачиваем точку t относительно точки t0 — получаем точку t'.

&x'=x_0+(x-x_0)cos\varphi-(y-y_0)sin\varphi,&\\&y'=y_0+(x-x_0)sin\varphi+(y-y_0)cos\varphi.&\\

Описание алгоритма #

Начало координат находится в верхнем левом углу, координатные оси направлены вправо и вниз. Центральная точка для поворотов t0 расположена в центре фигуры. Квадрат — это массив из четырёх точек-вершин. Обходим массив точек, поворачиваем каждую из них на угол, затем соединяем точки линиями и рисуем линии на холсте. Обновляем картинку с частотой 20 кадров в секунду.

Реализация #

Холст для отображения результатов вычислений

HTML #

<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
  <p>Холст для отображения результатов вычислений</p>
</canvas>

JavaScript #

'use strict';
let canvas = document.getElementById('canvas');
// исходный массив точек-вершин квадрата
let square = [{x:50,y:50},{x:50,y:250},{x:250,y:250},{x:250,y:50}];
// центр фигуры, вокруг него будем выполнять поворот
let t0 = {x:150, y:150};
// угол поворота в градусах
let deg = 1;
// поворот фигуры и обновление изображения
function repaint() {
  // поворачиваем исходный массив точек на угол
  for (let i = 0; i < square.length; i++)
    square[i] = rotateOnDegree(t0, square[i], deg);
  // рисуем текущий массив точек
  drawFigure(canvas, square);
}
// поворачиваем точку (t) на угол (deg) относительно точки (t0)
function rotateOnDegree(t0, t, deg) {
  let t_new = {};
  // переводим угол поворота из градусов в радианы
  let rad = (Math.PI / 180) * deg;
  // рассчитываем координаты новой точки по формуле
  t_new.x = t0.x+(t.x-t0.x)*Math.cos(rad)-(t.y-t0.y)*Math.sin(rad);
  t_new.y = t0.y+(t.x-t0.x)*Math.sin(rad)+(t.y-t0.y)*Math.cos(rad);
  // возвращаем новую точку
  return t_new;
}
// рисуем фигуру по точкам из массива
function drawFigure(canvas, arr) {
  let context = canvas.getContext('2d');
  // очищаем весь холст целиком
  context.clearRect(0, 0, canvas.width, canvas.height);
  // обходим массив точек и соединяем их линиями
  context.beginPath();
  for (let i = 0; i < arr.length; i++)
    if (i == 0)
      context.moveTo(arr[i].x, arr[i].y);
    else
      context.lineTo(arr[i].x, arr[i].y);
  context.closePath();
  // рисуем линии на холсте
  context.lineWidth = 2.2;
  context.strokeStyle = '#222';
  context.stroke();
}
// после загрузки страницы, задаём частоту обновления изображения 20 Гц
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));

Вращение в обратную сторону #

Добавим ещё одну точку, которую будем вращать в обратную сторону. Точка удалена от центра фигуры на четверть длины стороны квадрата. Сместим центр квадрата в эту точку — сдвинем массив его вершин. Сам квадрат будем вращать по часовой стрелке, а его центральную точку — против часовой стрелки. Этот код работает вместе с предыдущим.

Холст для отображения результатов вычислений

HTML #

<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
  <p>Холст для отображения результатов вычислений</p>
</canvas>

JavaScript #

'use strict';
let canvas2 = document.getElementById('canvas2');
// текущий массив точек
let square2 = [];
// вращающаяся точка
let t2 = {x:100, y:100};
// поворот фигуры и обновление изображения
function repaint2() {
  // поворачиваем точку в обратную сторону
  t2 = rotateOnDegree(t0, t2, -deg);
  // обходим точки исходного массива и сдвигаем
  for (let i = 0; i < square.length; i++) {
    // текущая точка
    square2[i] = {};
    // сдвигаем точку исходного массива
    square2[i].x = square[i].x - t0.x + t2.x;
    square2[i].y = square[i].y - t0.y + t2.y;
  }
  // рисуем текущий массив точек
  drawFigure(canvas2, square2);
}
// после загрузки страницы, задаём частоту обновления изображения 20 Гц
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint2,50));

© Головин Г.Г., Код с комментариями, 2023