need then one plane radial grid within X(horizontal) position through the same relative X(horizontal) rotation of planets around the Sun.
If you want to use a radial grid in the X(horizontal) plane relative to the rotation of the planets around the Sun, you can modify the drawGrid function to calculate the position of each grid line based on its distance from the Sun’s position along the X(horizontal) axis. Here’s an example of how you could modify the function to achieve this:


function drawGrid() {
  const gridSpacing = 100;

  // Find the minimum and maximum X(horizontal) positions of the planets
  const minPosX = Math.min(sunPos.x, mercuryPos.x, venusPos.x, earthPos.x);
  const maxPosX = Math.max(sunPos.x, mercuryPos.x, venusPos.x, earthPos.x);

  // Draw grid lines that lie on the X(horizontal) axis
  ctx.beginPath();
  ctx.strokeStyle = “rgba(255, 255, 255, 0.2)”;
  for (let i = Math.floor(minPosX / gridSpacing) * gridSpacing; i <= maxPosX; i += gridSpacing) {
    const p1 = { x: i, y: -gridSize, z: 0 };
    const p2 = { x: i, y: gridSize, z: 0 };
    ctx.moveTo(projectTo2D(p1.x, p1.y, p1.z).x, projectTo2D(p1.x, p1.y, p1.z).y);
    ctx.lineTo(projectTo2D(p2.x, p2.y, p2.z).x, projectTo2D(p2.x, p2.y, p2.z).y);
  }
  ctx.stroke();
  ctx.closePath();
}



In this modified version, the minPosX and maxPosX variables are calculated as the minimum and maximum X(horizontal) positions of the planets. The for loop then iterates over the X(horizontal) positions within the range of minPosX and maxPosX, with a step size of gridSpacing. For each position, p1 and p2 are calculated with the X(horizontal) position as the x coordinate and gridSize as the
and min/max grid size is irrelevant in that case? : const canvas = document.createElement('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);

const ctx = canvas.getContext('2d');

const sunPos = { x: 0, y: 0, z: 0, size: 20 };
const mercuryPos = { x: 50, y: 0, z: 0, size: 3 };
const venusPos = { x: 70, y: 0, z: -10, size: 4 };
const earthPos = { x: 100, y: 0, z: 0, size: 5 };

let rotation = { x: 0, y: 0, z: 0 };

function drawSolarSystem() {
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);

function drawGrid() {
const gridSize = 1000;
const gridSpacing = 50;



// Find the normal vector of the orbital plane by taking the cross-product of the positions
// of two planets that are not collinear with the Sun (in this case, Mercury and Earth)
const v1 = { x: earthPos.x - sunPos.x, y: earthPos.y - sunPos.y, z: earthPos.z - sunPos.z };
const v2 = { x: mercuryPos.x - sunPos.x, y: mercuryPos.y - sunPos.y, z: mercuryPos.z - sunPos.z };
const normal = {
x: v1.y * v2.z - v1.z * v2.y,
y: v1.z * v2.x - v1.x * v2.z,
z: v1.x * v2.y - v1.y * v2.x
};

// Normalize the normal vector to get the direction of the orbital plane
const length = Math.sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z);
const planeDir = { x: normal.x / length, y: normal.y / length, z: normal.z / length };

// Calculate a point on the plane by projecting the Sun position onto it
const planePos = {
x: sunPos.x - (sunPos.x * planeDir.x + sunPos.y * planeDir.y + sunPos.z * planeDir.z) * planeDir.x,
y: sunPos.y - (sunPos.x * planeDir.x + sunPos.y * planeDir.y + sunPos.z * planeDir.z) * planeDir.y,
z: sunPos.z - (sunPos.x * planeDir.x + sunPos.y * planeDir.y + sunPos.z * planeDir.z) * planeDir.z
};

// Draw grid lines that lie on the orbital plane
ctx.beginPath();
ctx.strokeStyle = 'rgba(255,255,255,0.2)';
for (let i = -gridSize; i <= gridSize; i += gridSpacing) {
const p1 = {
x: planePos.x + (i * planeDir.x),
y: planePos.y + (i * planeDir.y),
z: planePos.z + (i * planeDir.z)
};
const p2 = {
x: planePos.x + (i * planeDir.x),
y: planePos.y + (i * planeDir.y) + (gridSize * planeDir.z),
z: planePos.z + (i * planeDir.z) - (gridSize * planeDir.y)
};
ctx.moveTo(projectTo2D(p1.x, p1.y, p1.z).x, projectTo2D(p1.x, p1.y, p1.z).y);
ctx.lineTo(projectTo2D(p2.x, p2.y, p2.z).x, projectTo2D(p2.x, p2.y, p2.z).y);
}
ctx.stroke();
ctx.closePath();
}
drawGrid();

