1/jekyll_site/ru/2023/01/05/spinning-square-on-plane.md
2023-12-17 07:55:25 +03:00

7.3 KiB
Raw Blame History

title description sections tags scripts canonical_url url_translated title_translated date
Вращаем квадрат на плоскости Напишем алгоритм на JavaScript для поворота квадрата на угол вокруг своего центра, повторим программу средней школы. Для расчётов будем использовать класс...
Линейная алгебра
Матрица поворота
javascript
canvas
геометрия
графика
изображение
картинка
квадрат
/js/spinning-square.js
/js/spinning-square2.js
/ru/2023/01/05/spinning-square-on-plane.html /en/2023/01/06/spinning-square-on-plane.html Spinning square on plane 2023.01.05

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

Развитие мысли, объёмная модель: [Вращаем куб в пространстве]({{ '/ru/2023/01/10/spinning-cube-in-space.html' | relative_url }}).

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

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

{% include image_svg.html src="/img/column-vector2d.svg" style="width: 246.793pt; height: 37.2836pt;" alt="&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 кадров в секунду.

Реализация

Ваш браузер не поддерживает Canvas

HTML

<canvas id="canvas" width="300" height="300" style="border: 1px solid gray;">
  <p>Ваш браузер не поддерживает Canvas</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();
}
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint,50));

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

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

Ваш браузер не поддерживает Canvas

HTML

<canvas id="canvas2" width="300" height="300" style="border: 1px solid gray;">
  <p>Ваш браузер не поддерживает Canvas</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);
}
// после загрузки страницы, задаём интервал обновления изображения
document.addEventListener('DOMContentLoaded',()=>setInterval(repaint2,50));