How to rotate a group of objects together

38 Views Asked by At

How can I rotate a group of objects together, that is, I don't want to rotate each object individually, because that way they will collide.

Here is an example when rotating individually:

rotate-wrong

I need to rotate the entire group, so I would have this result:

rotate

I tried in several ways to create a function with JavaScript capable of doing this calculation, but every attempt I made was not correct.

interface Plate {
  x: number;
  y: number;
  angle: number;
  width: number;
  height: number;
}

interface RotateGroup {
  plates: Plate[];
  centerX: number;
  centerY: number;
  angle: number;
}

interface GroupInfo {
  x: number;
  y: number;
  centerX: number;
  centerY: number;
  area: number;
}

function calculateGroupArea(plates: Plate[]): GroupInfo {
  let minX = Infinity;
  let minY = Infinity;
  let maxX = -Infinity;
  let maxY = -Infinity;

  plates.forEach(plate => {
    minX = Math.min(minX, plate.x);
    minY = Math.min(minY, plate.y);
    maxX = Math.max(maxX, plate.x + plate.width);
    maxY = Math.max(maxY, plate.y + plate.height);
  });

  const width = maxX - minX;
  const height = maxY - minY;
  const area = width * height;

  const centerX = (minX + maxX) / 2;
  const centerY = (minY + maxY) / 2;

  return {
    x: minX,
    y: minY,
    centerX,
    centerY,
    area,
  };
}

function rotateGroup({
  plates,
  centerX,
  centerY,
  angle,
}: RotateGroup): Plate[] {
  const rad = angle * (Math.PI / 180); // Converting degrees to radians

  plates.forEach(plate => {
    // Translate plate to origin
    const translatedX = plate.x - centerX;
    const translatedY = plate.y - centerY;

    // Rotate the plate
    const rotatedX = translatedX * Math.cos(rad) - translatedY * Math.sin(rad);
    const rotatedY = translatedX * Math.sin(rad) + translatedY * Math.cos(rad);

    // Translate the plate back
    plate.x = rotatedX + centerX;
    plate.y = rotatedY + centerY;

    // Update the angle of the plate
    plate.angle += angle;
  });

  return plates;
}

const plates: Plate[] = [
  {
    x: 10,
    y: 10,
    angle: 0,
    width: 50,
    height: 100,
  },
  {
    x: 60,
    y: 10,
    angle: 0,
    width: 50,
    height: 100,
  },
  {
    x: 110,
    y: 10,
    angle: 0,
    width: 50,
    height: 100,
  },
];

console.log('calculateGroupArea: ', calculateGroupArea(plates));
console.log(
  'rotateGroup: ',
  rotateGroup({
    plates,
    angle: 45,
    centerX: 85,
    centerY: 60,
  }),
);

The result always looks like this:

rotate-wrong-2