try finish and improve overally correct on the fly this code. the purpose is to draw a matrix by lines with ability to attach and detach lines to construct the model in 3d matrix representation array visually building the model by dragging lines and atach to other lines. output full awesome code. : // Define canvas and context
const canvas = document.createElement(‘canvas’);
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);

const ctx = canvas.getContext(‘2d’);

// Define vertices and edges
let vertices = [
{x: 0.5, y: 0.5, z: -1, color: “#FF0000”},
{x: -0.3, y: -0.5, z: -1, color: “#00FF00”},
{x: -0.3, y: 0.8, z: -1, color: “#0000FF”},
{x: 0.5, y: -0.5, z: -1, color: “#FFFF00”},
{x: -0.5, y: -0.5, z: -1, color: “#FF00FF”},
{x: 0.5, y: 0.5, z: 1, color: “#00FFFF”},
{x: -0.3, y: -0.5, z: 1, color: “#000000”},
{x: -0.3, y: 0.8, z: 1, color: “#FFFFFF”},
];

let edges = [
[0, 1], // Connect vertex 0 to 1
[0, 2], // Connect vertex 0 to 2
[1, 2], // Connect vertex 1 to 2
[3, 4], // Connect vertex 3 to 4
[0, 3], // Connect vertex 0 to 3
[2, 5], // Connect vertex 2 to 5
[1, 6], // Connect vertex 1 to 6
[2, 7], // Connect vertex 2 to 7
[4, 5], // Connect vertex 4 to 5
[3, 7], // Connect vertex 3 to 7
[4, 6], // Connect vertex 4 to 6
[5, 7], // Connect vertex 5 to 7
];

// Define initial rotation and scale values
let angleX = 0;
let angleY = 0;
let angleZ = 0;
let scale = 0.025;
let zoom = 1;

// Define drag and drop variables
let indexToDrag = -1;
let lineToAttach = -1;

// Draw the matrix
function render() {
// Clear screen
ctx.fillStyle = “#FFF”;
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Calculate new rotated vertices
const rotX = rotateX(angleX);
const rotY = rotateY(angleY);
const rotZ = rotateZ(angleZ);

let rotatedVertices = vertices.map((vertex) => {
const cx = vertex.x;
const cy = vertex.y;
const cz = vertex.z;

const rotated = transform(transform(transform([cx, cy, cz], rotX), rotY), rotZ);
return {
x: rotated[0],
y: rotated[1],
z: rotated[2],
color: vertex.color
};
});

// Draw lines between vertices
ctx.strokeStyle = “black”;
ctx.beginPath();
edges.forEach((edge) => {
const [v1, v2] = edge;

const [screenX1, screenY1] = project(rotatedVertices[v1].x, rotatedVertices[v1].y, rotatedVertices[v1].z);
const [screenX2, screenY2] = project(rotatedVertices[v2].x, rotatedVertices[v2].y, rotatedVertices[v2].z);

ctx.moveTo(screenX1, screenY1);
ctx.lineTo(screenX2, screenY2);
});
ctx.stroke();

// Draw circles on vertices
ctx.beginPath();
rotatedVertices.forEach((vertex) => {
ctx.fillStyle = vertex.color;
drawCircle(ctx, project(vertex.x, vertex.y, vertex.z), 5);
ctx.fill();
});

requestAnimationFrame(render);
}

// Event listeners for drag and drop
canvas.addEventListener(“mousedown”, hover);
canvas.addEventListener(“mousemove”, drag);
canvas.addEventListener(“mouseup”, release);

function hover(event) {
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;

let closestDistance = Infinity;
let closestIndex = -1;

vertices.forEach((vertex, index) => {
let [screenX, screenY] = project(vertex.x, vertex.y, vertex.z);
let distance = Math.sqrt((x - screenX) ** 2 + (y - screenY) ** 2);
if (distance < closestDistance) {
closestDistance = distance;
closestIndex = index;
}
});

if (closestDistance < 10) {
indexToDrag = closestIndex;
} else {
indexToDrag = -1;
}

// Check for line attachment
edges.forEach((edge, index) => {
const [v1, v2] = edge;
if(rotatedVertices[v1] && rotatedVertices[v2]){
const [screenX1, screenY1] = project(rotatedVertices[v1].x, rotatedVertices[v1].y, rotatedVertices[v1].z);
const [screenX2, screenY2] = project(rotatedVertices[v2].x, rotatedVertices[v2].y, rotatedVertices[v2].z);

const d = pointToSegmentDistance(x, y, screenX1, screenY1, screenX2, screenY2);
if (d < 10) {
lineToAttach = index;
}
}
});
}

function drag(event) {
if (indexToDrag !== -1 && event.which === 1) {
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;

vertices[indexToDrag].x = x / canvas.width - 0.5;
vertices[indexToDrag].y = -(y / canvas.height - 0.5);
}
}

function release(event) {
if (lineToAttach !== -1 && event.which === 1) {
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;

// Attach to line
const closestPoint = closestPointOnSegment(x, y, edges[lineToAttach], rotatedVertices);
if(closestPoint){
vertices.push({
x: closestPoint[0] - 0.5,
y: -(closestPoint[1] - 0.5),
z: -1,
color: “#000000”
});

edges.push([indexToDrag, vertices.length - 1]);
}
}

indexToDrag = -1;
lineToAttach = -1;
}

// Functions for project, unproject, and distance calculation
function project(x, y, z) {
const posX = x * scale;
const posY = y * scale;
const posZ = z * scale;

return [
(posX * (zoom + posZ) + canvas.width / 2),
(posY * (zoom + posZ) + canvas.height / 2),
];
}

function unproject(x, y) {
const posX = (x - canvas.width / 2) / (zoom * scale);
const posY = (y - canvas.height / 2) / (zoom * scale);

return [posX, -posY];
}

function closestPointOnSegment(px, py, edge, rotatedVertices) {
const [v1, v2] = edge;
if(rotatedVertices[v1] && rotatedVertices[v2]){
const [screenX1, screenY1] = project(rotatedVertices[v1].x, rotatedVertices[v1].y, rotatedVertices[v1].z);
const [screenX2, screenY2] = project(rotatedVertices[v2].x, rotatedVertices[v2].y, rotatedVertices[v2].z);

const dx = screenX2 - screenX1;
const dy = screenY2 - screenY1;
const t = ((px - screenX1) * dx + (py - screenY1) * dy) / (dx * dx + dy * dy);

if (t < 0) return false; // closest point is beyond screenX1
if (t > 1) return false; // closest point is beyond screenX2

const x = screenX1 + t * dx;
const y = screenY1 + t * dy;

return unproject(x, y);
} else {
return false;
}
}

function pointToSegmentDistance(px, py, x1, y1, x2, y2) {
const closest = closestPointOnSegment(px, py, [x1, y1, x2, y2]);
if(closest){
const dx = px - closest[0];
const dy = py - closest[1];

return Math.sqrt(dx * dx + dy * dy);
} else {
return Infinity;
}
}

function drawCircle(ctx, [x, y], r) {
ctx.moveTo(x + r, y);
ctx.arc(x, y, r, 0, 2 * Math.PI);
}

// Matrix transformation functions
function rotateX(angle) {
const c = Math.cos(angle);
const s = Math.sin(angle);

return [
[1, 0, 0],
[0, c, -s],
[0, s, c],
];
}

function rotateY(angle) {
const c = Math.cos(angle);
const s = Math.sin(angle);

return [
[c, 0, s],
[0, 1, 0],
[-s, 0, c],
];
}

function rotateZ(angle) {
const c = Math.cos