// Draw Milky Way background
ctx.globalCompositeOperation = "lighter";
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = "lighter";
for (let i = 0; i < 1000; i++) {
const size = Math.random() * 2;
const x = Math.random() * canvas.width;
const y = Math.random() * canvas.height;
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fillStyle = 'rgba(255, 255, 255, ' + 0.1 + ')';
ctx.fill();
}

// Draw the Sun
const sunPos2D = projectTo2D(sunPos.x, sunPos.y, sunPos.z);
drawPlanet(sunPos2D.x, sunPos2D.y, sunPos.size, '#ffcc00');

// Draw Mercury
const mercPos2D = projectTo2D(mercuryPos.x - sunPos.x, mercuryPos.y - sunPos.y, mercuryPos.z - sunPos.z);
drawPlanet(mercPos2D.x, mercPos2D.y, mercuryPos.size, '#ff6666');

// Draw Venus
const venusPos2D = projectTo2D(venusPos.x - sunPos.x, venusPos.y - sunPos.y, venusPos.z - sunPos.z);
drawPlanet(venusPos2D.x, venusPos2D.y, venusPos.size, '#ffa500');

// Draw Earth
const earthPos2D = projectTo2D(earthPos.x - sunPos.x, earthPos.y - sunPos.y, earthPos.z - sunPos.z);
drawPlanet(earthPos2D.x, earthPos2D.y, earthPos.size, '#6699ff');

// Update planet positions for the next frame
updatePlanetPositions();

// Update rotation angles based on mouse position
let isDragging = false;
let initialMousePos = { x: 0, y: 0 }; // store initial mouse position when dragging starts
let currentRotation = { x: rotation.x, y: rotation.y }; // initialize current rotation angles to the current rotation
let prevRotation = { x: 0, y: 0 }; // store previous (last) rotation angles

canvas.addEventListener('mousedown', function (event) {
isDragging = true;
initialMousePos.x = event.clientX;
initialMousePos.y = event.clientY;
prevRotation.x = currentRotation.x; // store previous rotation angles
prevRotation.y = currentRotation.y;
});

canvas.addEventListener('mouseup', function (event) {
isDragging = false;
});

canvas.addEventListener('mousemove', function (event) {
if (isDragging) {
// calculate new rotation angles based on difference between current mouse position and initial mouse position
currentRotation.x = prevRotation.x + (event.clientY - initialMousePos.y) / canvas.height * Math.PI;
currentRotation.y = prevRotation.y + (event.clientX - initialMousePos.x) / canvas.width * Math.PI;

// update lastRotation whenever rotation angles are set to new values
if (currentRotation.x !== prevRotation.x || currentRotation.y !== prevRotation.y) {
rotation.x = currentRotation.x;
rotation.y = currentRotation.y;
}
}
});
}

function updatePlanetPositions() {
// Update Mercury's position
mercuryPos.x = 50 * Math.cos(Date.now() / 1000);
mercuryPos.z = 50 * Math.sin(Date.now() / 1000);

// Update Venus's position
venusPos.x = 70 * Math.cos(Date.now() / 1500);
venusPos.z = -10 * Math.sin(Date.now() / 1500);

// Update Earth's position
earthPos.x = 100 * Math.cos(Date.now() / 2000);
earthPos.z = 100 * Math.sin(Date.now() / 2000);
}

function drawPlanet(x, y, size, color) {
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
ctx.closePath();
}

function projectTo2D(x, y, z) {
const fov = 90; // Field of view angle in degrees
const distance = canvas.width / 2 / Math.tan(fov / 2 * Math.PI / 180);

const cosX = Math.cos(rotation.x);
const sinX = Math.sin(rotation.x);
const cosY = Math.cos(rotation.y);
const sinY = Math.sin(rotation.y);
const cosZ = Math.cos(rotation.z);
const sinZ = Math.sin(rotation.z);

const x1 = x * cosY * cosZ - y * cosY * sinZ + z * sinY;
const y1 = x * (sinX * sinY * cosZ + cosX * sinZ) + y * (sinX * sinY * sinZ - cosX * cosZ) - z * sinX * cosY;
const z1 = x * (cosX * sinY * cosZ - sinX * sinZ) + y * (cosX * sinY * sinZ + sinX * cosZ) + z * cosX * cosY;

const scale = distance / (distance + z1);
const x2d = canvas.width / 2 + x1 * scale;
const y2d = canvas.height / 2 - y1 * scale;

return { x: x2d, y: y2d };
}
// Update planet positions for the next frame
function update() {
updatePlanetPositions();
drawSolarSystem();
requestAnimationFrame(update);
}

update();