This commit is contained in:
Gašper Dobrovoljc
2024-10-23 15:24:56 +02:00
commit ff56a51b82
11 changed files with 586 additions and 0 deletions

5
naloga_1/.prettierrc Normal file
View File

@@ -0,0 +1,5 @@
{
"semi": true,
"trailingComma": "all",
"tabWidth": 4
}

13
naloga_1/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Domača Naloga 1</title>
<script defer src="script.js"></script>
</head>
<body style="margin: 0; padding: 0;">
<canvas id="canvas" width="512px" height="512px"></canvas>
</body>
</html>

169
naloga_1/script.js Normal file
View File

@@ -0,0 +1,169 @@
async function main() {
const canvas = document.getElementById("canvas");
/**
* @type RenderingContext
*/
const ctx = canvas.getContext("2d");
const { models, scene } = await fetch("test.json").then(res => res.json());
for (const { model, transforms } of scene) {
let m = Matrix.identity();
for (const transform of transforms) {
switch (transform.type) {
case "scale":
m = m.scale(transform.factor[0], transform.factor[1]);
break;
case "rotate":
m = m.rotate(transform.angle);
break;
case "translate":
m = m.translate(transform.vector[0], transform.vector[1]);
break;
}
}
m = m.screen(0, 0, canvas.width, canvas.height);
for (const line of models[model]) {
const p1 = m.multiply(Matrix.vector(...line[0], 1));
ctx.moveTo(p1.vector[0], p1.vector[1]);
const p2 = m.multiply(Matrix.vector(...line[1], 1));
ctx.lineTo(p2.vector[0], p2.vector[1]);
}
ctx.stroke();
}
}
main();
class Matrix extends Array {
/**
* @param {number[][]} matrix
*/
constructor(matrix) {
super();
this.push(...matrix);
}
static identity() {
return new Matrix([
[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
]);
}
/**
* @param {number} vector
*/
static vector(...vector) {
const matrix = Array(vector.length);
for (let i = 0; i < vector.length; i++) {
matrix[i] = [vector[i]];
}
return new Matrix(matrix);
}
get width() {
if (this.length === 0) {
return 0;
}
return this[0].length;
}
get height() {
return this.length;
}
get vector() {
const v = [];
for (const l of this) {
v.push(l[0]);
}
return v;
}
toString() {
let str = "";
for (const line of this) {
str += line.join(", ") + "\n";
}
return str;
}
/**
* @param {Matrix} matrix
*/
multiply(matrix) {
if (this.width !== matrix.height) {
throw Error("Can not multiply");
}
const m = Array.from({ length: this.height },
() => Array.from(
{ length: matrix.width }, () => 0,
),
);
for (let i = 0; i < m.length; i++) {
for (let j = 0; j < m[0].length; j++) {
let sum = 0;
for (let k = 0; k < this.width; k++) {
sum += this[i][k] * matrix[k][j];
}
m[i][j] = sum;
}
}
return new Matrix(m);
}
/**
* @param {number} x
* @param {number} y
*/
scale(x, y) {
return new Matrix([
[x, 0, 0],
[0, y, 0],
[0, 0, 1],
]).multiply(this);
}
/**
* @param {number} angle
*/
rotate(angle) {
return new Matrix([
[Math.cos(angle), -Math.sin(angle), 0],
[Math.sin(angle), Math.cos(angle), 0],
[0, 0, 1],
]).multiply(this);
}
translate(x, y) {
return new Matrix([
[1, 0, x],
[0, 1, y],
[0, 0, 1],
]).multiply(this);
}
/**
* @param {number} x0
* @param {number} y0
* @param {number} x1
* @param {number} y1
*/
screen(x0, y0, x1, y1) {
return new Matrix([
[(x1 - x0) / 2, 0, (x0 + x1) / 2],
[0, -(y1 - y0) / 2, (y0 + y1) / 2],
[0, 0, 1],
]).multiply(this);
}
}

198
naloga_1/test.json Normal file
View File

@@ -0,0 +1,198 @@
{
"models": [
[
[[-1, -1], [1, -1]],
[[1, -1], [0, 1]],
[[0, 1], [-1, -1]]
],
[
[[0, 1], [-0.5878, -0.8090]],
[[-0.5878, -0.8090], [0.9511, 0.3090]],
[[0.9511, 0.3090], [-0.9511, 0.3090]],
[[-0.9511, 0.3090], [0.5878, -0.8090]],
[[0.5878, -0.8090], [0, 1]]
]
],
"scene": [
{
"model": 0,
"transforms": [
{ "type": "scale", "factor": [0.01, 0.01] },
{ "type": "rotate", "angle": 1 },
{ "type": "translate", "vector": [0.05, 0] },
{ "type": "rotate", "angle": 0.5 }
]
},
{
"model": 1,
"transforms": [
{ "type": "scale", "factor": [0.02, 0.02] },
{ "type": "rotate", "angle": 2 },
{ "type": "translate", "vector": [0.1, 0] },
{ "type": "rotate", "angle": 1 }
]
},
{
"model": 0,
"transforms": [
{ "type": "scale", "factor": [0.03, 0.03] },
{ "type": "rotate", "angle": 3 },
{ "type": "translate", "vector": [0.15, 0] },
{ "type": "rotate", "angle": 1.5 }
]
},
{
"model": 1,
"transforms": [
{ "type": "scale", "factor": [0.04, 0.04] },
{ "type": "rotate", "angle": 4 },
{ "type": "translate", "vector": [0.2, 0] },
{ "type": "rotate", "angle": 2 }
]
},
{
"model": 0,
"transforms": [
{ "type": "scale", "factor": [0.05, 0.05] },
{ "type": "rotate", "angle": 5 },
{ "type": "translate", "vector": [0.25, 0] },
{ "type": "rotate", "angle": 2.5 }
]
},
{
"model": 1,
"transforms": [
{ "type": "scale", "factor": [0.06, 0.06] },
{ "type": "rotate", "angle": 6 },
{ "type": "translate", "vector": [0.3, 0] },
{ "type": "rotate", "angle": 3 }
]
},
{
"model": 0,
"transforms": [
{ "type": "scale", "factor": [0.07, 0.07] },
{ "type": "rotate", "angle": 7 },
{ "type": "translate", "vector": [0.35, 0] },
{ "type": "rotate", "angle": 3.5 }
]
},
{
"model": 1,
"transforms": [
{ "type": "scale", "factor": [0.08, 0.08] },
{ "type": "rotate", "angle": 8 },
{ "type": "translate", "vector": [0.4, 0] },
{ "type": "rotate", "angle": 4 }
]
},
{
"model": 0,
"transforms": [
{ "type": "scale", "factor": [0.09, 0.09] },
{ "type": "rotate", "angle": 9 },
{ "type": "translate", "vector": [0.45, 0] },
{ "type": "rotate", "angle": 4.5 }
]
},
{
"model": 1,
"transforms": [
{ "type": "scale", "factor": [0.1, 0.1] },
{ "type": "rotate", "angle": 10 },
{ "type": "translate", "vector": [0.5, 0] },
{ "type": "rotate", "angle": 5 }
]
},
{
"model": 0,
"transforms": [
{ "type": "scale", "factor": [0.11, 0.11] },
{ "type": "rotate", "angle": 11 },
{ "type": "translate", "vector": [0.55, 0] },
{ "type": "rotate", "angle": 5.5 }
]
},
{
"model": 1,
"transforms": [
{ "type": "scale", "factor": [0.12, 0.12] },
{ "type": "rotate", "angle": 12 },
{ "type": "translate", "vector": [0.6, 0] },
{ "type": "rotate", "angle": 6 }
]
},
{
"model": 0,
"transforms": [
{ "type": "scale", "factor": [0.13, 0.13] },
{ "type": "rotate", "angle": 13 },
{ "type": "translate", "vector": [0.65, 0] },
{ "type": "rotate", "angle": 6.5 }
]
},
{
"model": 1,
"transforms": [
{ "type": "scale", "factor": [0.14, 0.14] },
{ "type": "rotate", "angle": 14 },
{ "type": "translate", "vector": [0.7, 0] },
{ "type": "rotate", "angle": 7 }
]
},
{
"model": 0,
"transforms": [
{ "type": "scale", "factor": [0.15, 0.15] },
{ "type": "rotate", "angle": 15 },
{ "type": "translate", "vector": [0.75, 0] },
{ "type": "rotate", "angle": 7.5 }
]
},
{
"model": 1,
"transforms": [
{ "type": "scale", "factor": [0.16, 0.16] },
{ "type": "rotate", "angle": 16 },
{ "type": "translate", "vector": [0.8, 0] },
{ "type": "rotate", "angle": 8 }
]
},
{
"model": 0,
"transforms": [
{ "type": "scale", "factor": [0.17, 0.17] },
{ "type": "rotate", "angle": 17 },
{ "type": "translate", "vector": [0.85, 0] },
{ "type": "rotate", "angle": 8.5 }
]
},
{
"model": 1,
"transforms": [
{ "type": "scale", "factor": [0.18, 0.18] },
{ "type": "rotate", "angle": 18 },
{ "type": "translate", "vector": [0.9, 0] },
{ "type": "rotate", "angle": 9 }
]
},
{
"model": 0,
"transforms": [
{ "type": "scale", "factor": [0.19, 0.19] },
{ "type": "rotate", "angle": 19 },
{ "type": "translate", "vector": [0.95, 0] },
{ "type": "rotate", "angle": 9.5 }
]
},
{
"model": 1,
"transforms": [
{ "type": "scale", "factor": [0.2, 0.2] },
{ "type": "rotate", "angle": 20 },
{ "type": "translate", "vector": [1, 0] },
{ "type": "rotate", "angle": 10 }
]
}
]
}