Сортировка точек по часовой стрелке - PullRequest
0 голосов
/ 16 февраля 2019

Если у меня есть список точек [(x1,y1), (x2,y2), (x3,y3)...], могу ли я как-то расположить их по часовой стрелке?

По часовой стрелке я имею в виду по часовой стрелке относительно центра фигуры.

1 Ответ

0 голосов
/ 16 февраля 2019

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

Затем вам нужно вычислить угол, под которым точки находятся относительноцентр и ось x.Чтобы вычислить угол, вы можете использовать Math.atan2(y - center.y, x - center.x).

. Затем вы упорядочите точки по углу, используя Array.sort.

. После правильного упорядочения точек вы сможете нарисовать линию.который соединяет точки и не пересекает себя.Я сделал демо, используя холст.Начальная точка показана квадратом.Я нарисовал ось x/y, переведенную в центр тяжести ваших точек.Я также добавил линии, соединяющие точки с центроидом, чтобы материализовать их углы.

const width = 250;
const height = 250;

// Random points
const points = Array.from({ length: 20 }, () =>
  ({ x: Math.random() * width, y: Math.random() * height })
);

// Get the center (mean value) using reduce
const center = points.reduce((acc, { x, y }) => {
  acc.x += x / points.length;
  acc.y += y / points.length;
  return acc;
}, { x: 0, y: 0 });

// Add an angle property to each point using tan(angle) = y/x
const angles = points.map(({ x, y }) => {
  return { x, y, angle: Math.atan2(y - center.y, x - center.x) * 180 / Math.PI };
});

// Sort your points by angle
const pointsSorted = angles.sort((a, b) => a.angle - b.angle);

// Draw them
const canvas = document.querySelector('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
let lastPoint = pointsSorted[0];

ctx.fillRect(lastPoint.x, lastPoint.y, 5, 5);

ctx.beginPath();
ctx.moveTo(0, center.y);
ctx.lineTo(width, center.y);
ctx.strokeStyle = 'black';
ctx.stroke();

ctx.beginPath();
ctx.moveTo(center.x, 0);
ctx.lineTo(center.x, height);
ctx.strokeStyle = 'black';
ctx.stroke();  

pointsSorted.forEach(({ x, y }) => {
  ctx.beginPath();
  ctx.moveTo(lastPoint.x, lastPoint.y);
  ctx.lineTo(x, y);
  ctx.strokeStyle = 'red';
  ctx.stroke();  
  
  ctx.fillRect(x, y, 2, 2);
  
  ctx.beginPath();
  ctx.moveTo(center.x, center.y);
  ctx.lineTo(x, y);
  ctx.strokeStyle = 'grey';
  ctx.stroke();  
  
  lastPoint = { x, y };
});
canvas {
  border: 1px solid black;
}
<canvas></canvas>

Надеюсь, это поможет!

...